diff options
author | fche <fche> | 2005-05-05 20:31:53 +0000 |
---|---|---|
committer | fche <fche> | 2005-05-05 20:31:53 +0000 |
commit | 829198553c89ca7f2da93559c61c04ee89079ea1 (patch) | |
tree | 2f23d20d3d6d1c4078cbb50fc8f35d323e922cde | |
parent | e3f6c9cdd804120df4ec0b0fa33c033371958f17 (diff) | |
download | systemtap-steved-829198553c89ca7f2da93559c61c04ee89079ea1.tar.gz systemtap-steved-829198553c89ca7f2da93559c61c04ee89079ea1.tar.xz systemtap-steved-829198553c89ca7f2da93559c61c04ee89079ea1.zip |
* preliminaries for code generation logic
2005-05-05 Frank Ch. Eigler <fche@redhat.com>
* parse.cxx (parse): Add helper methods.
(lexer::scan, parse_assignment): Parse "<<<" operator. Fix assignment
associativity.
(parse_symbol): Permit function with empty arg list.
(parse_global, parse_statement, parse_functiondecl): Expect
unconsumed leading keyword.
(parse_global): Don't use ";" termination.
* parse.h: Corresponding changes.
* staptree.cxx (binary_expression::resolve_types): Fix <<<
type inference.
(translator_output): Improve pretty-printing.
(*): Add general visitors to statement/expression types.
* staptree.h: Corresponding changes. Tweak symresolution_info fields.
Add semantic_error class.
* semtest.cxx: Adapt to this.
* testsuite/parseok/two.stp, semok/*.stp: Adapt to syntax changes.
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | parse.cxx | 115 | ||||
-rw-r--r-- | parse.h | 3 | ||||
-rw-r--r-- | semtest.cxx | 13 | ||||
-rw-r--r-- | staptree.cxx | 552 | ||||
-rw-r--r-- | staptree.h | 201 | ||||
-rwxr-xr-x | testsuite/parseok/two.stp | 2 | ||||
-rwxr-xr-x | testsuite/semok/five.stp | 4 | ||||
-rwxr-xr-x | testsuite/semok/four.stp | 2 | ||||
-rwxr-xr-x | testsuite/semok/one.stp | 2 | ||||
-rwxr-xr-x | testsuite/semok/six.stp | 2 | ||||
-rwxr-xr-x | testsuite/semok/three.stp | 4 | ||||
-rwxr-xr-x | testsuite/semok/two.stp | 2 |
13 files changed, 824 insertions, 97 deletions
@@ -1,3 +1,22 @@ +2005-05-05 Frank Ch. Eigler <fche@redhat.com> + + * parse.cxx (parse): Add helper methods. + (lexer::scan, parse_assignment): Parse "<<<" operator. Fix assignment + associativity. + (parse_symbol): Permit function with empty arg list. + (parse_global, parse_statement, parse_functiondecl): Expect + unconsumed leading keyword. + (parse_global): Don't use ";" termination. + * parse.h: Corresponding changes. + * staptree.cxx (binary_expression::resolve_types): Fix <<< + type inference. + (translator_output): Improve pretty-printing. + (*): Add general visitors to statement/expression types. + * staptree.h: Corresponding changes. Tweak symresolution_info fields. + Add semantic_error class. + * semtest.cxx: Adapt to this. + * testsuite/parseok/two.stp, semok/*.stp: Adapt to syntax changes. + 2005-03-15 Frank Ch. Eigler <fche@redhat.com> * semtest.cxx: Print probe signatures properly. @@ -32,6 +32,22 @@ parser::~parser() } +stapfile* +parser::parse (std::istream& i) +{ + parser p (i); + return p.parse (); +} + + +stapfile* +parser::parse (const std::string& n) +{ + parser p (n); + return p.parse (); +} + + ostream& operator << (ostream& o, const token& t) { @@ -257,7 +273,15 @@ lexer::scan () (c == ':' && c2 == ':') || (c == '-' && c2 == '>') || false) // XXX: etc. - n->content.push_back((char) input_get ()); + n->content.push_back ((char) input_get ()); + + // handle three-character operator + if (c == '<' && c2 == '<') + { + int c3 = input.peek (); + if (c3 == '<') + n->content.push_back ((char) input_get ()); + } return n; } @@ -291,21 +315,11 @@ parser::parse () empty = false; if (t->type == tok_identifier && t->content == "probe") - { - next (); - f->probes.push_back (parse_probe ()); - } + f->probes.push_back (parse_probe ()); else if (t->type == tok_identifier && t->content == "global") - { - next (); - parse_global (f->globals); - } + parse_global (f->globals); else if (t->type == tok_identifier && t->content == "function") - { - next (); - f->functions.push_back (parse_functiondecl ()); - // XXX: check for duplicate function decl - } + f->functions.push_back (parse_functiondecl ()); else throw parse_error ("expected 'probe', 'global', or 'function'"); } @@ -345,13 +359,18 @@ parser::parse () probe* parser::parse_probe () { + const token* t0 = next (); + if (! (t0->type == tok_identifier && t0->content == "probe")) + throw parse_error ("expected 'probe'"); + probe *p = new probe; + p->tok = t0; + while (1) { const token *t = peek (); if (t && t->type == tok_identifier) { - p->tok = t; p->locations.push_back (parse_probe_point ()); t = peek (); @@ -467,6 +486,10 @@ parser::parse_statement () void parser::parse_global (vector <vardecl*>& globals) { + const token* t0 = next (); + if (! (t0->type == tok_identifier && t0->content == "global")) + throw parse_error ("expected 'global'"); + while (1) { const token* t = next (); @@ -478,13 +501,14 @@ parser::parse_global (vector <vardecl*>& globals) d->tok = t; globals.push_back (d); // XXX: check for duplicates - t = next (); - if (t->type == tok_operator && t->content == ";") - break; - else if (t->type == tok_operator && t->content == ",") - continue; + t = peek (); + if (t && t->type == tok_operator && t->content == ",") + { + next (); + continue; + } else - throw parse_error ("expected ';' or ','"); + break; } } @@ -492,9 +516,13 @@ parser::parse_global (vector <vardecl*>& globals) functiondecl* parser::parse_functiondecl () { + const token* t = next (); + if (! (t->type == tok_identifier && t->content == "function")) + throw parse_error ("expected 'function'"); + functiondecl *fd = new functiondecl (); - const token* t = next (); + t = next (); if (! (t->type == tok_identifier)) throw parse_error ("expected identifier"); fd->name = t->content; @@ -675,11 +703,6 @@ parser::parse_expression () return parse_assignment (); } -// XXX: in all subsequent calls to parse_expression(), -// check whether operator priority / associativity -// suggests that a different expression subtype parser -// should be called instead - expression* parser::parse_assignment () @@ -687,10 +710,10 @@ parser::parse_assignment () expression* op1 = parse_ternary (); const token* t = peek (); - // left-associative operators - while (t && t->type == tok_operator + // right-associative operators + if (t && t->type == tok_operator && (t->content == "=" || - t->content == "<<" || + t->content == "<<<" || t->content == "+=" || false)) // XXX: add /= etc. { @@ -701,9 +724,10 @@ parser::parse_assignment () e->op = t->content; e->tok = t; next (); - e->right = parse_ternary (); + e->right = parse_expression (); op1 = e; - t = peek (); + // XXX: map assign/accumlate operators like +=, /= + // to ordinary assignment + nested binary_expression } return op1; @@ -1056,17 +1080,24 @@ parser::parse_symbol () struct functioncall* f = new functioncall; f->tok = t2; f->function = name; + // Allow empty actual parameter list + const token* t3 = peek (); + if (t3 && t3->type == tok_operator && t3->content == ")") + { + next (); + return f; + } while (1) - { - f->args.push_back (parse_expression ()); - t = next (); - if (t->type == tok_operator && t->content == ")") - break; - if (t->type == tok_operator && t->content == ",") - continue; - else - throw parse_error ("expected ',' or ')'"); - } + { + f->args.push_back (parse_expression ()); + t = next (); + if (t->type == tok_operator && t->content == ")") + break; + if (t->type == tok_operator && t->content == ",") + continue; + else + throw parse_error ("expected ',' or ')'"); + } return f; } else @@ -64,6 +64,9 @@ public: stapfile* parse (); + static stapfile* parse (std::istream& i); + static stapfile* parse (const std::string& n); + private: std::string input_name; std::istream* free_input; diff --git a/semtest.cxx b/semtest.cxx index a37e3323..09cd7576 100644 --- a/semtest.cxx +++ b/semtest.cxx @@ -21,7 +21,7 @@ semantic_pass_1 (vector<stapfile*>& files) for (unsigned j=0; j<f->functions.size(); j++) { functiondecl* fn = f->functions[j]; - symresolution_info ri (fn->locals, f->globals, files, f, fn); + symresolution_info ri (fn->locals, f->globals, f->functions, fn); fn->body->resolve_symbols (ri); if (ri.num_unresolved) @@ -32,7 +32,7 @@ semantic_pass_1 (vector<stapfile*>& files) for (unsigned j=0; j<f->probes.size(); j++) { probe* pn = f->probes[j]; - symresolution_info ri (pn->locals, f->globals, files, f); + symresolution_info ri (pn->locals, f->globals, f->functions); pn->body->resolve_symbols (ri); if (ri.num_unresolved) @@ -113,8 +113,7 @@ main (int argc, char *argv []) vector<stapfile*> files; if (argc == 1) { - parser p (cin); - stapfile* f = p.parse (); + stapfile* f = parser::parse (cin); if (f) files.push_back (f); else @@ -122,8 +121,7 @@ main (int argc, char *argv []) } else for (int i = 1; i < argc; i ++) { - parser p (argv[i]); - stapfile* f = p.parse (); + stapfile* f = parser::parse (argv[i]); if (f) files.push_back (f); else @@ -131,7 +129,8 @@ main (int argc, char *argv []) } rc += semantic_pass_1 (files); - rc += semantic_pass_2 (files); + if (rc == 0) + rc += semantic_pass_2 (files); for (unsigned i=0; i<files.size(); i++) { diff --git a/staptree.cxx b/staptree.cxx index 34242c8f..ab2ebb97 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -62,7 +62,13 @@ symboldecl::~symboldecl () probe_point::probe_point (): - tok (0), prov (0) + tok (0) +{ +} + + +probe::probe (): + body (0), tok (0) { } @@ -342,6 +348,13 @@ void probe_point::print (ostream& o) } +ostream& operator << (ostream& o, probe_point& k) +{ + k.print (o); + return o; +} + + ostream& operator << (ostream& o, symboldecl& k) { k.print (o); @@ -355,9 +368,8 @@ ostream& operator << (ostream& o, symboldecl& k) symresolution_info::symresolution_info (vector<vardecl*>& l, vector<vardecl*>& g, - vector<stapfile*>& f, - stapfile* tf): - locals (l), globals (g), files (f), current_file (tf), current_function (0) + vector<functiondecl*>& f): + locals (l), globals (g), functions (f), current_function (0) { num_unresolved = 0; } @@ -365,10 +377,9 @@ symresolution_info::symresolution_info (vector<vardecl*>& l, symresolution_info::symresolution_info (vector<vardecl*>& l, vector<vardecl*>& g, - vector<stapfile*>& f, - stapfile* tf, + vector<functiondecl*>& f, functiondecl* cf): - locals (l), globals (g), files (f), current_file (tf), current_function (cf) + locals (l), globals (g), functions (f), current_function (cf) { num_unresolved = 0; } @@ -576,9 +587,9 @@ functiondecl* symresolution_info::find_function (const string& name, const vector<expression*>& args) { - for (unsigned j = 0; j < current_file->functions.size(); j++) + for (unsigned j = 0; j < functions.size(); j++) { - functiondecl* fd = current_file->functions[j]; + functiondecl* fd = functions[j]; if (fd->name == name) return fd; } @@ -621,15 +632,15 @@ literal::resolve_types (typeresolution_info& r, exp_type t) void binary_expression::resolve_types (typeresolution_info& r, exp_type t) { - if (op == "<<") + if (op == "<<<") // stats aggregation { left->resolve_types (r, pe_stats); right->resolve_types (r, pe_long); - if (t == pe_long || t == pe_string) - r.mismatch (tok, t, pe_stats); + if (t == pe_stats || t == pe_string) + r.mismatch (tok, t, pe_long); else if (type == pe_unknown) { - type = pe_stats; + type = pe_long; r.resolved (tok, type); } } @@ -645,7 +656,9 @@ binary_expression::resolve_types (typeresolution_info& r, exp_type t) r.resolved (tok, type); } } - else if (op == "==") // XXX: other comparison operators + else if (op == "==" + || op == "in" // XXX: really a unary operator + || false) // XXX: other comparison operators { left->resolve_types (r, pe_unknown); right->resolve_types (r, pe_unknown); @@ -977,26 +990,519 @@ typeresolution_info::resolved (const token* tok, exp_type t) // ------------------------------------------------------------------------ -// semantic processing: lvalue checking +// semantic processing: lvalue checking: XXX: unneeded? + bool -pre_crement::is_lvalue () +assignment::is_lvalue () { - return operand->is_lvalue (); + return left->is_lvalue (); } -bool -post_crement::is_lvalue () +// ------------------------------------------------------------------------ +// unparser + + +translator_output::translator_output (ostream& f): + o (f), tablevel (0) { - return operand->is_lvalue (); } -bool -assignment::is_lvalue () +ostream& +translator_output::newline (int indent) { - return left->is_lvalue (); + assert (indent > 0 || tablevel >= (unsigned)-indent); + tablevel += indent; + o << endl; + for (unsigned i=0; i<tablevel; i++) + o << " "; + return o; +} + + +void +translator_output::indent (int indent) +{ + assert (indent > 0 || tablevel >= (unsigned)-indent); + tablevel += indent; +} + + +ostream& +translator_output::line () +{ + return o; +} + + + +// ------------------------------------------------------------------------ +// visitors + + +void +block::visit (visitor* u) +{ + u->visit_block (this); +} + +void +for_loop::visit (visitor* u) +{ + u->visit_for_loop (this); +} + +void +null_statement::visit (visitor* u) +{ + u->visit_null_statement (this); +} + +void +expr_statement::visit (visitor* u) +{ + u->visit_expr_statement (this); +} + +void +return_statement::visit (visitor* u) +{ + u->visit_return_statement (this); +} + +void +delete_statement::visit (visitor* u) +{ + u->visit_delete_statement (this); +} + +void +if_statement::visit (visitor* u) +{ + u->visit_if_statement (this); +} + +void +literal_string::visit(visitor* u) +{ + u->visit_literal_string (this); +} + +void +literal_number::visit(visitor* u) +{ + u->visit_literal_number (this); +} + +void +binary_expression::visit (visitor* u) +{ + u->visit_binary_expression (this); +} + +void +unary_expression::visit (visitor* u) +{ + u->visit_unary_expression (this); +} + +void +pre_crement::visit (visitor* u) +{ + u->visit_pre_crement (this); +} + +void +post_crement::visit (visitor* u) +{ + u->visit_post_crement (this); +} + +void +logical_or_expr::visit (visitor* u) +{ + u->visit_logical_or_expr (this); +} + +void +logical_and_expr::visit (visitor* u) +{ + u->visit_logical_and_expr (this); +} + +void +array_in::visit (visitor* u) +{ + u->visit_array_in (this); +} + +void +comparison::visit (visitor* u) +{ + u->visit_comparison (this); +} + +void +concatenation::visit (visitor* u) +{ + u->visit_concatenation (this); +} + +void +exponentiation::visit (visitor* u) +{ + u->visit_exponentiation (this); +} + +void +ternary_expression::visit (visitor* u) +{ + u->visit_ternary_expression (this); +} + +void +assignment::visit (visitor* u) +{ + u->visit_assignment (this); +} + +void +symbol::visit (visitor* u) +{ + u->visit_symbol (this); +} + +void +arrayindex::visit (visitor* u) +{ + u->visit_arrayindex (this); +} + +void +functioncall::visit (visitor* u) +{ + u->visit_functioncall (this); +} + + +// ------------------------------------------------------------------------ + +void +traversing_visitor::visit_block (block *s) +{ + for (unsigned i=0; i<s->statements.size(); i++) + s->statements[i]->visit (this); +} + +void +traversing_visitor::visit_null_statement (null_statement *s) +{ +} + +void +traversing_visitor::visit_expr_statement (expr_statement *s) +{ + s->value->visit (this); +} + +void +traversing_visitor::visit_if_statement (if_statement* s) +{ + s->condition->visit (this); + s->thenblock->visit (this); + s->elseblock->visit (this); +} + +void +traversing_visitor::visit_for_loop (for_loop* s) +{ + s->init->visit (this); + s->cond->visit (this); + s->incr->visit (this); + s->block->visit (this); +} + +void +traversing_visitor::visit_return_statement (return_statement* s) +{ + s->value->visit (this); +} + +void +traversing_visitor::visit_delete_statement (delete_statement* s) +{ + s->value->visit (this); +} + +void +traversing_visitor::visit_literal_string (literal_string* e) +{ +} + +void +traversing_visitor::visit_literal_number (literal_number* e) +{ +} + +void +traversing_visitor::visit_binary_expression (binary_expression* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_unary_expression (unary_expression* e) +{ + e->operand->visit (this); +} + +void +traversing_visitor::visit_pre_crement (pre_crement* e) +{ + e->operand->visit (this); +} + +void +traversing_visitor::visit_post_crement (post_crement* e) +{ + e->operand->visit (this); +} + + +void +traversing_visitor::visit_logical_or_expr (logical_or_expr* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_logical_and_expr (logical_and_expr* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_array_in (array_in* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_comparison (comparison* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_concatenation (concatenation* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_exponentiation (exponentiation* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_ternary_expression (ternary_expression* e) +{ + e->cond->visit (this); + e->truevalue->visit (this); + e->falsevalue->visit (this); +} + +void +traversing_visitor::visit_assignment (assignment* e) +{ + e->left->visit (this); + e->right->visit (this); +} + +void +traversing_visitor::visit_symbol (symbol* e) +{ +} + +void +traversing_visitor::visit_arrayindex (arrayindex* e) +{ + for (unsigned i=0; i<e->indexes.size(); i++) + e->indexes[i]->visit (this); +} + +void +traversing_visitor::visit_functioncall (functioncall* e) +{ + for (unsigned i=0; i<e->args.size(); i++) + e->args[i]->visit (this); +} + + +// ------------------------------------------------------------------------ + + +throwing_visitor::throwing_visitor (const std::string& m): msg (m) {} +throwing_visitor::throwing_visitor (): msg ("invalid element") {} + + +void +throwing_visitor::throwone (const token* t) +{ + throw semantic_error (msg, t); +} + +void +throwing_visitor::visit_block (block *s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_null_statement (null_statement *s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_expr_statement (expr_statement *s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_if_statement (if_statement* s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_for_loop (for_loop* s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_return_statement (return_statement* s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_delete_statement (delete_statement* s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_literal_string (literal_string* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_literal_number (literal_number* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_binary_expression (binary_expression* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_unary_expression (unary_expression* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_pre_crement (pre_crement* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_post_crement (post_crement* e) +{ + throwone (e->tok); } +void +throwing_visitor::visit_logical_or_expr (logical_or_expr* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_logical_and_expr (logical_and_expr* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_array_in (array_in* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_comparison (comparison* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_concatenation (concatenation* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_exponentiation (exponentiation* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_ternary_expression (ternary_expression* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_assignment (assignment* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_symbol (symbol* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_arrayindex (arrayindex* e) +{ + throwone (e->tok); +} + +void +throwing_visitor::visit_functioncall (functioncall* e) +{ + throwone (e->tok); +} @@ -2,14 +2,38 @@ // Copyright 2005 Red Hat Inc. // GPL +#ifndef STAPTREE_H +#define STAPTREE_H + #include <string> #include <vector> #include <map> #include <iostream> +#include <stdexcept> + using namespace std; +struct token; // parse.h +struct semantic_error: public std::runtime_error +{ + const token* tok1; + const string msg2; + const token* tok2; + + ~semantic_error () throw () {} + semantic_error (const string& msg): + runtime_error (msg), tok1 (0), tok2 (0) {} + semantic_error (const string& msg, const token* t1): + runtime_error (msg), tok1 (t1), tok2 (0) {} + semantic_error (const string& msg, const token* t1, + const string& m2, const token* t2): + runtime_error (msg), tok1 (t1), msg2 (m2), tok2 (t2) {} +}; + + + enum exp_type { pe_unknown, @@ -23,16 +47,19 @@ ostream& operator << (ostream& o, const exp_type& e); struct token; struct symresolution_info; struct typeresolution_info; +struct visitor; + struct expression { exp_type type; const token* tok; - virtual void print (ostream& o) = 0; expression (); virtual ~expression (); + virtual void print (ostream& o) = 0; virtual void resolve_symbols (symresolution_info& r) = 0; virtual void resolve_types (typeresolution_info& r, exp_type t) = 0; - virtual bool is_lvalue () = 0; + virtual bool is_lvalue () = 0; // XXX: deprecate + virtual void visit (visitor* u) = 0; }; ostream& operator << (ostream& o, expression& k); @@ -51,6 +78,7 @@ struct literal_string: public literal string value; literal_string (const string& v); void print (ostream& o); + void visit (visitor* u); }; @@ -59,6 +87,7 @@ struct literal_number: public literal long value; literal_number (long v); void print (ostream& o); + void visit (visitor* u); }; @@ -68,6 +97,7 @@ struct binary_expression: public expression string op; expression* right; void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r, exp_type t); bool is_lvalue () { return false; } @@ -79,6 +109,7 @@ struct unary_expression: public expression string op; expression* operand; void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r, exp_type t); bool is_lvalue () { return false; } @@ -87,44 +118,50 @@ struct unary_expression: public expression struct pre_crement: public unary_expression { - bool is_lvalue (); + void visit (visitor* u); }; struct post_crement: public unary_expression { - bool is_lvalue (); void print (ostream& o); + void visit (visitor* u); }; struct logical_or_expr: public binary_expression { + void visit (visitor* u); }; struct logical_and_expr: public binary_expression { + void visit (visitor* u); }; struct array_in: public binary_expression { + void visit (visitor* u); }; struct comparison: public binary_expression { + void visit (visitor* u); }; struct concatenation: public binary_expression { + void visit (visitor* u); }; struct exponentiation: public binary_expression { + void visit (visitor* u); }; @@ -134,6 +171,7 @@ struct ternary_expression: public expression expression* truevalue; expression* falsevalue; void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r, exp_type t); bool is_lvalue () { return false; } @@ -143,6 +181,7 @@ struct ternary_expression: public expression struct assignment: public binary_expression { bool is_lvalue (); + void visit (visitor* u); }; @@ -153,6 +192,7 @@ struct symbol: public expression vardecl *referent; symbol (); void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r, exp_type t); bool is_lvalue () { return true; } @@ -166,6 +206,7 @@ struct arrayindex: public expression vardecl *referent; arrayindex (); void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r, exp_type t); bool is_lvalue () { return true; } @@ -180,6 +221,7 @@ struct functioncall: public expression functiondecl *referent; functioncall (); void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r, exp_type t); bool is_lvalue () { return false; } @@ -195,19 +237,16 @@ struct symresolution_info { vector<vardecl*>& locals; // includes incoming function parameters vector<vardecl*>& globals; - vector<stapfile*>& files; - stapfile* current_file; + vector<functiondecl*>& functions; functiondecl* current_function; symresolution_info (vector<vardecl*>& l, vector<vardecl*>& g, - vector<stapfile*>& f, - stapfile* cfil, + vector<functiondecl*>& f, functiondecl* cfun); symresolution_info (vector<vardecl*>& l, vector<vardecl*>& g, - vector<stapfile*>& f, - stapfile* cfil); + vector<functiondecl*>& f); vardecl* find_scalar (const string& name); vardecl* find_array (const string& name, const vector<expression*>&); @@ -225,8 +264,7 @@ struct typeresolution_info bool assert_resolvability; functiondecl* current_function; - void mismatch (const token* tok, exp_type t1, - exp_type t2); + void mismatch (const token* tok, exp_type t1, exp_type t2); void unresolved (const token* tok); void resolved (const token* tok, exp_type t); void invalid (const token* tok, exp_type t); @@ -282,6 +320,7 @@ struct functiondecl: public symboldecl struct statement { virtual void print (ostream& o) = 0; + virtual void visit (visitor* u) = 0; const token* tok; statement (); virtual ~statement (); @@ -296,6 +335,7 @@ struct block: public statement { vector<statement*> statements; void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r); }; @@ -307,6 +347,7 @@ struct for_loop: public statement expression* incr; statement* block; void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r); }; @@ -315,6 +356,7 @@ struct for_loop: public statement struct null_statement: public statement { void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r) {} void resolve_types (typeresolution_info& r) {} }; @@ -324,6 +366,7 @@ struct expr_statement: public statement { expression* value; // executed for side-effects void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r); }; @@ -335,6 +378,7 @@ struct if_statement: public statement statement* thenblock; statement* elseblock; void print (ostream& o); + void visit (visitor* u); void resolve_symbols (symresolution_info& r); void resolve_types (typeresolution_info& r); }; @@ -343,6 +387,7 @@ struct if_statement: public statement struct return_statement: public expr_statement { void print (ostream& o); + void visit (visitor* u); void resolve_types (typeresolution_info& r); }; @@ -350,6 +395,7 @@ struct return_statement: public expr_statement struct delete_statement: public expr_statement { void print (ostream& o); + void visit (visitor* u); }; @@ -364,29 +410,152 @@ struct stapfile }; -class provider; struct probe_point { struct component // XXX: sort of a restricted functioncall { string functor; - literal* arg; + literal* arg; // optional component (); }; vector<component*> components; const token* tok; // points to first component's functor - provider* prov; void print (ostream& o); probe_point (); }; +ostream& operator << (ostream& o, probe_point& k); + struct probe { vector<probe_point*> locations; - const token* tok; block* body; + const token* tok; vector<vardecl*> locals; + probe (); void print (ostream& o); void printsig (ostream &o); }; + + + +// Output context for systemtap translation, intended to allow +// pretty-printing. +class translator_output +{ + ostream& o; + unsigned tablevel; + +public: + translator_output (ostream& file); + + ostream& newline (int indent = 0); + void indent (int indent = 0); + ostream& line(); +}; + + +// An derived visitor instance is used to visit the entire +// statement/expression tree. +struct visitor +{ + virtual ~visitor () {} + virtual void visit_block (block *s) = 0; + virtual void visit_null_statement (null_statement *s) = 0; + virtual void visit_expr_statement (expr_statement *s) = 0; + virtual void visit_if_statement (if_statement* s) = 0; + virtual void visit_for_loop (for_loop* s) = 0; + virtual void visit_return_statement (return_statement* s) = 0; + virtual void visit_delete_statement (delete_statement* s) = 0; + virtual void visit_literal_string (literal_string* e) = 0; + virtual void visit_literal_number (literal_number* e) = 0; + virtual void visit_binary_expression (binary_expression* e) = 0; + virtual void visit_unary_expression (unary_expression* e) = 0; + virtual void visit_pre_crement (pre_crement* e) = 0; + virtual void visit_post_crement (post_crement* e) = 0; + virtual void visit_logical_or_expr (logical_or_expr* e) = 0; + virtual void visit_logical_and_expr (logical_and_expr* e) = 0; + virtual void visit_array_in (array_in* e) = 0; + virtual void visit_comparison (comparison* e) = 0; + virtual void visit_concatenation (concatenation* e) = 0; + virtual void visit_exponentiation (exponentiation* e) = 0; + virtual void visit_ternary_expression (ternary_expression* e) = 0; + virtual void visit_assignment (assignment* e) = 0; + virtual void visit_symbol (symbol* e) = 0; + virtual void visit_arrayindex (arrayindex* e) = 0; + virtual void visit_functioncall (functioncall* e) = 0; +}; + + +// A default kind of visitor, which by default travels down +// to the leaves of the statement/expression tree, up to +// but excluding following vardecls (referent pointers). +struct traversing_visitor: public visitor +{ + void visit_block (block *s); + void visit_null_statement (null_statement *s); + void visit_expr_statement (expr_statement *s); + void visit_if_statement (if_statement* s); + void visit_for_loop (for_loop* s); + void visit_return_statement (return_statement* s); + void visit_delete_statement (delete_statement* s); + void visit_literal_string (literal_string* e); + void visit_literal_number (literal_number* e); + void visit_binary_expression (binary_expression* e); + void visit_unary_expression (unary_expression* e); + void visit_pre_crement (pre_crement* e); + void visit_post_crement (post_crement* e); + void visit_logical_or_expr (logical_or_expr* e); + void visit_logical_and_expr (logical_and_expr* e); + void visit_array_in (array_in* e); + void visit_comparison (comparison* e); + void visit_concatenation (concatenation* e); + void visit_exponentiation (exponentiation* e); + void visit_ternary_expression (ternary_expression* e); + void visit_assignment (assignment* e); + void visit_symbol (symbol* e); + void visit_arrayindex (arrayindex* e); + void visit_functioncall (functioncall* e); +}; + + +// A kind of visitor that throws an semantic_error exception +// whenever a non-overridden method is called. +struct throwing_visitor: public visitor +{ + std::string msg; + throwing_visitor (const std::string& m); + throwing_visitor (); + + virtual void throwone (const token* t); + + void visit_block (block *s); + void visit_null_statement (null_statement *s); + void visit_expr_statement (expr_statement *s); + void visit_if_statement (if_statement* s); + void visit_for_loop (for_loop* s); + void visit_return_statement (return_statement* s); + void visit_delete_statement (delete_statement* s); + void visit_literal_string (literal_string* e); + void visit_literal_number (literal_number* e); + void visit_binary_expression (binary_expression* e); + void visit_unary_expression (unary_expression* e); + void visit_pre_crement (pre_crement* e); + void visit_post_crement (post_crement* e); + void visit_logical_or_expr (logical_or_expr* e); + void visit_logical_and_expr (logical_and_expr* e); + void visit_array_in (array_in* e); + void visit_comparison (comparison* e); + void visit_concatenation (concatenation* e); + void visit_exponentiation (exponentiation* e); + void visit_ternary_expression (ternary_expression* e); + void visit_assignment (assignment* e); + void visit_symbol (symbol* e); + void visit_arrayindex (arrayindex* e); + void visit_functioncall (functioncall* e); +}; + + + +#endif // STAPTREE_H diff --git a/testsuite/parseok/two.stp b/testsuite/parseok/two.stp index b6b843de..fdcf335e 100755 --- a/testsuite/parseok/two.stp +++ b/testsuite/parseok/two.stp @@ -2,7 +2,7 @@ probe syscall (231) { - array[idx] << value; + array[idx] <<< value; if (global > 5) { global -- } else ; } diff --git a/testsuite/semok/five.stp b/testsuite/semok/five.stp index c8b59e73..2bb656b1 100755 --- a/testsuite/semok/five.stp +++ b/testsuite/semok/five.stp @@ -1,7 +1,7 @@ -#! parsetest +#! semtest probe foo { array[1] = array[2] = 3; - statvar << value << 4; + statvar <<< value <<< 4; } diff --git a/testsuite/semok/four.stp b/testsuite/semok/four.stp index c3b2a7d0..eb87f3f9 100755 --- a/testsuite/semok/four.stp +++ b/testsuite/semok/four.stp @@ -2,7 +2,7 @@ # these will ultimately be somehow associated with "providers" # and have a syntax of their own -global kernel_jiffies, kernel_current_comm; +global kernel_jiffies, kernel_current_comm function kernel_netlink(a, b) { # this should be a builtin function diff --git a/testsuite/semok/one.stp b/testsuite/semok/one.stp index 336e57d2..764bd476 100755 --- a/testsuite/semok/one.stp +++ b/testsuite/semok/one.stp @@ -2,7 +2,7 @@ # these will ultimately be somehow associated with "providers" # and have a syntax of their own -global kernel_jiffies, kernel_current_comm; +global kernel_jiffies, kernel_current_comm function kernel_netlink(a, b) { # this should be a builtin function diff --git a/testsuite/semok/six.stp b/testsuite/semok/six.stp index 53d69503..72b7e065 100755 --- a/testsuite/semok/six.stp +++ b/testsuite/semok/six.stp @@ -1,4 +1,4 @@ -#! parsetest +#! semtest probe foo { diff --git a/testsuite/semok/three.stp b/testsuite/semok/three.stp index 6ae531a2..100a5f2b 100755 --- a/testsuite/semok/three.stp +++ b/testsuite/semok/three.stp @@ -1,6 +1,6 @@ #! semtest probe foo { - a << 2; - b[4] << 4; + a <<< 2; + b[4] <<< 4; } diff --git a/testsuite/semok/two.stp b/testsuite/semok/two.stp index f3c6046e..5a124474 100755 --- a/testsuite/semok/two.stp +++ b/testsuite/semok/two.stp @@ -1,6 +1,6 @@ #! semtest -global bar, baz; +global bar, baz function koo (p) { baz [p, "p", p] ++; |