# HG changeset patch # User John W. Eaton # Date 1289368474 18000 # Node ID 883b9308353cd9f0d119ed8fb8d9f07b45a6ca08 # Parent 29d515b9d30c250c1fd68a012bdf515d5a937d23 allow class function to be called from methods as well as constructors diff -r 29d515b9d30c -r 883b9308353c src/ChangeLog --- 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 + + * 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 * lex.ll (handle_number): Set lexer_flags.looking_for_object_index diff -r 29d515b9d30c -r 883b9308353c src/ov-class.cc --- 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; diff -r 29d515b9d30c -r 883b9308353c src/ov-fcn-handle.cc --- 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 ())) diff -r 29d515b9d30c -r 883b9308353c src/ov-fcn.h --- 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; } diff -r 29d515b9d30c -r 883b9308353c src/ov-usr-fcn.h --- 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& idx)