Mercurial > hg > octave-terminal
changeset 7972:5bf4e2c13ed8
make superiorto and inferiorto work
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 25 Jul 2008 14:25:35 -0400 |
parents | dd5cc5016487 |
children | e69bca367ed7 |
files | src/ChangeLog src/ov-class.cc src/symtab.cc src/symtab.h |
diffstat | 4 files changed, 155 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2008-07-25 John W. Eaton <jwe@octave.org> + + * 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 <jwe@octave.org> * load-path.h (load_path::dir_info::class_info): New struct.
--- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -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");
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -53,6 +53,8 @@ std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table; +std::map<std::string, std::set<std::string> > 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<std::string>& inferior_classes = p->second; + + std::set<std::string>::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<std::string>& inferior_classes = p->second; + std::set<std::string>::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) {
--- a/src/symtab.h +++ b/src/symtab.h @@ -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<std::string, fcn_info> fcn_table; + // Mape from class names to set of classes that have lower + // precedence. + static std::map<std::string, std::set<std::string> > class_precedence_table; + + typedef std::map<std::string, std::set<std::string> >::const_iterator class_precedence_table_const_iterator; + typedef std::map<std::string, std::set<std::string> >::iterator class_precedence_table_iterator; + static const scope_id xglobal_scope; static const scope_id xtop_scope;