Mercurial > hg > octave-lojdl
changeset 9450:cf714e75c656
implement overloaded function handles
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 23 Jul 2009 14:44:30 +0200 |
parents | a35d8ec8a0c4 |
children | 350148cc0774 |
files | src/ChangeLog src/DLD-FUNCTIONS/bsxfun.cc src/DLD-FUNCTIONS/cellfun.cc src/ov-fcn-handle.cc src/ov-fcn-handle.h src/symtab.cc src/symtab.h |
diffstat | 7 files changed, 478 insertions(+), 364 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,23 @@ +2009-07-23 Jaroslav Hajek <highegg@gmail.com> + + * symtab.cc (get_dispatch_type): Omit first-arg dispatch, export. + * symtab.h (get_dispatch_type): Provide decl. + * ov-fcn-handle.h (octave_fcn_handle::warn_reload): Delete. + (octave_fcn_handle::disp): New field. + (octave_fcn_handle::str_ov_map): New typedef. + (octave_fcn_handle::octave_fcn_handle (..., str_ov_map *)): New + constructor. + (octave_fcn_handle::do_multi_index_op): New method decl. + (octave_fcn_handle::is_overloaded): New method. + * ov-fcn-handle.cc + (octave_fcn_handle::do_multi_index_op): New method. + (octave_fcn_handle::subsref): Rewrite using do_multi_index_op. + (octave_fcn_handle::make_fcn_handle): Construct overloaded handles if + appropriate. + (Ffunctions): Indicate (statically) overloaded handles. + * DLD-FUNCTIONS/cellfun.cc (Fcellfun): Update & modernize. + * DLD-FUNCTIONS/bsxfun.cc (Fbsxfun): Ditto. + 2009-07-22 Jaroslav Hajek <highegg@gmail.com> * symtab.cc (symbol_table::find,
--- a/src/DLD-FUNCTIONS/bsxfun.cc +++ b/src/DLD-FUNCTIONS/bsxfun.cc @@ -148,24 +148,17 @@ print_usage (); else { - octave_function *func = 0; - std::string name; - std::string fcn_name; + octave_value func = args(0); - if (args(0).is_function_handle () || args(0).is_inline_function ()) - func = args(0).function_value (); - else if (args(0).is_string ()) - { - name = args(0).string_value (); - fcn_name = unique_symbol_name ("__bsxfun_fcn_"); - std::string fname = "function y = "; - fname.append (fcn_name); - fname.append ("(x) y = "); - func = extract_function (args(0), "bsxfun", fcn_name, fname, - "; endfunction"); - } - else - error ("bsxfun: first argument must be a string or function handle"); + if (func.is_string ()) + { + std::string name = func.string_value (); + func = symbol_table::find_function (name); + if (func.is_undefined ()) + error ("bsxfun: invalid function name: %s", name.c_str ()); + } + else if (! (args(0).is_function_handle () || args(0).is_inline_function ())) + error ("bsxfun: first argument must be a string or function handle"); if (! error_state) { @@ -207,14 +200,14 @@ octave_value_list inputs; inputs (0) = A; inputs (1) = B; - retval = feval (func, inputs, 1); + retval = func.do_multi_index_op (1, inputs); } else if (dvc.numel () < 1) { octave_value_list inputs; inputs (0) = A.resize (dvc); inputs (1) = B.resize (dvc); - retval = feval (func, inputs, 1); + retval = func.do_multi_index_op (1, inputs); } else { @@ -257,7 +250,7 @@ if (maybe_update_column (Bc, B, dvb, dvc, i, idxB)) inputs (1) = Bc; - octave_value_list tmp = feval (func, inputs, 1); + octave_value_list tmp = func.do_multi_index_op (1, inputs); if (error_state) break; @@ -454,9 +447,6 @@ } } } - - if (! fcn_name.empty ()) - clear_function (fcn_name); } return retval;
--- a/src/DLD-FUNCTIONS/cellfun.cc +++ b/src/DLD-FUNCTIONS/cellfun.cc @@ -267,8 +267,6 @@ @end deftypefn") { octave_value_list retval; - std::string name = "function"; - octave_function *func = 0; int nargin = args.length (); nargout = (nargout < 1 ? 1 : nargout); @@ -279,20 +277,7 @@ return retval; } - if (args(0).is_function_handle () || args(0).is_inline_function ()) - { - func = args(0).function_value (); - - if (error_state) - return retval; - } - else if (args(0).is_string ()) - name = args(0).string_value (); - else - { - error ("cellfun: first argument must be a string or function handle"); - return retval; - } + octave_value func = args(0); if (! args(1).is_cell ()) { @@ -305,334 +290,327 @@ octave_idx_type k = f_args.numel (); - if (name == "isempty") - { - boolNDArray result (f_args.dims ()); - for (octave_idx_type count = 0; count < k ; count++) - result(count) = f_args.elem(count).is_empty (); - retval(0) = result; - } - else if (name == "islogical") - { - boolNDArray result (f_args.dims ()); - for (octave_idx_type count= 0; count < k ; count++) - result(count) = f_args.elem(count).is_bool_type (); - retval(0) = result; - } - else if (name == "isreal") - { - boolNDArray result (f_args.dims ()); - for (octave_idx_type count= 0; count < k ; count++) - result(count) = f_args.elem(count).is_real_type (); - retval(0) = result; - } - else if (name == "length") - { - NDArray result (f_args.dims ()); - for (octave_idx_type count= 0; count < k ; count++) - result(count) = static_cast<double> (f_args.elem(count).length ()); - retval(0) = result; - } - else if (name == "ndims") + if (func.is_string ()) { - NDArray result (f_args.dims ()); - for (octave_idx_type count = 0; count < k ; count++) - result(count) = static_cast<double> (f_args.elem(count).ndims ()); - retval(0) = result; - } - else if (name == "prodofsize" || name == "numel") - { - NDArray result (f_args.dims ()); - for (octave_idx_type count = 0; count < k ; count++) - result(count) = static_cast<double> (f_args.elem(count).numel ()); - retval(0) = result; - } - else if (name == "size") - { - if (nargin == 3) + std::string name = func.string_value (); + if (name.find_first_of ("(x)") != std::string::npos) + warning ("cellfun: passing function body as string is no longer supported." + " Use @ or `inline'."); + + if (name == "isempty") + { + boolNDArray result (f_args.dims ()); + for (octave_idx_type count = 0; count < k ; count++) + result(count) = f_args.elem(count).is_empty (); + retval(0) = result; + } + else if (name == "islogical") + { + boolNDArray result (f_args.dims ()); + for (octave_idx_type count= 0; count < k ; count++) + result(count) = f_args.elem(count).is_bool_type (); + retval(0) = result; + } + else if (name == "isreal") + { + boolNDArray result (f_args.dims ()); + for (octave_idx_type count= 0; count < k ; count++) + result(count) = f_args.elem(count).is_real_type (); + retval(0) = result; + } + else if (name == "length") + { + NDArray result (f_args.dims ()); + for (octave_idx_type count= 0; count < k ; count++) + result(count) = static_cast<double> (f_args.elem(count).length ()); + retval(0) = result; + } + else if (name == "ndims") { - int d = args(2).nint_value () - 1; - - if (d < 0) - error ("cellfun: third argument must be a positive integer"); - - if (! error_state) + NDArray result (f_args.dims ()); + for (octave_idx_type count = 0; count < k ; count++) + result(count) = static_cast<double> (f_args.elem(count).ndims ()); + retval(0) = result; + } + else if (name == "prodofsize" || name == "numel") + { + NDArray result (f_args.dims ()); + for (octave_idx_type count = 0; count < k ; count++) + result(count) = static_cast<double> (f_args.elem(count).numel ()); + retval(0) = result; + } + else if (name == "size") + { + if (nargin == 3) { - NDArray result (f_args.dims ()); - for (octave_idx_type count = 0; count < k ; count++) + int d = args(2).nint_value () - 1; + + if (d < 0) + error ("cellfun: third argument must be a positive integer"); + + if (! error_state) { - dim_vector dv = f_args.elem(count).dims (); - if (d < dv.length ()) - result(count) = static_cast<double> (dv(d)); - else - result(count) = 1.0; + NDArray result (f_args.dims ()); + for (octave_idx_type count = 0; count < k ; count++) + { + dim_vector dv = f_args.elem(count).dims (); + if (d < dv.length ()) + result(count) = static_cast<double> (dv(d)); + else + result(count) = 1.0; + } + retval(0) = result; } + } + else + error ("not enough arguments for `size'"); + } + else if (name == "isclass") + { + if (nargin == 3) + { + std::string class_name = args(2).string_value(); + boolNDArray result (f_args.dims ()); + for (octave_idx_type count = 0; count < k ; count++) + result(count) = (f_args.elem(count).class_name() == class_name); + retval(0) = result; } + else + error ("not enough arguments for `isclass'"); } else - error ("not enough arguments for `size'"); + { + func = symbol_table::find_function (name); + if (func.is_undefined ()) + error ("cellfun: invalid function name: %s", name.c_str ()); + } } - else if (name == "isclass") - { - if (nargin == 3) - { - std::string class_name = args(2).string_value(); - boolNDArray result (f_args.dims ()); - for (octave_idx_type count = 0; count < k ; count++) - result(count) = (f_args.elem(count).class_name() == class_name); - - retval(0) = result; - } - else - error ("not enough arguments for `isclass'"); - } - else + + if (error_state || ! retval.empty ()) + return retval; + + if (func.is_function_handle () || func.is_inline_function () + || func.is_function ()) { unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); unwind_protect::protect_var (buffer_error_messages); - std::string fcn_name; - - if (! func) - { - fcn_name = unique_symbol_name ("__cellfun_fcn_"); - std::string fname = "function y = "; - fname.append (fcn_name); - fname.append ("(x) y = "); - func = extract_function (args(0), "cellfun", fcn_name, fname, - "; endfunction"); - } + octave_value_list inputlist; + bool uniform_output = true; + octave_value error_handler; + int offset = 1; + int i = 1; + OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin); + // This is to prevent copy-on-write. + const Cell *cinputs = inputs; - if (! func) - error ("unknown function"); - else - { - octave_value_list inputlist; - bool uniform_output = true; - bool have_error_handler = false; - std::string err_name; - octave_function *error_handler = 0; - int offset = 1; - int i = 1; - OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin); - // This is to prevent copy-on-write. - const Cell *cinputs = inputs; + while (i < nargin) + { + if (args(i).is_string()) + { + std::string arg = args(i++).string_value(); + if (i == nargin) + { + error ("cellfun: parameter value is missing"); + goto cellfun_err; + } - while (i < nargin) - { - if (args(i).is_string()) - { - std::string arg = args(i++).string_value(); - if (i == nargin) - { - error ("cellfun: parameter value is missing"); - goto cellfun_err; - } - - std::transform (arg.begin (), arg.end (), - arg.begin (), tolower); - - if (arg == "uniformoutput") - uniform_output = args(i++).bool_value(); - else if (arg == "errorhandler") - { - if (args(i).is_function_handle () || - args(i).is_inline_function ()) - { - error_handler = args(i).function_value (); + std::transform (arg.begin (), arg.end (), + arg.begin (), tolower); - if (error_state) - goto cellfun_err; - } - else if (args(i).is_string ()) - { - err_name = unique_symbol_name ("__cellfun_fcn_"); - std::string fname = "function y = "; - fname.append (fcn_name); - fname.append ("(x) y = "); - error_handler = extract_function (args(i), "cellfun", - err_name, fname, - "; endfunction"); - } - - if (! error_handler) - goto cellfun_err; + if (arg == "uniformoutput") + uniform_output = args(i++).bool_value(); + else if (arg == "errorhandler") + { + if (args(i).is_function_handle () || + args(i).is_inline_function ()) + { + error_handler = args(i++); + } + else if (args(i).is_string ()) + { + std::string err_name = args(i++).string_value (); + error_handler = symbol_table::find_function (err_name); + if (error_handler.is_undefined ()) + { + error ("cellfun: invalid function name: %s", err_name.c_str ()); + goto cellfun_err; + } + } + else + { + error ("invalid errorhandler value"); + goto cellfun_err; + } + } + else + { + error ("cellfun: unrecognized parameter %s", + arg.c_str()); + goto cellfun_err; + } - have_error_handler = true; - i++; - } - else - { - error ("cellfun: unrecognized parameter %s", - arg.c_str()); - goto cellfun_err; - } - offset += 2; - } - else - { - inputs[i-offset] = args(i).cell_value (); - if (f_args.dims() != inputs[i-offset].dims()) - { - error ("cellfun: Dimension mismatch"); - goto cellfun_err; + offset += 2; + } + else + { + inputs[i-offset] = args(i).cell_value (); + if (f_args.dims() != inputs[i-offset].dims()) + { + error ("cellfun: Dimension mismatch"); + goto cellfun_err; + + } + i++; + } + } - } - i++; - } - } + nargin -= offset; + inputlist.resize(nargin); - nargin -= offset; - inputlist.resize(nargin); - - if (have_error_handler) - buffer_error_messages++; + if (error_handler.is_defined ()) + buffer_error_messages++; - if (uniform_output) - { - OCTAVE_LOCAL_BUFFER (std::auto_ptr<scalar_col_helper>, retptr, nargout); + if (uniform_output) + { + OCTAVE_LOCAL_BUFFER (std::auto_ptr<scalar_col_helper>, retptr, nargout); - for (octave_idx_type count = 0; count < k ; count++) - { - for (int j = 0; j < nargin; j++) - inputlist(j) = cinputs[j](count); + for (octave_idx_type count = 0; count < k ; count++) + { + for (int j = 0; j < nargin; j++) + inputlist(j) = cinputs[j](count); - octave_value_list tmp = feval (func, inputlist, nargout); + octave_value_list tmp = func.do_multi_index_op (nargout, inputlist); - if (error_state && have_error_handler) - { - Octave_map msg; - msg.assign ("identifier", last_error_id ()); - msg.assign ("message", last_error_message ()); - msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1)))); - octave_value_list errlist = inputlist; - errlist.prepend (msg); - buffer_error_messages--; - error_state = 0; - tmp = feval (error_handler, errlist, nargout); - buffer_error_messages++; + if (error_state && error_handler.is_defined ()) + { + Octave_map msg; + msg.assign ("identifier", last_error_id ()); + msg.assign ("message", last_error_message ()); + msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1)))); + octave_value_list errlist = inputlist; + errlist.prepend (msg); + buffer_error_messages--; + error_state = 0; + tmp = error_handler.do_multi_index_op (nargout, errlist); + buffer_error_messages++; - if (error_state) - goto cellfun_err; - } + if (error_state) + goto cellfun_err; + } - if (tmp.length() < nargout) - { - error ("cellfun: too many output arguments"); - goto cellfun_err; - } + if (tmp.length() < nargout) + { + error ("cellfun: too many output arguments"); + goto cellfun_err; + } - if (error_state) - break; + if (error_state) + break; - if (count == 0) - { - for (int j = 0; j < nargout; j++) - { - octave_value val = tmp(j); + if (count == 0) + { + for (int j = 0; j < nargout; j++) + { + octave_value val = tmp(j); - if (val.numel () == 1) - retptr[j].reset (make_col_helper (val, f_args.dims ())); - else - { - error ("cellfun: expecting all values to be scalars for UniformOutput = true"); - break; - } - } - } - else - { - for (int j = 0; j < nargout; j++) - { - octave_value val = tmp(j); + if (val.numel () == 1) + retptr[j].reset (make_col_helper (val, f_args.dims ())); + else + { + error ("cellfun: expecting all values to be scalars for UniformOutput = true"); + break; + } + } + } + else + { + for (int j = 0; j < nargout; j++) + { + octave_value val = tmp(j); - if (! retptr[j]->collect (count, val)) - { - // FIXME: A more elaborate structure would allow again a virtual - // constructor here. - retptr[j].reset (new scalar_col_helper_def (retptr[j]->result (), - f_args.dims ())); - retptr[j]->collect (count, val); - } + if (! retptr[j]->collect (count, val)) + { + // FIXME: A more elaborate structure would allow again a virtual + // constructor here. + retptr[j].reset (new scalar_col_helper_def (retptr[j]->result (), + f_args.dims ())); + retptr[j]->collect (count, val); } - } + } + } - if (error_state) - break; - } + if (error_state) + break; + } - retval.resize (nargout); - for (int j = 0; j < nargout; j++) - { - if (retptr[j].get ()) - retval(j) = retptr[j]->result (); - else - retval(j) = Matrix (); - } - } - else - { - OCTAVE_LOCAL_BUFFER (Cell, results, nargout); - for (int j = 0; j < nargout; j++) - results[j].resize(f_args.dims()); + retval.resize (nargout); + for (int j = 0; j < nargout; j++) + { + if (retptr[j].get ()) + retval(j) = retptr[j]->result (); + else + retval(j) = Matrix (); + } + } + else + { + OCTAVE_LOCAL_BUFFER (Cell, results, nargout); + for (int j = 0; j < nargout; j++) + results[j].resize(f_args.dims()); - for (octave_idx_type count = 0; count < k ; count++) - { - for (int j = 0; j < nargin; j++) - inputlist(j) = cinputs[j](count); + for (octave_idx_type count = 0; count < k ; count++) + { + for (int j = 0; j < nargin; j++) + inputlist(j) = cinputs[j](count); - octave_value_list tmp = feval (func, inputlist, nargout); + octave_value_list tmp = func.do_multi_index_op (nargout, inputlist); - if (error_state && have_error_handler) - { - Octave_map msg; - msg.assign ("identifier", last_error_id ()); - msg.assign ("message", last_error_message ()); - msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1)))); - octave_value_list errlist = inputlist; - errlist.prepend (msg); - buffer_error_messages--; - error_state = 0; - tmp = feval (error_handler, errlist, nargout); - buffer_error_messages++; + if (error_state && error_handler.is_defined ()) + { + Octave_map msg; + msg.assign ("identifier", last_error_id ()); + msg.assign ("message", last_error_message ()); + msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1)))); + octave_value_list errlist = inputlist; + errlist.prepend (msg); + buffer_error_messages--; + error_state = 0; + tmp = error_handler.do_multi_index_op (nargout, errlist); + buffer_error_messages++; - if (error_state) - goto cellfun_err; - } + if (error_state) + goto cellfun_err; + } - if (tmp.length() < nargout) - { - error ("cellfun: too many output arguments"); - goto cellfun_err; - } + if (tmp.length() < nargout) + { + error ("cellfun: too many output arguments"); + goto cellfun_err; + } - if (error_state) - break; + if (error_state) + break; - for (int j = 0; j < nargout; j++) - results[j](count) = tmp(j); - } - - retval.resize(nargout); - for (int j = 0; j < nargout; j++) - retval(j) = results[j]; - } + for (int j = 0; j < nargout; j++) + results[j](count) = tmp(j); + } - cellfun_err: - if (error_state) - retval = octave_value_list(); + retval.resize(nargout); + for (int j = 0; j < nargout; j++) + retval(j) = results[j]; + } - if (! fcn_name.empty ()) - clear_function (fcn_name); - - if (! err_name.empty ()) - clear_function (err_name); - } +cellfun_err: + if (error_state) + retval = octave_value_list(); unwind_protect::run_frame (uwp_frame); } + else + error ("cellfun: first argument must be a string or function handle"); return retval; }
--- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -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"); }
--- a/src/ov-fcn-handle.h +++ b/src/ov-fcn-handle.h @@ -25,6 +25,7 @@ #include <iosfwd> #include <string> +#include <memory> #include "oct-alloc.h" @@ -39,18 +40,29 @@ OCTINTERP_API octave_fcn_handle : public octave_base_value { +private: + + typedef std::map<std::string, octave_value> str_ov_map; + + octave_fcn_handle (const octave_value& f, const std::string& n, + str_ov_map *sdisp) + : fcn (f), nm (n), disp (sdisp) { } + public: octave_fcn_handle (void) - : warn_reload (true), fcn (), nm () { } + : fcn (), nm () { } octave_fcn_handle (const std::string& n) - : warn_reload (true), fcn (), nm (n) { } + : fcn (), nm (n) { } octave_fcn_handle (const octave_value& f, const std::string& n); octave_fcn_handle (const octave_fcn_handle& fh) - : octave_base_value (fh), warn_reload (fh.warn_reload), - fcn (fh.fcn), nm (fh.nm) { } + : octave_base_value (fh), fcn (fh.fcn), nm (fh.nm) + { + if (fh.disp.get ()) + disp.reset (new str_ov_map (*fh.disp)); + } ~octave_fcn_handle (void) { } @@ -68,10 +80,15 @@ const std::list<octave_value_list>& idx, int nargout); + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& args); + bool is_defined (void) const { return true; } bool is_function_handle (void) const { return true; } + bool is_overloaded (void) const { return disp.get () && ! disp->empty (); } + dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; } octave_function *function_value (bool = false) @@ -116,11 +133,6 @@ DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA - // If TRUE, print a warning if the pointed-to fucntion is out of - // date. This variable may be removed when updating is properly - // implemented. - mutable bool warn_reload; - protected: // The function we are handling. @@ -128,6 +140,12 @@ // The name of the handle, including the "@". std::string nm; + + // A pointer to statical dispatch to standard classes. If null, we don't want + // to dispatch at all. + std::auto_ptr<str_ov_map> disp; + + friend octave_value make_fcn_handle (const std::string &); }; extern octave_value make_fcn_handle (const std::string& nm);
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -283,16 +283,18 @@ } bool -out_of_date_check (octave_value& function) +out_of_date_check (octave_value& function, + const std::string& dispatch_type) { - return out_of_date_check_internal (function); + return out_of_date_check_internal (function, dispatch_type); } bool -out_of_date_check (octave_function* fcn) +out_of_date_check (octave_function* fcn, + const std::string& dispatch_type) { octave_value function; - return out_of_date_check_internal (fcn, function); + return out_of_date_check_internal (fcn, function, dispatch_type); } octave_value @@ -423,7 +425,7 @@ return retval; } -static std::string +std::string get_dispatch_type (const octave_value_list& args) { std::string dispatch_type; @@ -462,13 +464,6 @@ dispatch_type = cname; } } - - if (dispatch_type.empty ()) - { - // No object found, so use class of first argument. - - dispatch_type = args(0).class_name (); - } } return dispatch_type; @@ -621,6 +616,9 @@ { 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 @@ -2316,9 +2316,13 @@ void do_cache_name (const std::string& name) { table_name = name; } }; -extern bool out_of_date_check (octave_value& function); - -extern bool out_of_date_check (octave_function* fcn); +extern bool out_of_date_check (octave_value& function, + const std::string& dispatch_type = std::string ()); + +extern bool out_of_date_check (octave_function* fcn, + const std::string& dispatch_type = std::string ()); + +extern std::string get_dispatch_type (const octave_value_list& args); #endif