Problem with recursive function handles with new symbol table code

View: New views
3 Messages — Rating Filter:   Alert me  

Problem with recursive function handles with new symbol table code

by David Bateman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The function

function y = testrecursionfunc (f, x, n)
  functions(f);

  if (nargin < 3)
    n = 0;
  endif
  if (n > 2)
    y = f (x);
  else
    n++;
    y = testrecursionfunc (@(x) f(2*x), x, n);
  endif
endfunction

demonstrates an issue with the function handles with the new symbol
table code. With 3.0.1 this returns

octave:1> testrecursionfunc (@(x) x, 1)
ans =
{
  function = @(x) x
  type = anonymous
  file =
}

ans =
{
  function = @(x) f (2 * x)
  type = anonymous
  file =
  workspace =
  {
    f =

@(x) x

  }

}

ans =
{
  function = @(x) f (2 * x)
  type = anonymous
  file =
  workspace =
  {
    f =

@(x) f (2 * x)

  }

}

ans =  4

whereas with the current repository it returns

octave:1> testrecursionfunc(@(x) x, 1)
ans =
{
  function = @(x) x
  type = anonymous
  file =
}

ans =
{
  function = @(x) f (2 * x)
  type = anonymous
  file =
}

ans =
{
  function = @(x) f (2 * x)
  type = anonymous
  file =
}

error: `f' undefined near line 12 column 33
error: evaluating argument list element number 1
error: called from `?unknown?'
error: evaluating assignment expression near line 9, column 7
error: evaluating if command near line 8, column 3
error: called from `testrecursionfunc' in file
`/home/adb014/nobackup/perso/octave/testrecursionfunc.m'
error: evaluating assignment expression near line 12, column 7
error: evaluating if command near line 8, column 3
error: called from `testrecursionfunc' in file
`/home/adb014/nobackup/perso/octave/testrecursionfunc.m'
error: evaluating assignment expression near line 12, column 7
error: evaluating if command near line 8, column 3
error: called from `testrecursionfunc' in file
`/home/adb014/nobackup/perso/octave/testrecursionfunc.m'

It seems the workspace with recursive function handles is being lost
somewhere. This is an issue for me since it means that I can't do
variable substitution on a function handle to avoid singularities in a
quadrature, or at least not for a double integral. It seems to work for
the first recursion even if the workspace of the function handle is not
shown by functions and so I can do variable substitution on a 1-D integral.

I don't really understand yet the new symbol table code, so I have no
ideas what is causing this issue.

Regards
David

--
David Bateman                                David.Bateman@...
Motorola Labs - Paris                        +33 1 69 35 48 04 (Ph)
Parc Les Algorithmes, Commune de St Aubin    +33 6 72 01 06 33 (Mob)
91193 Gif-Sur-Yvette FRANCE                  +33 1 69 35 77 01 (Fax)

The information contained in this communication has been classified as:

[x] General Business Information
[ ] Motorola Internal Use Only
[ ] Motorola Confidential Proprietary

_______________________________________________
Bug-octave mailing list
Bug-octave@...
https://www.cae.wisc.edu/mailman/listinfo/bug-octave

Problem with recursive function handles with new symbol table code

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On  7-May-2008, David Bateman wrote:

| The function
|
| function y = testrecursionfunc (f, x, n)
|   functions(f);
|
|   if (nargin < 3)
|     n = 0;
|   endif
|   if (n > 2)
|     y = f (x);
|   else
|     n++;
|     y = testrecursionfunc (@(x) f(2*x), x, n);
|   endif
| endfunction
|
| demonstrates an issue with the function handles with the new symbol
| table code. With 3.0.1 this returns

OK, I see the problem, but I don't think the fix is trivial and I'm
busy at the moment so it may take a few days for me to find the time
to fix it properly.

jwe
_______________________________________________
Bug-octave mailing list
Bug-octave@...
https://www.cae.wisc.edu/mailman/listinfo/bug-octave

Problem with recursive function handles with new symbol table code

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On  7-May-2008, John W. Eaton wrote:

| OK, I see the problem, but I don't think the fix is trivial and I'm
| busy at the moment so it may take a few days for me to find the time
| to fix it properly.

Try the following patch.  I think it will fix the problem you
reported, but I'm still not happy with the way scope (the symbols for
a given function) and context (the variable values visible at a
particular call depth) is handled.  I need to think more about how to
do this in a better way.

 One thing I know that is still broken is

  function f (n)
    if (n == 0)
      f (n + 1)
      x
    else
      evalin ('caller', 'x = 13;');
    end
  end
  f (0)

This should print

  x =  13

but it fails.  It's not really a regression though, because it also
failed in Octave 3.0 (and probably all previous versions of Octave)
though the failure was different.

I think everything necessary to make this work is now present in the
symbol table code and the octave_call_stack class from toplev.h, but I
haven't updated evalin yet.

So, I wouldn't be surprised to find other bugs related to recursion,
scoping, and function handles...

jwe



# HG changeset patch
# User John W. Eaton <jwe@...>
# Date 1210182330 14400
# Node ID 71f068b22fccc42d7a55b2cb379887eda29406eb
# Parent  fc81e027c53c487657f0799289f1ee82131c8e95
scope and context fixes for function handles

diff --git a/src/ChangeLog b/src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,67 @@ 2008-05-06  David Bateman  <dbateman@fre
+2008-05-07  John W. Eaton  <jwe@...>
+
+ * pt-arg-list.cc, pt-arg-list.h (tree_argument_list::dup):
+ New arg, context.
+ * pt-assign.cc, pt-assign.h (tree_simple_assignment::dup,
+ tree_multi_assignment::dup): Likewise.
+ * pt-binop.cc, pt-binop.h (tree_binary_expression::dup,
+ tree_boolean_expression::dup): Likewise.
+ * pt-cell.cc, pt-cell.h (tree_cell::dup): Likewise.
+ * pt-cmd.cc, pt-cmd.h (tree_no_op_command::dup,
+ tree_function_def::dup): Likewise.
+ * pt-colon.cc, pt-colon.h (tree_colon_expression::dup): Likewise.
+ * pt-const.cc, pt-const.h (tree_constant::dup): Likewise.
+ * pt-decl.cc, pt-decl.h (tree_decl_elt::dup, tree_decl_init_list::dup,
+ tree_global_command::dup, tree_static_command::dup): Likewise.
+ * pt-except.cc, pt-except.h (tree_try_catch_command::dup,
+ tree_unwind_protect_command::dup): Likewise.
+ * pt-exp.h (tree_expression:dup): Likewise.
+ * pt-fcn-handle.cc, pt-exp.h (tree_expression:dup): Likewise.
+ * pt-fcn-handle.h (tree_fcn_handle::dup,
+ tree_anon_fcn_handle::dup): Likewise.
+ * pt-id.cc, pt-id.h (tree_identifier::dup): Likewise.
+ * pt-idx.cc, pt-idx.h (tree_index_expression::dup): Likewise.
+ * pt-jump.cc, pt-jump.h (tree_break_command::dup,
+ tree_continue_command::dup, tree_return_command::dup): Likewise.
+ * pt-loop.cc, pt-loop.h (tree_while_command::dup,
+ tree_do_until_command::dup, tree_simple_for_command::dup,
+ tree_complex_for_command::dup): Likewise.
+ * pt-mat.cc, pt-mat.h (tree_matrix::dup): Likewise.
+ * pt-misc.cc, pt-misc.h (tree_parameter_list::dup,
+ tree_return_list::dup): Likewise.
+ * pt-select.cc, pt-select.h (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, tree_statement::dup,
+ tree_statement_list::dup, tree_prefix_expression::dup,
+ tree_postfix_expression::dup): Likewise.
+
+ * ov-fcn-handle.cc (octave_fcn_handle::save_ascii,
+ octave_fcn_handle::save_binary, octave_fcn_handle::save_hdf5):
+ Pass context to symbol_table::all_variables.
+ * load-save.cc (dump_octave_core): Likewise.
+ * ov-fcn-handle.cc (Ffunctions): Don't skip anonymous functions
+ with the name set to the text of the function body.
+ Pass context to symbol_table::all_variables and
+ symbol_table::symbol_record::varval.
+
+ * symtab.h (symbol_table::varref, symbol_table::do_varref,
+ symbol_table::varval, symbol_table::do_varval,
+ symbol_table::all_variables, symbol_table::do_all_variables,
+ symbol_table::symbol_record::varref,
+ symbol_table::symbol_record::varval,
+ symbol_table::symbol_record::is_defined,
+ symbol_table::symbol_record::is_variable,
+ symbol_table::symbol_record::symbol_record_rep::varref,
+ symbol_table::symbol_record::symbol_record_rep::varval,
+ symbol_table::symbol_record::symbol_record_rep::is_defined,
+ symbol_table::symbol_record::symbol_record_rep::is_variable,
+ ):
+ * symtab.h (symbol_table::do_inherit): New arg, donor_context.
+ Look for value in donor_contxt.  Set value in base context.
+ * symtab.cc (symbol_table::symbol_record::symbol_record_rep::dump):
+ Pass xcurrent_context to varval.
+
 2008-05-06  David Bateman  <dbateman@...>
 
  * ov-fcn-inline.cc (Finline): Also ignore NaN, Inf, pi, NA and eps.
diff --git a/src/load-save.cc b/src/load-save.cc
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -1270,7 +1270,8 @@ dump_octave_core (std::ostream& os, cons
 {
   write_header (os, fmt);
 
-  std::list<symbol_table::symbol_record> vars = symbol_table::all_variables ();
+  std::list<symbol_table::symbol_record> vars
+    = symbol_table::all_variables (symbol_table::top_scope (), 0);
 
   double save_mem_size = 0;
 
diff --git a/src/ov-fcn-handle.cc b/src/ov-fcn-handle.cc
--- a/src/ov-fcn-handle.cc
+++ b/src/ov-fcn-handle.cc
@@ -242,7 +242,7 @@ octave_fcn_handle::save_ascii (std::ostr
       octave_user_function *f = fcn.user_function_value ();
 
       std::list<symbol_table::symbol_record> vars
- = symbol_table::all_variables (f->scope ());
+ = symbol_table::all_variables (f->scope (), 0);
 
       size_t varlen = vars.size ();
 
@@ -410,7 +410,7 @@ octave_fcn_handle::save_binary (std::ost
       octave_user_function *f = fcn.user_function_value ();
 
       std::list<symbol_table::symbol_record> vars
- = symbol_table::all_variables (f->scope ());
+ = symbol_table::all_variables (f->scope (), 0);
 
       size_t varlen = vars.size ();
 
@@ -654,7 +654,7 @@ octave_fcn_handle::save_hdf5 (hid_t loc_
       octave_user_function *f = fcn.user_function_value ();
 
       std::list<symbol_table::symbol_record> vars
- = symbol_table::all_variables (f->scope ());
+ = symbol_table::all_variables (f->scope (), 0);
 
       size_t varlen = vars.size ();
 
@@ -1276,41 +1276,36 @@ Return a struct containing information a
 
       std::string nm = fcn->fcn_file_name ();
 
-      if (nm.empty ())
+      if (fh_nm == "@<anonymous>")
  {
-  if (fh_nm == "@<anonymous>")
+  m.assign ("file", nm);
+
+  octave_user_function *fu = fh->user_function_value ();
+
+  std::list<symbol_table::symbol_record> vars
+    = symbol_table::all_variables (fu->scope (), 0);
+
+  size_t varlen = vars.size ();
+
+  if (varlen > 0)
     {
-      m.assign ("file", "");
+      Octave_map ws;
+      for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin ();
+   p != vars.end (); p++)
+ {
+  ws.assign (p->name (), p->varval (0));
+ }
 
-      octave_user_function *fu = fh->user_function_value ();
-
-      std::list<symbol_table::symbol_record> vars
- = symbol_table::all_variables (fu->scope ());
-
-      size_t varlen = vars.size ();
-
-      if (varlen > 0)
- {
-  Octave_map ws;
-  for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin ();
-       p != vars.end (); p++)
-    {
-      ws.assign (p->name (), p->varval ());
-    }
-
-  m.assign ("workspace", ws);
- }
+      m.assign ("workspace", ws);
     }
-  else if (fcn->is_user_function () || fcn->is_user_script ())
-    {
-      octave_function *fu = fh->function_value ();
-      m.assign ("file", fu->fcn_file_name ());
-    }
-  else
-    m.assign ("file", "");
+ }
+      else if (fcn->is_user_function () || fcn->is_user_script ())
+ {
+  octave_function *fu = fh->function_value ();
+  m.assign ("file", fu->fcn_file_name ());
  }
       else
- m.assign ("file", nm);
+ m.assign ("file", "");
 
       retval = m;
     }
@@ -1387,6 +1382,21 @@ Return a function handle constructed fro
 }
 
 /*
+%!function y = testrecursionfunc (f, x, n)
+%!  if (nargin < 3)
+%!    n = 0;
+%!  endif
+%!  if (n > 2)
+%!    y = f (x);
+%!  else
+%!    n++;
+%!    y = testrecursionfunc (@(x) f(2*x), x, n);
+%!  endif
+%!test
+%! assert (testrecursionfunc (@(x) x, 1), 8);
+*/
+
+/*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
 ;;; End: ***
diff --git a/src/pt-arg-list.cc b/src/pt-arg-list.cc
--- a/src/pt-arg-list.cc
+++ b/src/pt-arg-list.cc
@@ -253,7 +253,8 @@ tree_argument_list::get_arg_names (void)
 }
 
 tree_argument_list *
-tree_argument_list::dup (symbol_table::scope_id scope)
+tree_argument_list::dup (symbol_table::scope_id scope,
+ symbol_table::context_id context)
 {
   tree_argument_list *new_list = new tree_argument_list ();
 
@@ -264,7 +265,7 @@ tree_argument_list::dup (symbol_table::s
     {
       tree_expression *elt = *p;
 
-      new_list->append (elt ? elt->dup (scope) : 0);
+      new_list->append (elt ? elt->dup (scope, context) : 0);
     }
 
   return new_list;
diff --git a/src/pt-arg-list.h b/src/pt-arg-list.h
--- a/src/pt-arg-list.h
+++ b/src/pt-arg-list.h
@@ -78,7 +78,8 @@ public:
 
   string_vector get_arg_names (void) const;
 
-  tree_argument_list *dup (symbol_table::scope_id scope);
+  tree_argument_list *dup (symbol_table::scope_id scope,
+   symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-assign.cc b/src/pt-assign.cc
--- a/src/pt-assign.cc
+++ b/src/pt-assign.cc
@@ -289,11 +289,12 @@ tree_simple_assignment::oper (void) cons
 }
 
 tree_expression *
-tree_simple_assignment::dup (symbol_table::scope_id scope)
+tree_simple_assignment::dup (symbol_table::scope_id scope,
+     symbol_table::context_id context)
 {
   tree_simple_assignment *new_sa
-    = new tree_simple_assignment (lhs ? lhs->dup (scope) : 0,
-  rhs ? rhs->dup (scope) : 0,
+    = new tree_simple_assignment (lhs ? lhs->dup (scope, context) : 0,
+  rhs ? rhs->dup (scope, context) : 0,
   preserve, etype);
 
   new_sa->copy_base (*this);
@@ -516,11 +517,12 @@ tree_multi_assignment::oper (void) const
 }
 
 tree_expression *
-tree_multi_assignment::dup (symbol_table::scope_id scope)
+tree_multi_assignment::dup (symbol_table::scope_id scope,
+    symbol_table::context_id context)
 {
   tree_multi_assignment *new_ma
-    = new tree_multi_assignment (lhs ? lhs->dup (scope) : 0,
- rhs ? rhs->dup (scope) : 0,
+    = new tree_multi_assignment (lhs ? lhs->dup (scope, context) : 0,
+ rhs ? rhs->dup (scope, context) : 0,
  preserve, etype);
 
   new_ma->copy_base (*this);
diff --git a/src/pt-assign.h b/src/pt-assign.h
--- a/src/pt-assign.h
+++ b/src/pt-assign.h
@@ -73,7 +73,8 @@ public:
 
   tree_expression *right_hand_side (void) { return rhs; }
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -143,7 +144,8 @@ public:
 
   tree_expression *right_hand_side (void) { return rhs; }
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
   
diff --git a/src/pt-binop.cc b/src/pt-binop.cc
--- a/src/pt-binop.cc
+++ b/src/pt-binop.cc
@@ -106,11 +106,12 @@ tree_binary_expression::oper (void) cons
 }
 
 tree_expression *
-tree_binary_expression::dup (symbol_table::scope_id scope)
+tree_binary_expression::dup (symbol_table::scope_id scope,
+     symbol_table::context_id context)
 {
   tree_binary_expression *new_be
-    = new tree_binary_expression (op_lhs ? op_lhs->dup (scope) : 0,
-  op_rhs ? op_rhs->dup (scope) : 0,
+    = new tree_binary_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
+  op_rhs ? op_rhs->dup (scope, context) : 0,
   line (), column (), etype);
 
   new_be->copy_base (*this);
@@ -233,11 +234,12 @@ tree_boolean_expression::oper (void) con
 }
 
 tree_expression *
-tree_boolean_expression::dup (symbol_table::scope_id scope)
+tree_boolean_expression::dup (symbol_table::scope_id scope,
+      symbol_table::context_id context)
 {
   tree_boolean_expression *new_be
-    = new tree_boolean_expression (op_lhs ? op_lhs->dup (scope) : 0,
-   op_rhs ? op_rhs->dup (scope) : 0,
+    = new tree_boolean_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
+   op_rhs ? op_rhs->dup (scope, context) : 0,
    line (), column (), etype);
 
   new_be->copy_base (*this);
diff --git a/src/pt-binop.h b/src/pt-binop.h
--- a/src/pt-binop.h
+++ b/src/pt-binop.h
@@ -83,7 +83,8 @@ public:
   tree_expression *lhs (void) { return op_lhs; }
   tree_expression *rhs (void) { return op_rhs; }
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -140,7 +141,8 @@ public:
 
   type op_type (void) const { return etype; }
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
 private:
 
diff --git a/src/pt-cell.cc b/src/pt-cell.cc
--- a/src/pt-cell.cc
+++ b/src/pt-cell.cc
@@ -102,7 +102,8 @@ tree_cell::rvalue (int nargout)
 }
 
 tree_expression *
-tree_cell::dup (symbol_table::scope_id scope)
+tree_cell::dup (symbol_table::scope_id scope,
+ symbol_table::context_id context)
 {
   tree_cell *new_cell = new tree_cell (0, line (), column ());
 
@@ -110,7 +111,7 @@ tree_cell::dup (symbol_table::scope_id s
     {
       tree_argument_list *elt = *p;
 
-      new_cell->append (elt ? elt->dup (scope) : 0);
+      new_cell->append (elt ? elt->dup (scope, context) : 0);
     }
 
   new_cell->copy_base (*this);
diff --git a/src/pt-cell.h b/src/pt-cell.h
--- a/src/pt-cell.h
+++ b/src/pt-cell.h
@@ -53,7 +53,8 @@ public:
 
   octave_value_list rvalue (int);
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-cmd.cc b/src/pt-cmd.cc
--- a/src/pt-cmd.cc
+++ b/src/pt-cmd.cc
@@ -31,7 +31,8 @@ along with Octave; see the file COPYING.
 // No-op.
 
 tree_command *
-tree_no_op_command::dup (symbol_table::scope_id)
+tree_no_op_command::dup (symbol_table::scope_id,
+ symbol_table::context_id context)
 {
   return new tree_no_op_command (orig_cmd, line (), column ());
 }
@@ -63,7 +64,8 @@ tree_function_def::eval (void)
 }
 
 tree_command *
-tree_function_def::dup (symbol_table::scope_id)
+tree_function_def::dup (symbol_table::scope_id,
+ symbol_table::context_id context)
 {
   return new tree_function_def (fcn, line (), column ());
 }
diff --git a/src/pt-cmd.h b/src/pt-cmd.h
--- a/src/pt-cmd.h
+++ b/src/pt-cmd.h
@@ -47,7 +47,8 @@ public:
 
   virtual void eval (void) = 0;
 
-  virtual tree_command *dup (symbol_table::scope_id) = 0;
+  virtual tree_command *dup (symbol_table::scope_id,
+     symbol_table::context_id context) = 0;
 
 private:
 
@@ -72,7 +73,8 @@ public:
 
   void eval (void) { MAYBE_DO_BREAKPOINT; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -103,7 +105,8 @@ public:
 
   void eval (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-colon.cc b/src/pt-colon.cc
--- a/src/pt-colon.cc
+++ b/src/pt-colon.cc
@@ -210,13 +210,14 @@ tree_colon_expression::column (void) con
 }
 
 tree_expression *
-tree_colon_expression::dup (symbol_table::scope_id scope)
+tree_colon_expression::dup (symbol_table::scope_id scope,
+    symbol_table::context_id context)
 {
-  tree_colon_expression *new_ce
-    = new tree_colon_expression (op_base ? op_base->dup (scope) : 0,
- op_limit ? op_limit->dup (scope) : 0,
- op_increment ? op_increment->dup (scope) : 0,
- line (), column ());
+  tree_colon_expression *new_ce = new
+    tree_colon_expression (op_base ? op_base->dup (scope, context) : 0,
+   op_limit ? op_limit->dup (scope, context) : 0,
+   op_increment ? op_increment->dup (scope, context) : 0,
+   line (), column ());
 
   new_ce->copy_base (*new_ce);
 
diff --git a/src/pt-colon.h b/src/pt-colon.h
--- a/src/pt-colon.h
+++ b/src/pt-colon.h
@@ -92,7 +92,8 @@ public:
   int line (void) const;
   int column (void) const;
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-const.cc b/src/pt-const.cc
--- a/src/pt-const.cc
+++ b/src/pt-const.cc
@@ -71,7 +71,8 @@ tree_constant::rvalue (int nargout)
 }
 
 tree_expression *
-tree_constant::dup (symbol_table::scope_id)
+tree_constant::dup (symbol_table::scope_id,
+    symbol_table::context_id context)
 {
   tree_constant *new_tc
     = new tree_constant (val, orig_text, line (), column ());
diff --git a/src/pt-const.h b/src/pt-const.h
--- a/src/pt-const.h
+++ b/src/pt-const.h
@@ -82,7 +82,8 @@ public:
 
   octave_value_list rvalue (int nargout);
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-decl.cc b/src/pt-decl.cc
--- a/src/pt-decl.cc
+++ b/src/pt-decl.cc
@@ -69,10 +69,11 @@ tree_decl_elt::eval (void)
 }
 
 tree_decl_elt *
-tree_decl_elt::dup (symbol_table::scope_id scope)
+tree_decl_elt::dup (symbol_table::scope_id scope,
+    symbol_table::context_id context)
 {
-  return new tree_decl_elt (id ? id->dup (scope) : 0,
-    expr ? expr->dup (scope) : 0);
+  return new tree_decl_elt (id ? id->dup (scope, context) : 0,
+    expr ? expr->dup (scope, context) : 0);
 }
 
 void
@@ -98,7 +99,8 @@ tree_decl_init_list::eval (tree_decl_elt
 }
 
 tree_decl_init_list *
-tree_decl_init_list::dup (symbol_table::scope_id scope)
+tree_decl_init_list::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
   tree_decl_init_list *new_dil = new tree_decl_init_list ();
 
@@ -106,7 +108,7 @@ tree_decl_init_list::dup (symbol_table::
     {
       tree_decl_elt *elt = *p;
 
-      new_dil->append (elt ? elt->dup (scope) : 0);
+      new_dil->append (elt ? elt->dup (scope, context) : 0);
     }
   
   return new_dil;
@@ -177,10 +179,12 @@ tree_global_command::eval (void)
 }
 
 tree_command *
-tree_global_command::dup (symbol_table::scope_id scope)
+tree_global_command::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
-  return new tree_global_command (init_list ? init_list->dup (scope) : 0,
-  line (), column ());
+  return
+    new tree_global_command (init_list ? init_list->dup (scope, context) : 0,
+     line (), column ());
 }
 
 // Static.
@@ -228,10 +232,12 @@ tree_static_command::eval (void)
 }
 
 tree_command *
-tree_static_command::dup (symbol_table::scope_id scope)
+tree_static_command::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
-  return new tree_static_command (init_list ? init_list->dup (scope) : 0,
-  line (), column ());
+  return
+    new tree_static_command (init_list ? init_list->dup (scope, context) : 0,
+     line (), column ());
 }
 
 /*
diff --git a/src/pt-decl.h b/src/pt-decl.h
--- a/src/pt-decl.h
+++ b/src/pt-decl.h
@@ -78,7 +78,8 @@ public:
 
   tree_expression *expression (void) { return expr; }
 
-  tree_decl_elt *dup (symbol_table::scope_id scope);
+  tree_decl_elt *dup (symbol_table::scope_id scope,
+      symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -118,7 +119,8 @@ public:
 
   void eval (tree_decl_elt::eval_fcn);
 
-  tree_decl_init_list *dup (symbol_table::scope_id scope);
+  tree_decl_init_list *dup (symbol_table::scope_id scope,
+    symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -187,7 +189,8 @@ public:
 
   void eval (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
 private:
 
@@ -217,7 +220,8 @@ public:
 
   void eval (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
 private:
 
diff --git a/src/pt-except.cc b/src/pt-except.cc
--- a/src/pt-except.cc
+++ b/src/pt-except.cc
@@ -135,14 +135,16 @@ tree_try_catch_command::eval (void)
 }
 
 tree_command *
-tree_try_catch_command::dup (symbol_table::scope_id scope)
+tree_try_catch_command::dup (symbol_table::scope_id scope,
+     symbol_table::context_id context)
 {
-  return new tree_try_catch_command (try_code ? try_code->dup (scope) : 0,
-     catch_code ? catch_code->dup (scope) : 0,
-     lead_comm ? lead_comm->dup () : 0,
-     mid_comm ? mid_comm->dup () : 0,
-     trail_comm ? trail_comm->dup () : 0,
-     line (), column ());
+  return new
+    tree_try_catch_command (try_code ? try_code->dup (scope, context) : 0,
+    catch_code ? catch_code->dup (scope, context) : 0,
+    lead_comm ? lead_comm->dup () : 0,
+    mid_comm ? mid_comm->dup () : 0,
+    trail_comm ? trail_comm->dup () : 0,
+    line (), column ());
 }
 
 void
@@ -251,11 +253,12 @@ tree_unwind_protect_command::eval (void)
 }
 
 tree_command *
-tree_unwind_protect_command::dup (symbol_table::scope_id scope)
+tree_unwind_protect_command::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
   return new tree_unwind_protect_command
-    (unwind_protect_code ? unwind_protect_code->dup (scope) : 0,
-     cleanup_code ? cleanup_code->dup (scope) : 0,
+    (unwind_protect_code ? unwind_protect_code->dup (scope, context) : 0,
+     cleanup_code ? cleanup_code->dup (scope, context) : 0,
      lead_comm ? lead_comm->dup () : 0,
      mid_comm ? mid_comm->dup () : 0,
      trail_comm ? trail_comm->dup () : 0,
diff --git a/src/pt-except.h b/src/pt-except.h
--- a/src/pt-except.h
+++ b/src/pt-except.h
@@ -65,7 +65,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -127,7 +128,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-exp.h b/src/pt-exp.h
--- a/src/pt-exp.h
+++ b/src/pt-exp.h
@@ -47,7 +47,8 @@ public:
 
   virtual bool has_magic_end (void) const = 0;
 
-  virtual tree_expression *dup (symbol_table::scope_id) = 0;
+  virtual tree_expression *dup (symbol_table::scope_id,
+ symbol_table::context_id context) = 0;
 
   virtual bool is_constant (void) const { return false; }
 
diff --git a/src/pt-fcn-handle.cc b/src/pt-fcn-handle.cc
--- a/src/pt-fcn-handle.cc
+++ b/src/pt-fcn-handle.cc
@@ -71,7 +71,8 @@ tree_fcn_handle::rvalue (int nargout)
 }
 
 tree_expression *
-tree_fcn_handle::dup (symbol_table::scope_id)
+tree_fcn_handle::dup (symbol_table::scope_id,
+      symbol_table::context_id)
 {
   tree_fcn_handle *new_fh = new tree_fcn_handle (nm, line (), column ());
 
@@ -99,13 +100,14 @@ tree_anon_fcn_handle::rvalue (void)
   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::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,
- ret_list ? ret_list->dup (new_scope) : 0,
- cmd_list ? cmd_list->dup (new_scope) : 0);
+ 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 ();
 
@@ -135,7 +137,8 @@ tree_anon_fcn_handle::rvalue (int nargou
 }
 
 tree_expression *
-tree_anon_fcn_handle::dup (symbol_table::scope_id parent_scope)
+tree_anon_fcn_handle::dup (symbol_table::scope_id parent_scope,
+   symbol_table::context_id parent_context)
 {
   tree_parameter_list *param_list = parameter_list ();
   tree_parameter_list *ret_list = return_list ();
@@ -145,13 +148,13 @@ tree_anon_fcn_handle::dup (symbol_table:
   symbol_table::scope_id new_scope = symbol_table::dup_scope (this_scope);
 
   if (new_scope > 0)
-    symbol_table::inherit (new_scope, parent_scope);
+    symbol_table::inherit (new_scope, parent_scope, parent_context);
 
-  tree_anon_fcn_handle *new_afh
-    = new tree_anon_fcn_handle (param_list ? param_list->dup (new_scope) : 0,
- ret_list ? ret_list->dup (new_scope) : 0,
- cmd_list ? cmd_list->dup (new_scope) : 0,
- new_scope, line (), column ());
+  tree_anon_fcn_handle *new_afh = new
+    tree_anon_fcn_handle (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,
+  new_scope, line (), column ());
 
   new_afh->copy_base (*this);
 
diff --git a/src/pt-fcn-handle.h b/src/pt-fcn-handle.h
--- a/src/pt-fcn-handle.h
+++ b/src/pt-fcn-handle.h
@@ -69,7 +69,8 @@ public:
 
   octave_value_list rvalue (int nargout);
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -123,7 +124,8 @@ public:
 
   symbol_table::scope_id scope (void) { return fcn ? fcn->scope () : -1; }
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-id.cc b/src/pt-id.cc
--- a/src/pt-id.cc
+++ b/src/pt-id.cc
@@ -123,7 +123,8 @@ tree_identifier::lvalue (void)
 }
 
 tree_identifier *
-tree_identifier::dup (symbol_table::scope_id sc)
+tree_identifier::dup (symbol_table::scope_id sc,
+      symbol_table::context_id context)
 {
   // The new tree_identifier object contains a symbol_record
   // entry from the duplicated scope.
diff --git a/src/pt-id.h b/src/pt-id.h
--- a/src/pt-id.h
+++ b/src/pt-id.h
@@ -111,7 +111,8 @@ public:
 
   void eval_undefined_error (void);
 
-  tree_identifier *dup (symbol_table::scope_id scope);
+  tree_identifier *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-idx.cc b/src/pt-idx.cc
--- a/src/pt-idx.cc
+++ b/src/pt-idx.cc
@@ -689,12 +689,13 @@ tree_index_expression::eval_error (void)
 }
 
 tree_index_expression *
-tree_index_expression::dup (symbol_table::scope_id scope)
+tree_index_expression::dup (symbol_table::scope_id scope,
+    symbol_table::context_id context)
 {
   tree_index_expression *new_idx_expr
     = new tree_index_expression (line (), column ());
 
-  new_idx_expr->expr = expr ? expr->dup (scope) : 0;
+  new_idx_expr->expr = expr ? expr->dup (scope, context) : 0;
 
   std::list<tree_argument_list *> new_args;
 
@@ -704,7 +705,7 @@ tree_index_expression::dup (symbol_table
     {
       tree_argument_list *elt = *p;
 
-      new_args.push_back (elt ? elt->dup (scope) : 0);
+      new_args.push_back (elt ? elt->dup (scope, context) : 0);
     }
 
   new_idx_expr->args = new_args;
@@ -721,7 +722,7 @@ tree_index_expression::dup (symbol_table
     {
       tree_expression *elt = *p;
 
-      new_dyn_field.push_back (elt ? elt->dup (scope) : 0);
+      new_dyn_field.push_back (elt ? elt->dup (scope, context) : 0);
     }
 
   new_idx_expr->dyn_field = new_dyn_field;
diff --git a/src/pt-idx.h b/src/pt-idx.h
--- a/src/pt-idx.h
+++ b/src/pt-idx.h
@@ -90,7 +90,8 @@ public:
 
   void eval_error (void) const;
 
-  tree_index_expression *dup (symbol_table::scope_id scope);
+  tree_index_expression *dup (symbol_table::scope_id scope,
+      symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-jump.cc b/src/pt-jump.cc
--- a/src/pt-jump.cc
+++ b/src/pt-jump.cc
@@ -49,7 +49,8 @@ tree_break_command::eval (void)
 }
 
 tree_command *
-tree_break_command::dup (symbol_table::scope_id)
+tree_break_command::dup (symbol_table::scope_id,
+ symbol_table::context_id context)
 {
   return new tree_break_command (line (), column ());
 }
@@ -75,7 +76,8 @@ tree_continue_command::eval (void)
 }
 
 tree_command *
-tree_continue_command::dup (symbol_table::scope_id)
+tree_continue_command::dup (symbol_table::scope_id,
+    symbol_table::context_id context)
 {
   return new tree_continue_command (line (), column ());
 }
@@ -101,7 +103,8 @@ tree_return_command::eval (void)
 }
 
 tree_command *
-tree_return_command::dup (symbol_table::scope_id)
+tree_return_command::dup (symbol_table::scope_id,
+  symbol_table::context_id context)
 {
   return new tree_return_command (line (), column ());
 }
diff --git a/src/pt-jump.h b/src/pt-jump.h
--- a/src/pt-jump.h
+++ b/src/pt-jump.h
@@ -42,7 +42,8 @@ public:
 
   void eval (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -71,7 +72,8 @@ public:
 
   void eval (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -100,7 +102,8 @@ public:
 
   void eval (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-loop.cc b/src/pt-loop.cc
--- a/src/pt-loop.cc
+++ b/src/pt-loop.cc
@@ -126,10 +126,11 @@ tree_while_command::eval_error (void)
 }
 
 tree_command *
-tree_while_command::dup (symbol_table::scope_id scope)
+tree_while_command::dup (symbol_table::scope_id scope,
+ symbol_table::context_id context)
 {
-  return new tree_while_command (expr ? expr->dup (scope) : 0,
- list ? list->dup (scope) : 0,
+  return new tree_while_command (expr ? expr->dup (scope, context) : 0,
+ list ? list->dup (scope, context) : 0,
  lead_comm ? lead_comm->dup () : 0,
  trail_comm ? trail_comm->dup (): 0,
  line (), column ());
@@ -189,10 +190,11 @@ tree_do_until_command::eval_error (void)
 }
 
 tree_command *
-tree_do_until_command::dup (symbol_table::scope_id scope)
+tree_do_until_command::dup (symbol_table::scope_id scope,
+    symbol_table::context_id context)
 {
-  return new tree_do_until_command (expr ? expr->dup (scope) : 0,
-    list ? list->dup (scope) : 0,
+  return new tree_do_until_command (expr ? expr->dup (scope, context) : 0,
+    list ? list->dup (scope, context) : 0,
     lead_comm ? lead_comm->dup () : 0,
     trail_comm ? trail_comm->dup (): 0,
     line (), column ());
@@ -495,11 +497,12 @@ tree_simple_for_command::eval_error (voi
 }
 
 tree_command *
-tree_simple_for_command::dup (symbol_table::scope_id scope)
+tree_simple_for_command::dup (symbol_table::scope_id scope,
+      symbol_table::context_id context)
 {
-  return new tree_simple_for_command (lhs ? lhs->dup (scope) : 0,
-      expr ? expr->dup (scope) : 0,
-      list ? list->dup (scope) : 0,
+  return new tree_simple_for_command (lhs ? lhs->dup (scope, context) : 0,
+      expr ? expr->dup (scope, context) : 0,
+      list ? list->dup (scope, context) : 0,
       lead_comm ? lead_comm->dup () : 0,
       trail_comm ? trail_comm->dup () : 0,
       line (), column ());
@@ -616,14 +619,15 @@ tree_complex_for_command::eval_error (vo
 }
 
 tree_command *
-tree_complex_for_command::dup (symbol_table::scope_id scope)
+tree_complex_for_command::dup (symbol_table::scope_id scope,
+       symbol_table::context_id context)
 {
-  return new tree_complex_for_command (lhs ? lhs->dup (scope) : 0,
-      expr ? expr->dup (scope) : 0,
-      list ? list->dup (scope) : 0,
-      lead_comm ? lead_comm->dup () : 0,
-      trail_comm ? trail_comm->dup () : 0,
-      line (), column ());
+  return new tree_complex_for_command (lhs ? lhs->dup (scope, context) : 0,
+       expr ? expr->dup (scope, context) : 0,
+       list ? list->dup (scope, context) : 0,
+       lead_comm ? lead_comm->dup () : 0,
+       trail_comm ? trail_comm->dup () : 0,
+       line (), column ());
 }
 
 void
diff --git a/src/pt-loop.h b/src/pt-loop.h
--- a/src/pt-loop.h
+++ b/src/pt-loop.h
@@ -79,7 +79,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -134,7 +135,8 @@ public:
 
   void eval_error (void);
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -182,7 +184,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -246,7 +249,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-mat.cc b/src/pt-mat.cc
--- a/src/pt-mat.cc
+++ b/src/pt-mat.cc
@@ -951,7 +951,8 @@ done:
 }
 
 tree_expression *
-tree_matrix::dup (symbol_table::scope_id scope)
+tree_matrix::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
   tree_matrix *new_matrix = new tree_matrix (0, line (), column ());
 
@@ -959,7 +960,7 @@ tree_matrix::dup (symbol_table::scope_id
     {
       tree_argument_list *elt = *p;
 
-      new_matrix->append (elt ? elt->dup (scope) : 0);
+      new_matrix->append (elt ? elt->dup (scope, context) : 0);
     }
 
   new_matrix->copy_base (*this);
diff --git a/src/pt-mat.h b/src/pt-mat.h
--- a/src/pt-mat.h
+++ b/src/pt-mat.h
@@ -64,7 +64,8 @@ public:
 
   octave_value_list rvalue (int nargout);
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-misc.cc b/src/pt-misc.cc
--- a/src/pt-misc.cc
+++ b/src/pt-misc.cc
@@ -247,7 +247,8 @@ tree_parameter_list::is_defined (void)
 }
 
 tree_parameter_list *
-tree_parameter_list::dup (symbol_table::scope_id scope)
+tree_parameter_list::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
   tree_parameter_list *new_list = new tree_parameter_list ();
 
@@ -258,7 +259,7 @@ tree_parameter_list::dup (symbol_table::
     {
       tree_decl_elt *elt = *p;
 
-      new_list->append (elt->dup (scope));
+      new_list->append (elt->dup (scope, context));
     }
 
   return new_list;
@@ -283,7 +284,8 @@ tree_return_list::~tree_return_list (voi
 }
 
 tree_return_list *
-tree_return_list::dup (symbol_table::scope_id scope)
+tree_return_list::dup (symbol_table::scope_id scope,
+       symbol_table::context_id context)
 {
   tree_return_list *new_list = new tree_return_list ();
 
@@ -291,7 +293,7 @@ tree_return_list::dup (symbol_table::sco
     {
       tree_index_expression *elt = *p;
 
-      new_list->append (elt->dup (scope));
+      new_list->append (elt->dup (scope, context));
     }
 
   return new_list;
diff --git a/src/pt-misc.h b/src/pt-misc.h
--- a/src/pt-misc.h
+++ b/src/pt-misc.h
@@ -81,7 +81,8 @@ public:
 
   octave_value_list convert_to_const_vector (const Cell& varargout);
 
-  tree_parameter_list *dup (symbol_table::scope_id scope);
+  tree_parameter_list *dup (symbol_table::scope_id scope,
+    symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -114,7 +115,8 @@ public:
 
   ~tree_return_list (void);
 
-  tree_return_list *dup (symbol_table::scope_id scope);
+  tree_return_list *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-select.cc b/src/pt-select.cc
--- a/src/pt-select.cc
+++ b/src/pt-select.cc
@@ -60,10 +60,11 @@ tree_if_clause::eval (void)
 }
 
 tree_if_clause *
-tree_if_clause::dup (symbol_table::scope_id scope)
+tree_if_clause::dup (symbol_table::scope_id scope,
+     symbol_table::context_id context)
 {
-  return new tree_if_clause (expr ? expr->dup (scope) : 0,
-     list ? list->dup (scope) : 0,
+  return new tree_if_clause (expr ? expr->dup (scope, context) : 0,
+     list ? list->dup (scope, context) : 0,
      lead_comm ? lead_comm->dup () : 0);
 }
 
@@ -88,7 +89,8 @@ tree_if_command_list::eval (void)
 }
 
 tree_if_command_list *
-tree_if_command_list::dup (symbol_table::scope_id scope)
+tree_if_command_list::dup (symbol_table::scope_id scope,
+   symbol_table::context_id context)
 {
   tree_if_command_list *new_icl = new tree_if_command_list ();
 
@@ -96,7 +98,7 @@ tree_if_command_list::dup (symbol_table:
     {
       tree_if_clause *elt = *p;
 
-      new_icl->append (elt ? elt->dup (scope) : 0);
+      new_icl->append (elt ? elt->dup (scope, context) : 0);
     }
 
   return new_icl;
@@ -129,9 +131,10 @@ tree_if_command::eval (void)
 }
 
 tree_command *
-tree_if_command::dup (symbol_table::scope_id scope)
+tree_if_command::dup (symbol_table::scope_id scope,
+      symbol_table::context_id context)
 {
-  return new tree_if_command (list ? list->dup (scope) : 0,
+  return new tree_if_command (list ? list->dup (scope, context) : 0,
       lead_comm ? lead_comm->dup () : 0,
       trail_comm ? trail_comm->dup () : 0,
       line (), column ());
@@ -243,10 +246,11 @@ tree_switch_case::eval_error (void)
 }
 
 tree_switch_case *
-tree_switch_case::dup (symbol_table::scope_id scope)
+tree_switch_case::dup (symbol_table::scope_id scope,
+       symbol_table::context_id context)
 {
-  return new tree_switch_case (label ? label->dup (scope) : 0,
-       list ? list->dup (scope) : 0,
+  return new tree_switch_case (label ? label->dup (scope, context) : 0,
+       list ? list->dup (scope, context) : 0,
        lead_comm ? lead_comm->dup () : 0);
 }
 
@@ -271,7 +275,8 @@ tree_switch_case_list::eval (const octav
 }
 
 tree_switch_case_list *
-tree_switch_case_list::dup (symbol_table::scope_id scope)
+tree_switch_case_list::dup (symbol_table::scope_id scope,
+    symbol_table::context_id context)
 {
   tree_switch_case_list *new_scl = new tree_switch_case_list ();
 
@@ -279,7 +284,7 @@ tree_switch_case_list::dup (symbol_table
     {
       tree_switch_case *elt = *p;
 
-      new_scl->append (elt ? elt->dup (scope) : 0);
+      new_scl->append (elt ? elt->dup (scope, context) : 0);
     }
   
   return new_scl;
@@ -332,10 +337,11 @@ tree_switch_command::eval_error (void)
 }
 
 tree_command *
-tree_switch_command::dup (symbol_table::scope_id scope)
+tree_switch_command::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
-  return new tree_switch_command (expr ? expr->dup (scope) : 0,
-  list ? list->dup (scope) : 0,
+  return new tree_switch_command (expr ? expr->dup (scope, context) : 0,
+  list ? list->dup (scope, context) : 0,
   lead_comm ? lead_comm->dup () : 0,
   trail_comm ? trail_comm->dup () : 0,
   line (), column ());
diff --git a/src/pt-select.h b/src/pt-select.h
--- a/src/pt-select.h
+++ b/src/pt-select.h
@@ -64,7 +64,8 @@ public:
 
   octave_comment_list *leading_comment (void) { return lead_comm; }
 
-  tree_if_clause *dup (symbol_table::scope_id scope);
+  tree_if_clause *dup (symbol_table::scope_id scope,
+       symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -107,7 +108,8 @@ public:
 
   void eval (void);
 
-  tree_if_command_list *dup (symbol_table::scope_id scope);
+  tree_if_command_list *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -142,7 +144,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -197,7 +200,8 @@ public:
 
   octave_comment_list *leading_comment (void) { return lead_comm; }
 
-  tree_switch_case *dup (symbol_table::scope_id scope);
+  tree_switch_case *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -240,7 +244,8 @@ public:
 
   void eval (const octave_value& val);
 
-  tree_switch_case_list *dup (symbol_table::scope_id scope);
+  tree_switch_case_list *dup (symbol_table::scope_id scope,
+      symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -282,7 +287,8 @@ public:
 
   octave_comment_list *trailing_comment (void) { return trail_comm; }
 
-  tree_command *dup (symbol_table::scope_id scope);
+  tree_command *dup (symbol_table::scope_id scope,
+     symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-stmt.cc b/src/pt-stmt.cc
--- a/src/pt-stmt.cc
+++ b/src/pt-stmt.cc
@@ -138,13 +138,14 @@ tree_statement::eval (bool silent, int n
 }
 
 tree_statement *
-tree_statement::dup (symbol_table::scope_id scope)
+tree_statement::dup (symbol_table::scope_id scope,
+     symbol_table::context_id context)
 {
   tree_statement *new_stmt = new tree_statement ();
 
-  new_stmt->cmd = cmd ? cmd->dup (scope) : 0;
+  new_stmt->cmd = cmd ? cmd->dup (scope, context) : 0;
 
-  new_stmt->expr = expr ? expr->dup (scope) : 0;
+  new_stmt->expr = expr ? expr->dup (scope, context) : 0;
 
   new_stmt->comm = comm ? comm->dup () : 0;
 
@@ -263,7 +264,8 @@ tree_statement_list::list_breakpoints (v
 }
 
 tree_statement_list *
-tree_statement_list::dup (symbol_table::scope_id scope)
+tree_statement_list::dup (symbol_table::scope_id scope,
+  symbol_table::context_id context)
 {
   tree_statement_list *new_list = new tree_statement_list ();
 
@@ -273,7 +275,7 @@ tree_statement_list::dup (symbol_table::
     {
       tree_statement *elt = *p;
 
-      new_list->append (elt ? elt->dup (scope) : 0);
+      new_list->append (elt ? elt->dup (scope, context) : 0);
     }
 
   return new_list;
diff --git a/src/pt-stmt.h b/src/pt-stmt.h
--- a/src/pt-stmt.h
+++ b/src/pt-stmt.h
@@ -86,7 +86,8 @@ public:
 
   void set_expression (tree_expression *e) { expr = e; }
 
-  tree_statement *dup (symbol_table::scope_id scope);
+  tree_statement *dup (symbol_table::scope_id scope,
+       symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -147,7 +148,8 @@ public:
 
   octave_value_list list_breakpoints (void);
 
-  tree_statement_list *dup (symbol_table::scope_id scope);
+  tree_statement_list *dup (symbol_table::scope_id scope,
+    symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/pt-unop.cc b/src/pt-unop.cc
--- a/src/pt-unop.cc
+++ b/src/pt-unop.cc
@@ -121,10 +121,11 @@ tree_prefix_expression::eval_error (void
 }
 
 tree_expression *
-tree_prefix_expression::dup (symbol_table::scope_id scope)
+tree_prefix_expression::dup (symbol_table::scope_id scope,
+     symbol_table::context_id context)
 {
   tree_prefix_expression *new_pe
-    = new tree_prefix_expression (op ? op->dup (scope) : 0,
+    = new tree_prefix_expression (op ? op->dup (scope, context) : 0,
   line (), column (), etype);
 
   new_pe->copy_base (*this);
@@ -218,10 +219,11 @@ tree_postfix_expression::eval_error (voi
 }
 
 tree_expression *
-tree_postfix_expression::dup (symbol_table::scope_id scope)
+tree_postfix_expression::dup (symbol_table::scope_id scope,
+      symbol_table::context_id context)
 {
   tree_postfix_expression *new_pe
-    = new tree_postfix_expression (op ? op->dup (scope) : 0,
+    = new tree_postfix_expression (op ? op->dup (scope, context) : 0,
    line (), column (), etype);
 
   new_pe->copy_base (*this);
diff --git a/src/pt-unop.h b/src/pt-unop.h
--- a/src/pt-unop.h
+++ b/src/pt-unop.h
@@ -104,7 +104,8 @@ public:
 
   void eval_error (void);
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
@@ -142,7 +143,8 @@ public:
 
   void eval_error (void);
 
-  tree_expression *dup (symbol_table::scope_id scope);
+  tree_expression *dup (symbol_table::scope_id scope,
+ symbol_table::context_id context);
 
   void accept (tree_walker& tw);
 
diff --git a/src/symtab.cc b/src/symtab.cc
--- a/src/symtab.cc
+++ b/src/symtab.cc
@@ -73,7 +73,7 @@ symbol_table::symbol_record::symbol_reco
 symbol_table::symbol_record::symbol_record_rep::dump
   (std::ostream& os, const std::string& prefix) const
 {
-  octave_value val = varval ();
+  octave_value val = varval (xcurrent_context);
 
   os << prefix << name;
 
diff --git a/src/symtab.h b/src/symtab.h
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -195,7 +195,7 @@ public:
  value_stack.push_back (v);
       }
 
-      octave_value& varref (void)
+      octave_value& varref (context_id context)
       {
  if (is_global ())
   return symbol_table::global_varref (name);
@@ -204,14 +204,14 @@ public:
  else
   {
     context_id n = value_stack.size ();
-    while (n++ <= symbol_table::xcurrent_context)
+    while (n++ <= context)
       value_stack.push_back (octave_value ());
 
-    return value_stack[symbol_table::xcurrent_context];
+    return value_stack[context];
   }
       }
 
-      octave_value varval (void) const
+      octave_value varval (context_id context) const
       {
  if (is_global ())
   return symbol_table::global_varval (name);
@@ -219,8 +219,8 @@ public:
   return symbol_table::persistent_varval (name);
  else
   {
-    if (symbol_table::xcurrent_context < value_stack.size ())
-      return value_stack[symbol_table::xcurrent_context];
+    if (context < value_stack.size ())
+      return value_stack[context];
     else
       return octave_value ();
   }
@@ -268,19 +268,24 @@ public:
 
     if (is_persistent ())
       {
- symbol_table::persistent_varref (name) = varval ();
+ symbol_table::persistent_varref (name)
+  = varval (xcurrent_context);
+
  unmark_persistent ();
       }
 
-    varref () = octave_value ();
+    varref (xcurrent_context) = octave_value ();
   }
       }
 
-      bool is_defined (void) const { return varval ().is_defined (); }
+      bool is_defined (context_id context) const
+      {
+ return varval (context).is_defined ();
+      }
 
-      bool is_variable (void) const
+      bool is_variable (context_id context) const
       {
- return (storage_class != local || is_defined ());
+ return (storage_class != local || is_defined (context));
       }
 
       bool is_local (void) const { return storage_class & local; }
@@ -321,11 +326,11 @@ public:
 
       void init_persistent (void)
       {
- if (! is_defined ())
+ if (! is_defined (xcurrent_context))
   {
     mark_persistent ();
 
-    varref () = symbol_table::persistent_varval (name);
+    varref (xcurrent_context) = symbol_table::persistent_varval (name);
   }
  // FIXME -- this causes trouble with recursive calls.
  // else
@@ -340,7 +345,8 @@ public:
 
       symbol_record_rep *dup (void)
       {
- return new symbol_record_rep (name, varval (), storage_class);
+ return new symbol_record_rep (name, varval (xcurrent_context),
+      storage_class);
       }
 
       void dump (std::ostream& os, const std::string& prefix) const;
@@ -400,9 +406,15 @@ public:
     find (tree_argument_list *args, const string_vector& arg_names,
   octave_value_list& evaluated_args, bool& args_evaluated) const;
 
-    octave_value& varref (void) { return rep->varref (); }
+    octave_value& varref (context_id context = xcurrent_context)
+    {
+      return rep->varref (context);
+    }
 
-    octave_value varval (void) const { return rep->varval (); }
+    octave_value varval (context_id context = xcurrent_context) const
+    {
+      return rep->varval (context);
+    }
 
     void push_context (void) { rep->push_context (); }
 
@@ -410,8 +422,15 @@ public:
 
     void clear (void) { rep->clear (); }
 
-    bool is_defined (void) const { return rep->is_defined (); }
-    bool is_variable (void) const { return rep->is_variable (); }
+    bool is_defined (context_id context = xcurrent_context) const
+    {
+      return rep->is_defined (context);
+    }
+
+    bool is_variable (context_id context = xcurrent_context) const
+    {
+      return rep->is_variable (context);
+    }
 
     bool is_local (void) const { return rep->is_local (); }
     bool is_automatic (void) const { return rep->is_automatic (); }
@@ -977,12 +996,13 @@ public:
     return inst ? inst->do_find_symbol (name) : symbol_record ();
   }
 
-  static void inherit (scope_id scope, scope_id donor_scope)
+  static void
+  inherit (scope_id scope, scope_id donor_scope, context_id donor_context)
   {
     symbol_table *inst = get_instance (scope);
 
     if (inst)
-      inst->do_inherit (donor_scope);
+      inst->do_inherit (donor_scope, donor_context);
   }
 
   static bool at_top_level (void) { return xcurrent_scope == xtop_scope; }
@@ -1005,21 +1025,23 @@ public:
   }
 
   static octave_value& varref (const std::string& name,
-       scope_id scope = xcurrent_scope)
+       scope_id scope = xcurrent_scope,
+       context_id context = xcurrent_context)
   {
     static octave_value foobar;
 
     symbol_table *inst = get_instance (scope);
 
-    return inst ? inst->do_varref (name) : foobar;
+    return inst ? inst->do_varref (name, context) : foobar;
   }
 
   static octave_value varval (const std::string& name,
-      scope_id scope = xcurrent_scope)
+      scope_id scope = xcurrent_scope,
+      context_id context = xcurrent_context)
   {
     symbol_table *inst = get_instance (scope);
 
-    return inst ? inst->do_varval (name) : octave_value ();
+    return inst ? inst->do_varval (name, context) : octave_value ();
   }
 
   static octave_value&
@@ -1488,12 +1510,14 @@ public:
   }
 
   static std::list<symbol_record>
-  all_variables (scope_id scope = xcurrent_scope, bool defined_only = true)
+  all_variables (scope_id scope = xcurrent_scope,
+ context_id context = xcurrent_context,
+ bool defined_only = true)
   {
     symbol_table *inst = get_instance (scope);
 
     return inst
-      ? inst->do_all_variables (defined_only) : std::list<symbol_record> ();
+      ? inst->do_all_variables (context, defined_only) : std::list<symbol_record> ();
   }
 
   static std::list<symbol_record> glob (const std::string& pattern)
@@ -1811,7 +1835,7 @@ private:
       return p->second;
   }
 
-  void do_inherit (scope_id donor_scope)
+  void do_inherit (scope_id donor_scope, context_id donor_context)
   {
     for (table_iterator p = table.begin (); p != table.end (); p++)
       {
@@ -1821,11 +1845,17 @@ private:
 
  if (! (sr.is_automatic () || sr.is_formal () || nm == "__retval__"))
   {
-    octave_value val = symbol_table::varval (nm, donor_scope);
+    octave_value val
+      = symbol_table::varval (nm, donor_scope, donor_context);
 
     if (val.is_defined ())
       {
- sr.varref () = val;
+ // Currently, inherit is always called when creating a
+ // new table, so it only makes sense to copy values into
+ // the base context (== 0), but maybe the context
+ // should be passed in as a parameter instead?
+
+ sr.varref (0) = val;
 
  sr.mark_inherited ();
       }
@@ -1847,7 +1877,7 @@ private:
       ? (table[name] = symbol_record (name)) : p->second;
   }
 
-  octave_value& do_varref (const std::string& name)
+  octave_value& do_varref (const std::string& name, context_id context)
   {
     table_iterator p = table.find (name);
 
@@ -1855,17 +1885,17 @@ private:
       {
  symbol_record& sr = do_insert (name);
 
- return sr.varref ();
+ return sr.varref (context);
       }
     else
-      return p->second.varref ();
+      return p->second.varref (context);
   }
 
-  octave_value do_varval (const std::string& name) const
+  octave_value do_varval (const std::string& name, context_id context) const
   {
     table_const_iterator p = table.find (name);
 
-    return (p != table.end ()) ? p->second.varval () : octave_value ();
+    return (p != table.end ()) ? p->second.varval (context) : octave_value ();
   }
 
   octave_value& do_persistent_varref (const std::string& name)
@@ -2017,7 +2047,8 @@ private:
       p->second.mark_global ();
   }
 
-  std::list<symbol_record> do_all_variables (bool defined_only) const
+  std::list<symbol_record>
+  do_all_variables (context_id context, bool defined_only) const
   {
     std::list<symbol_record> retval;
 
@@ -2025,7 +2056,7 @@ private:
       {
  const symbol_record& sr = p->second;
 
- if (defined_only && ! sr.is_defined ())
+ if (defined_only && ! sr.is_defined (context))
   continue;
 
  retval.push_back (sr);

_______________________________________________
Bug-octave mailing list
Bug-octave@...
https://www.cae.wisc.edu/mailman/listinfo/bug-octave