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)