changeset 9450:cf714e75c656

implement overloaded function handles
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 23 Jul 2009 14:44:30 +0200
parents a35d8ec8a0c4
children 350148cc0774
files src/ChangeLog src/DLD-FUNCTIONS/bsxfun.cc src/DLD-FUNCTIONS/cellfun.cc src/ov-fcn-handle.cc src/ov-fcn-handle.h src/symtab.cc src/symtab.h
diffstat 7 files changed, 478 insertions(+), 364 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/ChangeLog	Thu Jul 23 14:44:30 2009 +0200
@@ -1,3 +1,23 @@
+2009-07-23  Jaroslav Hajek  <highegg@gmail.com>
+
+	* symtab.cc (get_dispatch_type): Omit first-arg dispatch, export.
+	* symtab.h (get_dispatch_type): Provide decl.
+	* ov-fcn-handle.h (octave_fcn_handle::warn_reload): Delete.
+	(octave_fcn_handle::disp): New field.
+	(octave_fcn_handle::str_ov_map): New typedef.
+	(octave_fcn_handle::octave_fcn_handle (..., str_ov_map *)): New
+	constructor.
+	(octave_fcn_handle::do_multi_index_op): New method decl.
+	(octave_fcn_handle::is_overloaded): New method.
+	* ov-fcn-handle.cc 
+	(octave_fcn_handle::do_multi_index_op): New method.
+	(octave_fcn_handle::subsref): Rewrite using do_multi_index_op.
+	(octave_fcn_handle::make_fcn_handle): Construct overloaded handles if
+	appropriate.
+	(Ffunctions): Indicate (statically) overloaded handles.
+	* DLD-FUNCTIONS/cellfun.cc (Fcellfun): Update & modernize.
+	* DLD-FUNCTIONS/bsxfun.cc (Fbsxfun): Ditto.
+
 2009-07-22  Jaroslav Hajek  <highegg@gmail.com>
 
 	* symtab.cc (symbol_table::find, 
--- a/src/DLD-FUNCTIONS/bsxfun.cc	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/DLD-FUNCTIONS/bsxfun.cc	Thu Jul 23 14:44:30 2009 +0200
@@ -148,24 +148,17 @@
     print_usage ();
   else
     {
-      octave_function *func = 0;
-      std::string name;
-      std::string fcn_name;
+      octave_value func = args(0);
 
-      if (args(0).is_function_handle () || args(0).is_inline_function ())
-	func = args(0).function_value ();
-      else if (args(0).is_string ())
-	{
-	  name = args(0).string_value ();
-	  fcn_name = unique_symbol_name ("__bsxfun_fcn_");
-	  std::string fname = "function y = ";
-	  fname.append (fcn_name);
-	  fname.append ("(x) y = ");
-	  func = extract_function (args(0), "bsxfun", fcn_name, fname,
-				   "; endfunction");
-	}
-      else
-	  error ("bsxfun: first argument must be a string or function handle");
+      if (func.is_string ())
+        {
+          std::string name = func.string_value ();
+          func = symbol_table::find_function (name);
+          if (func.is_undefined ())
+            error ("bsxfun: invalid function name: %s", name.c_str ());
+        }
+      else if (! (args(0).is_function_handle () || args(0).is_inline_function ()))
+        error ("bsxfun: first argument must be a string or function handle");
 
       if (! error_state)
 	{
@@ -207,14 +200,14 @@
 		  octave_value_list inputs;
 		  inputs (0) = A;
 		  inputs (1) = B;
-		  retval = feval (func, inputs, 1);
+		  retval = func.do_multi_index_op (1, inputs);  
 		}
 	      else if (dvc.numel () < 1)
 		{
 		  octave_value_list inputs;
 		  inputs (0) = A.resize (dvc);
 		  inputs (1) = B.resize (dvc);
-		  retval = feval (func, inputs, 1);	      
+		  retval = func.do_multi_index_op (1, inputs);  
 		}
 	      else
 		{
@@ -257,7 +250,7 @@
 		      if (maybe_update_column (Bc, B, dvb, dvc, i, idxB))
 			inputs (1) = Bc;
 			
-		      octave_value_list tmp = feval (func, inputs, 1);
+		      octave_value_list tmp = func.do_multi_index_op (1, inputs);  
 
 		      if (error_state)
 			break;
@@ -454,9 +447,6 @@
 		}
 	    }
 	}
-
-      if (! fcn_name.empty ())
-	clear_function (fcn_name);
     }	
 
   return retval;
--- a/src/DLD-FUNCTIONS/cellfun.cc	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Thu Jul 23 14:44:30 2009 +0200
@@ -267,8 +267,6 @@
 @end deftypefn")
 {
   octave_value_list retval;
-  std::string name = "function";
-  octave_function *func = 0;
   int nargin = args.length ();
   nargout = (nargout < 1 ? 1 : nargout);
 
@@ -279,20 +277,7 @@
       return retval;
     }
 
-  if (args(0).is_function_handle () || args(0).is_inline_function ())
-    {
-      func = args(0).function_value ();
-
-      if (error_state)
-	return retval;
-    }
-  else if (args(0).is_string ())
-    name = args(0).string_value ();
-  else
-    {
-      error ("cellfun: first argument must be a string or function handle");
-      return retval;
-    }	
+  octave_value func = args(0);
 
   if (! args(1).is_cell ())
     {
@@ -305,334 +290,327 @@
   
   octave_idx_type k = f_args.numel ();
 
-  if (name == "isempty")
-    {      
-      boolNDArray result (f_args.dims ());
-      for (octave_idx_type count = 0; count < k ; count++)
-        result(count) = f_args.elem(count).is_empty ();
-      retval(0) = result;
-    }
-  else if (name == "islogical")
-    {
-      boolNDArray result (f_args.dims ());
-      for (octave_idx_type  count= 0; count < k ; count++)
-        result(count) = f_args.elem(count).is_bool_type ();
-      retval(0) = result;
-    }
-  else if (name == "isreal")
-    {
-      boolNDArray result (f_args.dims ());
-      for (octave_idx_type  count= 0; count < k ; count++)
-        result(count) = f_args.elem(count).is_real_type ();
-      retval(0) = result;
-    }
-  else if (name == "length")
-    {
-      NDArray result (f_args.dims ());
-      for (octave_idx_type  count= 0; count < k ; count++)
-        result(count) = static_cast<double> (f_args.elem(count).length ());
-      retval(0) = result;
-    }
-  else if (name == "ndims")
+  if (func.is_string ())
     {
-      NDArray result (f_args.dims ());
-      for (octave_idx_type count = 0; count < k ; count++)
-        result(count) = static_cast<double> (f_args.elem(count).ndims ());
-      retval(0) = result;
-    }
-  else if (name == "prodofsize" || name == "numel")
-    {
-      NDArray result (f_args.dims ());
-      for (octave_idx_type count = 0; count < k ; count++)
-        result(count) = static_cast<double> (f_args.elem(count).numel ());
-      retval(0) = result;
-    }
-  else if (name == "size")
-    {
-      if (nargin == 3)
+      std::string name = func.string_value ();
+      if (name.find_first_of ("(x)") != std::string::npos)
+        warning ("cellfun: passing function body as string is no longer supported."
+                 " Use @ or `inline'.");
+
+      if (name == "isempty")
+        {      
+          boolNDArray result (f_args.dims ());
+          for (octave_idx_type count = 0; count < k ; count++)
+            result(count) = f_args.elem(count).is_empty ();
+          retval(0) = result;
+        }
+      else if (name == "islogical")
+        {
+          boolNDArray result (f_args.dims ());
+          for (octave_idx_type  count= 0; count < k ; count++)
+            result(count) = f_args.elem(count).is_bool_type ();
+          retval(0) = result;
+        }
+      else if (name == "isreal")
+        {
+          boolNDArray result (f_args.dims ());
+          for (octave_idx_type  count= 0; count < k ; count++)
+            result(count) = f_args.elem(count).is_real_type ();
+          retval(0) = result;
+        }
+      else if (name == "length")
+        {
+          NDArray result (f_args.dims ());
+          for (octave_idx_type  count= 0; count < k ; count++)
+            result(count) = static_cast<double> (f_args.elem(count).length ());
+          retval(0) = result;
+        }
+      else if (name == "ndims")
         {
-          int d = args(2).nint_value () - 1;
-
-          if (d < 0)
-	    error ("cellfun: third argument must be a positive integer");
-
-	  if (! error_state)
+          NDArray result (f_args.dims ());
+          for (octave_idx_type count = 0; count < k ; count++)
+            result(count) = static_cast<double> (f_args.elem(count).ndims ());
+          retval(0) = result;
+        }
+      else if (name == "prodofsize" || name == "numel")
+        {
+          NDArray result (f_args.dims ());
+          for (octave_idx_type count = 0; count < k ; count++)
+            result(count) = static_cast<double> (f_args.elem(count).numel ());
+          retval(0) = result;
+        }
+      else if (name == "size")
+        {
+          if (nargin == 3)
             {
-              NDArray result (f_args.dims ());
-              for (octave_idx_type count = 0; count < k ; count++)
+              int d = args(2).nint_value () - 1;
+
+              if (d < 0)
+                error ("cellfun: third argument must be a positive integer");
+
+              if (! error_state)
                 {
-                  dim_vector dv = f_args.elem(count).dims ();
-                  if (d < dv.length ())
-	            result(count) = static_cast<double> (dv(d));
-                  else
-	            result(count) = 1.0;
+                  NDArray result (f_args.dims ());
+                  for (octave_idx_type count = 0; count < k ; count++)
+                    {
+                      dim_vector dv = f_args.elem(count).dims ();
+                      if (d < dv.length ())
+                        result(count) = static_cast<double> (dv(d));
+                      else
+                        result(count) = 1.0;
+                    }
+                  retval(0) = result;
                 }
+            }
+          else
+            error ("not enough arguments for `size'");
+        }
+      else if (name == "isclass")
+        {
+          if (nargin == 3)
+            {
+              std::string class_name = args(2).string_value();
+              boolNDArray result (f_args.dims ());
+              for (octave_idx_type count = 0; count < k ; count++)
+                result(count) = (f_args.elem(count).class_name() == class_name);
+
               retval(0) = result;
             }
+          else
+            error ("not enough arguments for `isclass'");
         }
       else
-        error ("not enough arguments for `size'");
+        {
+          func = symbol_table::find_function (name);
+          if (func.is_undefined ())
+            error ("cellfun: invalid function name: %s", name.c_str ());
+        }
     }
-  else if (name == "isclass")
-    {
-      if (nargin == 3)
-        {
-          std::string class_name = args(2).string_value();
-          boolNDArray result (f_args.dims ());
-          for (octave_idx_type count = 0; count < k ; count++)
-            result(count) = (f_args.elem(count).class_name() == class_name);
-          
-          retval(0) = result;
-        }
-      else
-        error ("not enough arguments for `isclass'");
-    }
-  else 
+
+  if (error_state || ! retval.empty ())
+    return retval;
+
+  if (func.is_function_handle () || func.is_inline_function ()
+      || func.is_function ())
     {
       unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
       unwind_protect::protect_var (buffer_error_messages);
 
-      std::string fcn_name;
-      
-      if (! func)
-	{
-	  fcn_name = unique_symbol_name ("__cellfun_fcn_");
-	  std::string fname = "function y = ";
-	  fname.append (fcn_name);
-	  fname.append ("(x) y = ");
-	  func = extract_function (args(0), "cellfun", fcn_name, fname,
-				       "; endfunction");
-	}
+      octave_value_list inputlist;
+      bool uniform_output = true;
+      octave_value error_handler;
+      int offset = 1;
+      int i = 1;
+      OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin);
+      // This is to prevent copy-on-write.
+      const Cell *cinputs = inputs;
 
-      if (! func)
-	error ("unknown function");
-      else
-	{
-	  octave_value_list inputlist;
-	  bool uniform_output = true;
-	  bool have_error_handler = false;
-	  std::string err_name;
-	  octave_function *error_handler = 0;
-	  int offset = 1;
-	  int i = 1;
-	  OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin);
-          // This is to prevent copy-on-write.
-          const Cell *cinputs = inputs;
+      while (i < nargin)
+        {
+          if (args(i).is_string())
+            {
+              std::string arg = args(i++).string_value();
+              if (i == nargin)
+                {
+                  error ("cellfun: parameter value is missing");
+                  goto cellfun_err;
+                }
 
-	  while (i < nargin)
-	    {
-	      if (args(i).is_string())
-		{
-		  std::string arg = args(i++).string_value();
-		  if (i == nargin)
-		    {
-		      error ("cellfun: parameter value is missing");
-		      goto cellfun_err;
-		    }
-
-		  std::transform (arg.begin (), arg.end (), 
-				  arg.begin (), tolower);
-
-		  if (arg == "uniformoutput")
-		    uniform_output = args(i++).bool_value();
-		  else if (arg == "errorhandler")
-		    {
-		      if (args(i).is_function_handle () || 
-			  args(i).is_inline_function ())
-			{
-			  error_handler = args(i).function_value ();
+              std::transform (arg.begin (), arg.end (), 
+                              arg.begin (), tolower);
 
-			  if (error_state)
-			    goto cellfun_err;
-			}
-		      else if (args(i).is_string ())
-			{
-			  err_name = unique_symbol_name ("__cellfun_fcn_");
-			  std::string fname = "function y = ";
-			  fname.append (fcn_name);
-			  fname.append ("(x) y = ");
-			  error_handler = extract_function (args(i), "cellfun", 
-							    err_name, fname,
-							    "; endfunction");
-			}
-
-		      if (! error_handler)
-			goto cellfun_err;
+              if (arg == "uniformoutput")
+                uniform_output = args(i++).bool_value();
+              else if (arg == "errorhandler")
+                {
+                  if (args(i).is_function_handle () || 
+                      args(i).is_inline_function ())
+                    {
+                      error_handler = args(i++);
+                    }
+                  else if (args(i).is_string ())
+                    {
+                      std::string err_name = args(i++).string_value ();
+                      error_handler = symbol_table::find_function (err_name);
+                      if (error_handler.is_undefined ())
+                        {
+                          error ("cellfun: invalid function name: %s", err_name.c_str ());
+                          goto cellfun_err;
+                        }
+                    }
+                  else
+                    {
+                      error ("invalid errorhandler value");
+                      goto cellfun_err;
+                    }
+                }
+              else
+                {
+                  error ("cellfun: unrecognized parameter %s", 
+                         arg.c_str());
+                  goto cellfun_err;
+                }
 
-		      have_error_handler = true;
-		      i++;
-		    }
-		  else
-		    {
-		      error ("cellfun: unrecognized parameter %s", 
-			     arg.c_str());
-		      goto cellfun_err;
-		    }
-		  offset += 2;
-		}
-	      else
-		{
-		  inputs[i-offset] = args(i).cell_value ();
-		  if (f_args.dims() != inputs[i-offset].dims())
-		    {
-		      error ("cellfun: Dimension mismatch");
-		      goto cellfun_err;
+              offset += 2;
+            }
+          else
+            {
+              inputs[i-offset] = args(i).cell_value ();
+              if (f_args.dims() != inputs[i-offset].dims())
+                {
+                  error ("cellfun: Dimension mismatch");
+                  goto cellfun_err;
+
+                }
+              i++;
+            }
+        }
 
-		    }
-		  i++;
-		}
-	    }
+      nargin -= offset;
+      inputlist.resize(nargin);
 
-          nargin -= offset;
-	  inputlist.resize(nargin);
-
-	  if (have_error_handler)
-	    buffer_error_messages++;
+      if (error_handler.is_defined ())
+        buffer_error_messages++;
 
-	  if (uniform_output)
-	    {
-              OCTAVE_LOCAL_BUFFER (std::auto_ptr<scalar_col_helper>, retptr, nargout);
+      if (uniform_output)
+        {
+          OCTAVE_LOCAL_BUFFER (std::auto_ptr<scalar_col_helper>, retptr, nargout);
 
-	      for (octave_idx_type count = 0; count < k ; count++)
-		{
-		  for (int j = 0; j < nargin; j++)
-		    inputlist(j) = cinputs[j](count);
+          for (octave_idx_type count = 0; count < k ; count++)
+            {
+              for (int j = 0; j < nargin; j++)
+                inputlist(j) = cinputs[j](count);
 
-		  octave_value_list tmp = feval (func, inputlist, nargout);
+              octave_value_list tmp = func.do_multi_index_op (nargout, inputlist);
 
-		  if (error_state && have_error_handler)
-		    {
-		      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 = feval (error_handler, errlist, nargout);
-		      buffer_error_messages++;
+              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)
-			goto cellfun_err;
-		    }
+                  if (error_state)
+                    goto cellfun_err;
+                }
 
-		  if (tmp.length() < nargout)
-		    {
-		      error ("cellfun: too many output arguments");
-		      goto cellfun_err;
-		    }
+              if (tmp.length() < nargout)
+                {
+                  error ("cellfun: too many output arguments");
+                  goto cellfun_err;
+                }
 
-		  if (error_state)
-		    break;
+              if (error_state)
+                break;
 
-		  if (count == 0)
-		    {
-		      for (int j = 0; j < nargout; j++)
-			{
-			  octave_value val = tmp(j);
+              if (count == 0)
+                {
+                  for (int j = 0; j < nargout; j++)
+                    {
+                      octave_value val = tmp(j);
 
-                          if (val.numel () == 1)
-                            retptr[j].reset (make_col_helper (val, f_args.dims ()));
-                          else
-                            {
-                              error ("cellfun: expecting all values to be scalars for UniformOutput = true");
-                              break;
-                            }
-			}
-		    }
-		  else
-		    {
-		      for (int j = 0; j < nargout; j++)
-			{
-			  octave_value val = tmp(j);
+                      if (val.numel () == 1)
+                        retptr[j].reset (make_col_helper (val, f_args.dims ()));
+                      else
+                        {
+                          error ("cellfun: expecting all values to be scalars for UniformOutput = true");
+                          break;
+                        }
+                    }
+                }
+              else
+                {
+                  for (int j = 0; j < nargout; j++)
+                    {
+                      octave_value val = tmp(j);
 
-                          if (! retptr[j]->collect (count, val))
-                            {
-                              // FIXME: A more elaborate structure would allow again a virtual
-                              // constructor here.
-                              retptr[j].reset (new scalar_col_helper_def (retptr[j]->result (), 
-                                                                          f_args.dims ()));
-                              retptr[j]->collect (count, val);
-                            }
+                      if (! retptr[j]->collect (count, val))
+                        {
+                          // FIXME: A more elaborate structure would allow again a virtual
+                          // constructor here.
+                          retptr[j].reset (new scalar_col_helper_def (retptr[j]->result (), 
+                                                                      f_args.dims ()));
+                          retptr[j]->collect (count, val);
                         }
-		    }
+                    }
+                }
 
-		  if (error_state)
-		    break;
-		}
+              if (error_state)
+                break;
+            }
 
-              retval.resize (nargout);
-              for (int j = 0; j < nargout; j++)
-                {
-                  if (retptr[j].get ())
-                    retval(j) = retptr[j]->result ();
-                  else
-                    retval(j) = Matrix ();
-                }
-	    }
-	  else
-	    {
-	      OCTAVE_LOCAL_BUFFER (Cell, results, nargout);
-	      for (int j = 0; j < nargout; j++)
-		results[j].resize(f_args.dims());
+          retval.resize (nargout);
+          for (int j = 0; j < nargout; j++)
+            {
+              if (retptr[j].get ())
+                retval(j) = retptr[j]->result ();
+              else
+                retval(j) = Matrix ();
+            }
+        }
+      else
+        {
+          OCTAVE_LOCAL_BUFFER (Cell, results, nargout);
+          for (int j = 0; j < nargout; j++)
+            results[j].resize(f_args.dims());
 
-	      for (octave_idx_type count = 0; count < k ; count++)
-		{
-		  for (int j = 0; j < nargin; j++)
-		    inputlist(j) = cinputs[j](count);
+          for (octave_idx_type count = 0; count < k ; count++)
+            {
+              for (int j = 0; j < nargin; j++)
+                inputlist(j) = cinputs[j](count);
 
-		  octave_value_list tmp = feval (func, inputlist, nargout);
+              octave_value_list tmp = func.do_multi_index_op (nargout, inputlist);
 
-		  if (error_state && have_error_handler)
-		    {
-		      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 = feval (error_handler, errlist, nargout);
-		      buffer_error_messages++;
+              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)
-			goto cellfun_err;
-		    }
+                  if (error_state)
+                    goto cellfun_err;
+                }
 
-		  if (tmp.length() < nargout)
-		    {
-		      error ("cellfun: too many output arguments");
-		      goto cellfun_err;
-		    }
+              if (tmp.length() < nargout)
+                {
+                  error ("cellfun: too many output arguments");
+                  goto cellfun_err;
+                }
 
-		  if (error_state)
-		    break;
+              if (error_state)
+                break;
 
 
-		  for (int j = 0; j < nargout; j++)
-		    results[j](count) = tmp(j);
-		}
-
-	      retval.resize(nargout);
-	      for (int j = 0; j < nargout; j++)
-		retval(j) = results[j];
-	    }
+              for (int j = 0; j < nargout; j++)
+                results[j](count) = tmp(j);
+            }
 
-	cellfun_err:
-	  if (error_state)
-	    retval = octave_value_list();
+          retval.resize(nargout);
+          for (int j = 0; j < nargout; j++)
+            retval(j) = results[j];
+        }
 
-	  if (! fcn_name.empty ())
-	    clear_function (fcn_name);
-
-	  if (! err_name.empty ())
-	    clear_function (err_name);
-	}
+cellfun_err:
+      if (error_state)
+        retval = octave_value_list();
 
       unwind_protect::run_frame (uwp_frame);
     }
+  else
+    error ("cellfun: first argument must be a string or function handle");
 
   return retval;
 }
--- a/src/ov-fcn-handle.cc	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/ov-fcn-handle.cc	Thu Jul 23 14:44:30 2009 +0200
@@ -69,7 +69,7 @@
 
 octave_fcn_handle::octave_fcn_handle (const octave_value& f,
 				      const std::string& n)
-  : warn_reload (true), fcn (f), nm (n)
+  : fcn (f), nm (n)
 {
   octave_user_function *uf = fcn.user_function_value (true);
 
@@ -88,27 +88,17 @@
     {
     case '(':
       {
-	out_of_date_check (fcn);
-
-	if (fcn.is_defined ())
-	  {
-	    octave_function *f = function_value ();
+	int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout;
 
-	    if (f)
-	      retval = f->subsref (type, idx, nargout);
-	    else
-	      error ("invalid function handle");
-	  }
-	else
-	  error ("invalid function handle");
+	retval = do_multi_index_op (tmp_nargout, idx.front ());
       }
       break;
 
     case '{':
     case '.':
       {
-	std::string typ_nm = type_name ();
-	error ("%s cannot be indexed with %c", typ_nm.c_str (), type[0]);
+	std::string tnm = type_name ();
+	error ("%s cannot be indexed with %c", tnm.c_str (), type[0]);
       }
       break;
 
@@ -116,8 +106,66 @@
       panic_impossible ();
     }
 
-  // There's no need to call next_subsref here --
-  // octave_function::subsref will handle that for us.
+  // FIXME -- perhaps there should be an
+  // octave_value_list::next_subsref member function?  See also
+  // octave_builtin::subsref.
+
+  if (idx.size () > 1)
+    retval = retval(0).next_subsref (nargout, type, idx);
+
+  return retval;
+}
+
+octave_value_list
+octave_fcn_handle::do_multi_index_op (int nargout, 
+                                      const octave_value_list& args)
+{
+  octave_value_list retval;
+
+  out_of_date_check (fcn);
+
+  if (disp.get () && ! args.empty ())
+    {
+      // Possibly overloaded function.
+      octave_value ovfcn = fcn;
+
+      // Get dynamic (class) dispatch type.
+      std::string ddt = get_dispatch_type (args);
+
+      if (ddt.empty ())
+        {
+          // Static dispatch (class of 1st arg)?
+          if (! disp->empty ())
+            {
+              std::string sdt = args(0).class_name ();
+              str_ov_map::iterator pos = disp->find (sdt);
+              if (pos != disp->end ())
+                {
+                  out_of_date_check (pos->second, sdt);
+                  ovfcn = pos->second;
+                }
+            }
+        }
+      else
+        {
+          octave_value method = symbol_table::find_method (nm, ddt);
+          if (method.is_defined ())
+            ovfcn = method;
+        }
+
+      if (ovfcn.is_defined ())
+        retval = ovfcn.do_multi_index_op (nargout, args);
+      else
+        error ("invalid function handle");
+    }
+  else
+    {
+      // Non-overloaded function (anonymous, subfunction, private function).
+      if (fcn.is_defined ())
+        retval = fcn.do_multi_index_op (nargout, args);
+      else
+        error ("invalid function handle");
+    }
 
   return retval;
 }
@@ -1214,6 +1262,40 @@
 			   current_print_indent_level ());
 }
 
+static string_vector
+get_builtin_classes (void)
+{
+  // FIXME: this should really be read from somewhere else.
+  static const char *cnames[15] = {
+      "double",
+      "single",
+      "int8",
+      "int16",
+      "int32",
+      "int64",
+      "uint8",
+      "uint16",
+      "uint32",
+      "uint64",
+      "logical",
+      "char",
+      "cell",
+      "struct",
+      "function_handle"
+  };
+
+  static string_vector retval;
+
+  if (retval.is_empty ())
+    {
+      retval = string_vector (15);
+      for (int i = 0; i < 15; i++)
+        retval(i) = cnames[i];
+    }
+
+  return retval;
+}
+
 octave_value
 make_fcn_handle (const std::string& nm)
 {
@@ -1348,9 +1430,31 @@
     }
 
   octave_value f = symbol_table::find_function (tnm);
+  octave_function *fptr = f.is_defined () ? f.function_value () : 0;
 
-  if (f.is_defined ())
-    retval = octave_value (new octave_fcn_handle (f, tnm));
+  if (fptr)
+    {
+      // If it's a subfunction, private function, or class constructor,
+      // we want no dispatch.
+      if (fptr->is_nested_function () || fptr->is_private_function ()
+          || fptr->is_class_constructor ())
+        retval = octave_value (new octave_fcn_handle (f, tnm));
+      else
+        {
+          typedef octave_fcn_handle::str_ov_map str_ov_map;
+          std::auto_ptr<str_ov_map> disp (new str_ov_map);
+          const string_vector cnames = get_builtin_classes ();
+          for (octave_idx_type i = 0; i < cnames.length (); i++)
+            {
+              std::string cnam = cnames(i);
+              octave_value method = symbol_table::find_method (tnm, cnam);
+              if (method.is_defined ())
+                (*disp)[cnam] = method;
+            }
+
+          retval = octave_value (new octave_fcn_handle (f, tnm, disp.release ()));
+        }
+    }
   else
     error ("error creating function handle \"@%s\"", nm.c_str ());
 
@@ -1434,6 +1538,8 @@
 		      parentage.elem(1) = fcn->parent_fcn_name ();
 		      m.assign ("parentage", octave_value (parentage)); 
 		    }
+                  else if (fh->is_overloaded ())
+		    m.assign ("type", "overloaded");
 		  else
 		    m.assign ("type", "simple");
 		}
--- a/src/ov-fcn-handle.h	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/ov-fcn-handle.h	Thu Jul 23 14:44:30 2009 +0200
@@ -25,6 +25,7 @@
 
 #include <iosfwd>
 #include <string>
+#include <memory>
 
 #include "oct-alloc.h"
 
@@ -39,18 +40,29 @@
 OCTINTERP_API
 octave_fcn_handle : public octave_base_value
 {
+private:
+
+  typedef std::map<std::string, octave_value> str_ov_map;
+
+  octave_fcn_handle (const octave_value& f, const std::string& n,
+                     str_ov_map *sdisp)
+    : fcn (f), nm (n), disp (sdisp) { }
+
 public:
   octave_fcn_handle (void)
-    : warn_reload (true), fcn (), nm () { }
+    : fcn (), nm () { }
 
   octave_fcn_handle (const std::string& n)
-    : warn_reload (true), fcn (), nm (n) { }
+    : fcn (), nm (n) { }
 
   octave_fcn_handle (const octave_value& f,  const std::string& n);
 
   octave_fcn_handle (const octave_fcn_handle& fh)
-    : octave_base_value (fh), warn_reload (fh.warn_reload),
-      fcn (fh.fcn), nm (fh.nm) { }
+    : octave_base_value (fh), fcn (fh.fcn), nm (fh.nm)
+   { 
+     if (fh.disp.get ())
+       disp.reset (new str_ov_map (*fh.disp));
+   }
 
   ~octave_fcn_handle (void) { }
 
@@ -68,10 +80,15 @@
 			     const std::list<octave_value_list>& idx,
 			     int nargout);
 
+  octave_value_list
+  do_multi_index_op (int nargout, const octave_value_list& args);
+
   bool is_defined (void) const { return true; }
 
   bool is_function_handle (void) const { return true; }
 
+  bool is_overloaded (void) const { return disp.get () && ! disp->empty (); }
+
   dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; }
 
   octave_function *function_value (bool = false)
@@ -116,11 +133,6 @@
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 
-  // If TRUE, print a warning if the pointed-to fucntion is out of
-  // date.  This variable may be removed when updating is properly
-  // implemented.
-  mutable bool warn_reload;
-
 protected:
 
   // The function we are handling.
@@ -128,6 +140,12 @@
 
   // The name of the handle, including the "@".
   std::string nm;
+
+  // A pointer to statical dispatch to standard classes. If null, we don't want
+  // to dispatch at all.
+  std::auto_ptr<str_ov_map> disp;
+
+  friend octave_value make_fcn_handle (const std::string &);
 };
 
 extern octave_value make_fcn_handle (const std::string& nm);
--- a/src/symtab.cc	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/symtab.cc	Thu Jul 23 14:44:30 2009 +0200
@@ -283,16 +283,18 @@
 }
 
 bool
-out_of_date_check (octave_value& function)
+out_of_date_check (octave_value& function,
+                   const std::string& dispatch_type)
 {
-  return out_of_date_check_internal (function);
+  return out_of_date_check_internal (function, dispatch_type);
 }
 
 bool
-out_of_date_check (octave_function* fcn)
+out_of_date_check (octave_function* fcn,
+                   const std::string& dispatch_type)
 {
   octave_value function;
-  return out_of_date_check_internal (fcn, function);
+  return out_of_date_check_internal (fcn, function, dispatch_type);
 }
 
 octave_value
@@ -423,7 +425,7 @@
   return retval;
 }
 
-static std::string
+std::string
 get_dispatch_type (const octave_value_list& args)
 {
   std::string dispatch_type;
@@ -462,13 +464,6 @@
 		dispatch_type = cname;
 	    }
 	}
-
-      if (dispatch_type.empty ())
-	{
-	  // No object found, so use class of first argument.
-
-	  dispatch_type = args(0).class_name ();
-	}
     }
 
   return dispatch_type;
@@ -621,6 +616,9 @@
     {
       std::string dispatch_type = get_dispatch_type (args);
 
+      if (dispatch_type.empty ())
+        dispatch_type = args(0).class_name ();
+
       octave_value fcn = find_method (dispatch_type);
 
       if (fcn.is_defined ())
--- a/src/symtab.h	Wed Jul 22 15:11:04 2009 +0200
+++ b/src/symtab.h	Thu Jul 23 14:44:30 2009 +0200
@@ -2316,9 +2316,13 @@
   void do_cache_name (const std::string& name) { table_name = name; }
 };
 
-extern bool out_of_date_check (octave_value& function);
-
-extern bool out_of_date_check (octave_function* fcn);
+extern bool out_of_date_check (octave_value& function,
+                               const std::string& dispatch_type = std::string ());
+
+extern bool out_of_date_check (octave_function* fcn,
+                               const std::string& dispatch_type = std::string ());
+
+extern std::string get_dispatch_type (const octave_value_list& args);
 
 #endif