changeset 10206:37a08e0ce2dc

support Matlab-style empty output/input arguments
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 27 Jan 2010 12:41:49 +0100
parents eea99d24adae
children 76a880a588ce
files src/ChangeLog src/oct-lvalue.cc src/oct-lvalue.h src/oct-parse.yy src/pt-arg-list.cc src/pt-arg-list.h src/pt-id.h src/pt-idx.cc src/pt-misc.cc
diffstat 9 files changed, 120 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/ChangeLog	Wed Jan 27 12:41:49 2010 +0100
@@ -1,3 +1,29 @@
+2010-01-27  Jaroslav Hajek  <highegg@gmail.com>
+
+	* oct-lvalue.h (octave_lvalue::is_black_hole): New method.
+	(octave_lvalue::black_hole): New field.
+	(octave_lvalue::is_defined, octave_lvalue::is_undefined,
+	octave_lvalue::is_map): Make const.
+	(octave_lvalue::index_set): Remove field.
+	(octave_lvalue::octave_lvalue, octave_lvalue::operator =): Correctly
+	handle black holes. Update.
+	(dummy_value): Remove.
+	* pt-id.h (tree_identifier::is_black_hole): New method.
+	(tree_identifier::is_variable): Make virtual.
+	(tree_black_hole): New class.
+	* oct-parse.yy (magic_tilde): New terminal.
+	(param_list): Allow magic_tilde.
+	(arg_list): Allow magic_tilde.
+	* pt-misc.cc (tree_parameter_list::validate): Handle black holes.
+	* pt-idx.cc (tree_index_expression::append): Gripe if arguments
+	contain magic tilde.
+	* pt-arg-list.h (tree_argument_list::has_magic_tilde): New method
+	decl.
+	(tree_argument_list::list_includes_magic_tilde): New field.
+	(tree_argument_list::tree_argument_list): Initialize it in ctors.
+	* pt-arg-list.cc (tree_argument_list::has_magic_tilde): New method.
+	(tree_argument_list::append): Update list_includes_magic_tilde.
+
 2010-01-27  Judd Storrs  <jstorrs@gmail.com>
 
 	* ov-class.cc (octave_class::print_with_name) Add default case for
--- a/src/oct-lvalue.cc	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/oct-lvalue.cc	Wed Jan 27 12:41:49 2010 +0100
@@ -45,11 +45,10 @@
 octave_lvalue::set_index (const std::string& t,
 			  const std::list<octave_value_list>& i)
 {
-  if (! index_set)
+  if (idx.empty ())
     {
       type = t;
       idx = i;
-      index_set = true;
     }
   else
     error ("invalid index expression in assignment");
--- a/src/oct-lvalue.h	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/oct-lvalue.h	Wed Jan 27 12:41:49 2010 +0100
@@ -32,32 +32,35 @@
 #include "oct-obj.h"
 #include "pt-idx.h"
 
-// FIXME -- eliminate the following kluge?
-
-// This variable is used when creating dummy octave_lvalue objects.
-static octave_value dummy_val;
-
 class
 octave_lvalue
 {
 public:
 
-  octave_lvalue (octave_value *v = &dummy_val)
-    : val (v), type (), idx (), nel (1), index_set (false) { }
+  octave_lvalue (octave_value *v = 0)
+    : val (v), type (), idx (), nel (1) 
+    {
+      if (! v)
+        val = &black_hole;
+    }
 
   octave_lvalue (const octave_lvalue& vr)
-    : val (vr.val), type (vr.type), idx (vr.idx), nel (vr.nel),
-      index_set (vr.index_set) { }
+    : val (vr.val), type (vr.type), idx (vr.idx), nel (vr.nel) 
+    { 
+      if (vr.is_black_hole ())
+        val = &black_hole;
+    }
 
   octave_lvalue& operator = (const octave_lvalue& vr)
     {
       if (this != &vr)
 	{
 	  val = vr.val;
+          if (vr.is_black_hole ())
+            val = &black_hole;
 	  type = vr.type;
 	  idx = vr.idx;
 	  nel = vr.nel;
-	  index_set = vr.index_set;
 	}
 
       return *this;
@@ -65,11 +68,13 @@
 
   ~octave_lvalue (void) { }
 
-  bool is_defined (void) { return val->is_defined (); }
+  bool is_black_hole (void) const { return val == &black_hole; }
+
+  bool is_defined (void) const { return val->is_defined (); }
 
-  bool is_undefined (void) { return val->is_undefined (); }
+  bool is_undefined (void) const { return val->is_undefined (); }
 
-  bool is_map (void) { return val->is_map (); }
+  bool is_map (void) const { return val->is_map (); }
 
   void define (const octave_value& v) { *val = v; }
 
@@ -99,7 +104,7 @@
 
   octave_idx_type nel;
 
-  bool index_set;
+  octave_value black_hole;
 };
 
 #endif
--- a/src/oct-parse.yy	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/oct-parse.yy	Wed Jan 27 12:41:49 2010 +0100
@@ -463,7 +463,7 @@
 %type <tree_expression_type> matrix cell
 %type <tree_expression_type> primary_expr postfix_expr prefix_expr binary_expr
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
-%type <tree_identifier_type> identifier fcn_name
+%type <tree_identifier_type> identifier fcn_name magic_tilde
 %type <tree_identifier_type> superclass_identifier meta_identifier
 %type <octave_user_function_type> function1 function2 classdef1
 %type <tree_index_expression_type> word_list_cmd
@@ -755,15 +755,28 @@
 		  }
 		;
 
+magic_tilde	: EXPR_NOT
+		  {
+		    $$ = new tree_black_hole ();
+		  }
+		;
+
 arg_list	: expression
 		  { $$ = new tree_argument_list ($1); }
 		| magic_colon
 		  { $$ = new tree_argument_list ($1); }
+		| magic_tilde
+		  { $$ = new tree_argument_list ($1); }
 		| arg_list ',' magic_colon
 		  {
 		    $1->append ($3);
 		    $$ = $1;
 		  }
+		| arg_list ',' magic_tilde
+		  {
+		    $1->append ($3);
+		    $$ = $1;
+		  }
 		| arg_list ',' expression
 		  {
 		    $1->append ($3);
@@ -1005,6 +1018,10 @@
 		    lexer_flags.looking_at_initializer_expression = false;
 		    $$ = new tree_decl_elt ($1, $4);
 		  }
+                | magic_tilde
+                  {
+                    $$ = new tree_decl_elt ($1);
+                  }
 		;
 
 // ====================
@@ -2972,6 +2989,12 @@
 		       char type)
 {
   tree_index_expression *retval = 0;
+  
+  if (args && args->has_magic_tilde ())
+    {
+      yyerror ("invalid use of empty argument (~) in index expression");
+      return retval;
+    }
 
   int l = expr->line ();
   int c = expr->column ();
--- a/src/pt-arg-list.cc	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/pt-arg-list.cc	Wed Jan 27 12:41:49 2010 +0100
@@ -39,6 +39,7 @@
 #include "parse.h"
 #include "pt-arg-list.h"
 #include "pt-exp.h"
+#include "pt-id.h"
 #include "pt-pr-code.h"
 #include "pt-walk.h"
 #include "toplev.h"
@@ -77,6 +78,12 @@
 
   if (! list_includes_magic_end && s && s->has_magic_end ())
     list_includes_magic_end = true;
+
+  if (! list_includes_magic_tilde && s && s->is_identifier ())
+    {
+      tree_identifier *id = dynamic_cast<tree_identifier *> (s);
+      list_includes_magic_tilde = id && id->is_black_hole ();
+    }
 }
 
 bool
--- a/src/pt-arg-list.h	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/pt-arg-list.h	Wed Jan 27 12:41:49 2010 +0100
@@ -46,16 +46,21 @@
   typedef tree_expression* element_type;
 
   tree_argument_list (void)
-    : list_includes_magic_end (false), simple_assign_lhs (false) { }
+    : list_includes_magic_end (false), list_includes_magic_tilde (false),
+    simple_assign_lhs (false) { }
 
   tree_argument_list (tree_expression *t)
-    : list_includes_magic_end (false), simple_assign_lhs (false)
+    : list_includes_magic_end (false), list_includes_magic_tilde (false),
+    simple_assign_lhs (false)
   { append (t); }
 
   ~tree_argument_list (void);
 
   bool has_magic_end (void) const;
 
+  bool has_magic_tilde (void) const
+    { return list_includes_magic_tilde; }
+
   tree_expression *remove_front (void)
     {
       iterator p = begin ();
@@ -87,6 +92,8 @@
 
   bool list_includes_magic_end;
 
+  bool list_includes_magic_tilde;
+
   bool simple_assign_lhs;
 
   // No copying!
--- a/src/pt-id.h	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/pt-id.h	Wed Jan 27 12:41:49 2010 +0100
@@ -66,7 +66,9 @@
 
   bool is_defined (void) { return xsym().is_defined (); }
 
-  bool is_variable (void) { return xsym().is_variable (); }
+  virtual bool is_variable (void) { return xsym().is_variable (); }
+
+  virtual bool is_black_hole (void) { return false; }
 
   // Try to find a definition for an identifier.  Here's how:
   //
@@ -143,4 +145,26 @@
   tree_identifier& operator = (const tree_identifier&);
 };
 
+class tree_black_hole : public tree_identifier
+{
+public:
+
+  tree_black_hole (int l = -1, int c = -1)
+    : tree_identifier (l, c) { }
+
+  std::string name (void) const { return "~"; }
+
+  bool is_variable (void) { return false; }
+
+  bool is_black_hole (void) { return true; }
+
+  tree_black_hole *dup (void) const
+    { return new tree_black_hole; }
+
+  octave_lvalue lvalue (void)
+    {
+      return octave_lvalue (0); // black hole lvalue
+    }
+};
+
 #endif
--- a/src/pt-idx.cc	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/pt-idx.cc	Wed Jan 27 12:41:49 2010 +0100
@@ -81,6 +81,9 @@
   type.append (1, t);
   arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
   dyn_field.push_back (static_cast<tree_expression *> (0));
+
+  if (lst && lst->has_magic_tilde ())
+    error ("invalid use of empty argument (~) in index expression");
 }
 
 void
--- a/src/pt-misc.cc	Wed Jan 27 02:24:17 2010 -0500
+++ b/src/pt-misc.cc	Wed Jan 27 12:41:49 2010 +0100
@@ -76,7 +76,12 @@
 	{
 	  std::string name = id->name ();
 
-	  if (dict.find (name) != dict.end ())
+          if (id->is_black_hole ())
+            {
+              if (type != in)
+                error ("invalid use of ~ in output list");
+            }
+          else if (dict.find (name) != dict.end ())
 	    {
 	      retval = false;
 	      error ("`%s' appears more than once in parameter list",