* [PATCH] Add support for compound (comma) expressions
@ 2018-08-24 5:33 Yichun Zhang (agentzh)
0 siblings, 0 replies; only message in thread
From: Yichun Zhang (agentzh) @ 2018-08-24 5:33 UTC (permalink / raw)
To: systemtap; +Cc: Yichun Zhang (agentzh)
Implemented the comma operator and compound expressions similar to the
ones in the C language.
The current parse tree, semantic analyzers, and the code emitter already
support the compound (comma) expressions. This patch simply exposes it to
the stap language level in the parser.
---
parse.cxx | 55 +++++++----
testsuite/systemtap.base/compound_expr.exp | 132 +++++++++++++++++++++++++++
testsuite/systemtap.base/compound_expr_1.stp | 7 ++
testsuite/systemtap.base/compound_expr_2.stp | 6 ++
testsuite/systemtap.base/compound_expr_3.stp | 6 ++
testsuite/systemtap.base/compound_expr_4.stp | 6 ++
6 files changed, 196 insertions(+), 16 deletions(-)
create mode 100644 testsuite/systemtap.base/compound_expr.exp
create mode 100644 testsuite/systemtap.base/compound_expr_1.stp
create mode 100644 testsuite/systemtap.base/compound_expr_2.stp
create mode 100644 testsuite/systemtap.base/compound_expr_3.stp
create mode 100644 testsuite/systemtap.base/compound_expr_4.stp
diff --git a/parse.cxx b/parse.cxx
index 751f56add..21aa6f999 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -211,6 +211,7 @@ private: // nonterminals
expression* parse_target_register (const token* t);
expression* parse_target_deref (const token* t);
expression* parse_expression ();
+ expression* parse_compound_expression ();
expression* parse_assignment ();
expression* parse_ternary ();
expression* parse_logical_or ();
@@ -3158,7 +3159,7 @@ parser::parse_foreach_loop ()
s->array_slice.push_back (NULL);
}
else
- s->array_slice.push_back (parse_expression());
+ s->array_slice.push_back (parse_assignment ());
t = peek ();
if (t && t->type == tok_operator && t->content == ",")
@@ -3210,7 +3211,7 @@ parser::parse_foreach_loop ()
if (tok_is(t, tok_keyword, "limit"))
{
swallow (); // get past the "limit"
- s->limit = parse_expression ();
+ s->limit = parse_assignment ();
}
t = next ();
@@ -3226,7 +3227,29 @@ parser::parse_foreach_loop ()
expression*
parser::parse_expression ()
{
- return parse_assignment ();
+ return parse_compound_expression ();
+}
+
+
+expression*
+parser::parse_compound_expression ()
+{
+ expression *op1 = parse_assignment ();
+
+ const token* t = peek ();
+ while (t && t->type == tok_operator && t->content == ",")
+ {
+ compound_expression *e = new compound_expression;
+ e->tok = t;
+ e->op = t->content;
+ e->left = op1;
+ next ();
+ e->right = parse_assignment ();
+ op1 = e;
+ t = peek ();
+ }
+
+ return op1;
}
@@ -3259,7 +3282,7 @@ parser::parse_assignment ()
e->op = t->content;
e->tok = t;
next ();
- e->right = parse_expression ();
+ e->right = parse_assignment ();
op1 = e;
}
@@ -3770,7 +3793,7 @@ parser::parse_hist_op_or_bare_name (hist_op *&hop, interned_string &name)
hop->htype = hist_log;
hop->tok = t;
expect_op("(");
- hop->stat = parse_expression ();
+ hop->stat = parse_assignment ();
int64_t tnum;
if (hop->htype == hist_linear)
{
@@ -3864,7 +3887,7 @@ expression* parser::parse_symbol ()
name.to_string().c_str()));
expect_op("(");
sop->tok = t;
- sop->stat = parse_expression ();
+ sop->stat = parse_assignment ();
while(1)
{
@@ -3927,7 +3950,7 @@ expression* parser::parse_symbol ()
struct arrayindex* ai = new arrayindex;
ai->tok = t;
ai->base = hop;
- ai->indexes.push_back (parse_expression ());
+ ai->indexes.push_back (parse_assignment ());
expect_op("]");
fmt->args.push_back(ai);
@@ -3937,7 +3960,7 @@ expression* parser::parse_symbol ()
// ')' is not possible here but we want to output a nicer
// parser error message.
(void) expect_op_any ({",", ")"});
- expression *e = parse_expression ();
+ expression *e = parse_assignment ();
fmt->args.push_back(e);
}
}
@@ -3982,7 +4005,7 @@ expression* parser::parse_symbol ()
// parser error message.
if (consumed_arg)
(void) expect_op_any({",", ")"});
- expression *e = parse_expression ();
+ expression *e = parse_assignment ();
fmt->args.push_back(e);
consumed_arg = true;
if (min_args)
@@ -4007,7 +4030,7 @@ expression* parser::parse_symbol ()
}
while (1)
{
- f->args.push_back (parse_expression ());
+ f->args.push_back (parse_assignment ());
interned_string op = expect_op_any({")", ","});
if (op == ")")
break;
@@ -4051,7 +4074,7 @@ expression* parser::parse_symbol ()
ai->indexes.push_back (NULL);
}
else
- ai->indexes.push_back (parse_expression ());
+ ai->indexes.push_back (parse_assignment ());
interned_string op = expect_op_any({"]", ","});
if (op == "]")
break;
@@ -4099,7 +4122,7 @@ cast_op* parser::parse_cast_op ()
cop->tok = t;
cop->name = t->content;
expect_op("(");
- cop->operand = parse_expression ();
+ cop->operand = parse_assignment ();
expect_op(",");
expect_unknown(tok_string, cop->type_name);
if (cop->type_name.empty())
@@ -4154,7 +4177,7 @@ expression* parser::parse_defined_op (const token* t)
defined_op* dop = new defined_op;
dop->tok = t;
expect_op("(");
- dop->operand = parse_expression ();
+ dop->operand = parse_assignment ();
expect_op(")");
return dop;
}
@@ -4186,7 +4209,7 @@ expression* parser::parse_entry_op (const token* t)
entry_op* eop = new entry_op;
eop->tok = t;
expect_op("(");
- eop->operand = parse_expression ();
+ eop->operand = parse_assignment ();
expect_op(")");
return eop;
}
@@ -4236,7 +4259,7 @@ expression* parser::parse_target_deref (const token* t)
expect_number(size);
tderef->size = size;
expect_op(",");
- tderef->addr = parse_expression();
+ tderef->addr = parse_assignment ();
expect_op(")");
return tderef;
}
@@ -4294,7 +4317,7 @@ parser::parse_target_symbol_components (target_symbol* e)
else if (peek_op ("["))
{
const token* t = next();
- expression* index = parse_expression();
+ expression* index = parse_assignment ();
literal_number* ln = dynamic_cast<literal_number*>(index);
if (ln)
e->components.push_back (target_symbol::component(t, ln->value));
diff --git a/testsuite/systemtap.base/compound_expr.exp b/testsuite/systemtap.base/compound_expr.exp
new file mode 100644
index 000000000..df0c3d590
--- /dev/null
+++ b/testsuite/systemtap.base/compound_expr.exp
@@ -0,0 +1,132 @@
+set test "compound_expr"
+set testpath "$srcdir/$subdir"
+
+if {! [installtest_p]} { untested "$test"; return }
+
+# --- TEST 1 ---
+
+set subtest1 "TEST 1: comma expr after assignment"
+foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} { set runtime "kernel" }
+ set test_name "$test: $subtest1 ($runtime)"
+
+ set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_1.stp'"
+ send_log "executing: $cmd\n"
+ set pipe [open "| sh -c {$cmd}" r]
+ set out [read $pipe]
+ set failed 0
+ if {[catch {close $pipe} stderr] != 0} { set failed 1 }
+
+ set exp_out "5\n-3\n"
+ regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+ if {$out eq $exp_out} {
+ pass "${test_name}: stdout matches \"$escaped_exp_out\""
+ } else {
+ fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+ }
+
+ if {$failed} {
+ fail "${test_name}: exit code not zero"
+ } else {
+ pass "${test_name}: exit code is zero"
+ }
+ if {$stderr ne ""} {
+ send_log "stderr:\n$stderr"
+ }
+}
+
+# --- TEST 2 ---
+
+set subtest2 "TEST 2: comma expr on statement level"
+foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} { set runtime "kernel" }
+ set test_name "$test: $subtest2 ($runtime)"
+
+ set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_2.stp'"
+ send_log "executing: $cmd\n"
+ set pipe [open "| sh -c {$cmd}" r]
+ set out [read $pipe]
+ set failed 0
+ if {[catch {close $pipe} stderr] != 0} { set failed 1 }
+
+ set exp_out "3\n5\n"
+ regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+ if {$out eq $exp_out} {
+ pass "${test_name}: stdout matches \"$escaped_exp_out\""
+ } else {
+ fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+ }
+
+ if {$failed} {
+ fail "${test_name}: exit code not zero"
+ } else {
+ pass "${test_name}: exit code is zero"
+ }
+ if {$stderr ne ""} {
+ send_log "stderr:\n$stderr"
+ }
+}
+
+# --- TEST 3 ---
+
+set subtest3 "TEST 3: in for stmt"
+foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} { set runtime "kernel" }
+ set test_name "$test: $subtest3 ($runtime)"
+
+ set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_3.stp'"
+ send_log "executing: $cmd\n"
+ set pipe [open "| sh -c {$cmd}" r]
+ set out [read $pipe]
+ set failed 0
+ if {[catch {close $pipe} stderr] != 0} { set failed 1 }
+
+ set exp_out "i = 1, j = 3\ni = 2, j = 4\ni = 3, j = 5\n"
+ regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+ if {$out eq $exp_out} {
+ pass "${test_name}: stdout matches \"$escaped_exp_out\""
+ } else {
+ fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+ }
+
+ if {$failed} {
+ fail "${test_name}: exit code not zero"
+ } else {
+ pass "${test_name}: exit code is zero"
+ }
+ if {$stderr ne ""} {
+ send_log "stderr:\n$stderr"
+ }
+}
+
+# --- TEST 4 ---
+
+set subtest4 "TEST 4: comma expr in cascaded assignment expressions"
+foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} { set runtime "kernel" }
+ set test_name "$test: $subtest4 ($runtime)"
+
+ set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_4.stp'"
+ send_log "executing: $cmd\n"
+ set pipe [open "| sh -c {$cmd}" r]
+ set out [read $pipe]
+ set failed 0
+ if {[catch {close $pipe} stderr] != 0} { set failed 1 }
+
+ set exp_out "7\n7\n7\n"
+ regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+ if {$out eq $exp_out} {
+ pass "${test_name}: stdout matches \"$escaped_exp_out\""
+ } else {
+ fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+ }
+
+ if {$failed} {
+ fail "${test_name}: exit code not zero"
+ } else {
+ pass "${test_name}: exit code is zero"
+ }
+ if {$stderr ne ""} {
+ send_log "stderr:\n$stderr"
+ }
+}
diff --git a/testsuite/systemtap.base/compound_expr_1.stp b/testsuite/systemtap.base/compound_expr_1.stp
new file mode 100644
index 000000000..4214c1dee
--- /dev/null
+++ b/testsuite/systemtap.base/compound_expr_1.stp
@@ -0,0 +1,7 @@
+probe begin {
+ a = (3, 4, 5);
+ println(a);
+ b = (7, -3);
+ println(b);
+ exit();
+}
diff --git a/testsuite/systemtap.base/compound_expr_2.stp b/testsuite/systemtap.base/compound_expr_2.stp
new file mode 100644
index 000000000..fac55ab34
--- /dev/null
+++ b/testsuite/systemtap.base/compound_expr_2.stp
@@ -0,0 +1,6 @@
+probe begin {
+ a = 3, b = 5;
+ println(a);
+ println(b);
+ exit();
+}
diff --git a/testsuite/systemtap.base/compound_expr_3.stp b/testsuite/systemtap.base/compound_expr_3.stp
new file mode 100644
index 000000000..669dc1967
--- /dev/null
+++ b/testsuite/systemtap.base/compound_expr_3.stp
@@ -0,0 +1,6 @@
+probe begin {
+ for (i = 1, j = 3; i < 4 || j < 6; i++, j++) {
+ printf("i = %d, j = %d\n", i, j);
+ }
+ exit();
+}
diff --git a/testsuite/systemtap.base/compound_expr_4.stp b/testsuite/systemtap.base/compound_expr_4.stp
new file mode 100644
index 000000000..fbc12b887
--- /dev/null
+++ b/testsuite/systemtap.base/compound_expr_4.stp
@@ -0,0 +1,6 @@
+probe begin {
+ println(a = b = (-3, 7));
+ println(a);
+ println(b);
+ exit();
+}
--
2.11.0.295.gd7dffce
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2018-08-24 5:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-24 5:33 [PATCH] Add support for compound (comma) expressions Yichun Zhang (agentzh)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).