changeset 7734:2dee19385d32

eliminate tree_statement_stack; handle current statement info in octave_call_stack
author John W. Eaton <jwe@octave.org>
date Fri, 25 Apr 2008 12:16:42 -0400
parents bb614b3883a9
children 6848970153ba
files src/ChangeLog src/error.cc src/input.cc src/pt-stmt.cc src/pt-stmt.h src/toplev.cc src/toplev.h
diffstat 7 files changed, 246 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/ChangeLog	Fri Apr 25 12:16:42 2008 -0400
@@ -1,3 +1,31 @@
+2008-04-25  John W. Eaton  <jwe@octave.org>
+
+	* error.cc (verror, pr_where): Use octave_call_stack instead of
+	tree_statement stack to get line and column information.
+	(pr_where): Use octave_call_stack instead of tree_statement stack
+	to get current statement.
+	* input.cc (get_user_input): Extract current line number from
+	octave_call_stack instead of tree_statement_stack.
+	* pt-stmt.cc (tree_statement::eval): Put current statement on
+	octave_call_stack instead of tree_statement_stack.
+	* pt-stmt.h, pt-stmt.cc (class tree_statement_stack): Delete.
+
+	* toplev.h, toplev.cc (octave_call_stack::call_stack_elt):
+	New nested struct.
+	(octave_call_stack::cs): Now a deque of call_stack_elts.
+	Change all uses.
+	(octave_call_stack::current_statement,
+	octave_call_stack::current_line,
+	octave_call_stack::current_column,
+	octave_call_stack::top_statement,
+	octave_call_stack::set_statement, octave_call_stack::backtrace):
+	New static functions.
+	(octave_call_stack::do_current_line,
+	octave_call_stack::do_current_column,
+	octave_call_stack::do_top_statement,
+	octave_call_stack::do_set_statement,
+	octave_call_stack::do_backtrace): New member functions.
+
 2008-04-24  John W. Eaton  <jwe@octave.org>
 
 	* toplev.h, toplev.cc (octave_call_stack::unwind_pop_script):
--- a/src/error.cc	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/error.cc	Fri Apr 25 12:16:42 2008 -0400
@@ -232,7 +232,7 @@
       Vlast_error_name = std::string ();
       Vlast_error_file = std::string ();
 
-      if (tree_statement_stack::current ())
+      if (octave_call_stack::current_statement ())
 	{
 	  octave_user_code *fcn = octave_call_stack::caller_user_code ();
 
@@ -240,8 +240,8 @@
 	    {
 	      Vlast_error_file = fcn->fcn_file_name ();
 	      Vlast_error_name = fcn->name();
-	      Vlast_error_line = tree_statement_stack::current_line ();
-	      Vlast_error_column = tree_statement_stack::current_column ();
+	      Vlast_error_line = octave_call_stack::current_line ();
+	      Vlast_error_column = octave_call_stack::current_column ();
 	    }
 	}
     }
@@ -421,7 +421,7 @@
 static void
 pr_where (const char *name, bool print_code = true)
 {
-  if (tree_statement_stack::current ())
+  if (octave_call_stack::current_statement ())
     {
       std::string nm;
 
@@ -437,8 +437,8 @@
 	  if (nm.empty ())
 	    nm = fcn->name ();
 
-	  l = tree_statement_stack::current_line ();
-	  c = tree_statement_stack::current_column ();
+	  l = octave_call_stack::current_line ();
+	  c = octave_call_stack::current_column ();
 	}
 
       if (nm.empty ())
@@ -469,7 +469,7 @@
 
 	  tree_print_code tpc (output_buf, ">>> ");
 
-	  tree_statement *curr_stmt = tree_statement_stack::current ();
+	  tree_statement *curr_stmt = octave_call_stack::current_statement ();
 
 	  if (curr_stmt)
 	    curr_stmt->accept (tpc);
--- a/src/input.cc	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/input.cc	Fri Apr 25 12:16:42 2008 -0400
@@ -607,7 +607,7 @@
 	  if (nm.empty ())
 	    nm = caller->name ();
 
-	  line = tree_statement_stack::current_line ();
+	  line = octave_call_stack::current_line ();
 	}
     }
 
@@ -699,7 +699,7 @@
 	    {
 	      tree::break_next = true;
 
-	      tree::last_line = tree_statement_stack::current_line ();
+	      tree::last_line = octave_call_stack::current_line ();
 
 	      tree::break_function = octave_call_stack::current ();
 
--- a/src/pt-stmt.cc	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/pt-stmt.cc	Fri Apr 25 12:16:42 2008 -0400
@@ -87,8 +87,7 @@
 
   if (cmd || expr)
     {
-      unwind_protect::add (tree_statement_stack::unwind_pop, 0);
-      tree_statement_stack::push (this);
+      octave_call_stack::set_statement (this);
 
       maybe_echo_code (in_function_body);
 
@@ -131,8 +130,6 @@
 	  octave_exception_state = octave_no_exception;
 	  error ("caught execution error in library function");
 	}
-
-      unwind_protect::run ();
     }
 
   return retval;
@@ -285,8 +282,6 @@
   tw.visit_statement_list (*this);
 }
 
-tree_statement_stack *tree_statement_stack::instance = 0;
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/pt-stmt.h	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/pt-stmt.h	Fri Apr 25 12:16:42 2008 -0400
@@ -160,106 +160,6 @@
   tree_statement_list& operator = (const tree_statement_list&);
 };
 
-class tree_statement_stack
-{
-protected:
-
-  tree_statement_stack (void) : tss () { }
-
-public:
-
-  typedef std::deque<tree_statement *>::iterator iterator ;
-
-  static bool instance_ok (void)
-  {
-    bool retval = true;
-
-    if (! instance)
-      instance = new tree_statement_stack ();
-
-    if (! instance)
-      {
-	::error ("unable to create stmt stack object!");
-
-	retval = false;
-      }
-
-    return retval;
-  }
-
-  // Current statement (top of stack).
-  static tree_statement *current (void) { return top (); }
-
-  static int current_line (void)
-  {
-    tree_statement *s = current ();
-    return s ? s->line () : -1;
-  }
-
-  static int current_column (void)
-  {
-    tree_statement *s = current ();
-    return s ? s->column () : -1;
-  }
-
-  // Statement at position N on the call stack (N == 0 is current).
-  static tree_statement *element (size_t n)
-  {
-    return instance_ok () ? instance->do_element (n) : 0;
-  }
-
-  // Caller statement
-  static tree_statement *caller (void) { return element (1); }
-
-  static void push (tree_statement *f)
-  {
-    if (instance_ok ())
-      instance->do_push (f);
-  }
-
-  static tree_statement *top (void)
-  {
-    return instance_ok () ? instance->do_top (): 0;
-  }
-
-  static void pop (void)
-  {
-    if (instance_ok ())
-      instance->do_pop ();
-  }
-  
-  // A function for popping the top of the call stack that is suitable
-  // for use as an unwind_protect handler.
-  static void unwind_pop (void *) { pop (); }
-
-  static void clear (void)
-  {
-    if (instance_ok ())
-      instance->do_clear ();
-  }
-
-private:
-
-  // The current stmt stack.
-  std::deque<tree_statement *> tss;
-
-  static tree_statement_stack *instance;
-
-  tree_statement *do_element (size_t n) { return tss.size () > n ? tss[n] : 0; }
-
-  void do_push (tree_statement *f) { tss.push_front (f); }
-
-  tree_statement *do_top (void) { return tss.empty () ? 0 : tss.front (); }
-
-  void do_pop (void)
-  {
-    if (! tss.empty ())
-      tss.pop_front ();
-  }
-
-  void do_clear (void) { tss.clear (); }
-};
-
 #endif
 
 /*
--- a/src/toplev.cc	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/toplev.cc	Fri Apr 25 12:16:42 2008 -0400
@@ -95,14 +95,32 @@
 
 octave_call_stack *octave_call_stack::instance = 0;
 
+int
+octave_call_stack::do_current_line (void) const
+{
+  tree_statement *stmt = do_top_statement ();
+
+  return stmt ? stmt->line () : -1;
+}
+
+int
+octave_call_stack::do_current_column (void) const
+{
+  tree_statement *stmt = do_top_statement ();
+
+  return stmt ? stmt->column () : -1;
+}
+
 octave_user_script *
-octave_call_stack::do_caller_user_script (void)
+octave_call_stack::do_caller_user_script (void) const
 {
   octave_user_script *retval = 0;
 
-  for (iterator p = cs.begin (); p != cs.end (); p++)
+  for (const_iterator p = cs.begin (); p != cs.end (); p++)
     {
-      octave_function *f = *p;
+      const call_stack_elt& elt = *p;
+
+      octave_function *f = elt.fcn;
 
       if (f && f->is_user_script ())
 	{
@@ -115,13 +133,15 @@
 }
 
 octave_user_function *
-octave_call_stack::do_caller_user_function (void)
+octave_call_stack::do_caller_user_function (void) const
 {
   octave_user_function *retval = 0;
 
-  for (iterator p = cs.begin (); p != cs.end (); p++)
+  for (const_iterator p = cs.begin (); p != cs.end (); p++)
     {
-      octave_function *f = *p;
+      const call_stack_elt& elt = *p;
+
+      octave_function *f = elt.fcn;
 
       if (f && f->is_user_function ())
 	{
@@ -134,13 +154,15 @@
 }
 
 octave_user_code *
-octave_call_stack::do_caller_user_code (void)
+octave_call_stack::do_caller_user_code (void) const
 {
   octave_user_code *retval = 0;
 
-  for (iterator p = cs.begin (); p != cs.end (); p++)
+  for (const_iterator p = cs.begin (); p != cs.end (); p++)
     {
-      octave_function *f = *p;
+      const call_stack_elt& elt = *p;
+
+      octave_function *f = elt.fcn;
 
       if (f && f->is_user_code ())
 	{
@@ -152,6 +174,77 @@
   return retval;
 }
 
+Octave_map
+octave_call_stack::do_backtrace (void) const
+{
+  Octave_map retval;
+
+  size_t nframes = cs.size () - 1;
+
+  Cell keys (4, 1);
+
+  keys(0) = "file";
+  keys(1) = "name";
+  keys(2) = "line";
+  keys(3) = "column";
+
+  Cell file (nframes, 1);
+  Cell name (nframes, 1);
+  Cell line (nframes, 1);
+  Cell column (nframes, 1);
+
+  const_iterator p = cs.begin ();
+  
+  // Skip innermost function as it will be the dbstatus function
+  // itself.  FIXME -- Is it best to do this here?
+  p++;
+
+  octave_idx_type k = 0;
+
+  while (p != cs.end ())
+    {
+      const call_stack_elt& elt = *p;
+
+      octave_function *f = elt.fcn;
+
+      if (f)
+	{
+	  file(k) = f->fcn_file_name ();
+	  name(k) = f->name ();
+
+	  tree_statement *stmt = elt.stmt;
+
+	  if (stmt)
+	    {
+	      line(k) = stmt->line ();
+	      column(k) = stmt->column ();
+	    }
+	  else
+	    {
+	      line(k) = -1;
+	      column(k) = -1;
+	    }
+	}
+      else
+	{
+	  file(k) = "<unknown>";
+	  name(k) = "<unknown>";
+	  line(k) = -1;
+	  column(k) = -1;
+	}
+
+      k++;
+      p++;
+    }
+
+  retval.assign ("file", file);
+  retval.assign ("name", name);
+  retval.assign ("line", line);
+  retval.assign ("column", column);
+
+  return retval;
+}
+
 void
 recover_from_exception (void)
 {
--- a/src/toplev.h	Thu Apr 24 16:18:44 2008 -0400
+++ b/src/toplev.h	Fri Apr 25 12:16:42 2008 -0400
@@ -33,9 +33,12 @@
 class octave_value_list;
 class octave_function;
 class octave_user_script;
+class tree_statement;
 class tree_statement_list;
 class charMatrix;
 
+#include "oct-map.h"
+
 extern OCTINTERP_API void
 clean_up_and_exit (int) GCC_ATTR_NORETURN;
 
@@ -68,13 +71,24 @@
 class
 octave_call_stack
 {
+private:
+
+  struct call_stack_elt
+  {
+    call_stack_elt (octave_function *f) : fcn (f), stmt (0) { }
+
+    octave_function *fcn;
+    tree_statement *stmt;
+  };
+
 protected:
 
   octave_call_stack (void) : cs () { }
 
 public:
 
-  typedef std::deque<octave_function *>::iterator iterator ;
+  typedef std::deque<call_stack_elt>::iterator iterator;
+  typedef std::deque<call_stack_elt>::const_iterator const_iterator;
 
   static bool instance_ok (void)
   {
@@ -96,6 +110,21 @@
   // Current function (top of stack).
   static octave_function *current (void) { return top (); }
 
+  // Current statement (top of stack).
+  static tree_statement *current_statement (void) { return top_statement (); }
+
+  // Current line in current function.
+  static int current_line (void)
+  {
+    return instance_ok () ? instance->do_current_line () : 0;
+  }
+
+  // Current column in current function.
+  static int current_column (void)
+  {
+    return instance_ok () ? instance->do_current_column () : 0;
+  }
+
   // Caller function, may be built-in.
   static octave_function *caller (void)
   {
@@ -138,6 +167,22 @@
     return instance_ok () ? instance->do_top (): 0;
   }
 
+  static tree_statement *top_statement (void)
+  {
+    return instance_ok () ? instance->do_top_statement (): 0;
+  }
+
+  static void set_statement (tree_statement *s)
+  {
+    if (instance_ok ())
+      instance->do_set_statement (s);
+  }
+
+  static Octave_map backtrace (void)
+  {
+    return instance_ok () ? instance->do_backtrace () : Octave_map ();
+  }
+
   static void pop (void)
   {
     if (instance_ok ())
@@ -157,21 +202,74 @@
 private:
 
   // The current call stack.
-  std::deque<octave_function *> cs;
+  std::deque<call_stack_elt> cs;
 
   static octave_call_stack *instance;
 
-  octave_function *do_element (size_t n) { return cs.size () > n ? cs[n] : 0; }
+  int do_current_line (void) const;
+
+  int do_current_column (void) const;
+
+  octave_function *do_element (size_t n)
+  {
+    octave_function *retval = 0;
+
+    if (cs.size () > n)
+      {
+	call_stack_elt& elt = cs[n];
+	retval = elt.fcn;
+      }
 
-  octave_user_script *do_caller_user_script (void);
+    return retval;
+  }
+
+  octave_user_script *do_caller_user_script (void) const;
+
+  octave_user_function *do_caller_user_function (void) const;
+
+  octave_user_code *do_caller_user_code (void) const;
 
-  octave_user_function *do_caller_user_function (void);
+  void do_push (octave_function *f)
+  {
+    cs.push_front (call_stack_elt (f));
+  }
+
+  octave_function *do_top (void) const
+  {
+    octave_function *retval = 0;
 
-  octave_user_code *do_caller_user_code (void);
+    if (! cs.empty ())
+      {
+	const call_stack_elt& elt = cs.front ();
+	retval = elt.fcn;
+      }
+
+    return retval;
+  }
+
+  tree_statement *do_top_statement (void) const
+  {
+    tree_statement *retval = 0;
 
-  void do_push (octave_function *f) { cs.push_front (f); }
+    if (! cs.empty ())
+      {
+	const call_stack_elt& elt = cs.front ();
+	retval = elt.stmt;
+      }
+
+    return retval;
+  }
 
-  octave_function *do_top (void) { return cs.empty () ? 0 : cs.front (); }
+  void do_set_statement (tree_statement *s)
+  {
+    if (! cs.empty ())
+      {
+	call_stack_elt& elt = cs.front ();
+	elt.stmt = s;
+      }
+  }
+
+  Octave_map do_backtrace (void) const;
 
   void do_pop (void)
   {