# HG changeset patch # User rtshort@smoketree.phaselocked.com # Date 1237908593 14400 # Node ID f914834836e75c63bcf99af360eb1e9459e1b48d # Parent da58ec8f62e8e9da22698efd87abfe69f2c5c5c8 Partial implementation of derived classes using the old form with "@" files. diff -r da58ec8f62e8 -r f914834836e7 scripts/ChangeLog --- a/scripts/ChangeLog Mon Mar 23 19:29:01 2009 -0400 +++ b/scripts/ChangeLog Tue Mar 24 11:29:53 2009 -0400 @@ -1,3 +1,7 @@ +2009-03-24 John W. Eaton + + * general/isa.m: Handle parent classes. + 2009-03-23 Ben Abbott * plot/gnuplot_drawnow.m: Check that gnuplot has internal variable diff -r da58ec8f62e8 -r f914834836e7 scripts/general/isa.m --- a/scripts/general/isa.m Mon Mar 23 19:29:01 2009 -0400 +++ b/scripts/general/isa.m Tue Mar 24 11:29:53 2009 -0400 @@ -41,7 +41,14 @@ elseif (strcmp (cname, "numeric")) retval = any (strcmp (class (x), fnum_classes)); else - retval = strcmp (class (x), cname); + 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 + endif endif endfunction diff -r da58ec8f62e8 -r f914834836e7 src/ChangeLog --- a/src/ChangeLog Mon Mar 23 19:29:01 2009 -0400 +++ b/src/ChangeLog Tue Mar 24 11:29:53 2009 -0400 @@ -1,3 +1,27 @@ +2009-03-24 John W. Eaton + + * ov-class.cc (F__parent_classes__): New function. + +2009-03-24 Robert T. Short + + * ov-class.h, ov-class.cc (octave_class::octave_class (const + Octave_map&, const std::string&, const octave_value_list&)): + New constructor. + (octave_class::find_parent_class, octave_class::parent_classes): + New functions. + (octave_class::dotref): Also look in parent class. + (Fclass): Handle parent class arguments. + + * ov-base.h (octave_base_value::get_parent_list, + octave_base_value::parent_classes): New virtual functions. + + * load-path.h, load-path.cc (load_path::parent_map): New data member. + (load_path::add_to_parent_map): New static function. + (load_path::do_add_to_parent_map): New member function. + (load_path::do_find_method): Also look in parent classes for methods. + (load_path::parent_map_type, load_path::const_parent_map_iterator, + load_path::parent_map_iterator): New typedefs. + 2009-03-23 John W. Eaton * symtab.h diff -r da58ec8f62e8 -r f914834836e7 src/load-path.cc --- a/src/load-path.cc Mon Mar 23 19:29:01 2009 -0400 +++ b/src/load-path.cc Tue Mar 24 11:29:53 2009 -0400 @@ -512,6 +512,7 @@ fcn_map.clear (); private_fcn_map.clear (); method_map.clear (); + parent_map.clear (); do_append (".", false); } @@ -1016,7 +1017,29 @@ const_fcn_map_iterator p = m.find (meth); - if (p != m.end ()) + if (p == m.end ()) + { + // Look in parent classes. + + const_parent_map_iterator r = parent_map.find (class_name); + + if (r != parent_map.end ()) + { + const std::list& plist = r->second; + std::list::const_iterator it = plist.begin (); + + while (it != plist.end ()) + { + retval = do_find_method (*it, meth, dir_name, type); + + if (retval != "") + break; + + it++; + } + } + } + else { const file_info_list_type& file_info_list = p->second; @@ -1538,6 +1561,13 @@ } void +load_path::do_add_to_parent_map (const std::string& classname, + const std::list& parent_list) const +{ + parent_map[classname] = parent_list; +} + +void load_path::add_to_fcn_map (const dir_info& di, bool at_end) const { std::string dir_name = di.dir_name; diff -r da58ec8f62e8 -r f914834836e7 src/load-path.h --- a/src/load-path.h Mon Mar 23 19:29:01 2009 -0400 +++ b/src/load-path.h Tue Mar 24 11:29:53 2009 -0400 @@ -37,7 +37,8 @@ { protected: - load_path (void) : dir_info_list (), fcn_map (), method_map () { } + load_path (void) + : dir_info_list (), fcn_map (), method_map (), parent_map () { } public: @@ -228,6 +229,13 @@ return instance_ok () ? instance->do_system_path () : std::string (); } + static void add_to_parent_map (const std::string& classname, + const std::list& parent_list) + { + if (instance_ok ()) + instance->do_add_to_parent_map (classname, parent_list); + } + private: static const int M_FILE = 1; @@ -386,6 +394,12 @@ typedef method_map_type::const_iterator const_method_map_iterator; typedef method_map_type::iterator method_map_iterator; + + // > + typedef std::map > parent_map_type; + + typedef parent_map_type::const_iterator const_parent_map_iterator; + typedef parent_map_type::iterator parent_map_iterator; mutable dir_info_list_type dir_info_list; @@ -395,6 +409,8 @@ mutable method_map_type method_map; + mutable parent_map_type parent_map; + static load_path *instance; static hook_fcn_ptr add_hook; @@ -493,6 +509,9 @@ std::string do_get_command_line_path (void) const { return command_line_path; } + void do_add_to_parent_map (const std::string& classname, + const std::list& parent_list) const; + void add_to_fcn_map (const dir_info& di, bool at_end) const; void add_to_private_fcn_map (const dir_info& di) const; diff -r da58ec8f62e8 -r f914834836e7 src/ov-base.h --- a/src/ov-base.h Mon Mar 23 19:29:01 2009 -0400 +++ b/src/ov-base.h Tue Mar 24 11:29:53 2009 -0400 @@ -450,6 +450,13 @@ virtual string_vector map_keys (void) const; + virtual string_vector parent_class_names (void) const + { return string_vector (); } + + // FIXME -- should this warn if called for a non-class type? + virtual octave_base_value *find_parent_class (const std::string&) + { return 0; } + virtual octave_function *function_value (bool silent = false); virtual const octave_function *function_value (bool silent = false) const; diff -r da58ec8f62e8 -r f914834836e7 src/ov-class.cc --- a/src/ov-class.cc Mon Mar 23 19:29:01 2009 -0400 +++ b/src/ov-class.cc Tue Mar 24 11:29:53 2009 -0400 @@ -62,6 +62,85 @@ (octave_class::t_name, "", octave_value (new octave_class ())); } +octave_class::octave_class (const Octave_map& m, const std::string& id, + const octave_value_list& parents) + : octave_base_value (), map (m), c_name (id) +{ + octave_idx_type n = parents.length (); + + for (octave_idx_type idx = 0; idx < n; idx++) + { + octave_value parent = parents(idx); + + if (! parent.is_object ()) + error ("parents must be objects"); + else + { + std::string cnm = parent.class_name (); + + parent_list.push_back (cnm); + + map.assign (cnm, parent); + } + } + + 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 ()) + { + Octave_map::const_iterator pmap = map.seek (parent_class_name); + + if (pmap != map.end ()) + { + const Cell& tmp = pmap->second; + + octave_value vtmp = tmp(0); + + 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); + + 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); + + if (retval) + break; + } + } + } + + return retval; +} + Cell octave_class::dotref (const octave_value_list& idx) { @@ -69,12 +148,27 @@ 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); + + // Find the class in which this method resides before attempting to access + // the requested field. + + octave_base_value *obvp = find_parent_class (method_class); + + Octave_map my_map; + + my_map = obvp ? obvp->map_value () : map; + std::string nm = idx(0).string_value (); - Octave_map::const_iterator p = map.seek (nm); + Octave_map::const_iterator p = my_map.seek (nm); - if (p != map.end ()) - retval = map.contents (p); + if (p != my_map.end ()) + retval = my_map.contents (p); else error ("class has no member `%s'", nm.c_str ()); @@ -1168,18 +1262,22 @@ "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} class (@var{expr})\n\ @deftypefnx {Built-in Function} {} class (@var{s}, @var{id})\n\ -\n\ -Return the class of the expression @var{expr}, as a string or\n\ -create a class object from the structure @var{s} with name @var{id}.\n\ +@deftypefnx {Built-in Function} {} class (@var{s}, @var{id}, @var{p}, @dots{})\n\ +Return the class of the expression @var{expr} or create a class with\n\ +fields from structure @var{s} and name (string) @var{id}. Additional\n\ +arguments name a list of parent classes from which the new class is\n\ +derived.\n\ @end deftypefn") { octave_value retval; int nargin = args.length (); - if (nargin == 1) + if (nargin == 0) + print_usage (); + else if (nargin == 1) retval = args(0).class_name (); - else if (nargin == 2) + else { Octave_map m = args(0).map_value (); @@ -1192,7 +1290,16 @@ octave_function *fcn = octave_call_stack::caller (); if (fcn && fcn->is_class_constructor ()) - retval = octave_value (new octave_class (m, 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)); + } + } else error ("class: invalid call from outside class constructor"); } @@ -1202,13 +1309,31 @@ else error ("class: expecting structure as first argument"); } + + return retval; +} + +DEFUN (__parent_classes__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __parent_classes__ (@var{x})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval = Cell (); + + if (args.length () == 1) + { + octave_value arg = args(0); + + if (arg.is_object ()) + retval = Cell (arg.parent_class_names ()); + } else print_usage (); return retval; } - DEFUN (isobject, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} isobject (@var{x})\n\ diff -r da58ec8f62e8 -r f914834836e7 src/ov-class.h --- a/src/ov-class.h Mon Mar 23 19:29:01 2009 -0400 +++ b/src/ov-class.h Tue Mar 24 11:29:53 2009 -0400 @@ -55,7 +55,11 @@ : octave_base_value (), map (m), c_name (id) { } octave_class (const octave_class& s) - : octave_base_value (s), map (s.map), c_name (s.c_name) { } + : octave_base_value (s), map (s.map), c_name (s.c_name), + parent_list (s.parent_list) { } + + octave_class (const Octave_map& m, const std::string& id, + const octave_value_list& parents); ~octave_class (void) { } @@ -118,6 +122,11 @@ string_vector map_keys (void) const; + string_vector parent_class_names (void) const + { return string_vector (parent_list); } + + octave_base_value *find_parent_class (const std::string&); + void print (std::ostream& os, bool pr_as_read_syntax = false) const; void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; @@ -165,6 +174,7 @@ static const std::string t_name; std::string c_name; + std::list parent_list; bool in_class_method (void) const; }; diff -r da58ec8f62e8 -r f914834836e7 src/ov.h --- a/src/ov.h Mon Mar 23 19:29:01 2009 -0400 +++ b/src/ov.h Tue Mar 24 11:29:53 2009 -0400 @@ -830,6 +830,13 @@ string_vector map_keys (void) const { return rep->map_keys (); } + string_vector parent_class_names (void) const + { return rep->parent_class_names (); } + + octave_base_value * + find_parent_class (const std::string& parent_class_name) + { return rep->find_parent_class (parent_class_name); } + octave_function *function_value (bool silent = false); const octave_function *function_value (bool silent = false) const;