changeset 11220:883b9308353c

allow class function to be called from methods as well as constructors
author John W. Eaton <jwe@octave.org>
date Wed, 10 Nov 2010 00:54:34 -0500
parents 29d515b9d30c
children ae9d536eadaf
files src/ChangeLog src/ov-class.cc src/ov-fcn-handle.cc src/ov-fcn.h src/ov-usr-fcn.h
diffstat 5 files changed, 66 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Nov 09 21:02:44 2010 -0800
+++ b/src/ChangeLog	Wed Nov 10 00:54:34 2010 -0500
@@ -1,3 +1,16 @@
+2010-11-10  John W. Eaton  <jwe@octave.org>
+
+	* ov-fcn.h (octave_base_value::is_class_constructor)
+	octave_base_value::is_class_method): New optional character
+	string argument.
+	* ov-usr-fcn.h (octave_usr_fcn::is_class_constructor)
+	octave_usr_fcn::is_class_method): New optional arg. If this
+	argument is not empty, also check it against the name of the
+	dispatch class.
+	* ov-class.cc (Fclass): Allow class function to be called inside
+	a class method.  Require that the to-be-constructed object is of
+	the same class as the class constructor or method.
+
 2010-11-09  John W. Eaton  <jwe@octave.org>
 
 	* lex.ll (handle_number): Set lexer_flags.looking_for_object_index
--- a/src/ov-class.cc	Tue Nov 09 21:02:44 2010 -0800
+++ b/src/ov-class.cc	Wed Nov 10 00:54:34 2010 -0500
@@ -123,6 +123,8 @@
 
   octave_function *fcn = octave_call_stack::current ();
 
+  // Here we are just looking to see if FCN is a method or constructor
+  // for any class, not specifically this one.
   if (fcn->is_class_method () || fcn->is_class_constructor ())
     retval = fcn->dispatch_class ();
 
@@ -1726,45 +1728,53 @@
     {
       octave_function *fcn = octave_call_stack::caller ();
 
-      if (fcn && fcn->is_class_constructor ())
-        {
-          octave_map m = args(0).map_value ();
-
-          if (! error_state)
-            {
-              std::string id = args(1).string_value ();
+      std::string id = args(1).string_value ();
 
-              if (! error_state)
+      if (! error_state)
+        {
+          if (fcn)
+            {
+              if (fcn->is_class_constructor (id) || fcn->is_class_method (id))
                 {
-                  if (nargin == 2)
-                    retval = octave_value (new octave_class (m, id));
-                  else
-                    {
-                      octave_value_list parents = args.slice (2, nargin-2);
-
-                      retval = octave_value (new octave_class (m, id, parents));
-                    }
+                  octave_map m = args(0).map_value ();
 
                   if (! error_state)
                     {
-                      octave_class::exemplar_const_iterator it
-                        = octave_class::exemplar_map.find (id);
+                      if (nargin == 2)
+                        retval = octave_value (new octave_class (m, id));
+                      else
+                        {
+                          octave_value_list parents = args.slice (2, nargin-2);
+
+                          retval
+                            = octave_value (new octave_class (m, id, parents));
+                        }
 
-                      if (it == octave_class::exemplar_map.end ())
-                        octave_class::exemplar_map[id]
-                          = octave_class::exemplar_info (retval);
-                      else if (! it->second.compare (retval))
-                        error ("class: object of class `%s' does not match previously constructed objects", id.c_str ());
+                      if (! error_state)
+                        {
+                          octave_class::exemplar_const_iterator it
+                            = octave_class::exemplar_map.find (id);
+
+                          if (it == octave_class::exemplar_map.end ())
+                            octave_class::exemplar_map[id]
+                              = octave_class::exemplar_info (retval);
+                          else if (! it->second.compare (retval))
+                            error ("class: object of class `%s' does not match previously constructed objects",
+                                   id.c_str ());
+                        }
                     }
+                  else
+                    error ("class: expecting structure as first argument");
                 }
               else
-                error ("class: expecting character string as second argument");
+                error ("class: `%s' is invalid as a class name in this context",
+                       id.c_str ());
             }
           else
-            error ("class: expecting structure as first argument");
+            error ("class: invalid call from outside class constructor or method");
         }
       else
-        error ("class: invalid call from outside class constructor");
+        error ("class: expecting character string as second argument");
     }
 
   return retval;
--- a/src/ov-fcn-handle.cc	Tue Nov 09 21:02:44 2010 -0800
+++ b/src/ov-fcn-handle.cc	Wed Nov 10 00:54:34 2010 -0500
@@ -1493,8 +1493,11 @@
 
   octave_value f = symbol_table::find_function (tnm, octave_value_list (),
                                                 local_funcs);
+
   octave_function *fptr = f.function_value (true);
 
+  // Here we are just looking to see if FCN is a method or constructor
+  // for any class.
   if (local_funcs && fptr 
       && (fptr->is_nested_function () || fptr->is_private_function ()
           || fptr->is_class_constructor ()))
--- a/src/ov-fcn.h	Tue Nov 09 21:02:44 2010 -0800
+++ b/src/ov-fcn.h	Wed Nov 10 00:54:34 2010 -0500
@@ -78,9 +78,11 @@
 
   virtual bool is_nested_function (void) const { return false; }
 
-  virtual bool is_class_constructor (void) const { return false; }
+  virtual bool is_class_constructor (const std::string& = std::string ()) const
+    { return false; }
 
-  virtual bool is_class_method (void) const { return false; }
+  virtual bool is_class_method (const std::string& = std::string ()) const
+    { return false; }
 
   virtual bool takes_varargs (void) const { return false; }
 
--- a/src/ov-usr-fcn.h	Tue Nov 09 21:02:44 2010 -0800
+++ b/src/ov-usr-fcn.h	Wed Nov 10 00:54:34 2010 -0500
@@ -251,11 +251,19 @@
 
   void mark_as_class_constructor (void) { class_constructor = true; }
 
-  bool is_class_constructor (void) const { return class_constructor; }
+  bool is_class_constructor (const std::string& cname = std::string ()) const
+    {
+      return class_constructor
+        ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+    }
 
   void mark_as_class_method (void) { class_method = true; }
 
-  bool is_class_method (void) const { return class_method; }
+  bool is_class_method (const std::string& cname = std::string ()) const
+    {
+      return class_method
+        ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+    }
 
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx)