changeset 10181:a668fbd32e34

improve cellfun & avoid undefined values from builtins
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 21 Jan 2010 14:22:20 +0100
parents be952ce74023
children 0522a65bcd56
files src/ChangeLog src/DLD-FUNCTIONS/cellfun.cc src/oct-obj.h src/ov-base.h src/ov-builtin.cc src/ov-dld-fcn.cc src/ov-dld-fcn.h src/ov-type-conv.h
diffstat 8 files changed, 89 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/ChangeLog	Thu Jan 21 14:22:20 2010 +0100
@@ -1,3 +1,15 @@
+2010-01-21  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-base.h (octave_base_value::dim_vector): Return 0x0 by default.
+	* oct-obj.h (octave_value_list::xelem, octave_value_list::clear): New
+	methods.
+	* ov-builtin.cc (octave_builtin::do_multi_index_op): Don't call
+	make_storable_values. Chop a potential single undefined value.
+	* ov-type-conv.h (octave_type_conv_body): Ensure storable value.
+	* ov-dld-fcn.cc (octave_dld_function::do_multi_index_op): New method.
+	* DLD-FUNCTIONS/cellfun.cc (get_output_list): New helper function.
+	(Fcellfun): Call it here. Optimize.
+
 2010-01-20  John W. Eaton  <jwe@octave.org>
 
 	* defaults.h.in, graphics.h.in, oct-conf.h.in, oct-errno.cc.in,
--- a/src/DLD-FUNCTIONS/cellfun.cc	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Thu Jan 21 14:22:20 2010 +0100
@@ -223,6 +223,39 @@
   return retval;
 }
 
+static octave_value_list 
+get_output_list (octave_idx_type count, octave_idx_type nargout,
+                 const octave_value_list& inputlist,
+                 octave_value& func,
+                 octave_value& error_handler)
+{
+  octave_value_list tmp = func.do_multi_index_op (nargout, inputlist);
+
+  if (error_state)
+    {
+      if (error_handler.is_defined ())
+        {
+          Octave_map msg;
+          msg.assign ("identifier", last_error_id ());
+          msg.assign ("message", last_error_message ());
+          msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1))));
+          octave_value_list errlist = inputlist;
+          errlist.prepend (msg);
+          buffer_error_messages--;
+          error_state = 0;
+          tmp = error_handler.do_multi_index_op (nargout, errlist);
+          buffer_error_messages++;
+
+          if (error_state)
+            tmp.clear ();
+        }
+      else
+        tmp.clear ();
+    }
+
+  return tmp;
+}
+
 DEFUN_DLD (cellfun, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {} cellfun (@var{name}, @var{c})\n\
@@ -607,30 +640,14 @@
               for (int j = 0; j < nargin; j++)
                 {
                   if (mask[j])
-                    inputlist(j) = cinputs[j](count);
+                    inputlist.xelem (j) = cinputs[j](count);
                 }
 
-              octave_value_list tmp = func.do_multi_index_op (nargout, inputlist);
-
-              if (error_state && error_handler.is_defined ())
-                {
-                  Octave_map msg;
-                  msg.assign ("identifier", last_error_id ());
-                  msg.assign ("message", last_error_message ());
-                  msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1))));
-                  octave_value_list errlist = inputlist;
-                  errlist.prepend (msg);
-                  buffer_error_messages--;
-                  error_state = 0;
-                  tmp = error_handler.do_multi_index_op (nargout, errlist);
-                  buffer_error_messages++;
-
-                  if (error_state)
-                    return octave_value_list ();
-                }
+              const octave_value_list tmp = get_output_list (count, nargout, inputlist,
+                                                             func, error_handler);
 
               if (error_state)
-                return octave_value_list ();
+                return retval;
 
               if (tmp.length () < nargout1)
                 {
@@ -699,30 +716,14 @@
               for (int j = 0; j < nargin; j++)
                 {
                   if (mask[j])
-                    inputlist(j) = cinputs[j](count);
+                    inputlist.xelem (j) = cinputs[j](count);
                 }
 
-              octave_value_list tmp = func.do_multi_index_op (nargout, inputlist);
-
-              if (error_state && error_handler.is_defined ())
-                {
-                  Octave_map msg;
-                  msg.assign ("identifier", last_error_id ());
-                  msg.assign ("message", last_error_message ());
-                  msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1))));
-                  octave_value_list errlist = inputlist;
-                  errlist.prepend (msg);
-                  buffer_error_messages--;
-                  error_state = 0;
-                  tmp = error_handler.do_multi_index_op (nargout, errlist);
-                  buffer_error_messages++;
-
-                  if (error_state)
-                    return octave_value_list ();
-                }
+              const octave_value_list tmp = get_output_list (count, nargout, inputlist,
+                                                             func, error_handler);
 
               if (error_state)
-                return octave_value_list ();
+                return retval;
 
               if (tmp.length () < nargout1)
                 {
--- a/src/oct-obj.h	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/oct-obj.h	Thu Jan 21 14:22:20 2010 +0100
@@ -149,6 +149,16 @@
 
   void make_storable_values (void);
 
+  octave_value& xelem (octave_idx_type i)
+    {
+      return data.xelem (i);
+    }
+
+  void clear (void)
+    {
+      data.clear ();
+    }
+
 private:
 
   static octave_allocator allocator;
--- a/src/ov-base.h	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/ov-base.h	Thu Jan 21 14:22:20 2010 +0100
@@ -272,7 +272,7 @@
 
   virtual idx_vector index_vector (void) const;
 
-  virtual dim_vector dims (void) const { return dim_vector (-1, -1); }
+  virtual dim_vector dims (void) const { return dim_vector (); }
 
   octave_idx_type rows (void) const
     {
--- a/src/ov-builtin.cc	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/ov-builtin.cc	Thu Jan 21 14:22:20 2010 +0100
@@ -105,9 +105,16 @@
       try
 	{
 	  retval = (*f) (args, nargout);
-          // Do not allow null values to be returned from functions.
-          // FIXME -- perhaps true builtins should be allowed?
-          retval.make_storable_values ();
+          // We don't check for null values here, builtins should handle that
+          // possibility themselves.
+          // Fix the case of a single undefined value.
+          // This happens when a compiled function uses
+          //   octave_value retval;
+          // instead of
+          //   octave_value_list retval;
+          // the idiom is very common, so we solve that here.
+          if (retval.length () == 1 && retval.xelem (0).is_undefined ())
+            retval.clear ();
 	}
       catch (octave_execution_exception)
 	{
--- a/src/ov-dld-fcn.cc	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/ov-dld-fcn.cc	Thu Jan 21 14:22:20 2010 +0100
@@ -89,3 +89,14 @@
 {
   return new octave_dld_function (ff, shl, nm, ds);
 }
+
+octave_value_list
+octave_dld_function::do_multi_index_op (int nargout, const octave_value_list& args)
+{
+  octave_value_list retval = this->octave_builtin::do_multi_index_op (nargout, args);
+  // Guard against the possibility of null values leaking from user DLD functions.
+  // FIXME: is this needed?
+  retval.make_storable_values ();
+
+  return retval;
+}
--- a/src/ov-dld-fcn.h	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/ov-dld-fcn.h	Thu Jan 21 14:22:20 2010 +0100
@@ -75,6 +75,9 @@
   octave_shlib get_shlib (void) const
     { return sh_lib; }
 
+  octave_value_list
+  do_multi_index_op (int nargout, const octave_value_list& args);
+
 private:
 
   octave_shlib sh_lib;
--- a/src/ov-type-conv.h	Thu Jan 21 03:25:23 2010 -0500
+++ b/src/ov-type-conv.h	Thu Jan 21 14:22:20 2010 +0100
@@ -32,7 +32,7 @@
 
   if (t_arg == t_result || arg.class_name () == name)
     {
-      retval = arg;
+      retval = arg.storable_value ();
     }
   else
     {