Mercurial > hg > octave-lyh
changeset 10087:090173f2db40
improve overload dispatching of built-in classes
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Tue, 12 Jan 2010 13:20:17 +0100 |
parents | 76df75b10c80 |
children | 5edee330d4cb |
files | src/ChangeLog src/ov-base.cc src/ov-base.h src/ov-cell.h src/ov-fcn-handle.cc src/ov-fcn-handle.h src/ov-struct.h src/symtab.cc src/symtab.h |
diffstat | 9 files changed, 155 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2010-01-12 Jaroslav Hajek <highegg@gmail.com> + + * ov-base.h (builtin_type_t): New enum constants: btyp_cell, + btyp_struct and btyp_func_handle. + (btyp_isinteger, btyp_isfloat, btyp_isarray): New funcs. + (btyp_class_name): New array. + (get_builtin_classes): New func. + * ov-cell.h (octave_cell::builtin_type): New virtual override. + * ov-struct.h (octave_struct::builtin_type): New virtual override. + * ov-fcn-handle.h (octave_fcn_handle::builtin_type): New virtual override. + * symtab.cc (get_dispatch_type): Rewrite. Add overload. + * symtab.h: Update decls. + * ov-fcn-handle.cc (octave_fcn_handle::do_multi_index_op): Rewrite. + (get_builtin_classes): Remove. + 2010-01-12 Jaroslav Hajek <highegg@gmail.com> * oct-obj.cc (octave_value_list::any_cell): New method.
--- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -78,6 +78,36 @@ return retval; } +std::string btyp_class_name[btyp_num_types] = +{ + "double", "single", "double", "single", + "int8", "int16", "int32", "int64", + "uint8", "uint16", "uint32", "uint64", + "logical", "char", + "struct", "cell", "function_handle" +}; + +string_vector +get_builtin_classes (void) +{ + static string_vector retval; + + if (retval.is_empty ()) + { + int n = btyp_num_types - 2; + retval = string_vector (n); + int j = 0; + for (int i = 0; i < btyp_num_types; i++) + { + builtin_type_t ityp = static_cast<builtin_type_t> (i); + if (ityp != btyp_complex && ityp != btyp_float_complex) + retval(j++) = btyp_class_name[i]; + } + } + + return retval; +} + DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value, "<unknown type>", "unknown");
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -71,13 +71,31 @@ btyp_uint64, btyp_bool, btyp_char, + btyp_struct, + btyp_cell, + btyp_func_handle, btyp_unknown, btyp_num_types = btyp_unknown }; +extern OCTINTERP_API std::string +btyp_class_name [btyp_num_types]; + +extern OCTINTERP_API string_vector +get_builtin_classes (void); + inline bool btyp_isnumeric (builtin_type_t btyp) { return btyp <= btyp_uint64; } +inline bool btyp_isinteger (builtin_type_t btyp) +{ return btyp >= btyp_int8 && btyp <= btyp_uint64; } + +inline bool btyp_isfloat (builtin_type_t btyp) +{ return btyp <= btyp_float_complex; } + +inline bool btyp_isarray (builtin_type_t btyp) +{ return btyp <= btyp_char; } + // Compute a numeric type for a possibly mixed-type operation, using these rules: // bool -> double // single + double -> single
--- a/src/ov-cell.h +++ b/src/ov-cell.h @@ -119,6 +119,8 @@ bool is_cell (void) const { return true; } + builtin_type_t builtin_type (void) const { return btyp_cell; } + bool is_cellstr (void) const; bool is_true (void) const;
--- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -131,36 +131,24 @@ // Possibly overloaded function. octave_value ovfcn = fcn; + // No need to compute built-in class dispatch if we don't have builtin class overloads. + bool builtin_class = ! disp->empty (); // Get dynamic (class) dispatch type. - std::string ddt = get_dispatch_type (args); + std::string dt = get_dispatch_type (args, builtin_class); - if (ddt.empty ()) + if (! dt.empty ()) { - // Static dispatch (class of 1st arg)? - if (! disp->empty ()) - { - std::string sdt = args(0).class_name (); - str_ov_map::iterator pos = disp->find (sdt); - if (pos != disp->end ()) - { - out_of_date_check (pos->second, sdt, false); - ovfcn = pos->second; - } - } - } - else - { - str_ov_map::iterator pos = disp->find (ddt); + str_ov_map::iterator pos = disp->find (dt); if (pos != disp->end ()) { - out_of_date_check (pos->second, ddt, false); + out_of_date_check (pos->second, dt, false); ovfcn = pos->second; } - else + else if (! builtin_class) { - octave_value method = symbol_table::find_method (nm, ddt); + octave_value method = symbol_table::find_method (nm, dt); if (method.is_defined ()) - (*disp)[ddt] = ovfcn = method; + (*disp)[dt] = ovfcn = method; } } @@ -168,10 +156,10 @@ retval = ovfcn.do_multi_index_op (nargout, args); else if (fcn.is_undefined ()) { - if (ddt.empty ()) - ddt = args(0).class_name (); + if (dt.empty ()) + dt = args(0).class_name (); - error ("no %s method to handle class %s", nm.c_str (), ddt.c_str ()); + error ("no %s method to handle class %s", nm.c_str (), dt.c_str ()); } else error ("invalid function handle"); @@ -1336,40 +1324,6 @@ current_print_indent_level ()); } -static string_vector -get_builtin_classes (void) -{ - // FIXME: this should really be read from somewhere else. - static const char *cnames[15] = { - "double", - "single", - "int8", - "int16", - "int32", - "int64", - "uint8", - "uint16", - "uint32", - "uint64", - "logical", - "char", - "cell", - "struct", - "function_handle" - }; - - static string_vector retval; - - if (retval.is_empty ()) - { - retval = string_vector (15); - for (int i = 0; i < 15; i++) - retval(i) = cnames[i]; - } - - return retval; -} - octave_value make_fcn_handle (const std::string& nm, bool local_funcs) {
--- a/src/ov-fcn-handle.h +++ b/src/ov-fcn-handle.h @@ -87,6 +87,8 @@ bool is_function_handle (void) const { return true; } + builtin_type_t builtin_type (void) const { return btyp_func_handle; } + bool is_overloaded (void) const { return disp.get () && ! disp->empty (); } dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; }
--- a/src/ov-struct.h +++ b/src/ov-struct.h @@ -120,6 +120,8 @@ bool is_map (void) const { return true; } + builtin_type_t builtin_type (void) const { return btyp_struct; } + Octave_map map_value (void) const { return map; } string_vector map_keys (void) const { return map.keys (); }
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -448,9 +448,38 @@ return retval; } +// :-) JWE, can you parse this? Returns a 2D array with second dimension equal +// to btyp_num_types (static constant). Only the leftmost dimension can be +// variable in C/C++. Typedefs are boring. + +static builtin_type_t (*build_sup_table (void))[btyp_num_types] +{ + static builtin_type_t sup_table[btyp_num_types][btyp_num_types]; + for (int i = 0; i < btyp_num_types; i++) + for (int j = 0; j < btyp_num_types; j++) + { + builtin_type_t ityp = static_cast<builtin_type_t> (i); + builtin_type_t jtyp = static_cast<builtin_type_t> (j); + // FIXME: Is this really right? + bool use_j = + (jtyp == btyp_func_handle || ityp == btyp_bool + || (btyp_isarray (ityp) + && (! btyp_isarray (jtyp) + || (btyp_isinteger (jtyp) && ! btyp_isinteger (ityp)) + || ((ityp == btyp_double || ityp == btyp_complex || ityp == btyp_char) + && (jtyp == btyp_float || jtyp == btyp_float_complex))))); + + sup_table[i][j] = use_j ? jtyp : ityp; + } + + return sup_table; +} + std::string -get_dispatch_type (const octave_value_list& args) +get_dispatch_type (const octave_value_list& args, + bool& builtin_class) { + static builtin_type_t (*sup_table)[btyp_num_types] = build_sup_table (); std::string dispatch_type; int n = args.length (); @@ -459,39 +488,62 @@ { // Find first object, if any. - int i; - - for (i = 0; i < n; i++) + for (int i = 0; i < n; i++) { octave_value arg = args(i); if (arg.is_object ()) { dispatch_type = arg.class_name (); - break; + for (int j = i+1; j < n; j++) + { + octave_value arg1 = args(j); + + if (arg1.is_object ()) + { + std::string cname = arg1.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; + } + } + + builtin_class = false; + break; } } - for (int j = i+1; j < n; j++) - { - octave_value arg = args(j); + // No object. - if (arg.is_object ()) - { - std::string cname = arg.class_name (); + if (builtin_class) + { + // Use the builtin_type mechanism to do this by one method call per + // element. - // 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; - } - } + builtin_type_t btyp = args(0).builtin_type (); + for (int i = 1; i < n; i++) + btyp = sup_table[btyp][args(i).builtin_type ()]; + + if (btyp != btyp_unknown) + dispatch_type = btyp_class_name[btyp]; + else + builtin_class = false; + } } return dispatch_type; } +std::string +get_dispatch_type (const octave_value_list& args) +{ + bool builtin_class = true; + return get_dispatch_type (args, builtin_class); +} + // Find the definition of NAME according to the following precedence // list: // @@ -639,9 +691,6 @@ { std::string dispatch_type = get_dispatch_type (args); - if (dispatch_type.empty ()) - dispatch_type = args(0).class_name (); - octave_value fcn = find_method (dispatch_type); if (fcn.is_defined ())
--- a/src/symtab.h +++ b/src/symtab.h @@ -2370,7 +2370,10 @@ const std::string& dispatch_type = std::string (), bool check_relative = true); -extern std::string get_dispatch_type (const octave_value_list& args); +extern OCTINTERP_API std::string +get_dispatch_type (const octave_value_list& args); +extern OCTINTERP_API std::string +get_dispatch_type (const octave_value_list& args, bool& builtin_class); #endif