Mercurial > octave
diff src/pt-fcn-handle.cc @ 8906:ab87d08d9a1b
improve symbol inheritance for anonymous functions
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 03 Mar 2009 14:10:54 -0500 |
parents | 73c4516fae10 |
children | 35cd375d4bb3 |
line wrap: on
line diff
--- a/src/pt-fcn-handle.cc Tue Mar 03 14:02:20 2009 -0500 +++ b/src/pt-fcn-handle.cc Tue Mar 03 14:10:54 2009 -0500 @@ -31,6 +31,7 @@ #include "ov-fcn-handle.h" #include "pt-fcn-handle.h" #include "pager.h" +#include "pt-const.h" #include "pt-walk.h" #include "variables.h" @@ -87,6 +88,9 @@ octave_value tree_anon_fcn_handle::rvalue1 (int) { + // FIXME -- should CMD_LIST be limited to a single expression? + // I think that is what Matlab does. + tree_parameter_list *param_list = parameter_list (); tree_parameter_list *ret_list = return_list (); tree_statement_list *cmd_list = body (); @@ -127,6 +131,21 @@ return fh; } +/* +%!function r = f2 (f, x) +%! r = f (x); +%!function f = f1 (k) +%! f = @(x) f2 (@(y) y-k, x); +%!test +%! assert ((f1 (3)) (10) == 7) +%! +%!shared f, g, h +%! h = @(x) sin (x); +%! g = @(f, x) h (x); +%! f = @() g (@(x) h, pi); +%!assert (f () == sin (pi)) +*/ + octave_value_list tree_anon_fcn_handle::rvalue (int nargout) { @@ -140,6 +159,7 @@ return retval; } +#if 0 tree_expression * tree_anon_fcn_handle::dup (symbol_table::scope_id parent_scope, symbol_table::context_id parent_context) @@ -164,6 +184,55 @@ return new_afh; } +#endif + +tree_expression * +tree_anon_fcn_handle::dup (symbol_table::scope_id, symbol_table::context_id) +{ + // Instead of simply duplicating, transform to a tree_constant + // object that contains an octave_fcn_handle object with the symbol + // table of the referenced function primed with values from the + // current scope and context. + + tree_parameter_list *param_list = parameter_list (); + tree_parameter_list *ret_list = return_list (); + tree_statement_list *cmd_list = body (); + symbol_table::scope_id this_scope = scope (); + + symbol_table::scope_id new_scope = symbol_table::dup_scope (this_scope); + + if (new_scope > 0) + symbol_table::inherit (new_scope, symbol_table::current_scope (), + symbol_table::current_context ()); + + octave_user_function *uf + = new octave_user_function (new_scope, + param_list ? param_list->dup (new_scope, 0) : 0, + ret_list ? ret_list->dup (new_scope, 0) : 0, + cmd_list ? cmd_list->dup (new_scope, 0) : 0); + + octave_function *curr_fcn = octave_call_stack::current (); + + if (curr_fcn) + { + uf->stash_parent_fcn_name (curr_fcn->name ()); + + symbol_table::scope_id parent_scope = curr_fcn->parent_fcn_scope (); + + if (parent_scope < 0) + parent_scope = curr_fcn->scope (); + + uf->stash_parent_fcn_scope (parent_scope); + } + + uf->mark_as_inline_function (); + + octave_value ov_fcn (uf); + + octave_value fh (new octave_fcn_handle (ov_fcn, "@<anonymous>")); + + return new tree_constant (fh, line (), column ()); +} void tree_anon_fcn_handle::accept (tree_walker& tw)