# HG changeset patch # User John W. Eaton # Date 1217010335 14400 # Node ID 5bf4e2c13ed8560de014765efd8c699eea90fbf5 # Parent dd5cc5016487f81a49b0f17a8127cdabc61a4c6c make superiorto and inferiorto work diff -r dd5cc5016487 -r 5bf4e2c13ed8 src/ChangeLog --- a/src/ChangeLog Thu Jul 24 15:42:40 2008 -0400 +++ b/src/ChangeLog Fri Jul 25 14:25:35 2008 -0400 @@ -1,3 +1,16 @@ +2008-07-25 John W. Eaton + + * symtab.cc (get_dispatch_type): New function. + (symbol_table::fcn_info::fcn_info_rep::find): Use it. + + * ov-class.cc (set_class_relationship): Delete static function. + (Fsuperiorto, Finferiorto): Warn about precedence conflicts. + Call symbol_table::set_class_relationship instead of local static + function. + * symtab.h (symbol_table::class_precedence_table): New data member. + (symbol_table::set_class_relationship, symbol_table::is_superiorto): + New static functions. + 2008-07-24 John W. Eaton * load-path.h (load_path::dir_info::class_info): New struct. diff -r dd5cc5016487 -r 5bf4e2c13ed8 src/ov-class.cc --- a/src/ov-class.cc Thu Jul 24 15:42:40 2008 -0400 +++ b/src/ov-class.cc Fri Jul 25 14:25:35 2008 -0400 @@ -1097,15 +1097,6 @@ return built_in_class_names.find (cn) != built_in_class_names.end (); } -static void -set_class_relationship (const std::string& sup_class, - const std::string& inf_class) -{ - // FIXME - - warning ("class precedence not implemented"); -} - DEFUN (superiorto, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} superiorto (@var{class_name})\n\ @@ -1130,7 +1121,10 @@ { std::string this_class_name = fcn->name (); - set_class_relationship (this_class_name, class_name); + if (! symbol_table::set_class_relationship (this_class_name, + class_name)) + error ("superiorto: precedence already set for %s and %s", + this_class_name.c_str (), class_name.c_str ()); } else { @@ -1174,7 +1168,13 @@ { std::string this_class_name = fcn->name (); - set_class_relationship (class_name, this_class_name); + symbol_table::set_class_relationship (class_name, + this_class_name); + + if (! symbol_table::set_class_relationship (this_class_name, + class_name)) + error ("inferiorto: precedence already set for %s and %s", + this_class_name.c_str (), class_name.c_str ()); } else error ("inferiorto: cannot give user-defined class lower precedence than built-in class"); diff -r dd5cc5016487 -r 5bf4e2c13ed8 src/symtab.cc --- a/src/symtab.cc Thu Jul 24 15:42:40 2008 -0400 +++ b/src/symtab.cc Fri Jul 25 14:25:35 2008 -0400 @@ -53,6 +53,8 @@ std::map symbol_table::fcn_table; +std::map > symbol_table::class_precedence_table; + const symbol_table::scope_id symbol_table::xglobal_scope = 0; const symbol_table::scope_id symbol_table::xtop_scope = 1; @@ -359,6 +361,57 @@ return retval; } +static std::string +get_dispatch_type (const octave_value_list& evaluated_args) +{ + std::string dispatch_type; + + int n = evaluated_args.length (); + + if (n > 0) + { + // Find first object, if any. + + int i; + + for (i = 0; i < n; i++) + { + octave_value arg = evaluated_args(i); + + if (arg.is_object ()) + { + dispatch_type = arg.class_name (); + break; + } + } + + for (int j = i+1; j < n; j++) + { + octave_value arg = evaluated_args(j); + + if (arg.is_object ()) + { + std::string cname = arg.class_name (); + + // Only switch to type of ARG if it is marked superior + // to the current DISPATCH_TYPE. + if (! symbol_table::is_superiorto (dispatch_type, cname) + && symbol_table::is_superiorto (cname, dispatch_type)) + dispatch_type = cname; + } + } + + if (dispatch_type.empty ()) + { + // No object found, so use class of first argument. + + dispatch_type = evaluated_args(0).class_name (); + } + } + + return dispatch_type; +} + // Find the definition of NAME according to the following precedence // list: // @@ -519,25 +572,15 @@ args_evaluated = true; - // FIXME -- need to handle precedence. - - std::string dispatch_type = evaluated_args(0).class_name (); - - for (int i = 1; i < n; i++) + if (n > 0) { - octave_value arg = evaluated_args(i); + std::string dispatch_type = get_dispatch_type (evaluated_args); - if (arg.is_object ()) - { - dispatch_type = arg.class_name (); - break; - } + octave_value fcn = find_method (dispatch_type); + + if (fcn.is_defined ()) + return fcn; } - - octave_value fcn = find_method (dispatch_type); - - if (fcn.is_defined ()) - return fcn; } else return octave_value (); @@ -706,6 +749,65 @@ return function_on_path; } +// Insert INF_CLASS in the set of class names that are considered +// inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently +// marked as superior to SUP_CLASS. + +bool +symbol_table::set_class_relationship (const std::string& sup_class, + const std::string& inf_class) +{ + class_precedence_table_const_iterator p + = class_precedence_table.find (inf_class); + + if (p != class_precedence_table.end ()) + { + const std::set& inferior_classes = p->second; + + std::set::const_iterator q + = inferior_classes.find (sup_class); + + if (q != inferior_classes.end ()) + return false; + } + + class_precedence_table[sup_class].insert (inf_class); + + return true; +} + +// Has class A been marked as superior to class B? Also returns +// TRUE if B has been marked as inferior to A, since we only keep +// one table, and convert inferiort information to a superiorto +// relationship. Two calls are required to determine whether there +// is no relationship between two classes: +// +// if (symbol_table::is_superiorto (a, b)) +// // A is superior to B, or B has been marked inferior to A. +// else if (symbol_table::is_superiorto (b, a)) +// // B is superior to A, or A has been marked inferior to B. +// else +// // No relation. + +bool +symbol_table::is_superiorto (const std::string& a, const std::string& b) +{ + bool retval = false; + + class_precedence_table_const_iterator p = class_precedence_table.find (a); + + if (p != class_precedence_table.end ()) + { + const std::set& inferior_classes = p->second; + std::set::const_iterator q = inferior_classes.find (b); + + if (q != inferior_classes.end ()) + retval = true; + } + + return retval; +} + static std::string fcn_file_name (const octave_value& fcn) { diff -r dd5cc5016487 -r 5bf4e2c13ed8 src/symtab.h --- a/src/symtab.h Thu Jul 24 15:42:40 2008 -0400 +++ b/src/symtab.h Fri Jul 25 14:25:35 2008 -0400 @@ -821,7 +821,7 @@ void clear_user_function (void) { rep->clear_user_function (); } void clear_mex_function (void) { rep->clear_mex_function (); } - + void add_dispatch (const std::string& type, const std::string& fname) { rep->add_dispatch (type, fname); @@ -1396,6 +1396,11 @@ } } + static bool set_class_relationship (const std::string& sup_class, + const std::string& inf_class); + + static bool is_superiorto (const std::string& a, const std::string& b); + static void alias_built_in_function (const std::string& alias, const std::string& name) { @@ -1814,6 +1819,13 @@ // functions, class constructors, class methods, etc.) static std::map fcn_table; + // Mape from class names to set of classes that have lower + // precedence. + static std::map > class_precedence_table; + + typedef std::map >::const_iterator class_precedence_table_const_iterator; + typedef std::map >::iterator class_precedence_table_iterator; + static const scope_id xglobal_scope; static const scope_id xtop_scope;