changeset 13147:6c952376482d

look for methods before constructors * symtab.cc (symbol_table::fcn_info::fcn_info_rep::find): Look for class methods before constructors, contrary to Matlab documentation. * test/ctor-vs-method: New directory of test classes. * test/test_ctor_vs_method.m: New file. * test/Makefile.am: Include ctor-vs-method/module.mk. (FCN_FILES): Include test_ctor_vs_method.m in the list.
author John W. Eaton <jwe@octave.org>
date Fri, 16 Sep 2011 15:42:06 -0400
parents 1ce5cd703af0
children 54f804016276
files src/symtab.cc test/Makefile.am test/ctor-vs-method/@derived/derived.m test/ctor-vs-method/@derived/parent.m test/ctor-vs-method/@other/other.m test/ctor-vs-method/@other/parent.m test/ctor-vs-method/@parent/method.m test/ctor-vs-method/@parent/parent.m test/ctor-vs-method/__trace__.m test/ctor-vs-method/module.mk test/test_ctor_vs_method.m
diffstat 11 files changed, 146 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/symtab.cc	Fri Sep 16 21:04:30 2011 +0200
+++ b/src/symtab.cc	Fri Sep 16 15:42:06 2011 -0400
@@ -575,13 +575,16 @@
 //   variable
 //   subfunction
 //   private function
+//   class method
 //   class constructor
-//   class method
 //   legacy dispatch
 //   command-line function
 //   autoload function
 //   function on the path
 //   built-in function
+//
+// Matlab documentation states that constructors have higher precedence
+// than methods, but that does not seem to be the case.
 
 octave_value
 symbol_table::fcn_info::fcn_info_rep::find (const octave_value_list& args,
@@ -687,6 +690,18 @@
         }
     }
 
+  // Class methods.
+
+  if (! args.empty ())
+    {
+      std::string dispatch_type = get_dispatch_type (args);
+
+      octave_value fcn = find_method (dispatch_type);
+
+      if (fcn.is_defined ())
+        return fcn;
+    }
+
   // Class constructors.  The class name and function name are the same.
 
   str_val_iterator q = class_constructors.find (name);
@@ -716,18 +731,6 @@
         }
     }
 
-  // Class methods.
-
-  if (! args.empty ())
-    {
-      std::string dispatch_type = get_dispatch_type (args);
-
-      octave_value fcn = find_method (dispatch_type);
-
-      if (fcn.is_defined ())
-        return fcn;
-    }
-
   // Legacy dispatch.
 
   if (! args.empty () && ! dispatch_map.empty ())
--- a/test/Makefile.am	Fri Sep 16 21:04:30 2011 +0200
+++ b/test/Makefile.am	Fri Sep 16 15:42:06 2011 -0400
@@ -25,6 +25,7 @@
   test_args.m \
   test_classes.m \
   test_contin.m \
+  test_ctor_vs_method.m \
   test_diag_perm.m \
   test_error.m \
   test_eval-catch.m \
@@ -61,6 +62,8 @@
 include @Snork/module.mk
 include @Spork/module.mk
 
+include ctor-vs-method/module.mk
+
 check: test_sparse.m test_bc_overloads.m
 	$(top_builddir)/run-octave --norc --silent --no-history $(srcdir)/fntests.m $(srcdir)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@derived/derived.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,5 @@
+function r = derived (varargin)
+  __trace__ ('begin derived/derived');
+  r = class (struct (), 'derived', parent ());
+  __trace__ ('end derived/derived');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@derived/parent.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,9 @@
+function r = parent (a)
+  __trace__ ('begin derived/parent');
+  if (isa (a, 'parent'))
+    r = parent (a.parent);
+  else
+    error ('foo');
+  end
+  __trace__ ('end derived/parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@other/other.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,5 @@
+function r = other (varargin)
+  __trace__ ('begin other/other');
+  r = class (struct (), 'other');
+  __trace__ ('end other/other');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@other/parent.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,4 @@
+function r = parent (a)
+  __trace__ ('begin other/parent');
+  __trace__ ('end other/parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@parent/method.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,5 @@
+function r = method (a)
+  __trace__ ('begin parent/method');
+  r = parent (a);
+  __trace__ ('end parent/method');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/@parent/parent.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,15 @@
+function rot = parent (a)
+  __trace__ ('begin parent/parent');
+  if (nargin == 0)
+    rot = class (struct (), 'parent');
+  else
+    switch class (a)
+      case 'parent'
+        %% copy constructor
+	rot = a;
+      otherwise
+	error ('type mismatch in parent constructor')
+    end
+  end
+  __trace__ ('end parent/parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/__trace__.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,18 @@
+function r = __trace__ (t)
+  persistent history
+  if (isempty (history))
+    history = {};
+  end
+  if (nargin == 0)
+    if (nargout == 0)
+      history = {};
+    else
+      r = history;
+    end
+  elseif (nargin == 1);
+    history = [history; t];
+  else
+    error ('incorrect call to __trace__');
+  end
+end
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ctor-vs-method/module.mk	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,10 @@
+ctor_vs_method_FCN_FILES = \
+  ctor-vs-method/@derived/derived.m \
+  ctor-vs-method/@derived/parent.m \
+  ctor-vs-method/@other/other.m \
+  ctor-vs-method/@other/parent.m \
+  ctor-vs-method/@parent/method.m \
+  ctor-vs-method/@parent/parent.m \
+  ctor-vs-method/__trace__.m
+
+FCN_FILES += $(ctor_vs_method_FCN_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_ctor_vs_method.m	Fri Sep 16 15:42:06 2011 -0400
@@ -0,0 +1,56 @@
+## Copyright (C) 2011 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+%%  Test script for legacy OOP.
+%%  Requires the path to contain the directory ctor-vs-method.
+%%
+%%  Note: This script and all classes are also intended to run
+%%        in Matlab to test compatibility.  Don't break that!
+
+%!shared d, o
+%! d = derived ();
+%! o = other ();
+%!
+%!error method (o);
+
+%!test
+%! ctrace = {'begin parent/method';
+%!           'begin derived/parent';
+%!           'begin parent/parent';
+%!           'end parent/parent';
+%!           'end derived/parent';
+%!           'end parent/method'};
+%! __trace__ (); %% clear call trace info
+%! method (d);
+%! assert (__trace__ (), ctrace);
+
+%!test
+%! ctrace = {'begin other/parent';
+%!           'end other/parent'};
+%! __trace__ (); %% clear call trace info
+%! parent (o);
+%! assert (__trace__ (), ctrace);
+
+%!test
+%! ctrace = {'begin derived/parent';
+%!           'begin parent/parent';
+%!           'end parent/parent';
+%!           'end derived/parent'};
+%! __trace__ (); %% clear call trace info
+%! parent (d);
+%! assert (__trace__ (), ctrace);