changeset 5861:2a6cb4ed8f1e

[project @ 2006-06-16 05:09:41 by jwe]
author jwe
date Fri, 16 Jun 2006 05:09:42 +0000
parents b645066d40ad
children 2b35a7fe9302
files src/ChangeLog src/comment-list.cc src/comment-list.h src/parse.y src/pt-arg-list.cc src/pt-arg-list.h src/pt-assign.cc src/pt-assign.h src/pt-binop.cc src/pt-binop.h src/pt-bp.cc src/pt-bp.h src/pt-cell.cc src/pt-cell.h src/pt-check.cc src/pt-check.h src/pt-cmd.cc src/pt-cmd.h src/pt-colon.cc src/pt-colon.h src/pt-const.cc src/pt-const.h src/pt-decl.cc src/pt-decl.h src/pt-except.cc src/pt-except.h src/pt-exp.h src/pt-fcn-handle.cc src/pt-fcn-handle.h src/pt-id.cc src/pt-id.h src/pt-idx.cc src/pt-idx.h src/pt-jump.cc src/pt-jump.h src/pt-loop.cc src/pt-loop.h src/pt-mat.cc src/pt-mat.h src/pt-misc.cc src/pt-misc.h src/pt-pr-code.cc src/pt-pr-code.h src/pt-select.cc src/pt-select.h src/pt-stmt.cc src/pt-stmt.h src/pt-unop.cc src/pt-unop.h src/pt-walk.h src/symtab.cc src/symtab.h
diffstat 52 files changed, 1000 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/ChangeLog	Fri Jun 16 05:09:42 2006 +0000
@@ -1,3 +1,110 @@
+2006-06-16  John W. Eaton  <jwe@octave.org>
+
+	* parse.y (%union): New type, anon_fcn_handle_type.
+	(anon_fcn_handle): Now anon_fcn_handle_type, not tree_constant_type.
+	(make_anon_fcn_handle):	Return tree_anon_fcn_handle, not tree_constant.
+
+	* comment-list.cc (octave_comment_list::dup): New function.
+	* comment-list.h: Provide decl.
+
+	* pt-cmd.cc (tree_no_op_command::dup): New function.
+	* pt-cmd.h: Provide decl.
+	(tree_command::dup): New pure virtual function.
+
+	* pt-loop.cc (tree_while_command::dup, tree_do_until_command::dup,
+	tree_simple_for_command::dup, tree_complex_for_command::dup):
+	New functions.
+	* pt-loop.h: Provide decls.
+
+	* pt-jump.cc (tree_break_command::dup, tree_continue_command::dup,
+	tree_return_command::dup): New functions.
+	* pt-jump.h: Provide decls.
+
+	* pt-except.cc (tree_try_catch_command::dup,
+	tree_unwind_protect_command::dup): New functions.
+	* pt-except.h: Provide decls.
+
+	* pt-select.cc (tree_if_clause::dup, tree_if_command_list::dup,
+	tree_if_command::dup, tree_switch_case::dup,
+	tree_switch_case_list::dup, tree_switch_command::dup):
+	New functions.
+	* pt-select.h: Provide decls.
+
+	* pt-decl.cc (tree_decl_elt::dup, tree_decl_init_list::dup,
+	tree_global_command::dup, tree_static_command::dup): New functions.
+	* pt-decl.h: Provide decls.
+	
+	* pt-exp.h (tree_expression::copy_base): New function.
+	(tree_expression::dup): New pure virtual function.
+	
+	* pt-fcn-handle.cc, pt-fcn-handle.h (tree_anon_fcn_handle): New class.
+
+	* pt-fcn-handle.cc (tree_function_handle::dup): New function.
+	* pt-fcn-handle.h: Provide decl.
+
+	* pt-colon.cc (tree_colon_expression::dup): New function.
+	* pt-colon.h: Provide decl.
+	(tree_colon_expression::tree_colon_expression (tree_expression *,
+	tree_expression *, tree_expression *, int, int)): New constructor.
+	
+	* pt-const.cc (tree_constant::dup): New function.
+	(tree_constant::tree_constant (const octave_value&, const
+	std::string&, int, int)): New constructor.
+	* pt-const.h: Provide decls.
+
+	* pt-idx.cc (tree_index_expression::dup): New functoin.
+	(tree_index_expression::tree_index_expression (int, int)):
+	New constructor.
+	* pt-idx.h: Provide decls.
+
+	* pt-arg-list.cc (tree_argument_list::dup): New function.
+	* pt-arg-list.h: Provide decl.
+
+	* pt-id.cc (tree_identifier::dup): New function.
+	* pt-id.h: Provide decl.
+
+	* pt-cell.cc (tree_cell::dup): New function.
+	* pt-cell.h: Provide decl.
+
+	* pt-mat.cc (tree_matrix::dup): New function.
+	* pt-mat.h: Provide decl.
+
+	* pt-assign.cc (tree_simple_assignment::dup,
+	tree_multi_assignment::dup): New functions.
+	* pt-assign.h: Provide decls.
+
+	* pt-binop.cc (tree_binary_expression::dup,
+	tree_boolean_expression::dup): New functions.
+	* pt-binop.h: Provide decls.
+	
+	* pt-unop.cc (tree_prefix_expression::dup,
+	tree_postfix_expression::dup): New functions.
+	* pt-unop.h: Provide decls.
+
+	* pt-stmt.cc (tree_statement::dup, tree_statement_list::dup):
+	New functions.
+	* pt-stmt.h: Provide decls.
+
+	* pt-misc.cc (tree_parameter_list::dup,
+	tree_return_list::dup): New functions.
+	* pt-misc.h: Provide decls.
+
+	* symtab.cc (symbol_table::dup, symbol_table::inherit,
+	symbol_record:is_automatic_variable): New functions.
+	* symtab.h: Provide decls.
+	(symbol_record::automatic_variable): New data member.
+	(symbol_record::symbol_record): Initialize it.
+	(symbol_record::mark_as_automatic_variable): New function.
+
+	* pt-walk.h (tree_walker::visit_anon_fcn_handle):
+	New pure virtual function.
+	* pt-pr-code.cc (tree_print_code::visit_anon_fcn_handle): New function.
+	* pt-pr-code.h: Provide decl.
+	* pt-bp.cc (tree_breakpoint::visit_anon_fcn_handle): New function.
+	* pt-bp.h: Provide decl.
+	* pt-check.cc (tree_checker::visit_anon_fcn_handle): New function.
+	* pt-check.h: Provide decl.
+
 2006-06-13  John W. Eaton  <jwe@octave.org>
 
 	* pt-stmt.cc (tree_statement_list::eval): Revise previous change
--- a/src/comment-list.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/comment-list.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -32,6 +32,21 @@
 
 octave_comment_buffer *octave_comment_buffer::instance = 0;
 
+octave_comment_list *
+octave_comment_list::dup (void)
+{
+  octave_comment_list *new_cl = new octave_comment_list ();
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      octave_comment_elt elt = *p;
+
+      new_cl->append (elt);
+    }
+
+  return new_cl;
+}
+
 bool
 octave_comment_buffer::instance_ok (void)
 {
--- a/src/comment-list.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/comment-list.h	Fri Jun 16 05:09:42 2006 +0000
@@ -86,12 +86,16 @@
 {
 public:
 
+  octave_comment_list (void) { }
+
   void append (const octave_comment_elt& elt)
     { octave_base_list<octave_comment_elt>::append (elt); }
 
   void append (const std::string& s,
 	       octave_comment_elt::comment_type t = octave_comment_elt::unknown)
     { append (octave_comment_elt (s, t)); }
+
+  octave_comment_list *dup (void);
 };
 
 class
@@ -100,7 +104,7 @@
 public:
 
   octave_comment_buffer (void)
-    : comment_list (new octave_comment_list) { }
+    : comment_list (new octave_comment_list ()) { }
   
   static bool instance_ok (void);
 
--- a/src/parse.y	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/parse.y	Fri Jun 16 05:09:42 2006 +0000
@@ -158,7 +158,7 @@
 make_fcn_handle (token *tok_val);
 
 // Build an anonymous function handle.
-static tree_constant *
+static tree_anon_fcn_handle *
 make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
 
 // Build a binary expression.
@@ -347,6 +347,7 @@
   tree_expression *tree_expression_type;
   tree_constant *tree_constant_type;
   tree_fcn_handle *tree_fcn_handle_type;
+  tree_anon_fcn_handle *tree_anon_fcn_handle_type;
   tree_identifier *tree_identifier_type;
   tree_index_expression *tree_index_expression_type;
   tree_colon_expression *tree_colon_expression_type;
@@ -401,7 +402,8 @@
 %type <comment_type> stash_comment function_beg
 %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep
 %type <tree_type> input
-%type <tree_constant_type> string constant magic_colon anon_fcn_handle
+%type <tree_constant_type> string constant magic_colon
+%type <tree_anon_fcn_handle_type> anon_fcn_handle
 %type <tree_fcn_handle_type> fcn_handle
 %type <tree_matrix_type> matrix_rows matrix_rows1
 %type <tree_cell_type> cell_rows cell_rows1
@@ -1756,7 +1758,7 @@
 
 // Make an anonymous function handle.
 
-static tree_constant *
+static tree_anon_fcn_handle *
 make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt)
 {
   // FIXME -- need to get these from the location of the @ symbol.
@@ -1766,9 +1768,18 @@
 
   tree_parameter_list *ret_list = 0;
 
+  symbol_table *fcn_sym_tab = curr_sym_tab;
+
+  if (symtab_context.empty ())
+    panic_impossible ();
+
+  curr_sym_tab = symtab_context.top ();
+
+  symtab_context.pop ();
+
   if (stmt && stmt->is_expression ())
     {
-      symbol_record *sr = curr_sym_tab->lookup ("__retval__", true);
+      symbol_record *sr = fcn_sym_tab->lookup ("__retval__", true);
 
       tree_expression *e = stmt->expression ();
 
@@ -1793,18 +1804,8 @@
 
   body->mark_as_function_body ();
 
-  octave_value fcn (new octave_user_function (param_list, ret_list,
-					      body, curr_sym_tab));
-
-  if (symtab_context.empty ())
-    panic_impossible ();
-
-  curr_sym_tab = symtab_context.top ();
-  symtab_context.pop ();
-
-  octave_value fh (new octave_fcn_handle (fcn, "@<anonymous>"));
-
-  tree_constant *retval = new tree_constant (fh, l, c);
+  tree_anon_fcn_handle *retval
+    = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_sym_tab, l, c);
 
   return retval;
 }
--- a/src/pt-arg-list.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-arg-list.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -253,6 +253,24 @@
   return retval;
 }
 
+tree_argument_list *
+tree_argument_list::dup (symbol_table *sym_tab)
+{
+  tree_argument_list *new_list = new tree_argument_list ();
+
+  new_list->list_includes_magic_end = list_includes_magic_end;
+  new_list->simple_assign_lhs = simple_assign_lhs;
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_expression *elt = *p;
+
+      new_list->append (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  return new_list;
+}
+
 void
 tree_argument_list::accept (tree_walker& tw)
 {
--- a/src/pt-arg-list.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-arg-list.h	Fri Jun 16 05:09:42 2006 +0000
@@ -78,6 +78,8 @@
 
   string_vector get_arg_names (void) const;
 
+  tree_argument_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-assign.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-assign.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -158,6 +158,19 @@
   return octave_value::assign_op_as_string (etype);
 }
 
+tree_expression *
+tree_simple_assignment::dup (symbol_table *sym_tab)
+{
+  tree_simple_assignment *new_sa
+    = new tree_simple_assignment (lhs ? lhs->dup (sym_tab) : 0,
+				  rhs ? rhs->dup (sym_tab) : 0,
+				  preserve, etype);
+
+  new_sa->copy_base (*this);
+
+  return new_sa;
+}
+
 void
 tree_simple_assignment::accept (tree_walker& tw)
 {
@@ -359,6 +372,19 @@
   return octave_value::assign_op_as_string (etype);
 }
 
+tree_expression *
+tree_multi_assignment::dup (symbol_table *sym_tab)
+{
+  tree_multi_assignment *new_ma
+    = new tree_multi_assignment (lhs ? lhs->dup (sym_tab) : 0,
+				 rhs ? rhs->dup (sym_tab) : 0,
+				 preserve, etype);
+
+  new_ma->copy_base (*this);
+
+  return new_ma;
+}
+
 void
 tree_multi_assignment::accept (tree_walker& tw)
 {
--- a/src/pt-assign.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-assign.h	Fri Jun 16 05:09:42 2006 +0000
@@ -74,6 +74,8 @@
 
   tree_expression *right_hand_side (void) { return rhs; }
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -142,6 +144,8 @@
 
   tree_expression *right_hand_side (void) { return rhs; }
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-binop.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-binop.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -105,6 +105,19 @@
   return octave_value::binary_op_as_string (etype);
 }
 
+tree_expression *
+tree_binary_expression::dup (symbol_table *sym_tab)
+{
+  tree_binary_expression *new_be
+    = new tree_binary_expression (op_lhs ? op_lhs->dup (sym_tab) : 0,
+				  op_rhs ? op_rhs->dup (sym_tab) : 0,
+				  line (), column (), etype);
+
+  new_be->copy_base (*this);
+
+  return new_be;
+}
+
 void
 tree_binary_expression::accept (tree_walker& tw)
 {
@@ -219,6 +232,19 @@
   return retval;
 }
 
+tree_expression *
+tree_boolean_expression::dup (symbol_table *sym_tab)
+{
+  tree_boolean_expression *new_be
+    = new tree_boolean_expression (op_lhs ? op_lhs->dup (sym_tab) : 0,
+				   op_rhs ? op_rhs->dup (sym_tab) : 0,
+				   line (), column (), etype);
+
+  new_be->copy_base (*this);
+
+  return new_be;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-binop.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-binop.h	Fri Jun 16 05:09:42 2006 +0000
@@ -82,6 +82,8 @@
   tree_expression *lhs (void) { return op_lhs; }
   tree_expression *rhs (void) { return op_rhs; }
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 protected:
@@ -137,6 +139,8 @@
 
   type op_type (void) const { return etype; }
 
+  tree_expression *dup (symbol_table *sym_tab);
+
 private:
 
   // The type of the expression.
--- a/src/pt-bp.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-bp.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -430,6 +430,16 @@
     take_action (cmd);
 }
 
+void
+tree_breakpoint::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)
+{
+  if (found)
+    return;
+
+  if (afh.line () >= line)
+    take_action (afh);
+}
+
 void 
 tree_breakpoint::visit_constant (tree_constant& cmd)
 {
--- a/src/pt-bp.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-bp.h	Fri Jun 16 05:09:42 2006 +0000
@@ -94,6 +94,8 @@
 
   void visit_no_op_command (tree_no_op_command&);
 
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
+
   void visit_constant (tree_constant&);
 
   void visit_fcn_handle (tree_fcn_handle&);
--- a/src/pt-cell.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-cell.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -101,6 +101,23 @@
   return retval;
 }
 
+tree_expression *
+tree_cell::dup (symbol_table *sym_tab)
+{
+  tree_cell *new_cell = new tree_cell (0, line (), column ());
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_argument_list *elt = *p;
+
+      append (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  new_cell->copy_base (*this);
+
+  return new_cell;
+}
+
 void
 tree_cell::accept (tree_walker& tw)
 {
--- a/src/pt-cell.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-cell.h	Fri Jun 16 05:09:42 2006 +0000
@@ -52,6 +52,8 @@
 
   octave_value_list rvalue (int);
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-check.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-check.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -306,6 +306,11 @@
 }
 
 void
+tree_checker::visit_anon_fcn_handle (tree_anon_fcn_handle& /* afh */)
+{
+}
+
+void
 tree_checker::visit_constant (tree_constant& /* val */)
 {
 }
--- a/src/pt-check.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-check.h	Fri Jun 16 05:09:42 2006 +0000
@@ -78,6 +78,8 @@
 
   void visit_no_op_command (tree_no_op_command&);
 
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
+
   void visit_constant (tree_constant&);
 
   void visit_fcn_handle (tree_fcn_handle&);
--- a/src/pt-cmd.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-cmd.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -30,6 +30,12 @@
 
 // No-op.
 
+tree_command *
+tree_no_op_command::dup (symbol_table *sym_tab)
+{
+  return new tree_no_op_command (orig_cmd, line (), column ());
+}
+
 void
 tree_no_op_command::accept (tree_walker& tw)
 {
--- a/src/pt-cmd.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-cmd.h	Fri Jun 16 05:09:42 2006 +0000
@@ -27,6 +27,7 @@
 #include <string>
 
 class tree_walker;
+class symbol_table;
 
 #include "pt.h"
 #include "pt-bp.h"
@@ -45,6 +46,8 @@
 
   virtual void eval (void) = 0;
 
+  virtual tree_command *dup (symbol_table *) = 0;
+
 private:
 
   // No copying!
@@ -68,6 +71,8 @@
 
   void eval (void) { MAYBE_DO_BREAKPOINT; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
   std::string original_command (void) { return orig_cmd; }
--- a/src/pt-colon.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-colon.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -209,6 +209,20 @@
 		: -1)));
 }
 
+tree_expression *
+tree_colon_expression::dup (symbol_table *sym_tab)
+{
+  tree_colon_expression *new_ce
+    = new tree_colon_expression (op_base ? op_base->dup (sym_tab) : 0,
+				 op_limit ? op_limit->dup (sym_tab) : 0,
+				 op_increment ? op_increment->dup (sym_tab) : 0,
+				 line (), column ());
+
+  new_ce->copy_base (*new_ce);
+
+  return new_ce;
+}
+
 void
 tree_colon_expression::accept (tree_walker& tw)
 {
--- a/src/pt-colon.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-colon.h	Fri Jun 16 05:09:42 2006 +0000
@@ -49,6 +49,11 @@
     : tree_expression (l, c), op_base (e), op_limit (0),
       op_increment (0), save_base (false) { }
 
+  tree_colon_expression (tree_expression *bas, tree_expression *lim,
+			 tree_expression *inc, int l = -1, int c = -1)
+    : tree_expression (l, c), op_base (bas), op_limit (lim),
+      op_increment (inc), save_base (false) { }
+
   ~tree_colon_expression (void)
     {
       if (! save_base)
@@ -86,6 +91,8 @@
   int line (void) const;
   int column (void) const;
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-const.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-const.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -70,6 +70,17 @@
   return retval;
 }
 
+tree_expression *
+tree_constant::dup (symbol_table *sym_tab)
+{
+  tree_constant *new_tc
+    = new tree_constant (val, orig_text, line (), column ());
+
+  new_tc->copy_base (*this);
+
+  return new_tc;
+}
+
 void
 tree_constant::accept (tree_walker& tw)
 {
--- a/src/pt-const.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-const.h	Fri Jun 16 05:09:42 2006 +0000
@@ -49,6 +49,10 @@
   tree_constant (const octave_value& v, int l = -1, int c = -1)
     : tree_expression (l, c), val (v), orig_text () { }
 
+  tree_constant (const octave_value& v, const std::string& ot,
+		 int l = -1, int c = -1)
+    : tree_expression (l, c), val (v), orig_text (ot) { }
+
   ~tree_constant (void) { }
 
   bool has_magic_end (void) const { return false; }
@@ -79,6 +83,8 @@
 
   octave_value_list rvalue (int nargout);
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
   // Store the original text corresponding to this constant for later
--- a/src/pt-decl.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-decl.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -45,6 +45,13 @@
   delete expr;
 }
 
+tree_decl_elt *
+tree_decl_elt::dup (symbol_table *sym_tab)
+{
+  return new tree_decl_elt (id ? id->dup (sym_tab) : 0,
+			    expr ? expr->dup (sym_tab) : 0);
+}
+
 void
 tree_decl_elt::accept (tree_walker& tw)
 {
@@ -67,6 +74,21 @@
     }
 }
 
+tree_decl_init_list *
+tree_decl_init_list::dup (symbol_table *sym_tab)
+{
+  tree_decl_init_list *new_dil = new tree_decl_init_list ();
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_decl_elt *elt = *p;
+
+      new_dil->append (elt ? elt->dup (sym_tab) : 0);
+    }
+  
+  return new_dil;
+}
+
 void
 tree_decl_init_list::accept (tree_walker& tw)
 {
@@ -133,6 +155,13 @@
 	     line (), column ());
 }
 
+tree_command *
+tree_global_command::dup (symbol_table *sym_tab)
+{
+  return new tree_global_command (init_list ? init_list->dup (sym_tab) : 0,
+				  line (), column ());
+}
+
 // Static.
 
 void
@@ -179,6 +208,13 @@
     }
 }
 
+tree_command *
+tree_static_command::dup (symbol_table *sym_tab)
+{
+  return new tree_static_command (init_list ? init_list->dup (sym_tab) : 0,
+				  line (), column ());
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-decl.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-decl.h	Fri Jun 16 05:09:42 2006 +0000
@@ -54,6 +54,8 @@
 
   tree_expression *expression (void) { return expr; }
 
+  tree_decl_elt *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -92,6 +94,8 @@
 
   void eval (tree_decl_elt::eval_fcn);
 
+  tree_decl_init_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -162,6 +166,8 @@
 
   void eval (void);
 
+  tree_command *dup (symbol_table *sym_tab);
+
 private:
 
   static void do_init (tree_decl_elt& elt);
@@ -190,6 +196,8 @@
 
   void eval (void);
 
+  tree_command *dup (symbol_table *sym_tab);
+
 private:
 
   static void do_init (tree_decl_elt& elt);
--- a/src/pt-except.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-except.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -126,6 +126,17 @@
     }
 }
 
+tree_command *
+tree_try_catch_command::dup (symbol_table *sym_tab)
+{
+  return new tree_try_catch_command (try_code ? try_code->dup (sym_tab) : 0,
+				     catch_code ? catch_code->dup (sym_tab) : 0,
+				     lead_comm ? lead_comm->dup () : 0,
+				     mid_comm ? mid_comm->dup () : 0,
+				     trail_comm ? trail_comm->dup () : 0,
+				     line (), column ());
+}
+
 void
 tree_try_catch_command::accept (tree_walker& tw)
 {
@@ -231,6 +242,18 @@
   unwind_protect::run ();
 }
 
+tree_command *
+tree_unwind_protect_command::dup (symbol_table *sym_tab)
+{
+  return new tree_unwind_protect_command
+    (unwind_protect_code ? unwind_protect_code->dup (sym_tab) : 0,
+     cleanup_code ? cleanup_code->dup (sym_tab) : 0,
+     lead_comm ? lead_comm->dup () : 0,
+     mid_comm ? mid_comm->dup () : 0,
+     trail_comm ? trail_comm->dup () : 0,
+     line (), column ());
+}
+
 void
 tree_unwind_protect_command::accept (tree_walker& tw)
 {
--- a/src/pt-except.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-except.h	Fri Jun 16 05:09:42 2006 +0000
@@ -64,6 +64,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -124,6 +126,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-exp.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-exp.h	Fri Jun 16 05:09:42 2006 +0000
@@ -28,6 +28,7 @@
 
 class octave_value;
 class octave_lvalue;
+class symbol_table;
 
 #include "pt.h"
 
@@ -46,6 +47,8 @@
 
   virtual bool has_magic_end (void) const = 0;
 
+  virtual tree_expression *dup (symbol_table *) = 0;
+
   virtual bool is_constant (void) const { return false; }
 
   virtual bool is_matrix_constant (void) const { return false; }
@@ -104,6 +107,13 @@
       return this;
     }
 
+  virtual void copy_base (tree_expression& e)
+    {
+      num_parens = e.num_parens;
+      postfix_indexed = e.postfix_indexed;
+      print_flag = e.print_flag;
+    }
+
 protected:
 
   // A count of the number of times this expression appears directly
--- a/src/pt-fcn-handle.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-fcn-handle.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -33,6 +33,7 @@
 #include "pt-fcn-handle.h"
 #include "pager.h"
 #include "pt-walk.h"
+#include "variables.h"
 
 void
 tree_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax,
@@ -70,12 +71,96 @@
   return retval;
 }
 
+tree_expression *
+tree_fcn_handle::dup (symbol_table *sym_tab)
+{
+  tree_fcn_handle *new_fh = new tree_fcn_handle (nm, line (), column ());
+
+  new_fh->copy_base (*this);
+
+  return new_fh;
+}
+
 void
 tree_fcn_handle::accept (tree_walker& tw)
 {
   tw.visit_fcn_handle (*this);
 }
 
+tree_anon_fcn_handle::~tree_anon_fcn_handle (void)
+{
+  delete param_list;
+  delete cmd_list;
+  delete ret_list;
+  delete sym_tab;
+}
+
+octave_value
+tree_anon_fcn_handle::rvalue (void)
+{
+  MAYBE_DO_BREAKPOINT;
+
+  symbol_table *new_sym_tab = sym_tab ? sym_tab->dup () : 0;
+
+  if (new_sym_tab)
+    new_sym_tab->inherit (curr_sym_tab);
+
+  tree_parameter_list *new_param_list
+    = param_list ? param_list->dup (new_sym_tab) : 0;
+
+  tree_statement_list *new_cmd_list
+    = cmd_list ? cmd_list->dup (new_sym_tab) : 0;
+
+  tree_parameter_list *new_ret_list
+    = ret_list ? ret_list->dup (new_sym_tab) : 0;
+
+  octave_user_function *uf
+    = new octave_user_function (new_param_list, new_ret_list,
+				new_cmd_list, new_sym_tab);
+
+  octave_value fcn (uf);
+
+  octave_value fh (new octave_fcn_handle (fcn, "@<anonymous>"));
+
+  return fh;
+}
+
+octave_value_list
+tree_anon_fcn_handle::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  if (nargout > 1)
+    error ("invalid number of output arguments for anonymous function handle expression");
+  else
+    retval = rvalue ();
+
+  return retval;
+}
+
+tree_expression *
+tree_anon_fcn_handle::dup (symbol_table *st)
+{
+  tree_anon_fcn_handle *new_afh
+    = new tree_anon_fcn_handle (param_list ? param_list->dup (st) : 0,
+				ret_list ? ret_list->dup (st) : 0,
+				cmd_list ? cmd_list->dup (st) : 0,
+				sym_tab ? sym_tab->dup () : 0,
+				line (), column ());
+
+  new_afh->copy_base (*this);
+
+  return new_afh;
+}
+
+void
+tree_anon_fcn_handle::accept (tree_walker& tw)
+{
+  tw.visit_anon_fcn_handle (*this);
+}
+
+
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-fcn-handle.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-fcn-handle.h	Fri Jun 16 05:09:42 2006 +0000
@@ -29,6 +29,8 @@
 
 #include "pt-bp.h"
 #include "pt-exp.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
 
 class octave_value_list;
 
@@ -65,6 +67,8 @@
 
   octave_value_list rvalue (int nargout);
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -79,6 +83,60 @@
   tree_fcn_handle& operator = (const tree_fcn_handle&);
 };
 
+class
+tree_anon_fcn_handle : public tree_expression
+{
+public:
+
+  tree_anon_fcn_handle (int l = -1, int c = -1)
+    : tree_expression (l, c), param_list (0), cmd_list (0),
+      ret_list (0), sym_tab (0) { }
+
+  tree_anon_fcn_handle (tree_parameter_list *p, tree_parameter_list *r,
+			tree_statement_list *cl, symbol_table *st,
+			int l = -1, int c = -1)
+    : tree_expression (l, c), param_list (p), cmd_list (cl),
+      ret_list (r), sym_tab (st) { }
+
+  ~tree_anon_fcn_handle (void);
+
+  bool has_magic_end (void) const { return false; }
+
+  bool rvalue_ok (void) const { return true; }
+
+  octave_value rvalue (void);
+
+  octave_value_list rvalue (int nargout);
+
+  tree_parameter_list *parameter_list (void) { return param_list; }
+
+  tree_statement_list *body (void) { return cmd_list; }
+
+  tree_expression *dup (symbol_table *sym_tab);
+
+  void accept (tree_walker& tw);
+
+private:
+
+  // The parameter list.
+  tree_parameter_list *param_list;
+
+  // The statement that makes up the body of the function.
+  tree_statement_list *cmd_list;
+
+  // The list of return values.
+  tree_parameter_list *ret_list;
+
+  // The symbol table.
+  symbol_table *sym_tab;
+
+  // No copying!
+
+  tree_anon_fcn_handle (const tree_anon_fcn_handle&);
+
+  tree_anon_fcn_handle& operator = (const tree_anon_fcn_handle&);
+};
+
 #endif
 
 /*
--- a/src/pt-id.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-id.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -212,6 +212,18 @@
   return sym->variable_reference ();
 }
 
+tree_identifier *
+tree_identifier::dup (symbol_table *sym_tab)
+{
+  symbol_record *sr = (sym_tab && sym) ? sym_tab->lookup (sym->name ()) : 0;
+
+  tree_identifier *new_id = new tree_identifier (sr, line (), column ());
+
+  new_id->copy_base (*this);
+
+  return new_id;
+}
+
 void
 tree_identifier::accept (tree_walker& tw)
 {
--- a/src/pt-id.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-id.h	Fri Jun 16 05:09:42 2006 +0000
@@ -89,6 +89,8 @@
 
   void eval_undefined_error (void);
 
+  tree_identifier *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-idx.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-idx.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -41,6 +41,10 @@
 
 // Index expressions.
 
+tree_index_expression::tree_index_expression (int l, int c)
+  : tree_expression (l, c), expr (), args (), type (),
+    arg_nm (), dyn_field () { }
+
 tree_index_expression::tree_index_expression (tree_expression *e,
 					      tree_argument_list *lst,
 					      int l, int c, char t)
@@ -519,6 +523,49 @@
     ::error ("evaluating %s", type_str);
 }
 
+tree_index_expression *
+tree_index_expression::dup (symbol_table *sym_tab)
+{
+  tree_index_expression *new_idx_expr
+    = new tree_index_expression (line (), column ());
+
+  new_idx_expr->expr = expr ? expr->dup (sym_tab) : 0;
+
+  std::list<tree_argument_list *> new_args;
+
+  for (std::list<tree_argument_list *>::iterator p = args.begin ();
+       p != args.end ();
+       p++)
+    {
+      tree_argument_list *elt = *p;
+
+      new_args.push_back (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  new_idx_expr->args = new_args;
+  
+  new_idx_expr->type = type;
+
+  new_idx_expr->arg_nm = arg_nm;
+
+  std::list<tree_expression *> new_dyn_field;
+
+  for (std::list<tree_expression *>::iterator p = dyn_field.begin ();
+       p != dyn_field.end ();
+       p++)
+    {
+      tree_expression *elt = *p;
+
+      new_dyn_field.push_back (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  new_idx_expr->dyn_field = new_dyn_field;
+
+  new_idx_expr->copy_base (*this);
+  
+  return new_idx_expr;
+}
+
 void
 tree_index_expression::accept (tree_walker& tw)
 {
--- a/src/pt-idx.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-idx.h	Fri Jun 16 05:09:42 2006 +0000
@@ -89,6 +89,8 @@
 
   void eval_error (void) const;
 
+  tree_index_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -109,6 +111,8 @@
   // The list of dynamic field names, if any.
   std::list<tree_expression *> dyn_field;
 
+  tree_index_expression (int l = -1, int c = -1);
+
   Octave_map make_arg_struct (void) const;
 
   std::string
--- a/src/pt-jump.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-jump.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -48,6 +48,12 @@
     breaking = 1;
 }
 
+tree_command *
+tree_break_command::dup (symbol_table *)
+{
+  return new tree_break_command (line (), column ());
+}
+
 void
 tree_break_command::accept (tree_walker& tw)
 {
@@ -68,6 +74,12 @@
     continuing = 1;
 }
 
+tree_command *
+tree_continue_command::dup (symbol_table *)
+{
+  return new tree_continue_command (line (), column ());
+}
+
 void
 tree_continue_command::accept (tree_walker& tw)
 {
@@ -88,6 +100,12 @@
     returning = 1;
 }
 
+tree_command *
+tree_return_command::dup (symbol_table *)
+{
+  return new tree_return_command (line (), column ());
+}
+
 void
 tree_return_command::accept (tree_walker& tw)
 {
--- a/src/pt-jump.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-jump.h	Fri Jun 16 05:09:42 2006 +0000
@@ -42,6 +42,8 @@
 
   void eval (void);
 
+  tree_command *dup (symbol_table *);
+
   void accept (tree_walker& tw);
 
   static int breaking;
@@ -69,6 +71,8 @@
 
   void eval (void);
 
+  tree_command *dup (symbol_table *);
+
   void accept (tree_walker& tw);
 
   static int continuing;
@@ -96,6 +100,8 @@
 
   void eval (void);
 
+  tree_command *dup (symbol_table *);
+
   void accept (tree_walker& tw);
 
   static int returning;
--- a/src/pt-loop.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-loop.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -125,6 +125,16 @@
 	   line (), column ());
 }
 
+tree_command *
+tree_while_command::dup (symbol_table *sym_tab)
+{
+  return new tree_while_command (expr ? expr->dup (sym_tab) : 0,
+				 list ? list->dup (sym_tab) : 0,
+				 lead_comm ? lead_comm->dup () : 0,
+				 trail_comm ? trail_comm->dup (): 0,
+				 line (), column ());
+}
+
 void
 tree_while_command::accept (tree_walker& tw)
 {
@@ -178,6 +188,16 @@
 	   line (), column ());
 }
 
+tree_command *
+tree_do_until_command::dup (symbol_table *sym_tab)
+{
+  return new tree_do_until_command (expr ? expr->dup (sym_tab) : 0,
+				    list ? list->dup (sym_tab) : 0,
+				    lead_comm ? lead_comm->dup () : 0,
+				    trail_comm ? trail_comm->dup (): 0,
+				    line (), column ());
+}
+
 void
 tree_do_until_command::accept (tree_walker& tw)
 {
@@ -462,6 +482,17 @@
 	   line (), column ());
 }
 
+tree_command *
+tree_simple_for_command::dup (symbol_table *sym_tab)
+{
+  return new tree_simple_for_command (lhs ? lhs->dup (sym_tab) : 0,
+				      expr ? expr->dup (sym_tab) : 0,
+				      list ? list->dup (sym_tab) : 0,
+				      lead_comm ? lead_comm->dup () : 0,
+				      trail_comm ? trail_comm->dup () : 0,
+				      line (), column ());
+}
+
 void
 tree_simple_for_command::accept (tree_walker& tw)
 {
@@ -572,6 +603,17 @@
 	   line (), column ());
 }
 
+tree_command *
+tree_complex_for_command::dup (symbol_table *sym_tab)
+{
+  return new tree_complex_for_command (lhs ? lhs->dup (sym_tab) : 0,
+				      expr ? expr->dup (sym_tab) : 0,
+				      list ? list->dup (sym_tab) : 0,
+				      lead_comm ? lead_comm->dup () : 0,
+				      trail_comm ? trail_comm->dup () : 0,
+				      line (), column ());
+}
+
 void
 tree_complex_for_command::accept (tree_walker& tw)
 {
--- a/src/pt-loop.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-loop.h	Fri Jun 16 05:09:42 2006 +0000
@@ -78,6 +78,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 protected:
@@ -131,6 +133,8 @@
 
   void eval_error (void);
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -177,6 +181,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -239,6 +245,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-mat.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-mat.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -933,6 +933,23 @@
   return retval;
 }
 
+tree_expression *
+tree_matrix::dup (symbol_table *sym_tab)
+{
+  tree_matrix *new_matrix = new tree_matrix (0, line (), column ());
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_argument_list *elt = *p;
+
+      append (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  new_matrix->copy_base (*this);
+
+  return new_matrix;
+}
+
 void
 tree_matrix::accept (tree_walker& tw)
 {
--- a/src/pt-mat.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-mat.h	Fri Jun 16 05:09:42 2006 +0000
@@ -63,6 +63,8 @@
 
   octave_value_list rvalue (int nargout);
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-misc.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-misc.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -187,6 +187,24 @@
   return status;
 }
 
+tree_parameter_list *
+tree_parameter_list::dup (symbol_table *sym_tab)
+{
+  tree_parameter_list *new_list = new tree_parameter_list ();
+
+  if (takes_varargs ())
+    new_list->mark_varargs ();
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_identifier *elt = *p;
+
+      new_list->append (elt->dup (sym_tab));
+    }
+
+  return new_list;
+}
+
 void
 tree_parameter_list::accept (tree_walker& tw)
 {
@@ -205,6 +223,21 @@
     }
 }
 
+tree_return_list *
+tree_return_list::dup (symbol_table *sym_tab)
+{
+  tree_return_list *new_list = new tree_return_list ();
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_index_expression *elt = *p;
+
+      new_list->append (elt->dup (sym_tab));
+    }
+
+  return new_list;
+}
+
 void
 tree_return_list::accept (tree_walker& tw)
 {
--- a/src/pt-misc.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-misc.h	Fri Jun 16 05:09:42 2006 +0000
@@ -75,6 +75,8 @@
 
   octave_value_list convert_to_const_vector (const Cell& varargout);
 
+  tree_parameter_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -102,6 +104,8 @@
 
   ~tree_return_list (void);
 
+  tree_return_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-pr-code.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-pr-code.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -36,6 +36,30 @@
 #include "pt-all.h"
 
 void
+tree_print_code::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)
+{
+  indent ();
+
+  print_parens (afh, "(");
+
+  os << "@(";
+
+  tree_parameter_list *param_list = afh.parameter_list ();
+
+  if (param_list)
+    param_list->accept (*this);
+
+  os << ") ";
+
+  tree_statement_list *body = afh.body ();
+
+  if (body)
+    body->accept (*this);
+
+  print_parens (afh, ")");
+}
+
+void
 tree_print_code::visit_argument_list (tree_argument_list& lst)
 {
   tree_argument_list::iterator p = lst.begin ();
--- a/src/pt-pr-code.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-pr-code.h	Fri Jun 16 05:09:42 2006 +0000
@@ -53,6 +53,8 @@
 
   ~tree_print_code (void) { }
 
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
+
   void visit_argument_list (tree_argument_list&);
 
   void visit_binary_expression (tree_binary_expression&);
--- a/src/pt-select.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-select.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -59,6 +59,14 @@
   return 0;
 }
 
+tree_if_clause *
+tree_if_clause::dup (symbol_table *sym_tab)
+{
+  return new tree_if_clause (expr ? expr->dup (sym_tab) : 0,
+			     list ? list->dup (sym_tab) : 0,
+			     lead_comm ? lead_comm->dup () : 0);
+}
+
 void
 tree_if_clause::accept (tree_walker& tw)
 {
@@ -79,6 +87,21 @@
     }
 }
 
+tree_if_command_list *
+tree_if_command_list::dup (symbol_table *sym_tab)
+{
+  tree_if_command_list *new_icl = new tree_if_command_list ();
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_if_clause *elt = *p;
+
+      new_icl->append (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  return new_icl;
+}
+
 void
 tree_if_command_list::accept (tree_walker& tw)
 {
@@ -105,6 +128,15 @@
 	     line (), column ());
 }
 
+tree_command *
+tree_if_command::dup (symbol_table *sym_tab)
+{
+  return new tree_if_command (list ? list->dup (sym_tab) : 0,
+			      lead_comm ? lead_comm->dup () : 0,
+			      trail_comm ? trail_comm->dup () : 0,
+			      line (), column ());
+}
+
 void
 tree_if_command::accept (tree_walker& tw)
 {
@@ -210,6 +242,14 @@
   ::error ("evaluating switch case label");
 }
 
+tree_switch_case *
+tree_switch_case::dup (symbol_table *sym_tab)
+{
+  return new tree_switch_case (label ? label->dup (sym_tab) : 0,
+			       list ? list->dup (sym_tab) : 0,
+			       lead_comm ? lead_comm->dup () : 0);
+}
+
 void
 tree_switch_case::accept (tree_walker& tw)
 {
@@ -230,6 +270,21 @@
     }
 }
 
+tree_switch_case_list *
+tree_switch_case_list::dup (symbol_table *sym_tab)
+{
+  tree_switch_case_list *new_scl = new tree_switch_case_list ();
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_switch_case *elt = *p;
+
+      new_scl->append (elt ? elt->dup (sym_tab) : 0);
+    }
+  
+  return new_scl;
+}
+
 void
 tree_switch_case_list::accept (tree_walker& tw)
 {
@@ -276,6 +331,16 @@
 	   line (), column ());
 }
 
+tree_command *
+tree_switch_command::dup (symbol_table *sym_tab)
+{
+  return new tree_switch_command (expr ? expr->dup (sym_tab) : 0,
+				  list ? list->dup (sym_tab) : 0,
+				  lead_comm ? lead_comm->dup () : 0,
+				  trail_comm ? trail_comm->dup () : 0,
+				  line (), column ());
+}
+
 void
 tree_switch_command::accept (tree_walker& tw)
 {
--- a/src/pt-select.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-select.h	Fri Jun 16 05:09:42 2006 +0000
@@ -63,6 +63,8 @@
 
   octave_comment_list *leading_comment (void) { return lead_comm; }
 
+  tree_if_clause *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -104,6 +106,8 @@
 
   void eval (void);
 
+  tree_if_command_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -137,6 +141,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -190,6 +196,8 @@
 
   octave_comment_list *leading_comment (void) { return lead_comm; }
 
+  tree_switch_case *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -231,6 +239,8 @@
 
   void eval (const octave_value& val);
 
+  tree_switch_case_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -271,6 +281,8 @@
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
+  tree_command *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-stmt.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-stmt.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -143,6 +143,22 @@
   return retval;
 }
 
+tree_statement *
+tree_statement::dup (symbol_table *sym_tab)
+{
+  tree_statement *new_stmt = new tree_statement ();
+
+  new_stmt->cmd = cmd ? cmd->dup (sym_tab) : 0;
+
+  new_stmt->expr = expr ? expr->dup (sym_tab) : 0;
+
+  new_stmt->comm = comm ? comm->dup () : 0;
+
+  new_stmt->print_flag = print_flag;
+
+  return new_stmt;
+}
+
 void
 tree_statement::accept (tree_walker& tw)
 {
@@ -251,6 +267,23 @@
   return tbp.get_list ();
 }
 
+tree_statement_list *
+tree_statement_list::dup (symbol_table *sym_tab)
+{
+  tree_statement_list *new_list = new tree_statement_list ();
+
+  new_list->function_body = function_body;
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      tree_statement *elt = *p;
+
+      new_list->append (elt ? elt->dup (sym_tab) : 0);
+    }
+
+  return new_list;
+}
+
 void
 tree_statement_list::accept (tree_walker& tw)
 {
--- a/src/pt-stmt.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-stmt.h	Fri Jun 16 05:09:42 2006 +0000
@@ -82,6 +82,8 @@
 
   void set_expression (tree_expression *e) { expr = e; }
 
+  tree_statement *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -139,6 +141,8 @@
 
   octave_value_list list_breakpoints (void);
 
+  tree_statement_list *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-unop.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-unop.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -120,6 +120,18 @@
 	   oper () . c_str (), line (), column ());
 }
 
+tree_expression *
+tree_prefix_expression::dup (symbol_table *sym_tab)
+{
+  tree_prefix_expression *new_pe
+    = new tree_prefix_expression (op ? op->dup (sym_tab) : 0,
+				  line (), column (), etype);
+
+  new_pe->copy_base (*this);
+
+  return new_pe;
+}
+
 void
 tree_prefix_expression::accept (tree_walker& tw)
 {
@@ -205,6 +217,18 @@
 	   oper () . c_str (), line (), column ());
 }
 
+tree_expression *
+tree_postfix_expression::dup (symbol_table *sym_tab)
+{
+  tree_postfix_expression *new_pe
+    = new tree_postfix_expression (op ? op->dup (sym_tab) : 0,
+				   line (), column (), etype);
+
+  new_pe->copy_base (*this);
+
+  return new_pe;
+}
+
 void
 tree_postfix_expression::accept (tree_walker& tw)
 {
--- a/src/pt-unop.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-unop.h	Fri Jun 16 05:09:42 2006 +0000
@@ -101,6 +101,8 @@
 
   void eval_error (void);
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
@@ -137,6 +139,8 @@
 
   void eval_error (void);
 
+  tree_expression *dup (symbol_table *sym_tab);
+
   void accept (tree_walker& tw);
 
 private:
--- a/src/pt-walk.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/pt-walk.h	Fri Jun 16 05:09:42 2006 +0000
@@ -24,6 +24,7 @@
 #if !defined (octave_tree_walker_h)
 #define octave_tree_walker_h 1
 
+class tree_anon_fcn_handle;
 class tree_argument_list;
 class tree_binary_expression;
 class tree_break_command;
@@ -68,6 +69,9 @@
 public:
 
   virtual void
+  visit_anon_fcn_handle (tree_anon_fcn_handle&) = 0;
+
+  virtual void
   visit_argument_list (tree_argument_list&) = 0;
 
   virtual void
--- a/src/symtab.cc	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/symtab.cc	Fri Jun 16 05:09:42 2006 +0000
@@ -295,6 +295,19 @@
 }
 
 void
+symbol_record::mark_as_automatic_variable (void)
+{
+  if (is_linked_to_global ())
+    error ("can't mark global variable `%s' as automatic variable",
+	   nm.c_str ());
+  else if (is_static ())
+    error ("can't mark static variable `%s' as automatic variable",
+	   nm.c_str ());
+  else
+    automatic_variable = 1;
+}
+
+void
 symbol_record::mark_as_linked_to_global (void)
 {
   if (is_formal_parameter ())
@@ -1651,6 +1664,73 @@
     }
 }
 
+// Create a new symbol table with the same entries.  Only the symbol
+// names and some attributes are copied, not values.
+
+symbol_table *
+symbol_table::dup (void)
+{
+  symbol_table *new_sym_tab = new symbol_table (table_size);
+
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  std::string nm = ptr->name ();
+
+	  symbol_record *sr = new_sym_tab->lookup (nm, true);
+
+	  if (sr)
+	    {
+	      if (ptr->is_formal_parameter ())
+		sr->mark_as_formal_parameter ();
+
+	      if (ptr->is_automatic_variable ())
+		sr->mark_as_automatic_variable ();
+
+	      if (ptr->is_static ())
+		sr->mark_as_static ();
+	    }
+
+	  ptr = ptr->next ();
+	}
+    }
+
+  return new_sym_tab;
+}
+
+void
+symbol_table::inherit (symbol_table *parent_sym_tab)
+{
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  std::string nm = ptr->name ();
+
+	  if (! (nm == "__retval__"
+		 || ptr->is_automatic_variable ()
+		 || ptr->is_formal_parameter ()))
+	    {
+	      symbol_record *sr = parent_sym_tab->lookup (nm);
+
+	      if (sr)
+		{
+		  ptr->define (sr->variable_value ());
+
+		  ptr->mark_as_static ();
+		}
+	    }
+
+	  ptr = ptr->next ();
+	}
+    }
+}
+
 void
 symbol_table::print_info (std::ostream& os) const
 {
--- a/src/symtab.h	Fri Jun 16 05:01:39 2006 +0000
+++ b/src/symtab.h	Fri Jun 16 05:09:42 2006 +0000
@@ -256,19 +256,19 @@
   typedef int (*change_function) (void);
 
   symbol_record (void)
-    : formal_param (false), linked_to_global (false),
-      tagged_static (false), can_hide_function (true),
-      visible (true), nm (), chg_fcn (0),
+    : formal_param (false), automatic_variable (false),
+      linked_to_global (false), tagged_static (false),
+      can_hide_function (true), visible (true), nm (), chg_fcn (0),
       definition (new symbol_def ()), next_elem (0) { }
 
   // FIXME -- kluge alert!  We obviously need a better way of
   // handling allow_shadow!
 
   symbol_record (const std::string& n, symbol_record *nxt)
-    : formal_param (false), linked_to_global (false),
-      tagged_static (false), can_hide_function (n != "__end__"),
-      visible (true), nm (n), chg_fcn (0),
-      definition (new symbol_def ()), next_elem (nxt) { }
+    : formal_param (false), automatic_variable (false),
+      linked_to_global (false), tagged_static (false),
+      can_hide_function (n != "__end__"), visible (true), nm (n),
+      chg_fcn (0), definition (new symbol_def ()), next_elem (nxt) { }
 
   ~symbol_record (void)
     {
@@ -359,6 +359,9 @@
   void mark_as_formal_parameter (void);
   bool is_formal_parameter (void) const { return formal_param; }
 
+  void mark_as_automatic_variable (void);
+  bool is_automatic_variable (void) const { return automatic_variable; }
+
   void mark_as_linked_to_global (void);
   bool is_linked_to_global (void) const { return linked_to_global; }
 
@@ -433,6 +436,7 @@
 private:
 
   unsigned int formal_param : 1;
+  unsigned int automatic_variable : 1;
   unsigned int linked_to_global : 1;
   unsigned int tagged_static : 1;
   unsigned int can_hide_function : 1;
@@ -581,6 +585,13 @@
 
   void pop_context (void);
 
+  // Create a new symbol table with the same entries.  Only the symbol
+  // names and some attributes are copied, not values.
+  symbol_table *dup (void);
+
+  // Inherit some values from the parent_sym_tab.
+  void inherit (symbol_table *parent_sym_tab);
+
   void print_info (std::ostream& os) const;
 
 private: