changeset 23600:db947ba52118

explicitly limit anonymous functions to a single expression * ov-fcn-handle.cc (octave_fcn_handle::print_raw): Handle anonymous function body as a single expression. * parse.h, oct-parse.in.yy: Now expect 8 shift/reduce conflicts. (expr_no_assign): New non-terminal. (expression): Split into expr_no_assign and assign_expr. (anon_fcn_handle): Define body as expr_no_assign instead of statement. (base_parser::make_anon_fcn_handle): Handle body as a single expression instead of statement. * pt-eval.cc (tree_evaluator::visit_anon_fcn_handle): Handle body as a single expression instead of statement. * pt-fcn-handle.h, pt-fcn-handle.cc (class tree_anon_fcn_handle): Handle body as a single expression. Eliminate return list. * pt-pr-code.h, pt-pr-code.cc (tree_print_code::print_fcn_handle_body): Handle anonymous function handle body as single expression.
author John W. Eaton <jwe@octave.org>
date Sun, 11 Jun 2017 16:37:26 -0400
parents 5cb3a2bb5e1e
children a3898679d459
files libinterp/octave-value/ov-fcn-handle.cc libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-fcn-handle.cc libinterp/parse-tree/pt-fcn-handle.h libinterp/parse-tree/pt-pr-code.cc libinterp/parse-tree/pt-pr-code.h
diffstat 8 files changed, 78 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-fcn-handle.cc	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Sun Jun 11 16:37:26 2017 -0400
@@ -1444,7 +1444,21 @@
 
           os << ") ";
 
-          tpc.print_fcn_handle_body (f->body ());
+          octave::tree_statement_list *b = f->body ();
+
+          assert (b->length () == 1);
+
+          octave::tree_statement *s = b->front ();
+
+          if (s)
+            {
+              assert (s->is_expression ());
+
+              octave::tree_expression *e = s->expression ();
+
+              if (e)
+                tpc.print_fcn_handle_body (e);
+            }
 
           printed = true;
         }
--- a/libinterp/parse-tree/oct-parse.in.yy	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Sun Jun 11 16:37:26 2017 -0400
@@ -111,10 +111,10 @@
 
 // Bison declarations.
 
-// The grammar currently has 14 shift/reduce conflicts.  Ensure that
+// The grammar currently has 8 shift/reduce conflicts.  Ensure that
 // we notice if that number changes.
 
-%expect 14
+%expect 8
 
 %API_PREFIX_DECL%
 
@@ -244,7 +244,7 @@
 %type <tree_matrix_type> matrix_rows
 %type <tree_cell_type> cell_rows
 %type <tree_expression_type> matrix cell
-%type <tree_expression_type> primary_expr oper_expr power_expr
+%type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
 %type <tree_funcall_type> superclass_identifier meta_identifier
@@ -605,7 +605,7 @@
                   }
                 ;
 
-anon_fcn_handle : '@' param_list stmt_begin statement
+anon_fcn_handle : '@' param_list stmt_begin expr_no_assign
                   {
                     $$ = parser.make_anon_fcn_handle ($2, $4);
                     lexer.nesting_level.remove ();
@@ -909,7 +909,7 @@
                   { $$ = parser.make_assign_op (OR_EQ, $1, $2, $3); }
                 ;
 
-expression      : simple_expr
+expr_no_assign  : simple_expr
                   {
                     if ($1 && ($1->is_matrix () || $1->iscell ()))
                       {
@@ -924,6 +924,12 @@
                     else
                       $$ = $1;
                   }
+                | anon_fcn_handle
+                  { $$ = $1; }
+                ;
+
+expression      : expr_no_assign
+                  { $$ = $1; }
                 | assign_expr
                   {
                     if (! $1)
@@ -931,9 +937,6 @@
 
                     $$ = $1;
                   }
-                | anon_fcn_handle
-                  { $$ = $1; }
-                ;
 
 // ================================================
 // Commands, declarations, and function definitions
@@ -2480,29 +2483,24 @@
 
   tree_anon_fcn_handle *
   base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
-                                     tree_statement *stmt)
+                                     tree_expression *expr)
   {
     // FIXME: need to get these from the location of the @ symbol.
     int l = lexer.input_line_number;
     int c = lexer.current_input_column;
 
-    tree_parameter_list *ret_list = 0;
-
     symbol_table::scope_id fcn_scope = lexer.symtab_context.curr_scope ();
     symbol_table::scope_id parent_scope = lexer.symtab_context.parent_scope ();
 
     lexer.symtab_context.pop ();
 
-    stmt->set_print_flag (false);
-
-    tree_statement_list *body = new tree_statement_list (stmt);
-
-    body->mark_as_anon_function_body ();
+    expr->set_print_flag (false);
 
     tree_anon_fcn_handle *retval
-      = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope,
+      = new tree_anon_fcn_handle (param_list, expr, fcn_scope,
                                   parent_scope, l, c);
-    // FIXME: Stash the filename.  This does not work and produces
+
+// FIXME: Stash the filename.  This does not work and produces
     // errors when executed.
     //retval->stash_file_name (lexer.fcn_file_name);
 
--- a/libinterp/parse-tree/parse.h	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/parse.h	Sun Jun 11 16:37:26 2017 -0400
@@ -179,7 +179,8 @@
 
     // Build an anonymous function handle.
     tree_anon_fcn_handle *
-    make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
+    make_anon_fcn_handle (tree_parameter_list *param_list,
+                          tree_expression * expr);
 
     // Build a binary expression.
     tree_expression *
--- a/libinterp/parse-tree/pt-eval.cc	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Sun Jun 11 16:37:26 2017 -0400
@@ -88,32 +88,43 @@
   }
 
   void
-  tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle& expr)
+  tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle& anon_fh)
   {
     // FIXME: should CMD_LIST be limited to a single expression?
     // I think that is what Matlab does.
 
-    tree_parameter_list *param_list = expr.parameter_list ();
-    tree_parameter_list *ret_list = expr.return_list ();
-    tree_statement_list *stmt_list = expr.body ();
-
-    symbol_table::scope_id af_sid = expr.scope ();
+    tree_parameter_list *param_list = anon_fh.parameter_list ();
+    tree_expression *expr = anon_fh.expression ();
+
+    symbol_table::scope_id af_sid = anon_fh.scope ();
 
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
     symbol_table::scope_id af_parent_sid
-      = expr.has_parent_scope () ? symtab.current_scope () : -1;
+      = anon_fh.has_parent_scope () ? symtab.current_scope () : -1;
 
     symbol_table::scope_id new_scope = symtab.dup_scope (af_sid);
 
     if (new_scope > 0 && af_parent_sid > 0)
       symtab.inherit (new_scope, af_parent_sid);
 
+    tree_parameter_list *param_list_dup
+      = param_list ? param_list->dup (new_scope, 0) : 0;
+
+    tree_parameter_list *ret_list = 0;
+
+    tree_statement_list *stmt_list = 0;
+
+    if (expr)
+      {
+        tree_expression *expr_dup = expr->dup (new_scope, 0);
+        tree_statement *stmt = new tree_statement (expr_dup, 0);
+        stmt_list = new tree_statement_list (stmt);
+      }
+
     octave_user_function *af
-      = new octave_user_function (new_scope,
-                                  param_list ? param_list->dup (new_scope, 0) : 0,
-                                  ret_list ? ret_list->dup (new_scope, 0) : 0,
-                                  stmt_list ? stmt_list->dup (new_scope, 0) : 0);
+      = new octave_user_function (new_scope, param_list_dup, ret_list,
+                                  stmt_list);
 
     if (af_parent_sid > 0)
       symtab.set_parent (new_scope, af_parent_sid);
@@ -133,8 +144,10 @@
       }
 
     af->mark_as_anonymous_function ();
-    af->stash_fcn_file_name (expr.file_name ());
-    af->stash_fcn_location (expr.line (), expr.column ());
+
+    // FIXME: these should probably come from ANON_FH.
+    //    af->stash_fcn_file_name (expr.file_name ());
+    //    af->stash_fcn_location (expr.line (), expr.column ());
 
     octave_value ov_fcn (af);
 
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Sun Jun 11 16:37:26 2017 -0400
@@ -67,8 +67,7 @@
   tree_anon_fcn_handle::~tree_anon_fcn_handle (void)
   {
     delete m_parameter_list;
-    delete m_return_list;
-    delete m_statement_list;
+    delete m_expression;
   }
 
   tree_expression *
@@ -76,8 +75,7 @@
                              symbol_table::context_id) const
   {
     tree_parameter_list *param_list = parameter_list ();
-    tree_parameter_list *ret_list = return_list ();
-    tree_statement_list *stmt_list = body ();
+    tree_expression *expr = expression ();
 
     symbol_table::scope_id af_sid = scope ();
     symbol_table::scope_id af_parent_sid = parent_scope ();
@@ -92,8 +90,7 @@
 
     tree_anon_fcn_handle *new_afh = new
       tree_anon_fcn_handle (param_list ? param_list->dup (new_scope, 0) : 0,
-                            ret_list ? ret_list->dup (new_scope, 0) : 0,
-                            stmt_list ? stmt_list->dup (new_scope, 0) : 0,
+                            expr ? expr->dup (new_scope, 0) : 0,
                             new_scope, af_parent_sid, line (), column ());
 
     new_afh->copy_base (*this);
--- a/libinterp/parse-tree/pt-fcn-handle.h	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/pt-fcn-handle.h	Sun Jun 11 16:37:26 2017 -0400
@@ -92,17 +92,16 @@
   public:
 
     tree_anon_fcn_handle (int l = -1, int c = -1)
-      : tree_expression (l, c), m_parameter_list (0), m_return_list (0),
-        m_statement_list (0), m_sid (-1), m_parent_sid (-1), m_file_name ()
+      : tree_expression (l, c), m_parameter_list (0), m_expression (0),
+        m_sid (-1), m_parent_sid (-1), m_file_name ()
     { }
 
-    tree_anon_fcn_handle (tree_parameter_list *pl, tree_parameter_list *rl,
-                          tree_statement_list *cl, symbol_table::scope_id sid,
+    tree_anon_fcn_handle (tree_parameter_list *pl, tree_expression *ex,
+                          symbol_table::scope_id sid,
                           symbol_table::scope_id parent_sid,
                           int l = -1, int c = -1)
-      : tree_expression (l, c), m_parameter_list (pl), m_return_list (rl),
-        m_statement_list (cl), m_sid (sid), m_parent_sid (parent_sid),
-        m_file_name ()
+      : tree_expression (l, c), m_parameter_list (pl), m_expression (ex),
+        m_sid (sid), m_parent_sid (parent_sid), m_file_name ()
     { }
 
     // No copying!
@@ -122,9 +121,7 @@
       return m_parameter_list;
     }
 
-    tree_parameter_list * return_list (void) const { return m_return_list; }
-
-    tree_statement_list * body (void) const { return m_statement_list; }
+    tree_expression * expression (void) const { return m_expression; }
 
     symbol_table::scope_id scope (void) const { return m_sid; }
 
@@ -146,11 +143,8 @@
     // Inputs parameters.
     tree_parameter_list *m_parameter_list;
 
-    // Output parameters.
-    tree_parameter_list *m_return_list;
-
-    // Function body.
-    tree_statement_list *m_statement_list;
+    // Function body, limited to a single expression.
+    tree_expression *m_expression;
 
     // Function scope.
     symbol_table::scope_id m_sid;
--- a/libinterp/parse-tree/pt-pr-code.cc	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/pt-pr-code.cc	Sun Jun 11 16:37:26 2017 -0400
@@ -52,7 +52,7 @@
 
     os << ") ";
 
-    print_fcn_handle_body (afh.body ());
+    print_fcn_handle_body (afh.expression ());
 
     print_parens (afh, ")");
   }
@@ -1152,36 +1152,13 @@
   }
 
   void
-  tree_print_code::print_fcn_handle_body (tree_statement_list *b)
+  tree_print_code::print_fcn_handle_body (tree_expression *e)
   {
-    if (b)
+    if (e)
       {
-        assert (b->length () == 1);
-
-        tree_statement *s = b->front ();
-
-        if (s)
-          {
-            if (s->is_expression ())
-              {
-                tree_expression *e = s->expression ();
-
-                if (e)
-                  {
-                    suppress_newlines++;
-                    e->accept (*this);
-                    suppress_newlines--;
-                  }
-              }
-            else
-              {
-                tree_command *c = s->command ();
-
-                suppress_newlines++;
-                c->accept (*this);
-                suppress_newlines--;
-              }
-          }
+        suppress_newlines++;
+        e->accept (*this);
+        suppress_newlines--;
       }
   }
 
--- a/libinterp/parse-tree/pt-pr-code.h	Fri Jun 09 02:21:28 2017 -0400
+++ b/libinterp/parse-tree/pt-pr-code.h	Sun Jun 11 16:37:26 2017 -0400
@@ -148,7 +148,7 @@
 
     void visit_do_until_command (tree_do_until_command&);
 
-    void print_fcn_handle_body (tree_statement_list *);
+    void print_fcn_handle_body (tree_expression *);
 
   private: