# HG changeset patch # User rtshort@bristlecone.phaselocked.com # Date 1240425206 14400 # Node ID 5579998f8acfa700f062269e75ec21106192d488 # Parent a48c500e48e1c933e652aafe241b5e429db10c00 Update to OOP facilities. * scripts/general/isa.m: Fixed isa so that multiple layers of class hierarchy are reported correctly. * src/variables.cc: Make exist('obj') for objects report correctly. * src/ov-base.h: Added an assign method so ov-class is able to assign structure elements properly. * src/ov-class.h: Assign map elements. * src/ov-class.cc: - Made sure that there are no duplicate classes in parent tree. - Simplified search algorithm for parent classes. - Fixed subsasgn so cls = method(cls,value) works when properly when method is a parent-class method. - Added __isa_parent__ so isa works correctly. diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,7 @@ +2009-04-22 Robert T. Short + + * general/isa.m: Correctly report multiple layers of class hierarchy. + 2009-04-20 John W. Eaton * special-matrix/vander.m: Update tests. diff --git a/scripts/general/isa.m b/scripts/general/isa.m --- a/scripts/general/isa.m +++ b/scripts/general/isa.m @@ -44,10 +44,7 @@ class_of_x = class (x); retval = strcmp (class_of_x, cname); if (! retval && isobject (x)) - parent_classes_of_x = __parent_classes__ (x); - if (! isempty (parent_classes_of_x)) - retval = any (strcmp (parent_classes_of_x, cname)); - endif + retval = __isa_parent__ (x, cname); endif endif diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2009-04-22 Robert T. Short + + * variables.cc (symbol_exist): Also return 1 for objects. + * ov-base.h (octave_base_value::assign): New virtual function. + * ov-class.h (octave_class::assign): New function. + * ov-class.cc (octave_class::find_parent_class): Simplify. + (octave_class::octave_class): Don't allow duplicate parent classes. + (octave_class::subsasgn): Allow cls = method (cls, value) to work + properly when method is a parent-class method. + (get_method_class): New static function. + (octave_class:subsasgn, octave_class::dotref): Use it. + (F__isa_parent__): New function. + 2009-04-22 Jaroslav Hajek * ov-range.cc (octave_range::char_array_value): New virtual function diff --git a/src/ov-base.h b/src/ov-base.h --- a/src/ov-base.h +++ b/src/ov-base.h @@ -171,6 +171,8 @@ virtual octave_value_list do_multi_index_op (int nargout, const octave_value_list& idx); + virtual void assign (const std::string&, const octave_value&) { } + virtual octave_value subsasgn (const std::string& type, const std::list& idx, diff --git a/src/ov-class.cc b/src/ov-class.cc --- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -78,69 +78,67 @@ { std::string cnm = parent.class_name (); - parent_list.push_back (cnm); + if (find_parent_class (cnm)) + error ("duplicate class in parent tree"); + else + { + parent_list.push_back (cnm); - map.assign (cnm, parent); + map.assign (cnm, parent); + } } } - load_path::add_to_parent_map (id, parent_list); + if (! error_state) + load_path::add_to_parent_map (id, parent_list); } octave_base_value * octave_class::find_parent_class (const std::string& parent_class_name) { octave_base_value* retval = 0; - std::string dbg_clsnm = class_name (); if (parent_class_name == class_name ()) retval = this; else { - // Search in the list of immediate parents first, then in the - // ancestor tree. - - std::list::iterator - p = find (parent_list.begin (), parent_list.end (), parent_class_name); - - if (p != parent_list.end ()) + for (std::list::iterator pit = parent_list.begin (); + pit != parent_list.end (); + pit++) { - Octave_map::const_iterator pmap = map.seek (parent_class_name); + Octave_map::const_iterator smap = map.seek (*pit); - if (pmap != map.end ()) - { - const Cell& tmp = pmap->second; - - octave_value vtmp = tmp(0); + const Cell& tmp = smap->second; - retval = vtmp.internal_rep (); - } - } - else - { - for (std::list::iterator pit = parent_list.begin (); - pit != parent_list.end (); - pit++) - { - Octave_map::const_iterator smap = map.seek (*pit); + octave_value vtmp = tmp(0); + + octave_base_value *obvp = vtmp.internal_rep (); - const Cell& tmp = smap->second; - - octave_value vtmp = tmp(0); - - octave_base_value *obvp = vtmp.internal_rep (); + retval = obvp->find_parent_class (parent_class_name); - retval = obvp->find_parent_class (parent_class_name); - - if (retval) - break; - } + if (retval) + break; } } return retval; } +static std::string +get_current_method_class (void) +{ + // FIXME -- is there a better way to do this? + octave_function *fcn = octave_call_stack::current (); + + std::string my_dir = fcn->dir_name (); + + size_t ipos = my_dir.find_last_of ("@"); + + assert (ipos != std::string::npos); + + return my_dir.substr (ipos+1); +} + Cell octave_class::dotref (const octave_value_list& idx) { @@ -148,11 +146,7 @@ assert (idx.length () == 1); - // FIXME -- Is there a "proper" way to do this? - octave_function* fcn = octave_call_stack::current (); - std::string my_dir = fcn->dir_name (); - int ipos = my_dir.find_last_of ("@"); - std::string method_class = my_dir.substr (ipos+1); + std::string method_class = get_current_method_class (); // Find the class in which this method resides before attempting to access // the requested field. @@ -628,15 +622,27 @@ std::string key = key_idx(0).string_value (); - map.assign (key, t_rhs); + // Find the class in which this method resides before + // attempting to access the requested field. + + std::string method_class = get_current_method_class (); + + octave_base_value *obvp = find_parent_class (method_class); - if (! error_state) + if (obvp) { - count++; - retval = octave_value (this); + obvp->assign (key, t_rhs); + + if (! error_state) + { + count++; + retval = octave_value (this); + } + else + gripe_failed_assignment (); } else - gripe_failed_assignment (); + error ("malformed class"); } break; @@ -1313,6 +1319,33 @@ return retval; } +DEFUN (__isa_parent__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __isa_parent__ (@var{class}, @var{name})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 2) + { + octave_value cls = args(0); + octave_value nm = args(1); + + if (! error_state) + { + if (cls.find_parent_class (nm.string_value ())) + retval = true; + } + else + error ("__isa_parent__: expecting arguments to be character strings"); + } + else + print_usage (); + + return retval; +} + DEFUN (__parent_classes__, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} __parent_classes__ (@var{x})\n\ diff --git a/src/ov-class.h b/src/ov-class.h --- a/src/ov-class.h +++ b/src/ov-class.h @@ -86,6 +86,9 @@ static octave_value numeric_conv (const Cell& val, const std::string& type); + void assign(const std::string& k, const octave_value& rhs) + { map.assign (k, rhs); }; + octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); diff --git a/src/variables.cc b/src/variables.cc --- a/src/variables.cc +++ b/src/variables.cc @@ -408,7 +408,7 @@ if (! retval && var_ok && (type == "any" || type == "var") - && val.is_constant ()) + && (val.is_constant () || val.is_object ())) { retval = 1; }