diff options
author | fche <fche> | 2005-06-05 16:35:28 +0000 |
---|---|---|
committer | fche <fche> | 2005-06-05 16:35:28 +0000 |
commit | f3c26ea55e2f2c1d222312bf75035359c439ed21 (patch) | |
tree | 1a58dfcdebe04941002e7e0203f765b619ca9c67 /translate.cxx | |
parent | 8846477c222cdae649b02117cc96999b0be6ad40 (diff) | |
download | systemtap-steved-f3c26ea55e2f2c1d222312bf75035359c439ed21.tar.gz systemtap-steved-f3c26ea55e2f2c1d222312bf75035359c439ed21.tar.xz systemtap-steved-f3c26ea55e2f2c1d222312bf75035359c439ed21.zip |
2005-06-05 Frank Ch. Eigler <fche@elastic.org>
Implement for/next/continue/break/while statements.
* staptree.h: Declare new 0-arity statement types. Tweak for_loop.
* parse.cxx: Parse them all.
* translate.cxx (c_unparser): Maintain break/continue label stack.
(visit_for_loop, *_statement): New implementations.
* elaborate.*, staptree.cxx: Mechanical changes.
* testsuite/parseok/ten.stp, semko/twelve.stp, transko/two.stp,
transok/five.stp: New tests.
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/translate.cxx b/translate.cxx index 972e188c..df20389f 100644 --- a/translate.cxx +++ b/translate.cxx @@ -1,4 +1,4 @@ -// semantic analysis pass, beginnings of elaboration +// translation pass // Copyright (C) 2005 Red Hat Inc. // // This file is part of systemtap, and is free software. You can @@ -65,10 +65,11 @@ struct c_unparser: public unparser, public visitor unsigned current_probenum; functiondecl* current_function; unsigned tmpvar_counter; + unsigned label_counter; c_unparser (systemtap_session *ss): session (ss), o (ss->op), current_probe(0), current_function (0), - tmpvar_counter (0) {} + tmpvar_counter (0), label_counter (0) {} ~c_unparser () {} void emit_common_header (); @@ -79,9 +80,9 @@ struct c_unparser: public unparser, public visitor void emit_function (functiondecl* v); void emit_probe (derived_probe* v, unsigned i); - // XXX: for use by loop/nesting constructs - // vector<string> loop_break_labels; - // vector<string> loop_continue_labels; + // for use by looping constructs + vector<string> loop_break_labels; + vector<string> loop_continue_labels; string c_typename (exp_type e); string c_varname (const string& e); @@ -97,6 +98,9 @@ struct c_unparser: public unparser, public visitor void visit_foreach_loop (foreach_loop* s); void visit_return_statement (return_statement* s); void visit_delete_statement (delete_statement* s); + void visit_next_statement (next_statement* s); + void visit_break_statement (break_statement* s); + void visit_continue_statement (continue_statement* s); void visit_literal_string (literal_string* e); void visit_literal_number (literal_number* e); void visit_binary_expression (binary_expression* e); @@ -593,7 +597,7 @@ c_unparser::visit_block (block *s) o->newline() << "{"; o->indent (1); o->newline() << "c->actioncount += " << s->statements.size() << ";"; - o->newline() << "if (c->actioncount > MAXACTION) errorcount ++;" << endl; + o->newline() << "if (c->actioncount > MAXACTION) errorcount ++;"; for (unsigned i=0; i<s->statements.size(); i++) { @@ -653,7 +657,33 @@ c_unparser::visit_if_statement (if_statement *s) void c_unparser::visit_for_loop (for_loop *s) { - throw semantic_error ("not yet implemented", s->tok); + s->init->visit (this); + string ctr = stringify (label_counter++); + string contlabel = "continue_" + ctr; + string breaklabel = "break_" + ctr; + + o->newline() << contlabel << ":"; + + o->newline() << "c->actioncount ++;"; + o->newline() << "if (c->actioncount > MAXACTION) errorcount ++;"; + o->newline() << "if (errorcount) goto out;"; + + o->newline() << "if (! ("; + if (s->cond->type != pe_long) + throw semantic_error ("expected numeric type", s->cond->tok); + s->cond->visit (this); + o->line() << ")) goto " << breaklabel << ";"; + + loop_break_labels.push_back (breaklabel); + loop_continue_labels.push_back (contlabel); + s->block->visit (this); + loop_break_labels.pop_back (); + loop_continue_labels.pop_back (); + + s->incr->visit (this); + o->newline() << "goto " << contlabel << ";"; + + o->newline() << breaklabel << ": ; /* dummy statement */"; } @@ -680,17 +710,52 @@ c_unparser::visit_return_statement (return_statement* s) void +c_unparser::visit_next_statement (next_statement* s) +{ + if (current_probe == 0) + throw semantic_error ("cannot 'next' from non-probe", s->tok); + + o->newline() << "goto out;"; +} + + +void c_unparser::visit_delete_statement (delete_statement* s) { throw semantic_error ("not yet implemented", s->tok); } + +void +c_unparser::visit_break_statement (break_statement* s) +{ + if (loop_break_labels.size() == 0) + throw semantic_error ("cannot 'break' outside loop", s->tok); + + string label = loop_break_labels[loop_break_labels.size()-1]; + o->newline() << "goto " << label << ";"; +} + + +void +c_unparser::visit_continue_statement (continue_statement* s) +{ + if (loop_continue_labels.size() == 0) + throw semantic_error ("cannot 'continue' outside loop", s->tok); + + string label = loop_continue_labels[loop_continue_labels.size()-1]; + o->newline() << "goto " << label << ";"; +} + + + void c_unparser::visit_literal_string (literal_string* e) { o->line() << '"' << e->value << '"'; // XXX: escape special chars } + void c_unparser::visit_literal_number (literal_number* e) { |