public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* [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).