Mercurial > hg > octave-avbm
diff src/symtab.cc @ 7972:5bf4e2c13ed8
make superiorto and inferiorto work
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 25 Jul 2008 14:25:35 -0400 |
parents | 0d607e8dbbfa |
children | a2ab20ba78f7 |
line wrap: on
line diff
--- 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) {