Mercurial > octave-nkf
diff src/ov-fcn-handle.cc @ 9450:cf714e75c656
implement overloaded function handles
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 23 Jul 2009 14:44:30 +0200 |
parents | 0dd3c7a2ba19 |
children | 0c7d84a65386 |
line wrap: on
line diff
--- a/src/ov-fcn-handle.cc Wed Jul 22 15:11:04 2009 +0200 +++ b/src/ov-fcn-handle.cc Thu Jul 23 14:44:30 2009 +0200 @@ -69,7 +69,7 @@ octave_fcn_handle::octave_fcn_handle (const octave_value& f, const std::string& n) - : warn_reload (true), fcn (f), nm (n) + : fcn (f), nm (n) { octave_user_function *uf = fcn.user_function_value (true); @@ -88,27 +88,17 @@ { case '(': { - out_of_date_check (fcn); - - if (fcn.is_defined ()) - { - octave_function *f = function_value (); + int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout; - if (f) - retval = f->subsref (type, idx, nargout); - else - error ("invalid function handle"); - } - else - error ("invalid function handle"); + retval = do_multi_index_op (tmp_nargout, idx.front ()); } break; case '{': case '.': { - std::string typ_nm = type_name (); - error ("%s cannot be indexed with %c", typ_nm.c_str (), type[0]); + std::string tnm = type_name (); + error ("%s cannot be indexed with %c", tnm.c_str (), type[0]); } break; @@ -116,8 +106,66 @@ panic_impossible (); } - // There's no need to call next_subsref here -- - // octave_function::subsref will handle that for us. + // FIXME -- perhaps there should be an + // octave_value_list::next_subsref member function? See also + // octave_builtin::subsref. + + if (idx.size () > 1) + retval = retval(0).next_subsref (nargout, type, idx); + + return retval; +} + +octave_value_list +octave_fcn_handle::do_multi_index_op (int nargout, + const octave_value_list& args) +{ + octave_value_list retval; + + out_of_date_check (fcn); + + if (disp.get () && ! args.empty ()) + { + // Possibly overloaded function. + octave_value ovfcn = fcn; + + // Get dynamic (class) dispatch type. + std::string ddt = get_dispatch_type (args); + + if (ddt.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); + ovfcn = pos->second; + } + } + } + else + { + octave_value method = symbol_table::find_method (nm, ddt); + if (method.is_defined ()) + ovfcn = method; + } + + if (ovfcn.is_defined ()) + retval = ovfcn.do_multi_index_op (nargout, args); + else + error ("invalid function handle"); + } + else + { + // Non-overloaded function (anonymous, subfunction, private function). + if (fcn.is_defined ()) + retval = fcn.do_multi_index_op (nargout, args); + else + error ("invalid function handle"); + } return retval; } @@ -1214,6 +1262,40 @@ 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) { @@ -1348,9 +1430,31 @@ } octave_value f = symbol_table::find_function (tnm); + octave_function *fptr = f.is_defined () ? f.function_value () : 0; - if (f.is_defined ()) - retval = octave_value (new octave_fcn_handle (f, tnm)); + if (fptr) + { + // If it's a subfunction, private function, or class constructor, + // we want no dispatch. + if (fptr->is_nested_function () || fptr->is_private_function () + || fptr->is_class_constructor ()) + retval = octave_value (new octave_fcn_handle (f, tnm)); + else + { + typedef octave_fcn_handle::str_ov_map str_ov_map; + std::auto_ptr<str_ov_map> disp (new str_ov_map); + const string_vector cnames = get_builtin_classes (); + for (octave_idx_type i = 0; i < cnames.length (); i++) + { + std::string cnam = cnames(i); + octave_value method = symbol_table::find_method (tnm, cnam); + if (method.is_defined ()) + (*disp)[cnam] = method; + } + + retval = octave_value (new octave_fcn_handle (f, tnm, disp.release ())); + } + } else error ("error creating function handle \"@%s\"", nm.c_str ()); @@ -1434,6 +1538,8 @@ parentage.elem(1) = fcn->parent_fcn_name (); m.assign ("parentage", octave_value (parentage)); } + else if (fh->is_overloaded ()) + m.assign ("type", "overloaded"); else m.assign ("type", "simple"); }