changeset 26719:91b152968ec1

allow object.method@superclass (...) to work (bug #47680) * ov-classdef.cc (octave_classdef_superclass_ref::call): Allow the method portion of the superclass reference to be of the form object.method. * test/bug-47680/bug-47680.tst, test/bug-47680/sub_bug47680.m, test/bug-47680/super_bug47680.m, test/bug-47680/module.mk: New files. * test/module.mk: Update.
author John W. Eaton <jwe@octave.org>
date Mon, 11 Feb 2019 20:56:27 +0000
parents 9b0335f4bc74
children 9a678e0de658
files libinterp/octave-value/ov-classdef.cc test/bug-47680/bug-47680.tst test/bug-47680/module.mk test/bug-47680/sub_bug47680.m test/bug-47680/super_bug47680.m test/module.mk
diffstat 6 files changed, 92 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc	Mon Feb 11 20:49:48 2019 +0000
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Feb 11 20:56:27 2019 +0000
@@ -1157,6 +1157,9 @@
     std::string mname = m_method_name;
     std::string cname = m_class_name;
 
+    // CLS is the superclass.  The lookup_class function handles
+    // pkg.class names.
+
     cdef_class cls = lookup_class (cname);
 
     if (in_constructor)
@@ -1177,6 +1180,38 @@
       }
     else
       {
+        size_t pos = mname.find ('.');
+
+        cdef_object obj;
+
+        if (pos != std::string::npos)
+          {
+            // We are looking at obj.meth.
+
+            std::string oname = m_method_name.substr (0, pos);
+            mname = mname.substr (pos + 1);
+
+            octave_value tval = tw.varval (oname);
+
+            // FIXME: Can we only call superclass methods on the current
+            // object?  If so, and we are looking at something like
+            //
+            //   function meth (obj, ...)
+            //     obj.meth@superclass (...)
+            //
+            // Do we need to verify that the object that was passed to
+            // meth is the same as the object we find when looking up
+            // obj in the expression obj.meth?  If so, what is the right
+            // way to perform that check?
+
+            if (tval.is_classdef_object ())
+              {
+                octave_classdef *cdobj = tval.classdef_object_value ();
+
+                obj = cdobj->get_object ();
+              }
+          }
+
         if (mname != meth_name)
           error ("method name mismatch (`%s' != `%s')",
                  mname.c_str (), meth_name.c_str ());
@@ -1202,8 +1237,9 @@
           error ("no method `%s' found in superclass `%s'",
                  meth_name.c_str (), cname.c_str ());
 
-        retval = meth.execute (idx, nargout, true,
-                               meth_name);
+        retval = (obj.ok ()
+                  ? meth.execute (obj, idx, nargout, true, meth_name)
+                  : meth.execute (idx, nargout, true, meth_name));
       }
 
     return retval;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/bug-47680.tst	Mon Feb 11 20:56:27 2019 +0000
@@ -0,0 +1,6 @@
+%!shared obj
+%! obj = sub_bug47680 ("foo");
+%!assert<47680> (obj.meth1 (), "foo:super:meth1:sub:meth1")
+%!assert<47680> (obj.meth2 (), "foo:super:meth2:sub:meth2")
+%!assert<47680> (obj.meth3 (), "foo:super:meth3:sub:meth3")
+%!assert<47680> (obj.meth4 (), "foo:super:meth4:sub:meth4")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/module.mk	Mon Feb 11 20:56:27 2019 +0000
@@ -0,0 +1,6 @@
+bug_47680_TEST_FILES = \
+  %reldir%/bug-47680.tst \
+  %reldir%/sub_class47680.m \
+  %reldir%/super_class47680.m
+
+TEST_FILES += $(bug_47680_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/sub_bug47680.m	Mon Feb 11 20:56:27 2019 +0000
@@ -0,0 +1,19 @@
+classdef sub_bug47680 < super_bug47680
+  methods
+    function obj = sub_bug47680 (x)
+      obj = obj@super_bug47680 (x);
+    endfunction
+    function r = meth1 (obj)
+      r = meth1@super_bug47680 (obj, "sub:meth1");
+    endfunction
+    function r = meth2 (obj)
+      r = obj.meth2@super_bug47680 ("sub:meth2");
+    endfunction
+    function r = meth3 (obj)
+      r = meth3@super_bug47680 (obj, "sub:meth3");
+    endfunction
+    function r = meth4 (obj)
+      r = obj.meth4@super_bug47680 ("sub:meth4");
+    endfunction
+  endmethods
+endclassdef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/super_bug47680.m	Mon Feb 11 20:56:27 2019 +0000
@@ -0,0 +1,22 @@
+classdef super_bug47680
+  properties
+    tag;
+  end
+  methods
+    function obj = super_bug47680 (x)
+      obj.tag = x;
+    endfunction
+    function r = meth1 (obj, x)
+      r = [obj.tag ":super:meth1:" x];
+    endfunction
+    function r = meth2 (obj, x)
+      r = [obj.tag ":super:meth2:" x];
+    endfunction
+    function r = meth3 (obj, x)
+      r = [obj.tag ":super:meth3:" x];
+    endfunction
+    function r = meth4 (obj, x)
+      r = [obj.tag ":super:meth4:" x];
+    endfunction
+  endmethods
+endclassdef
--- a/test/module.mk	Mon Feb 11 20:49:48 2019 +0000
+++ b/test/module.mk	Mon Feb 11 20:56:27 2019 +0000
@@ -63,6 +63,7 @@
 include %reldir%/bug-41723/module.mk
 include %reldir%/bug-44940/module.mk
 include %reldir%/bug-46660/module.mk
+include %reldir%/bug-47680/module.mk
 include %reldir%/bug-49379/module.mk
 include %reldir%/bug-50014/module.mk
 include %reldir%/bug-50035/module.mk