changeset 2124:97a566037a75

[project @ 1996-05-12 07:16:36 by jwe]
author jwe
date Sun, 12 May 1996 07:16:36 +0000
parents ee55d81f585a
children 5049a300eee0
files src/help.cc src/parse.y src/pt-base.cc src/pt-base.h src/pt-cmd.cc src/pt-cmd.h src/pt-const.cc src/pt-const.h src/pt-exp-base.h src/pt-exp.cc src/pt-exp.h src/pt-fcn.cc src/pt-fcn.h src/pt-fvc.cc src/pt-fvc.h src/pt-mat.cc src/pt-mat.h src/pt-misc.cc src/pt-misc.h src/pt-mvr-base.h src/pt-mvr.cc src/pt-mvr.h src/pt-plot.cc src/pt-plot.h
diffstat 24 files changed, 739 insertions(+), 1154 deletions(-) [+]
line wrap: on
line diff
--- a/src/help.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/help.cc	Sun May 12 07:16:36 1996 +0000
@@ -49,6 +49,7 @@
 #include "pathsearch.h"
 #include "pt-const.h"
 #include "pt-exp.h"
+#include "pt-pr-code.h"
 #include "sighandlers.h"
 #include "symtab.h"
 #include "toplev.h"
@@ -754,7 +755,9 @@
 		  if (nargout == 0 && ! quiet)
 		    output_buf << argv[i] << " is a user-defined function\n";
 
-		  defn->print_code (output_buf);
+		  tree_print_code tpc (output_buf);
+
+		  defn->accept (tpc);
 		}
 
 	      // XXX FIXME XXX -- this code should be shared with
@@ -808,7 +811,9 @@
 		    }
 		  if (! tmp->is_map ())
 		    {
-		      tmp->print_code (output_buf);
+		      tree_print_code tpc (output_buf);
+
+		      tmp->accept (tpc);
 
 		      if (nargout == 0)
 			output_buf << "\n";
--- a/src/parse.y	Sun May 12 07:16:36 1996 +0000
+++ b/src/parse.y	Sun May 12 07:16:36 1996 +0000
@@ -763,7 +763,7 @@
 		  { $$ = make_constant (TEXT, $1); }
 		| '(' simple_expr ')'
 		  {
-		    $2->in_parens++;
+		    $2->mark_in_parens ();
 		    $$ = $2;
 		  }
 		| word_list_cmd
@@ -1327,7 +1327,7 @@
 {
   if (user_pref.warn_assign_as_truth_value
       && expr->is_assignment_expression ()
-      && expr->in_parens < 2)
+      && expr->is_in_parens () < 2)
     {
       warning ("suggest parenthesis around assignment used as truth value");
     }
--- a/src/pt-base.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-base.cc	Sun May 12 07:16:36 1996 +0000
@@ -35,48 +35,6 @@
 #include "pt-base.h"
 #include "user-prefs.h"
 
-// Current indentation.
-int tree_print_code::curr_print_indent_level = 0;
-
-// Nonzero means we are at the beginning of a line.
-bool tree_print_code::beginning_of_line = true;
-
-// All print_code() functions should use this to print new lines.
-
-void
-tree_print_code::print_code_new_line (ostream& os)
-{
-  os << "\n";
-
-  beginning_of_line = true;
-}
-
-// Each print_code() function should call this before printing
-// anything.
-//
-// This doesn't need to be fast, but isn't there a better way?
-
-void
-tree_print_code::print_code_indent (ostream& os)
-{
-  assert (curr_print_indent_level >= 0);
- 
-  if (beginning_of_line)
-    {
-      os.form ("%s%*s", user_pref.ps4.c_str (), curr_print_indent_level, "");
-      beginning_of_line = false;
-    }
-}
-
-// For ressetting print_code state.
-
-void
-tree_print_code::print_code_reset (void)
-{
-  beginning_of_line = true;
-  curr_print_indent_level = 0;
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-base.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-base.h	Sun May 12 07:16:36 1996 +0000
@@ -27,44 +27,15 @@
 #pragma interface
 #endif
 
-class ostream;
-
-// How to print the code that the trees represent.
-
-class
-tree_print_code
-{
-public:
-  virtual ~tree_print_code (void) { }
-
-  virtual void print_code (ostream& os) = 0;
-
-  void reset_indent_level (void)
-    { curr_print_indent_level = 0; }
-
-  void increment_indent_level (void)
-    { curr_print_indent_level += 2; }
-
-  void decrement_indent_level (void)
-    { curr_print_indent_level -= 2; }
-
-  void print_code_new_line (ostream& os);
-
-  void print_code_indent (ostream& os);
-
-  void print_code_reset (void);
-
-private:
-  static int curr_print_indent_level;
-  static bool beginning_of_line;
-};
+class tree_walker;
 
 // Base class for the parse tree.
 
 class
-tree : public tree_print_code
+tree
 {
 public:
+
   tree (int l = -1, int c = -1)
     {
       line_num = l;
@@ -77,7 +48,12 @@
   virtual int column (void) const
     { return column_num; }
 
+  virtual void accept (tree_walker& tw) = 0;
+
 private:
+
+  // The input line and column where we found the text that was
+  // eventually converted to this tree node.
   int line_num;
   int column_num;
 };
--- a/src/pt-cmd.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-cmd.cc	Sun May 12 07:16:36 1996 +0000
@@ -50,6 +50,7 @@
 #include "pt-fvc.h"
 #include "pt-misc.h"
 #include "pt-mvr.h"
+#include "pt-walk.h"
 #include "unwind-prot.h"
 #include "user-prefs.h"
 #include "variables.h"
@@ -118,14 +119,9 @@
 }
 
 void
-tree_global_command::print_code (ostream& os)
+tree_global_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "global ";
-
-  if (init_list)
-    init_list->print_code (os);
+  tw.visit_global_command (*this);
 }
 
 // While.
@@ -176,27 +172,9 @@
 }
 
 void
-tree_while_command::print_code (ostream& os)
+tree_while_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "while ";
-
-  if (expr)
-    expr->print_code (os);
-
-  print_code_new_line (os);
-
-  if (list)
-    {
-      increment_indent_level ();
-      list->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_indent (os);
-
-  os << "endwhile";
+  tw.visit_while_command (*this);
 }
 
 // For.
@@ -537,32 +515,9 @@
 }
 
 void
-tree_for_command::print_code (ostream& os)
+tree_for_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "for ";
-
-  if (id)
-    id->print_code (os);
-
-  os << " = ";
-
-  if (expr)
-    expr->print_code (os);
-
-  print_code_new_line (os);
-
-  if (list)
-    {
-      increment_indent_level ();
-      list->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_indent (os);
-
-  os << "endfor";
+  tw.visit_for_command (*this);
 }
 
 // If.
@@ -584,18 +539,9 @@
 }
 
 void
-tree_if_command::print_code (ostream& os)
+tree_if_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "if ";
-
-  if (list)
-    list->print_code (os);
-
-  print_code_indent (os);
-
-  os << "endif";
+  tw.visit_if_command (*this);
 }
 
 // Simple exception handling.
@@ -682,37 +628,9 @@
 }
 
 void
-tree_try_catch_command::print_code (ostream& os)
+tree_try_catch_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "try_catch";
-
-  print_code_new_line (os);
-
-  if (try_code)
-    {
-      increment_indent_level ();
-      try_code->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_indent (os);
-
-  os << "catch_code";
-
-  print_code_new_line (os);
-
-  if (catch_code)
-    {
-      increment_indent_level ();
-      catch_code->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_indent (os);
-
-  os << "end_try_catch";
+  tw.visit_try_catch_command (*this);
 }
 
 // Simple exception handling.
@@ -790,37 +708,9 @@
 }
 
 void
-tree_unwind_protect_command::print_code (ostream& os)
+tree_unwind_protect_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "unwind_protect";
-
-  print_code_new_line (os);
-
-  if (unwind_protect_code)
-    {
-      increment_indent_level ();
-      unwind_protect_code->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_indent (os);
-
-  os << "cleanup_code";
-
-  print_code_new_line (os);
-
-  if (cleanup_code)
-    {
-      increment_indent_level ();
-      cleanup_code->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_indent (os);
-
-  os << "end_unwind_protect";
+  tw.visit_unwind_protect_command (*this);
 }
 
 // Break.
@@ -833,11 +723,9 @@
 }
 
 void
-tree_break_command::print_code (ostream& os)
+tree_break_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "break";
+  tw.visit_break_command (*this);
 }
 
 // Continue.
@@ -850,11 +738,9 @@
 }
 
 void
-tree_continue_command::print_code (ostream& os)
+tree_continue_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "continue";
+  tw.visit_continue_command (*this);
 }
 
 // Return.
@@ -867,11 +753,9 @@
 }
 
 void
-tree_return_command::print_code (ostream& os)
+tree_return_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "return";
+  tw.visit_return_command (*this);
 }
 
 /*
--- a/src/pt-cmd.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-cmd.h	Sun May 12 07:16:36 1996 +0000
@@ -52,6 +52,8 @@
 class tree_continue_command;
 class tree_return_command;
 
+class tree_walker;
+
 #include "pt-base.h"
 
 // A base class for commands.
@@ -60,6 +62,7 @@
 tree_command : public tree
 {
 public:
+
   tree_command (int l = -1, int c = -1) : tree (l, c) { }
 
   virtual ~tree_command (void) { }
@@ -71,6 +74,7 @@
 tree_global_command : public tree_command
 {
 public:
+
   tree_global_command (int l = -1, int c = -1)
     : tree_command (l, c), init_list (0) { }
 
@@ -81,9 +85,14 @@
 
   void eval (void);
 
-  void print_code (ostream& os);
+  tree_global_init_list *initializer_list (void) { return init_list; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // The list of global variables or initializers in this global
+  // command.
   tree_global_init_list *init_list;
 };
 
@@ -93,6 +102,7 @@
 tree_while_command : public tree_command
 {
 public:
+
   tree_while_command (int l = -1, int c = -1)
     : tree_command (l, c), expr (0), list (0) { }
 
@@ -109,11 +119,19 @@
 
   void eval_error (void);
 
-  void print_code (ostream& os);
+  tree_expression *condition (void) { return expr; }
+
+  tree_statement_list *body (void) { return list; }
+
+  void accept (tree_walker& tw);
 
 private:
-  tree_expression *expr;	// Expression to test.
-  tree_statement_list *list;	// List of commands to execute.
+
+  // Expression to test.
+  tree_expression *expr;
+
+  // List of commands to execute.
+  tree_statement_list *list;
 };
 
 // For.
@@ -122,6 +140,7 @@
 tree_for_command : public tree_command
 {
 public:
+
   tree_for_command (int l = -1, int c = -1)
     : tree_command (l, c), id (0), id_list (0), expr (0), list (0) { }
 
@@ -141,9 +160,28 @@
 
   void eval_error (void);
 
-  void print_code (ostream& os);
+  tree_index_expression *ident (void) { return id; }
+
+  tree_expression *control_expr (void) { return expr; }
+
+  tree_statement_list *body (void) { return list; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // Identifier to modify.
+  tree_index_expression *id;
+
+  // List of identifiers to modify.
+  tree_return_list *id_list;
+
+  // Expression to evaluate.
+  tree_expression *expr;
+
+  // List of commands to execute.
+  tree_statement_list *list;
+
   void do_for_loop_once (tree_return_list *lst,
 			 const octave_value_list& rhs, bool& quit);
 
@@ -152,11 +190,6 @@
 
   void do_for_loop_once (tree_identifier *ident,
 			 octave_value& rhs, bool& quit);
-
-  tree_index_expression *id;	// Identifier to modify.
-  tree_return_list *id_list;	// List of identifiers to modify.
-  tree_expression *expr;	// Expression to evaluate.
-  tree_statement_list *list;	// List of commands to execute.
 };
 
 // If.
@@ -165,6 +198,7 @@
 tree_if_command : public tree_command
 {
 public:
+
   tree_if_command (int l = -1, int c = -1)
     : tree_command (l, c), list (0) { }
 
@@ -177,9 +211,13 @@
 
   void eval_error (void);
 
-  void print_code (ostream& os);
+  tree_if_command_list *cmd_list (void) { return list; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // List of if commands (if, elseif, elseif, ... else, endif)
   tree_if_command_list *list;
 };
 
@@ -189,6 +227,7 @@
 tree_unwind_protect_command : public tree_command
 {
 public:
+
   tree_unwind_protect_command (int l = -1, int c = -1)
     : tree_command (l, c), unwind_protect_code (0), cleanup_code (0) { }
 
@@ -201,10 +240,19 @@
 
   void eval (void);
 
-  void print_code (ostream& os);
+  tree_statement_list *body (void) { return unwind_protect_code; }
+
+  tree_statement_list *cleanup (void) { return cleanup_code; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // The first body of code to attempt to execute.
   tree_statement_list *unwind_protect_code;
+
+  // The body of code to execute no matter what happens in the first
+  // body of code.
   tree_statement_list *cleanup_code;
 };
 
@@ -214,6 +262,7 @@
 tree_try_catch_command : public tree_command
 {
 public:
+
   tree_try_catch_command (int l = -1, int c = -1)
     : tree_command (l, c), try_code (0), catch_code (0) { }
 
@@ -226,10 +275,18 @@
 
   void eval (void);
 
-  void print_code (ostream& os);
+  tree_statement_list *body (void) { return try_code; }
+
+  tree_statement_list *cleanup (void) { return catch_code; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // The first block of code to attempt to execute.
   tree_statement_list *try_code;
+
+  // The code to execute if an error occurs in the first block.
   tree_statement_list *catch_code;
 };
 
@@ -239,13 +296,14 @@
 tree_break_command : public tree_command
 {
 public:
+
   tree_break_command (int l = -1, int c = -1) : tree_command (l, c) { }
 
   ~tree_break_command (void) { }
 
   void eval (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 // Continue.
@@ -254,13 +312,14 @@
 tree_continue_command : public tree_command
 {
 public:
+
   tree_continue_command (int l = -1, int c = -1) : tree_command (l, c) { }
 
   ~tree_continue_command (void) { }
 
   void eval (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 // Return.
@@ -269,13 +328,14 @@
 tree_return_command : public tree_command
 {
 public:
+
   tree_return_command (int l = -1, int c = -1) : tree_command (l, c) { }
 
   ~tree_return_command (void) { }
 
   void eval (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 #endif
--- a/src/pt-const.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-const.cc	Sun May 12 07:16:36 1996 +0000
@@ -53,6 +53,7 @@
 #include "pr-output.h"
 #include "sysdep.h"
 #include "pt-const.h"
+#include "pt-walk.h"
 #include "unwind-prot.h"
 #include "user-prefs.h"
 #include "utils.h"
@@ -407,18 +408,9 @@
 }
 
 void
-octave_value::print_code (ostream& os)
+octave_value::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (rep)
-    rep->print_code (os);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_octave_value (*this);
 }
 
 // The real representation of constants.
@@ -2320,69 +2312,6 @@
 }
 
 void
-OCT_VAL_REP::print_code (ostream& os)
-{
-  switch (type_tag)
-    {
-    case scalar_constant:
-      if (orig_text.empty ())
-	octave_print_internal (os, scalar, 1);
-      else
-	os << orig_text;
-      break;
-
-    case matrix_constant:
-      octave_print_internal (os, *matrix, 1);
-      break;
-
-    case complex_scalar_constant:
-     {
-	double re = complex_scalar->real ();
-	double im = complex_scalar->imag ();
-
-	// If we have the original text and a pure imaginary, just
-	// print the original text, because this must be a constant
-	// that was parsed as part of a function.
-
-	if (! orig_text.empty () && re == 0.0 && im > 0.0)
-	  os << orig_text;
-	else
-	  octave_print_internal (os, *complex_scalar, 1);
-      }
-      break;
-
-    case complex_matrix_constant:
-      octave_print_internal (os, *complex_matrix, 1);
-      break;
-
-    case char_matrix_constant:
-      octave_print_internal (os, *char_matrix, 1);
-      break;
-
-    case char_matrix_constant_str:
-      octave_print_internal (os, *char_matrix, 1, 1);
-      break;
-
-    case range_constant:
-      octave_print_internal (os, *range, 1);
-      break;
-
-    case magic_colon:
-      os << ":";
-      break;
-
-    case all_va_args:
-      os << "all_va_args";
-      break;
-
-    case map_constant:
-    case unknown_constant:
-      panic_impossible ();
-      break;
-    }
-}
-
-void
 OCT_VAL_REP::gripe_wrong_type_arg (const char *name,
 			      const octave_value_rep& tcr) const
 {
--- a/src/pt-const.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-const.h	Sun May 12 07:16:36 1996 +0000
@@ -42,6 +42,8 @@
 class Octave_map;
 class octave_value_list;
 
+class tree_walker;
+
 // Constants.
 
 class
@@ -239,13 +241,13 @@
 
     void stash_original_text (const string& s);
 
+    string original_text (void) { return orig_text; }
+
     void maybe_mutate (void);
 
     void print (void);
     void print (ostream& os);
 
-    void print_code (ostream& os);
-
     void gripe_wrong_type_arg (const char *name,
 			       const octave_value_rep& tcr) const;
 
@@ -493,6 +495,7 @@
   bool is_real_matrix (void) const { return rep->is_real_matrix (); }
   bool is_complex_scalar (void) const { return rep->is_complex_scalar (); }
   bool is_complex_matrix (void) const { return rep->is_complex_matrix (); }
+  bool is_char_matrix (void) const { return rep->is_char_matrix (); }
   bool is_string (void) const { return rep->is_string (); }
   bool is_range (void) const { return rep->is_range (); }
   bool is_map (void) const { return rep->is_map (); }
@@ -645,9 +648,9 @@
   void stash_original_text (const string& s)
     { rep->stash_original_text (s); }
 
-  // Pretty print this constant.
- 
-  void print_code (ostream& os);
+  string original_text (void) { return rep->original_text (); }
+
+  void accept (tree_walker& tw);
 
   char *type_as_string (void) const
     { return rep->type_as_string (); }
--- a/src/pt-exp-base.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-exp-base.h	Sun May 12 07:16:36 1996 +0000
@@ -37,7 +37,6 @@
 tree_expression : public tree
 {
 public:
-  int in_parens;
 
   enum type
     {
@@ -110,11 +109,22 @@
 
   virtual bool is_logically_true (const char *);
 
+  virtual void mark_in_parens (void) { in_parens++; }
+
+  virtual bool is_in_parens (void) { return in_parens; }
+
+  virtual type expression_type (void) { return etype; }
+
   virtual void mark_for_possible_ans_assign (void);
 
   virtual octave_value eval (bool print) = 0;
 
 protected:
+
+  // Nonzero if this expression appears inside parentheses.
+  int in_parens;
+
+  // The type of this expression.
   type etype;
 };
 
--- a/src/pt-exp.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-exp.cc	Sun May 12 07:16:36 1996 +0000
@@ -43,6 +43,7 @@
 #include "pt-fvc.h"
 #include "pt-misc.h"
 #include "pt-mvr.h"
+#include "pt-walk.h"
 #include "user-prefs.h"
 #include "utils.h"
 
@@ -120,20 +121,9 @@
 }
 
 void
-tree_prefix_expression::print_code (ostream& os)
+tree_prefix_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  os << oper ();
-
-  if (id)
-    id->print_code (os);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_prefix_expression (*this);
 }
 
 // Postfix expressions.
@@ -199,20 +189,9 @@
 }
 
 void
-tree_postfix_expression::print_code (ostream& os)
+tree_postfix_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (id)
-    id->print_code (os);
-
-  os << oper ();
-
-  if (in_parens)
-    os << ")";
+  tw.visit_postfix_expression (*this);
 }
 
 // Unary expressions.
@@ -299,38 +278,9 @@
 }
 
 void
-tree_unary_expression::print_code (ostream& os)
+tree_unary_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  switch (etype)
-    {
-    case tree_expression::not:
-    case tree_expression::uminus:
-      os << oper ();
-      if (op)
-	op->print_code (os);
-      break;
-
-    case tree_expression::hermitian:
-    case tree_expression::transpose:
-      if (op)
-	op->print_code (os);
-      os << oper ();
-      break;
-
-    default:
-      os << oper ();
-      if (op)
-	op->print_code (os);
-      break;
-    }
-
-  if (in_parens)
-    os << ")";
+  tw.visit_unary_expression (*this);
 }
 
 // Binary expressions.
@@ -363,14 +313,14 @@
     case tree_expression::cmp_ne:
     case tree_expression::and:
     case tree_expression::or:
-      if (op1)
+      if (op_lhs)
 	{
-	  octave_value a = op1->eval (false);
+	  octave_value a = op_lhs->eval (false);
 	  if (error_state)
 	    eval_error ();
-	  else if (a.is_defined () && op2)
+	  else if (a.is_defined () && op_rhs)
 	    {
-	      octave_value b = op2->eval (false);
+	      octave_value b = op_rhs->eval (false);
 	      if (error_state)
 		eval_error ();
 	      else if (b.is_defined ())
@@ -391,9 +341,9 @@
     case tree_expression::or_or:
       {
 	bool result = false;
-	if (op1)
+	if (op_lhs)
 	  {
-	    octave_value a = op1->eval (false);
+	    octave_value a = op_lhs->eval (false);
 	    if (error_state)
 	      {
 		eval_error ();
@@ -424,9 +374,9 @@
 		  }
 	      }
 
-	    if (op2)
+	    if (op_rhs)
 	      {
-		octave_value b = op2->eval (false);
+		octave_value b = op_rhs->eval (false);
 		if (error_state)
 		  {
 		    eval_error ();
@@ -560,23 +510,9 @@
 }
 
 void
-tree_binary_expression::print_code (ostream& os)
+tree_binary_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (op1)
-    op1->print_code (os);
-
-  os << " " << oper () << " ";
-
-  if (op2)
-    op2->print_code (os);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_binary_expression (*this);
 }
 
 // Simple assignment expressions.
@@ -701,33 +637,9 @@
 }
 
 void
-tree_simple_assignment_expression::print_code (ostream& os)
+tree_simple_assignment_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (! is_ans_assign ())
-    {
-      if (lhs)
-	lhs->print_code (os);
-
-      if (index)
-	{
-	  os << " (";
-	  index->print_code (os);
-	  os << ")";
-	}
-
-      os << " = ";
-    }
-
-  if (rhs)
-    rhs->print_code (os);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_simple_assignment_expression (*this);
 }
 
 // Colon expressions.
@@ -735,22 +647,27 @@
 bool
 tree_colon_expression::is_range_constant (void) const
 {
-  bool tmp = (op1 && op1->is_constant ()
-	      && op2 && op2->is_constant ());
+  bool tmp = (op_base && op_base->is_constant ()
+	      && op_limit && op_limit->is_constant ());
 
-  return op3 ? (tmp && op3->is_constant ()) : tmp;
+  return op_increment ? (tmp && op_increment->is_constant ()) : tmp;
 }
 
 tree_colon_expression *
 tree_colon_expression::chain (tree_expression *t)
 {
   tree_colon_expression *retval = 0;
-  if (! op1 || op3)
+  if (! op_base || op_increment)
     ::error ("invalid colon expression");
   else
     {
-      op3 = op2;	// Stupid syntax.
-      op2 = t;
+      // Stupid syntax:
+      //
+      // base : limit
+      // base : increment : limit
+
+      op_increment = op_limit;
+      op_limit = t;
 
       retval = this;
     }
@@ -762,10 +679,10 @@
 {
   octave_value retval;
 
-  if (error_state || ! op1 || ! op2)
+  if (error_state || ! op_base || ! op_limit)
     return retval;
 
-  octave_value tmp = op1->eval (false);
+  octave_value tmp = op_base->eval (false);
 
   if (tmp.is_undefined ())
     {
@@ -782,7 +699,7 @@
       return retval;
     }
 
-  tmp = op2->eval (false);
+  tmp = op_limit->eval (false);
 
   if (tmp.is_undefined ())
     {
@@ -800,9 +717,10 @@
     }
 
   double inc = 1.0;
-  if (op3)
+
+  if (op_increment)
     {
-      tmp = op3->eval (false);
+      tmp = op_increment->eval (false);
 
       if (tmp.is_undefined ())
 	{
@@ -840,35 +758,11 @@
 }
 
 void
-tree_colon_expression::print_code (ostream& os)
+tree_colon_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (op1)
-    op1->print_code (os);
-
-  // Stupid syntax.
-
-  if (op3)
-    {
-      os << ":";
-      op3->print_code (os);
-    }
-
-  if (op2)
-    {
-      os << ":";
-      op2->print_code (os);
-    }
-
-  if (in_parens)
-    os << ")";
+  tw.visit_colon_expression (*this);
 }
 
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-exp.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-exp.h	Sun May 12 07:16:36 1996 +0000
@@ -34,6 +34,8 @@
 class tree_indirect_ref;
 class tree_argument_list;
 
+class tree_walker;
+
 #include "pt-exp-base.h"
 
 // Prefix expressions.
@@ -41,7 +43,8 @@
 class
 tree_prefix_expression : public tree_expression
 {
- public:
+public:
+
   tree_prefix_expression (int l = -1, int c = -1)
     : tree_expression (l, c), id (0) { }
 
@@ -60,9 +63,13 @@
 
   char *oper (void) const;
 
-  void print_code (ostream& os);
+  tree_identifier *ident (void) { return id; }
+
+  void accept (tree_walker& tw);
 
- private:
+private:
+
+  // Currently, a prefix expression can only apply to an identifier.
   tree_identifier *id;
 };
 
@@ -71,7 +78,8 @@
 class
 tree_postfix_expression : public tree_expression
 {
- public:
+public:
+
   tree_postfix_expression (int l = -1, int c = -1)
     : tree_expression (l, c), id (0) { }
 
@@ -87,9 +95,13 @@
 
   char *oper (void) const;
 
-  void print_code (ostream& os);
+  tree_identifier *ident (void) { return id; }
+
+  void accept (tree_walker& tw);
 
- private:
+private:
+
+  // Currently, a prefix expression can only apply to an identifier.
   tree_identifier *id;
 };
 
@@ -98,7 +110,8 @@
 class
 tree_unary_expression : public tree_expression
 {
- public:
+public:
+
   tree_unary_expression (int l = -1, int c = -1)
     : tree_expression (l, c), op (0) { }
 
@@ -115,9 +128,13 @@
 
   char *oper (void) const;
 
-  void print_code (ostream& os);
+  tree_expression *operand (void) { return op; }
+
+  void accept (tree_walker& tw);
 
- private:
+private:
+
+  // The operand for the expression.
   tree_expression *op;
 };
 
@@ -126,18 +143,19 @@
 class
 tree_binary_expression : public tree_expression
 {
- public:
+public:
+
   tree_binary_expression (int l = -1, int c = -1)
-    : tree_expression (l, c), op1 (0), op2 (0) { }
+    : tree_expression (l, c), op_lhs (0), op_rhs (0) { }
 
   tree_binary_expression (tree_expression *a, tree_expression *b,
 			  tree_expression::type t, int l = -1, int c = -1)
-    : tree_expression (l, c, t), op1 (a), op2 (b) { }
+    : tree_expression (l, c, t), op_lhs (a), op_rhs (b) { }
 
   ~tree_binary_expression (void)
     {
-      delete op1;
-      delete op2;
+      delete op_lhs;
+      delete op_rhs;
     }
 
   octave_value eval (bool print);
@@ -146,11 +164,16 @@
 
   char *oper (void) const;
 
-  void print_code (ostream& os);
+  tree_expression *lhs (void) { return op_lhs; }
+  tree_expression *rhs (void) { return op_rhs; }
+
+  void accept (tree_walker& tw);
 
- private:
-  tree_expression *op1;
-  tree_expression *op2;
+private:
+
+  // The operands for the expression.
+  tree_expression *op_lhs;
+  tree_expression *op_rhs;
 };
 
 // Simple assignment expressions.
@@ -158,19 +181,8 @@
 class
 tree_simple_assignment_expression : public tree_expression
 {
-private:
-  void init (bool plhs, bool ans_assign)
-    {
-      etype = tree_expression::assignment;
-      lhs_idx_expr = 0;
-      lhs = 0;
-      index = 0;
-      rhs = 0;
-      preserve = plhs;
-      ans_ass = ans_assign;
-    }
+public:
 
- public:
   tree_simple_assignment_expression (bool plhs = false,
 				     bool ans_assign = false,
 				     int l = -1, int c = -1)
@@ -217,15 +229,48 @@
 
   void eval_error (void);
 
-  void print_code (ostream& os);
+  tree_indirect_ref *left_hand_side (void) { return lhs; }
+
+  tree_argument_list *lhs_index (void) { return index; }
+
+  tree_expression *right_hand_side (void) { return rhs; }
+
+  void accept (tree_walker& tw);
 
- private:
+private:
+
+  // The left hand side of the assignment, as an index expression.  If
+  // the assignment is constructed from an index expression, the index
+  // expression is split into the its components in the constructor.
   tree_index_expression *lhs_idx_expr;
+
+  // The indirect reference (id or structure reference) on the left
+  // hand side of the assignemnt.
   tree_indirect_ref *lhs;
+
+  // The index of the left hand side of the assignment, if any.
   tree_argument_list *index;
+
+  // The right hand side of the assignment.
   tree_expression *rhs;
+
+  // True if we should not delete the lhs.
   bool preserve;
+
+  // True if this is an assignment to the built-in variable ans.
   bool ans_ass;
+
+  void init (bool plhs, bool ans_assign)
+    {
+      etype = tree_expression::assignment;
+      lhs_idx_expr = 0;
+      lhs = 0;
+      index = 0;
+      rhs = 0;
+      preserve = plhs;
+      ans_ass = ans_assign;
+    }
+
 };
 
 // Colon expressions.
@@ -233,21 +278,22 @@
 class
 tree_colon_expression : public tree_expression
 {
- public:
+public:
+
   tree_colon_expression (int l = -1, int c = -1)
     : tree_expression (l, c, tree_expression::colon),
-      op1(0), op2 (0), op3 (0) { }
+      op_base (0), op_limit (0), op_increment (0) { }
 
   tree_colon_expression (tree_expression *a, tree_expression *b,
 			 int l = -1, int c = -1)
     : tree_expression (l, c, tree_expression::colon),
-      op1 (a), op2 (b), op3 (0) { }
+      op_base (a), op_limit (b), op_increment (0) { }
 
   ~tree_colon_expression (void)
     {
-      delete op1;
-      delete op2;
-      delete op3;
+      delete op_base;
+      delete op_limit;
+      delete op_increment;
     }
 
   bool is_range_constant (void) const;
@@ -258,12 +304,18 @@
 
   void eval_error (const char *s);
 
-  void print_code (ostream& os);
+  tree_expression *base (void) { return op_base; }
+  tree_expression *limit (void) { return op_limit; }
+  tree_expression *increment (void) { return op_increment; }
+
+  void accept (tree_walker& tw);
 
- private:
-  tree_expression *op1;
-  tree_expression *op2;
-  tree_expression *op3;
+private:
+
+  // The components of the expression.
+  tree_expression *op_base;
+  tree_expression *op_limit;
+  tree_expression *op_increment;
 };
 
 #endif
--- a/src/pt-fcn.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-fcn.cc	Sun May 12 07:16:36 1996 +0000
@@ -41,6 +41,8 @@
 #include "pt-exp.h"
 #include "pt-fcn.h"
 #include "pt-misc.h"
+#include "pt-pr-code.h"
+#include "pt-walk.h"
 #include "unwind-prot.h"
 #include "user-prefs.h"
 #include "utils.h"
@@ -396,87 +398,25 @@
 }
 
 void
-tree_function::print_code (ostream& os)
-{
-  print_code_reset ();
-
-  print_code_function_header (os);
-
-  if (cmd_list)
-    {
-      increment_indent_level ();
-      cmd_list->print_code (os);
-      decrement_indent_level ();
-    }
-
-  print_code_function_trailer (os);
-}
-
-void
 tree_function::print_code_function_header (void)
 {
-  print_code_function_header (octave_stdout);
-}
-
-void
-tree_function::print_code_function_header (ostream& os)
-{
-  print_code_indent (os);
-
-  os << "function ";
-
-  if (ret_list)
-    {
-      int len = ret_list->length ();
-
-      if (len > 1)
-	os << "[";
-
-      ret_list->print_code (os);
-
-      if (len > 1)
-	os << "]";
+  tree_print_code tpc (octave_stdout);
 
-      os << " = ";
-    }
-
-  os << (fcn_name.empty () ? string ("(empty)") : fcn_name) << " ";
-
-  if (param_list)
-    {
-      int len = param_list->length ();
-      if (len > 0)
-	os << "(";
-
-      param_list->print_code (os);
-
-      if (len > 0)
-	{
-	  os << ")";
-	  print_code_new_line (os);
-	}
-    }
-  else
-    {
-      os << "()";
-      print_code_new_line (os);
-    }
+  tpc.visit_function_header (*this);
 }
 
 void
 tree_function::print_code_function_trailer (void)
 {
-  print_code_function_trailer (octave_stdout);
+  tree_print_code tpc (octave_stdout);
+
+  tpc.visit_function_trailer (*this);
 }
 
 void
-tree_function::print_code_function_trailer (ostream& os)
+tree_function::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  os << "endfunction";
-
-  print_code_new_line (os);
+  tw.visit_function (*this);
 }
 
 DEFUN (va_arg, args, ,
--- a/src/pt-fcn.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-fcn.h	Sun May 12 07:16:36 1996 +0000
@@ -37,6 +37,8 @@
 class tree_statement_list;
 class tree_va_return_list;
 
+class tree_walker;
+
 #include "oct-obj.h"
 #include "symtab.h"
 #include "pt-fvc.h"
@@ -46,27 +48,8 @@
 class
 tree_function : public tree_fvc
 {
-private:
-  void install_nargin_and_nargout (void);
-
-  void bind_nargin_and_nargout (int nargin, int nargout);
+public:
 
-  void init (void)
-    {
-      call_depth = 0;
-      param_list = 0;
-      ret_list = 0;
-      sym_tab = 0;
-      cmd_list = 0;
-      t_parsed = 0;
-      system_fcn_file = 0;
-      num_named_args = 0;
-      num_args_passed = 0;
-      curr_va_arg_number = 0;
-      vr_list = 0;
-    }
-
-public:
   tree_function (int l = -1, int c = -1) : tree_fvc (l, c)
     { init (); }
 
@@ -126,31 +109,89 @@
 
   void traceback_error (void);
 
-  void print_code (ostream& os);
+  tree_parameter_list *parameter_list (void) { return param_list; }
+
+  tree_parameter_list *return_list (void) { return ret_list; }
+
+  tree_statement_list *body (void) { return cmd_list; }
+
+  void accept (tree_walker& tw);
 
 private:
-  int call_depth;
+
+  // List of arguments for this function.  These are local variables.
   tree_parameter_list *param_list;
+
+  // List of parameters we return.  These are also local variables in
+  // this function.
   tree_parameter_list *ret_list;
+
+  // The list of commands that make up the body of this function.
+  tree_statement_list *cmd_list;
+
+  // The local symbol table for this function.
   symbol_table *sym_tab;
-  tree_statement_list *cmd_list;
+
+  // Used to keep track of recursion depth.
+  int call_depth;
+
+  // The name of the file we parsed
   string file_name;
+
+  // The name of the function.
   string fcn_name;
+
+  // The time the file was parsed.
   time_t t_parsed;
+
+  // True if this function came from a file that is considered to be a
+  // system function.  This affects whether we check the time stamp
+  // on the file to see if it has changed.
   bool system_fcn_file;
+
+  // The number of arguments that have names.
   int num_named_args;
+
+  // The values that were passed as arguments.
   octave_value_list args_passed;
+
+  // The number of arguments passed in.
   int num_args_passed;
+
+  // Used to keep track of the current offset into the list of va_args.
   int curr_va_arg_number;
+
+  // The list of return values when an unspecified number can be
+  // returned.
   tree_va_return_list *vr_list;
+
+  // The symbol record for nargin in the local symbol table.
   symbol_record *nargin_sr;
+
+  // The symbol record for nargout in the local symbol table.
   symbol_record *nargout_sr;
 
   void print_code_function_header (void);
-  void print_code_function_header (ostream& os);
+  void print_code_function_trailer (void);
+
+  void install_nargin_and_nargout (void);
+
+  void bind_nargin_and_nargout (int nargin, int nargout);
 
-  void print_code_function_trailer (void);
-  void print_code_function_trailer (ostream& os);
+  void init (void)
+    {
+      call_depth = 0;
+      param_list = 0;
+      ret_list = 0;
+      sym_tab = 0;
+      cmd_list = 0;
+      t_parsed = 0;
+      system_fcn_file = 0;
+      num_named_args = 0;
+      num_args_passed = 0;
+      curr_va_arg_number = 0;
+      vr_list = 0;
+    }
 };
 
 #endif
--- a/src/pt-fvc.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-fvc.cc	Sun May 12 07:16:36 1996 +0000
@@ -41,6 +41,7 @@
 #include "symtab.h"
 #include "pt-const.h"
 #include "pt-fvc.h"
+#include "pt-walk.h"
 #include "user-prefs.h"
 #include "utils.h"
 
@@ -443,18 +444,9 @@
 }
 
 void
-tree_identifier::print_code (ostream& os)
+tree_identifier::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  string nm = name ();
-  os << (nm.empty () ? string ("(empty)") : nm);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_identifier (*this);
 }
 
 // Indirect references to values (structure elements).
@@ -591,21 +583,9 @@
 }
 
 void
-tree_indirect_ref::print_code (ostream& os)
+tree_indirect_ref::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  string nm = id ? id->name () : string ("(null)");
-  os << (nm.empty () ? string ("(empty)") : nm);
-
-  for (Pix p = refs.first (); p != 0; refs.next (p))
-    os << "." << refs (p);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_indirect_ref (*this);
 }
 
 // Builtin functions.
@@ -818,9 +798,9 @@
 }
 
 void
-tree_builtin::print_code (ostream& os)
+tree_builtin::accept (tree_walker& tw)
 {
-  os << my_name << " can't be printed because it is a builtin function\n";
+  tw.visit_builtin (*this);
 }
 
 /*
--- a/src/pt-fvc.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-fvc.h	Sun May 12 07:16:36 1996 +0000
@@ -34,6 +34,8 @@
 class symbol_record;
 class tree_function;
 
+class tree_walker;
+
 #include "mappers.h"
 #include "pt-fvc-base.h"
 #include "variables.h"
@@ -46,6 +48,7 @@
   friend class tree_index_expression;
 
 public:
+
   tree_identifier (int l = -1, int c = -1)
     : tree_fvc (l, c), sym (0), maybe_do_ans_assign (false) { }
 
@@ -90,10 +93,15 @@
 
   void eval_undefined_error (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 
 private:
+
+  // The symbol record that this identifier references.
   symbol_record *sym;
+
+  // True if we should consider assigning the result of evaluating
+  // this identifier to the built-in variable ans.
   bool maybe_do_ans_assign;
 };
 
@@ -103,6 +111,7 @@
 tree_indirect_ref : public tree_fvc
 {
 public:
+
   tree_indirect_ref (int l = -1, int c = -1)
     : tree_fvc (l, c), id (0), preserve_ident (false) { }
 
@@ -135,13 +144,24 @@
 
   octave_value eval (bool print);
 
-  octave_value_list eval (bool print, int nargout, const octave_value_list& args);
+  octave_value_list eval (bool print, int nargout,
+			  const octave_value_list& args);
 
-  void print_code (ostream& os);
+  SLList<string> references (void) { return refs; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // The identifier for this structure reference.  For example, in
+  // a.b, a is the id.
   tree_identifier *id;
+
+  // The list of sub-element names.  For example, in a.b.c, refs
+  // contains the strings b and c.
   SLList<string> refs;
+
+  // True if we should not delete the identifier.
   bool preserve_ident;
 };
 
@@ -151,6 +171,7 @@
 tree_builtin : public tree_fvc
 {
 public:
+
   tree_builtin (const string& nm = string ());
 
   tree_builtin (const builtin_mapper_function& m_fcn,
@@ -172,12 +193,20 @@
   string name (void) const
     { return my_name; }
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 
 private:
+
+  // True if this is a mapper function.
   bool is_mapper;
+
+  // A structure describing the mapper function.
   builtin_mapper_function mapper_fcn;
+
+  // The actual function, if it is not a mapper.
   Octave_builtin_fcn fcn;
+
+  // The name of this function.
   string my_name;
 };
 
--- a/src/pt-mat.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-mat.cc	Sun May 12 07:16:36 1996 +0000
@@ -39,6 +39,7 @@
 #include "pt-mat.h"
 #include "pt-misc.h"
 #include "pt-mvr.h"
+#include "pt-walk.h"
 #include "user-prefs.h"
 
 // General matrices.  This list type is much more work to handle than
@@ -393,24 +394,9 @@
 }
 
 void
-tree_matrix_row::print_code (ostream& os)
+tree_matrix_row::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  while (p)
-    {
-      tree_expression *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << ", ";
-	}
-    }
+  tw.visit_matrix_row (*this);
 }
 
 bool
@@ -534,36 +520,9 @@
 }
 
 void
-tree_matrix::print_code (ostream& os)
+tree_matrix::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  os << "[";
-
-  Pix p = first ();
-
-  while (p)
-    {
-      tree_matrix_row *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << "; ";
-	}
-    }
-
-  os << "]";
-
-  if (in_parens)
-    os << ")";
+  tw.visit_matrix (*this);
 }
 
 /*
--- a/src/pt-mat.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-mat.h	Sun May 12 07:16:36 1996 +0000
@@ -32,6 +32,8 @@
 class octave_value;
 class tree_return_list;
 
+class tree_walker;
+
 #include <SLList.h>
 
 #include "pt-exp.h"
@@ -56,7 +58,7 @@
 
   tree_return_list *to_return_list (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 class
@@ -77,7 +79,7 @@
 
   octave_value eval (bool print);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 #endif
--- a/src/pt-misc.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-misc.cc	Sun May 12 07:16:36 1996 +0000
@@ -46,6 +46,8 @@
 #include "pt-fvc.h"
 #include "pt-misc.h"
 #include "pt-mvr.h"
+#include "pt-walk.h"
+#include "pt-pr-code.h"
 #include "user-prefs.h"
 
 // Nonzero means we're breaking out of a loop or function body.
@@ -61,22 +63,20 @@
 
 tree_statement::~tree_statement (void)
 {
-  delete command;
-  delete expression;
+  delete cmd;
+  delete expr;
 }
 
 int
 tree_statement::line (void)
 {
-  return command
-    ? command->line () : (expression ? expression->line () : -1);
+  return cmd ? cmd->line () : (expr ? expr->line () : -1);
 }
 
 int
 tree_statement::column (void)
 {
-  return command
-    ? command->column () : (expression ? expression->column () : -1);
+  return cmd ? cmd->column () : (expr ? expr->column () : -1);
 }
 
 void
@@ -84,30 +84,17 @@
 {
   if (in_function_body
       && (user_pref.echo_executing_commands & ECHO_FUNCTIONS))
-    print_code (octave_stdout);
+    {
+      tree_print_code tpc (octave_stdout);
+
+      accept (tpc);
+    }
 }
 
 void
-tree_statement::print_code (ostream& os)
+tree_statement::accept (tree_walker& tw)
 {
-  if (command)
-    {
-      command->print_code (os);
-
-      if (! print_flag)
-	os << ";";
-
-      command->print_code_new_line (os);
-    }
-  else if (expression)
-    {
-      expression->print_code (os);
-
-      if (! print_flag)
-	os << ";";
-
-      expression->print_code_new_line (os);
-    }
+  tw.visit_statement (*this);
 }
 
 octave_value
@@ -128,8 +115,8 @@
       else
 	pf = elt->print_flag;
 
-      tree_command *cmd = elt->command;
-      tree_expression *expr = elt->expression;
+      tree_command *cmd = elt->command ();
+      tree_expression *expr = elt->expression ();
 
       if (cmd || expr)
 	{
@@ -176,8 +163,8 @@
 	  else
 	    pf = elt->print_flag;
 
-	  tree_command *cmd = elt->command;
-	  tree_expression *expr = elt->expression;
+	  tree_command *cmd = elt->command ();
+	  tree_expression *expr = elt->expression ();
 
 	  if (cmd || expr)
 	    {
@@ -218,15 +205,9 @@
 }
 
 void
-tree_statement_list::print_code (ostream& os)
+tree_statement_list::accept (tree_walker& tw)
 {
-  for (Pix p = first (); p != 0; next (p))
-    {
-      tree_statement *elt = this->operator () (p);
-
-      if (elt)
-	elt->print_code (os);
-    }
+  tw.visit_statement_list (*this);
 }
 
 octave_value_list
@@ -292,24 +273,9 @@
 }
 
 void
-tree_argument_list::print_code (ostream& os)
+tree_argument_list::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  while (p)
-    {
-      tree_expression *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << ", ";
-	}
-    }
+  tw.visit_argument_list (*this);
 }
 
 // Parameter lists.
@@ -433,24 +399,9 @@
 }
 
 void
-tree_parameter_list::print_code (ostream& os)
+tree_parameter_list::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  while (p)
-    {
-      tree_identifier *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << ", ";
-	}
-    }
+  tw.visit_parameter_list (*this);
 }
 
 // Return lists.
@@ -465,49 +416,35 @@
 }
 
 void
-tree_return_list::print_code (ostream& os)
+tree_return_list::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  while (p)
-    {
-      tree_index_expression *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << ", ";
-	}
-    }
+  tw.visit_return_list (*this);
 }
 
 // Global.
 
 tree_global::~tree_global (void)
 {
-  delete ident;
-  delete assign_expr;
+  delete id;
+  delete ass_expr;
 }
 
 void
 tree_global::eval (void)
 {
-  if (ident)
+  if (id)
     {
-      ident->link_to_global ();
+      id->link_to_global ();
     }
-  else if (assign_expr)
+  else if (ass_expr)
     {
-      tree_identifier *id = 0;
-      if (assign_expr->left_hand_side_is_identifier_only ()
-	  && (id = assign_expr->left_hand_side_id ()))
+      tree_identifier *idnt = 0;
+
+      if (ass_expr->left_hand_side_is_identifier_only ()
+	  && (idnt = ass_expr->left_hand_side_id ()))
 	{
-	  id->link_to_global ();
-	  assign_expr->eval (false);
+	  idnt->link_to_global ();
+	  ass_expr->eval (false);
 	}
       else
 	error ("global: unable to make individual structure elements global");
@@ -515,13 +452,9 @@
 }
 
 void
-tree_global::print_code (ostream& os)
+tree_global::accept (tree_walker& tw)
 {
-  if (ident)
-    ident->print_code (os);
-
-  if (assign_expr)
-    assign_expr->print_code (os);
+  tw.visit_global (*this);
 }
 
 // Global initializer lists.
@@ -537,24 +470,9 @@
 }
 
 void
-tree_global_init_list::print_code (ostream& os)
+tree_global_init_list::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  while (p)
-    {
-      tree_global *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << ", ";
-	}
-    }
+  tw.visit_global_init_list (*this);
 }
 
 // If.
@@ -580,21 +498,9 @@
 }
 
 void
-tree_if_clause::print_code (ostream& os)
+tree_if_clause::accept (tree_walker& tw)
 {
-  if (expr)
-    expr->print_code (os);
-
-  print_code_new_line (os);
-
-  increment_indent_level ();
-
-  if (list)
-    {
-      list->print_code (os);
-
-      decrement_indent_level ();
-    }
+  tw.visit_if_clause (*this);
 }
 
 // List of if commands.
@@ -612,34 +518,9 @@
 }
 
 void
-tree_if_command_list::print_code (ostream& os)
+tree_if_command_list::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  bool first_elt = true;
-
-  while (p)
-    {
-      tree_if_clause *elt = this->operator () (p);
-
-      if (elt)
-	{
-	  if (! first_elt)
-	    {
-	      print_code_indent (os);
-
-	      if (elt->is_else_clause ())
-		os << "else";
-	      else
-		os << "elseif ";
-	    }
-
-	  elt->print_code (os);
-	}
-
-      first_elt = false;
-      next (p);
-    }
+  tw.visit_if_command_list (*this);
 }
 
 /*
--- a/src/pt-misc.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-misc.h	Sun May 12 07:16:36 1996 +0000
@@ -48,26 +48,30 @@
 class tree_global;
 class tree_global_init_list;
 
+class tree_walker;
+
 #include <SLList.h>
 
 #include "pt-base.h"
 
-// A list of expressions and commands to be executed.
+// A statement is either a command to execute or an expression to
+// evaluate.
 
 class
-tree_statement : public tree_print_code
+tree_statement
 {
 friend class tree_statement_list;
 
 public:
+
   tree_statement (void)
-    : tree_print_code (), command (0), expression (0), print_flag (true) { }
+    : cmd (0), expr (0), print_flag (true) { }
 
   tree_statement (tree_command *c)
-    : tree_print_code (), command (c), expression (0), print_flag (true) { }
+    : cmd (c), expr (0), print_flag (true) { }
 
   tree_statement (tree_expression *e)
-    : tree_print_code (), command (0), expression (e), print_flag (true) { }
+    : cmd (0), expr (e), print_flag (true) { }
 
   ~tree_statement (void);
 
@@ -75,35 +79,50 @@
     { print_flag = print; }
 
   bool is_command (void)
-    { return command != 0; }
+    { return cmd != 0; }
 
   bool is_expression (void)
-    { return expression != 0; }
+    { return expr != 0; }
 
   int line (void);
   int column (void);
 
   void maybe_echo_code (bool);
 
-  void print_code (ostream& os);
+  bool print_result (void) { return print_flag; }
+
+  tree_command *command (void) { return cmd; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker& tw);
 
 private:
-  tree_command *command;	// Command to execute.
-  tree_expression *expression;	// Command to execute.
-  bool print_flag;		// Print result of eval for this command?
+
+  // Only one of cmd or expr can be valid at once.
+
+  // Command to execute.
+  tree_command *cmd;
+
+  // Expression to evaluate.
+  tree_expression *expr;
+
+  // Print result of eval for this command?
+  bool print_flag;
 };
 
+// A list of statements to evaluate.
+
 class
-tree_statement_list : public SLList<tree_statement *>, public tree_print_code
+tree_statement_list : public SLList<tree_statement *>
 {
 public:
+
   tree_statement_list (void)
-    : SLList<tree_statement *> (), tree_print_code (), function_body (false)
-      { }
+    : SLList<tree_statement *> (), function_body (false) { }
 
   tree_statement_list (tree_statement *s)
-    : SLList<tree_statement *> (), tree_print_code (), function_body (false)
-      { append (s); }
+    : SLList<tree_statement *> (), function_body (false) { append (s); }
 
   ~tree_statement_list (void)
     {
@@ -120,9 +139,11 @@
 
   octave_value_list eval (bool print, int nargout);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 
 private:
+
+  // Does this list of statements make up the body of a function?
   bool function_body;
 };
 
@@ -130,15 +151,15 @@
 // arguments in a function call or index expression.
 
 class
-tree_argument_list : public SLList<tree_expression *>, public tree_print_code
+tree_argument_list : public SLList<tree_expression *>
 {
 public:
+
   tree_argument_list (void)
-    : SLList<tree_expression *> (), tree_print_code () { }
+    : SLList<tree_expression *> () { }
 
   tree_argument_list (tree_expression *t)
-    : SLList<tree_expression *> (), tree_print_code ()
-      { append (t); }
+    : SLList<tree_expression *> () { append (t); }
 
   ~tree_argument_list (void)
     {
@@ -151,7 +172,7 @@
 
   octave_value_list convert_to_const_vector (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 // Parameter lists.  Used to hold the list of input and output
@@ -159,22 +180,18 @@
 // only.
 
 class
-tree_parameter_list : public SLList<tree_identifier *>, public tree_print_code
+tree_parameter_list : public SLList<tree_identifier *>
 {
 public:
+
   tree_parameter_list (void)
-    : SLList<tree_identifier *> (), tree_print_code (),
-      marked_for_varargs (0) { }
+    : SLList<tree_identifier *> (), marked_for_varargs (0) { }
 
   tree_parameter_list (tree_identifier *t)
-    : SLList<tree_identifier *> (), tree_print_code (),
-      marked_for_varargs (0)
-      { append (t); }
+    : SLList<tree_identifier *> (), marked_for_varargs (0) { append (t); }
 
   ~tree_parameter_list (void);
 
-//  char *name (void) const;
-
   void mark_as_formal_parameters (void);
 
   void mark_varargs (void)
@@ -197,9 +214,10 @@
 
   octave_value_list convert_to_const_vector (tree_va_return_list *vr_list);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 
 private:
+
   int marked_for_varargs;
 };
 
@@ -207,26 +225,26 @@
 // assignment expressions.
 
 class
-tree_return_list : public SLList<tree_index_expression *>,
-  public tree_print_code 
+tree_return_list : public SLList<tree_index_expression *>
 {
 public:
+
   tree_return_list (void)
-    : SLList<tree_index_expression *> (), tree_print_code () { }
+    : SLList<tree_index_expression *> () { }
 
   tree_return_list (tree_index_expression *t)
-    : SLList<tree_index_expression *> (), tree_print_code ()
-      { append (t); }
+    : SLList<tree_index_expression *> () { append (t); }
 
   ~tree_return_list (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 class
 tree_va_return_list : public SLList<octave_value>
 {
 public:
+
   tree_va_return_list (void) : SLList<octave_value> () { }
 
   ~tree_va_return_list (void) { }
@@ -235,38 +253,51 @@
 // List of expressions that make up a global statement.
 
 class
-tree_global : public tree_print_code
+tree_global
 {
 public:
-  tree_global (void) : tree_print_code (), ident (0), assign_expr (0) { }
 
-  tree_global (tree_identifier *id)
-    : tree_print_code (), ident (id), assign_expr (0) { }
+  tree_global (void)
+    : id (0), ass_expr (0) { }
+
+  tree_global (tree_identifier *i)
+    : id (i), ass_expr (0) { }
 
   tree_global (tree_simple_assignment_expression *ass)
-    : tree_print_code (), ident (0), assign_expr (ass) { }
+    : id (0), ass_expr (ass) { }
 
   ~tree_global (void);
 
   void eval (void);
 
-  void print_code (ostream& os);
+  tree_identifier *ident (void) { return id; }
+
+  tree_simple_assignment_expression *assign_expr (void) { return ass_expr; }
+
+  void accept (tree_walker& tw);
 
 private:
-  tree_identifier *ident;
-  tree_simple_assignment_expression *assign_expr;
+
+  // Only one of id or ass_expr can be valid at once.
+
+  // An identifier to make global.
+  tree_identifier *id;
+
+  // An assignemnt expression.  Valid only if the left hand side of
+  // the assignment is a simple identifier.
+  tree_simple_assignment_expression *ass_expr;
 };
 
 class
-tree_global_init_list : public SLList<tree_global *>, public tree_print_code
+tree_global_init_list : public SLList<tree_global *>
 {
 public:
+
   tree_global_init_list (void)
-    : SLList<tree_global *> (), tree_print_code () { }
+    : SLList<tree_global *> () { }
 
   tree_global_init_list (tree_global *t)
-    : SLList<tree_global *> (), tree_print_code ()
-      { append (t); }
+    : SLList<tree_global *> () { append (t); }
 
   ~tree_global_init_list (void)
     {
@@ -279,20 +310,21 @@
 
   void eval (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 class
-tree_if_clause : public tree_print_code
+tree_if_clause
 {
 public:
-  tree_if_clause (void) : tree_print_code (), expr (0), list (0) { }
+
+  tree_if_clause (void) : expr (0), list (0) { }
 
   tree_if_clause (tree_statement_list *l)
-    : tree_print_code (), expr (0), list (l) { }
+    : expr (0), list (l) { }
 
   tree_if_clause (tree_expression *e, tree_statement_list *l)
-    : tree_print_code (), expr (e), list (l) { }
+    : expr (e), list (l) { }
 
   ~tree_if_clause (void);
 
@@ -301,23 +333,31 @@
 
   int eval (void);
 
-  void print_code (ostream& os);
+  tree_expression *condition (void) { return expr; }
+
+  tree_statement_list *commands (void) { return list; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // The condition to test.
   tree_expression *expr;
+
+  // The list of statements to evaluate if expr is true.
   tree_statement_list *list;
 };
 
 class
-tree_if_command_list : public SLList<tree_if_clause *>, public tree_print_code
+tree_if_command_list : public SLList<tree_if_clause *>
 {
 public:
+
   tree_if_command_list (void)
-    : SLList<tree_if_clause *> (), tree_print_code () { }
+    : SLList<tree_if_clause *> () { }
 
   tree_if_command_list (tree_if_clause *t)
-    : SLList<tree_if_clause *> (), tree_print_code ()
-      { append (t); }
+    : SLList<tree_if_clause *> () { append (t); }
 
   ~tree_if_command_list (void)
     {
@@ -330,7 +370,7 @@
 
   void eval (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 #endif
--- a/src/pt-mvr-base.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-mvr-base.h	Sun May 12 07:16:36 1996 +0000
@@ -38,6 +38,7 @@
 tree_multi_val_ret : public tree_expression
 {
 public:
+
   tree_multi_val_ret (int l = -1, int c = -1) : tree_expression (l, c) { }
 
   tree_multi_val_ret (int l = -1, int c = -1, tree_expression::type et)
--- a/src/pt-mvr.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-mvr.cc	Sun May 12 07:16:36 1996 +0000
@@ -38,6 +38,7 @@
 #include "pt-fvc.h"
 #include "pt-misc.h"
 #include "pt-mvr.h"
+#include "pt-walk.h"
 #include "user-prefs.h"
 
 // But first, some extra functions used by the tree classes.
@@ -71,6 +72,12 @@
   return values;
 }
 
+void
+tree_oct_obj::accept (tree_walker& tw)
+{
+  tw.visit_oct_obj (*this);
+}
+
 // Index expressions.
 
 tree_index_expression::tree_index_expression
@@ -239,25 +246,9 @@
 }
 
 void
-tree_index_expression::print_code (ostream& os)
+tree_index_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (id)
-    id->print_code (os);
-
-  if (list)
-    {
-      os << " (";
-      list->print_code (os);
-      os << ")";
-    }
-
-  if (in_parens)
-    os << ")";
+  tw.visit_index_expression (*this);
 }
 
 // Multi-valued assignmnt expressions.
@@ -375,33 +366,9 @@
 }
 
 void
-tree_multi_assignment_expression::print_code (ostream& os)
+tree_multi_assignment_expression::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  if (in_parens)
-    os << "(";
-
-  if (lhs)
-    {
-      int len = lhs->length ();
-
-      if (len > 1)
-	os << "[";
-
-      lhs->print_code (os);
-
-      if (len > 1)
-	os << "]";
-    }
-
-  os << " = ";
-
-  if (rhs)
-    rhs->print_code (os);
-
-  if (in_parens)
-    os << ")";
+  tw.visit_multi_assignment_expression (*this);
 }
 
 /*
--- a/src/pt-mvr.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-mvr.h	Sun May 12 07:16:36 1996 +0000
@@ -37,6 +37,8 @@
 class tree_indirect_ref;
 class tree_return_list;
 
+class tree_walker;
+
 #include <string>
 
 #include "pt-const.h"
@@ -49,6 +51,7 @@
 tree_oct_obj : public tree_multi_val_ret
 {
 public:
+
   tree_oct_obj (int l = -1, int c = -1) : tree_multi_val_ret (l, c) { }
 
   tree_oct_obj (const octave_value_list& v, int l = -1, int c = -1)
@@ -58,11 +61,13 @@
 
   octave_value eval (bool print);
 
-  octave_value_list eval (bool print, int nargout, const octave_value_list& args);
+  octave_value_list eval (bool print, int nargout,
+			  const octave_value_list& args);
 
-  void print_code (ostream&) { }
+  void accept (tree_walker& tw);
 
 private:
+
   const octave_value_list values;
 };
 
@@ -72,6 +77,7 @@
 tree_index_expression : public tree_multi_val_ret
 {
 public:
+
   tree_index_expression (int l = -1, int c = -1)
     : tree_multi_val_ret (l, c), id (0), list (0) { }
 
@@ -108,10 +114,12 @@
 
   void eval_error (void);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 
- private:
+private:
+
   tree_indirect_ref *id;
+
   tree_argument_list *list;
 };
 
@@ -120,7 +128,8 @@
 class
 tree_multi_assignment_expression : public tree_multi_val_ret
 {
- public:
+public:
+
   tree_multi_assignment_expression (bool plhs = false, int l = -1, int c = -1)
     : tree_multi_val_ret (l, c, tree_expression::multi_assignment),
       preserve (plhs), lhs (0), rhs (0) { }
@@ -143,9 +152,14 @@
 
   void eval_error (void);
 
-  void print_code (ostream& os);
+  tree_return_list *left_hand_side (void) { return lhs; }
+
+  tree_multi_val_ret *right_hand_side (void) { return rhs; }
 
- private:
+  void accept (tree_walker& tw);
+
+private:
+
   bool preserve;
   tree_return_list *lhs;
   tree_multi_val_ret *rhs;
--- a/src/pt-plot.cc	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-plot.cc	Sun May 12 07:16:36 1996 +0000
@@ -57,6 +57,7 @@
 #include "pt-cmd.h"
 #include "pt-exp.h"
 #include "pt-plot.h"
+#include "pt-walk.h"
 #include "sysdep.h"
 #include "user-prefs.h"
 #include "utils.h"
@@ -321,34 +322,9 @@
 }
 
 void
-tree_plot_command::print_code (ostream& os)
+tree_plot_command::accept (tree_walker& tw)
 {
-  print_code_indent (os);
-
-  switch (ndim)
-    {
-    case 1:
-      os << "replot";
-      break;
-
-    case 2:
-      os << "gplot";
-      break;
-
-    case 3:
-      os << "gsplot";
-      break;
-
-    default:
-      os << "<unkown plot command>";
-      break;
-    }
-
-  if (range)
-    range->print_code (os);
-
-  if (plot_list)
-    plot_list->print_code (os);
+  tw.visit_plot_command (*this);
 }
 
 plot_limits::~plot_limits (void)
@@ -379,16 +355,9 @@
 }
 
 void
-plot_limits::print_code (ostream& os)
+plot_limits::accept (tree_walker& tw)
 {
-  if (x_range)
-    x_range->print_code (os);
-
-  if (y_range)
-    y_range->print_code (os);
-
-  if (z_range)
-    z_range->print_code (os);
+  tw.visit_plot_limits (*this);
 }
 
 plot_range::~plot_range (void)
@@ -438,19 +407,9 @@
 }
 
 void
-plot_range::print_code (ostream& os)
+plot_range::accept (tree_walker& tw)
 {
-  os << " [";
-
-  if (lower)
-    lower->print_code (os);
-
-  os << ":";
-
-  if (upper)
-    upper->print_code (os);
-
-  os << "]";
+  tw.visit_plot_range (*this);
 }
 
 subplot_using::~subplot_using (void)
@@ -461,14 +420,14 @@
 int
 subplot_using::eval (int ndim, int n_max)
 {
-  if ((ndim == 2 && qualifier_count > 4)
-      || (ndim == 3 && qualifier_count > 3))
+  if ((ndim == 2 && qual_count > 4)
+      || (ndim == 3 && qual_count > 3))
     return -1;
 
-  if (qualifier_count > 0)
-    val.resize (qualifier_count);
+  if (qual_count > 0)
+    val.resize (qual_count);
 
-  for (int i = 0; i < qualifier_count; i++)
+  for (int i = 0; i < qual_count; i++)
     {
       if (x[i])
 	{
@@ -535,7 +494,7 @@
   if (status < 0)
     return -1;
 
-  for (int i = 0; i < qualifier_count; i++)
+  for (int i = 0; i < qual_count; i++)
     {
       if (i == 0)
 	plot_buf << " " << GNUPLOT_COMMAND_USING << " ";
@@ -549,57 +508,27 @@
 }
 
 void
-subplot_using::print_code (ostream& os)
-{
-  os << " using ";
-  for (int i = 0; i < qualifier_count; i++)
-    {
-      if (i > 0)
-	os << ":";
-
-      if (x[i])
-	x[i]->print_code (os);
-    }
-}
-
-subplot_style::subplot_style (const string& s)
+subplot_using::accept (tree_walker& tw)
 {
-  style = s;
-  linetype = 0;
-  pointtype = 0;
-}
-
-subplot_style::subplot_style (const string& s, tree_expression *lt)
-{
-  style = s;
-  linetype = lt;
-  pointtype = 0;
-}
-
-subplot_style::subplot_style (const string& s, tree_expression *lt,
-			      tree_expression *pt)
-{
-  style = s;
-  linetype = lt;
-  pointtype = pt;
+  tw.visit_subplot_using (*this);
 }
 
 subplot_style::~subplot_style (void)
 {
-  delete linetype;
-  delete pointtype;
+  delete sp_linetype;
+  delete sp_pointtype;
 }
 
 int
 subplot_style::print (ostrstream& plot_buf)
 {
-  if (! style.empty ())
+  if (! sp_style.empty ())
     {
-      plot_buf << " " << GNUPLOT_COMMAND_WITH << " " << style;
+      plot_buf << " " << GNUPLOT_COMMAND_WITH << " " << sp_style;
 
-      if (linetype)
+      if (sp_linetype)
 	{
-	  octave_value tmp = linetype->eval (false);
+	  octave_value tmp = sp_linetype->eval (false);
 	  if (! error_state && tmp.is_defined ())
 	    {
 	      double val = tmp.double_value ();
@@ -618,9 +547,9 @@
 	    }
 	}
 
-      if (pointtype)
+      if (sp_pointtype)
 	{
-	  octave_value tmp = pointtype->eval (false);
+	  octave_value tmp = sp_pointtype->eval (false);
 	  if (! error_state && tmp.is_defined ())
 	    {
 	      double val = tmp.double_value ();
@@ -648,34 +577,22 @@
 int
 subplot_style::errorbars (void)
 {
-  return (almost_match ("errorbars", style, 1, 0)
-	  || almost_match ("boxerrorbars", style, 5, 0));
+  return (almost_match ("errorbars", sp_style, 1, 0)
+	  || almost_match ("boxerrorbars", sp_style, 5, 0));
 }
 
 void
-subplot_style::print_code (ostream& os)
+subplot_style::accept (tree_walker& tw)
 {
-  os << " with " << style;
-
-  if (linetype)
-    {
-      os << " ";
-      linetype->print_code (os);
-    }
-
-  if (pointtype)
-    {
-      os << " ";
-      pointtype->print_code (os);
-    }
+  tw.visit_subplot_style (*this);
 }
 
 subplot::~subplot (void)
 {
-  delete plot_data;
-  delete using_clause;
-  delete title_clause;
-  delete style_clause;
+  delete sp_plot_data;
+  delete sp_using_clause;
+  delete sp_title_clause;
+  delete sp_style_clause;
 }
 
 octave_value
@@ -683,9 +600,9 @@
 {
   octave_value retval;
 
-  if (using_clause)
+  if (sp_using_clause)
     {
-      ColumnVector val = using_clause->values (ndim);
+      ColumnVector val = sp_using_clause->values (ndim);
 
       octave_value_list args;
       args(1) = val;
@@ -702,7 +619,7 @@
       retval = data;
     }
 
-  if (ndim == 2 && style_clause && style_clause->errorbars ())
+  if (ndim == 2 && sp_style_clause && sp_style_clause->errorbars ())
     {
       int nc = retval.columns ();
 
@@ -720,9 +637,9 @@
 int
 subplot::handle_plot_data (int ndim, ostrstream& plot_buf)
 {
-  if (plot_data)
+  if (sp_plot_data)
     {
-      octave_value data = plot_data->eval (false);
+      octave_value data = sp_plot_data->eval (false);
 
       if (! error_state && data.is_defined ())
 	{
@@ -754,9 +671,9 @@
 		  plot_buf << " " << data.string_value ();
 		}
 
-	      if (using_clause)
+	      if (sp_using_clause)
 		{
-		  int status = using_clause->print (ndim, n_max, plot_buf);
+		  int status = sp_using_clause->print (ndim, n_max, plot_buf);
 
 		  if (status < 0)
 		    return -1;
@@ -812,9 +729,9 @@
   if (status < 0)
     return -1;
 
-  if (title_clause)
+  if (sp_title_clause)
     {
-      octave_value tmp = title_clause->eval (false);
+      octave_value tmp = sp_title_clause->eval (false);
       if (! error_state && tmp.is_string ())
 	plot_buf << " " << GNUPLOT_COMMAND_TITLE << " "
 	  << '"' << tmp.string_value () << '"';
@@ -829,9 +746,9 @@
     plot_buf << " " << GNUPLOT_COMMAND_TITLE << " "
       << '"' << "line " << plot_line_count << '"';
 
-  if (style_clause)
+  if (sp_style_clause)
     {
-      int status = style_clause->print (plot_buf);
+      int status = sp_style_clause->print (plot_buf);
       if (status < 0)
 	return -1;
     }
@@ -840,22 +757,9 @@
 }
 
 void
-subplot::print_code (ostream& os)
+subplot::accept (tree_walker& tw)
 {
-  if (plot_data)
-    {
-      os << " ";
-      plot_data->print_code (os);
-    }
-
-  if (using_clause)
-    using_clause->print_code (os);
-
-  if (title_clause)
-    title_clause->print_code (os);
-
-  if (style_clause)
-    style_clause->print_code (os);
+  tw.visit_subplot (*this);
 }
 
 subplot_list::~subplot_list (void)
@@ -891,24 +795,9 @@
 }
 
 void
-subplot_list::print_code (ostream& os)
+subplot_list::accept (tree_walker& tw)
 {
-  Pix p = first ();
-
-  while (p)
-    {
-      subplot *elt = this->operator () (p);
-
-      next (p);
-
-      if (elt)
-	{
-	  elt->print_code (os);
-
-	  if (p)
-	    os << ",";
-	}
-    }
+  tw.visit_subplot_list (*this);
 }
 
 string
--- a/src/pt-plot.h	Sun May 12 07:16:36 1996 +0000
+++ b/src/pt-plot.h	Sun May 12 07:16:36 1996 +0000
@@ -39,6 +39,8 @@
 class subplot;
 class subplot_list;
 
+class tree_walker;
+
 #include <string>
 
 #include <SLList.h>
@@ -53,6 +55,7 @@
 tree_plot_command : public tree_command
 {
 public:
+
   tree_plot_command (subplot_list *plt = 0, plot_limits *rng = 0, int nd = 0)
     : tree_command (), ndim (nd), range (rng), plot_list (plt) { }
 
@@ -60,69 +63,91 @@
 
   void eval (void);
 
-  void print_code (ostream& os);
+  int num_dimensions (void) { return ndim; }
+
+  plot_limits *limits (void) { return range; }
+
+  subplot_list *subplots (void) { return plot_list; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // The number of dimensions.  1 indicates a replot command.
   int ndim;
+
+  // The data ranges for the plot.
   plot_limits *range;
+
+  // The list of plots for this plot command.  For example, the
+  // command "plot sin(x), cos(x)" has two subplot commands.
   subplot_list *plot_list;
 };
 
 class
-plot_limits : public tree_print_code
+plot_limits
 {
 public:
+
   plot_limits (plot_range *xlim = 0, plot_range *ylim = 0,
 	       plot_range *zlim = 0)
-    : tree_print_code (), x_range (xlim), y_range (ylim), z_range (zlim) { }
+    : x_range (xlim), y_range (ylim), z_range (zlim) { }
 
   ~plot_limits (void);
 
   void print (int ndim, ostrstream& plot_buf);
 
-  void print_code (ostream& os);
+  plot_range *x_limits (void) { return x_range; }
+  plot_range *y_limits (void) { return y_range; }
+  plot_range *z_limits (void) { return z_range; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // Specified limits of the x, y, and z axes we should display for
+  // this plot.
   plot_range *x_range;
   plot_range *y_range;
   plot_range *z_range;
 };
 
 class
-plot_range : public tree_print_code
+plot_range
 {
 public:
+
   plot_range (tree_expression *l = 0, tree_expression *u = 0)
-    : tree_print_code (), lower (l), upper (u) { }
+    : lower (l), upper (u) { }
 
   ~plot_range (void);
 
   void print (ostrstream& plot_buf);
 
-  void print_code (ostream& os);
+  tree_expression *lower_bound (void) { return lower; }
+
+  tree_expression *upper_bound (void) { return upper; }
+
+  void accept (tree_walker& tw);
 
 private:
+
+  // A range can specify a lower or upper bound or both.  If neither
+  // is specified, the range to display is determined from the data.
   tree_expression *lower;
   tree_expression *upper;
 };
 
 class
-subplot_using : public tree_print_code
+subplot_using
 {
 public:
-  subplot_using (void)
-    {
-      qualifier_count = 0;
-      x[0] = x[1] = x[2] = x[3] = 0;
-      scanf_fmt = 0;
-    }
 
-  subplot_using (tree_expression *fmt) : val (4, -1)
-    {
-      qualifier_count = 0;
-      x[0] = x[1] = x[2] = x[3] = 0;
-      scanf_fmt = fmt;
-    }
+  subplot_using (tree_expression *fmt = 0)
+    : qual_count (0), scanf_fmt (fmt), val (4, -1)
+      {
+	x[0] = x[1] = x[2] = x[3] = 0;
+      }
 
   ~subplot_using (void);
 
@@ -134,10 +159,10 @@
 
   subplot_using *add_qualifier (tree_expression *t)
     {
-      if (qualifier_count < 4)
-	x[qualifier_count] = t;
+      if (qual_count < 4)
+	x[qual_count] = t;
 
-      qualifier_count++;
+      qual_count++;
 
       return this;
     }
@@ -148,25 +173,40 @@
 
   int print (int ndim, int n_max, ostrstream& plot_buf);
 
-  void print_code (ostream& os);
+  int qualifier_count (void) { return qual_count; }
+
+  tree_expression **qualifiers (void) { return x; }
+
+  tree_expression *scanf_format (void) { return scanf_fmt; }
+
+  void accept (tree_walker& tw);
 
 private:
-  int qualifier_count;
+
+  // The number of using qualifiers (in "using 1:2", 1 and 2 are the
+  // qualifiers).
+  int qual_count;
+
+  // An optional scanf-style format.  This is parsed and stored but
+  // not currently used.
+  tree_expression *scanf_fmt;
+
+  // This is a cache for evaluated versions of the qualifiers stored
+  // in x.
+  ColumnVector val;
+
+  // A vector to hold using qualifiers.
   tree_expression *x[4];
-  tree_expression *scanf_fmt;
-  ColumnVector val;
 };
 
 class
-subplot_style : public tree_print_code
+subplot_style
 {
 public:
-  subplot_style (void)
-    : tree_print_code (), style (0), linetype (0), pointtype (0) { }
 
-  subplot_style (const string& s);
-  subplot_style (const string& s, tree_expression *lt);
-  subplot_style (const string& s, tree_expression *lt, tree_expression *pt);
+  subplot_style (const string& s = string (),
+		 tree_expression *lt = 0, tree_expression *pt = 0)
+    : sp_style (s), sp_linetype (lt), sp_pointtype (pt) { }
 
   ~subplot_style (void);
 
@@ -174,31 +214,44 @@
 
   int errorbars (void);
 
-  void print_code (ostream& os);
+  string style (void) { return sp_style; }
+
+  tree_expression *linetype (void) { return sp_linetype; }
+
+  tree_expression *pointtype (void) { return sp_pointtype; }
+
+  void accept (tree_walker& tw);
 
 private:
-  string style;
-  tree_expression *linetype;
-  tree_expression *pointtype;
+
+  // The style we are using: `lines', `points', etc.
+  string sp_style;
+
+  // The number of the line type to use.
+  tree_expression *sp_linetype;
+
+  // The number of the point type to use.
+  tree_expression *sp_pointtype;
 };
 
 class
-subplot : public tree_print_code
+subplot
 {
 public:
+
   subplot (tree_expression *data = 0)
-    : tree_print_code (), plot_data (data), using_clause (0),
-      title_clause (0), style_clause (0) { }
+    : sp_plot_data (data), sp_using_clause (0), sp_title_clause (0),
+      sp_style_clause (0) { }
 
   subplot (subplot_using *u, tree_expression *t, subplot_style *s)
-    : tree_print_code (), plot_data (0), using_clause (u),
-      title_clause (t), style_clause (s) { }
+    : sp_plot_data (0), sp_using_clause (u), sp_title_clause (t),
+      sp_style_clause (s) { }
 
   ~subplot (void);
 
   subplot *set_data (tree_expression *data)
     {
-      plot_data = data;
+      sp_plot_data = data;
       return this;
     }
 
@@ -208,29 +261,47 @@
 
   int print (int ndim, ostrstream& plot_buf);
 
-  void print_code (ostream& os);
+  tree_expression *plot_data (void) { return sp_plot_data; }
+
+  subplot_using *using_clause (void) { return sp_using_clause; }
+
+  tree_expression *title_clause (void) { return sp_title_clause; }
+
+  subplot_style *style_clause (void) { return sp_style_clause; }
+
+  void accept (tree_walker& tw);
 
 private:
-  tree_expression *plot_data;
-  subplot_using *using_clause;
-  tree_expression *title_clause;
-  subplot_style *style_clause;
+
+  // The data to plot.
+  tree_expression *sp_plot_data;
+
+  // The `using' option
+  subplot_using *sp_using_clause;
+
+  // The `title' option
+  tree_expression *sp_title_clause;
+
+  // The `style' option
+  subplot_style *sp_style_clause;
 };
 
 class
-subplot_list : public SLList<subplot *>, public tree_print_code
+subplot_list : public SLList<subplot *>
 {
 public:
-  subplot_list (void) : SLList<subplot *> (), tree_print_code () { }
 
-  subplot_list (subplot *t) : SLList<subplot *> (), tree_print_code ()
-    { append (t); }
+  subplot_list (void)
+    : SLList<subplot *> () { }
+
+  subplot_list (subplot *t)
+    : SLList<subplot *> () { append (t); }
 
   ~subplot_list (void);
 
   int print (int ndim, ostrstream& plot_buf);
 
-  void print_code (ostream& os);
+  void accept (tree_walker& tw);
 };
 
 extern string save_in_tmp_file (octave_value& t, int ndim = 2,