changeset 16354:fb27f1e08297

track line and column info directly in call stack (bug #38556) * toplev.h, toplev.cc (octave_call_stack::call_stack_elt::line, octave_call_stack::call_stack_elt::column): New data members. (octave_call_stack::call_stack_elt::stmt): Delete. Change all uses. (octave_call_stack::set_location, octave_call_stack::do_set_location, (octave_call_stack::set_line, octave_call_stack::do_set_line, (octave_call_stack::set_column, octave_call_stack::do_set_column): New functions. (octave_call_stack::set_statement, octave_call_stack::do_set_statement): Delete. Change all callers to use set_location or set_line and set_column. * pt-eval.cc (tree_evaluator::visit_if_command): Never call do_breakpoint here. (tree_evaluator::visit_if_command_list): Set call stack location for each if/elseif clause. (tree_evaluator::visit_switch_command): Don't call do_breakpoint for individual cases.
author John W. Eaton <jwe@octave.org>
date Thu, 21 Mar 2013 16:30:00 -0400
parents ca395af72d88
children 022898b4323b
files libinterp/interpfcn/toplev.cc libinterp/interpfcn/toplev.h libinterp/parse-tree/pt-eval.cc
diffstat 3 files changed, 81 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/interpfcn/toplev.cc	Thu Mar 21 07:45:04 2013 -0700
+++ b/libinterp/interpfcn/toplev.cc	Thu Mar 21 16:30:00 2013 -0400
@@ -118,17 +118,29 @@
 int
 octave_call_stack::do_current_line (void) const
 {
-  tree_statement *stmt = do_current_statement ();
+  int retval = -1;
 
-  return stmt ? stmt->line () : -1;
+  if (! cs.empty ())
+    {
+      const call_stack_elt& elt = cs[curr_frame];
+      retval = elt.line;
+    }
+
+  return retval;
 }
 
 int
 octave_call_stack::do_current_column (void) const
 {
-  tree_statement *stmt = do_current_statement ();
+  int retval = -1;
 
-  return stmt ? stmt->column () : -1;
+  if (! cs.empty ())
+    {
+      const call_stack_elt& elt = cs[curr_frame];
+      retval = elt.column;
+    }
+
+  return retval;
 }
 
 int
@@ -146,11 +158,9 @@
 
       if (f && f->is_user_code ())
         {
-          tree_statement *stmt = elt.stmt;
-
-          if (stmt)
+          if (elt.line > 0)
             {
-              retval = stmt->line ();
+              retval = elt.line;
               break;
             }
         }
@@ -174,11 +184,9 @@
 
       if (f && f->is_user_code ())
         {
-          tree_statement *stmt = elt.stmt;
-
-          if (stmt)
+          if (elt.column)
             {
-              retval = stmt->column ();
+              retval = elt.column;
               break;
             }
         }
@@ -310,18 +318,8 @@
                   else
                     name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
 
-                  tree_statement *stmt = elt.stmt;
-
-                  if (stmt)
-                    {
-                      line(k) = stmt->line ();
-                      column(k) = stmt->column ();
-                    }
-                  else
-                    {
-                      line(k) = -1;
-                      column(k) = -1;
-                    }
+                  line(k) = elt.line;
+                  column(k) = elt.column;
 
                   k++;
                 }
@@ -352,17 +350,9 @@
           octave_function *f = elt.fcn;
           std::string nm = f ? f->name () : std::string ("<unknown>");
 
-          tree_statement *s = elt.stmt;
-          int l = -1;
-          int c = -1;
-          if (s)
-            {
-              l = s->line ();
-              c = s->column ();
-            }
-
           octave_stdout << "stopped in " << nm
-                        << " at line " << l << " column " << c
+                        << " at line " << elt.line
+                        << " column " << elt.column
                         << " (" << elt.scope << "[" << elt.context << "])"
                         << std::endl;
         }
@@ -416,14 +406,8 @@
                   std::ostringstream buf;
 
                   if (f)
-                    {
-                      tree_statement *s = elt.stmt;
-
-                      int l = s ? s->line () : -1;
-
-                      buf << "stopped in " << f->name ()
-                          << " at line " << l << std::endl;
-                    }
+                    buf << "stopped in " << f->name ()
+                        << " at line " << elt.line << std::endl;
                   else
                     buf << "at top level" << std::endl;
 
@@ -509,7 +493,6 @@
       const call_stack_elt& elt = cs.back ();
 
       octave_function *fcn = elt.fcn;
-      tree_statement *stmt = elt.stmt;
 
       std::string fcn_name = "?unknown?";
 
@@ -521,11 +504,8 @@
             fcn_name = fcn->name ();
         }
 
-      int line = stmt ? stmt->line () : -1;
-      int column = stmt ? stmt->column () : -1;
-
       error ("  %s at line %d, column %d",
-             fcn_name.c_str (), line, column);
+             fcn_name.c_str (), elt.line, elt.column);
     }
 }
 
--- a/libinterp/interpfcn/toplev.h	Thu Mar 21 07:45:04 2013 -0700
+++ b/libinterp/interpfcn/toplev.h	Thu Mar 21 16:30:00 2013 -0400
@@ -84,14 +84,17 @@
   {
     call_stack_elt (octave_function *f, symbol_table::scope_id s,
                     symbol_table::context_id c, size_t p = 0)
-      : fcn (f), stmt (0), scope (s), context (c), prev (p) { }
+      : fcn (f), line (-1), column (-1), scope (s), context (c), prev (p)
+    { }
 
     call_stack_elt (const call_stack_elt& elt)
-      : fcn (elt.fcn), stmt (elt.stmt), scope (elt.scope),
-        context (elt.context), prev (elt.prev) { }
+      : fcn (elt.fcn), line (elt.line), column (elt.column),
+        scope (elt.scope), context (elt.context), prev (elt.prev)
+    { }
 
     octave_function *fcn;
-    tree_statement *stmt;
+    int line;
+    int column;
     symbol_table::scope_id scope;
     symbol_table::context_id context;
     size_t prev;
@@ -134,12 +137,6 @@
     return instance_ok () ? instance->do_current () : 0;
   }
 
-  // Current statement (top of stack).
-  static tree_statement *current_statement (void)
-  {
-    return instance_ok () ? instance->do_current_statement () : 0;
-  }
-
   // Current line in current function.
   static int current_line (void)
   {
@@ -226,10 +223,22 @@
       instance->do_push (0, scope, context);
   }
 
-  static void set_statement (tree_statement *s)
+  static void set_location (int l, int c)
   {
     if (instance_ok ())
-      instance->do_set_statement (s);
+      instance->do_set_location (l, c);
+  }
+
+  static void set_line (int l)
+  {
+    if (instance_ok ())
+      instance->do_set_line (l);
+  }
+
+  static void set_column (int c)
+  {
+    if (instance_ok ())
+      instance->do_set_column (c);
   }
 
   static bool goto_frame (size_t n = 0, bool verbose = false)
@@ -365,25 +374,34 @@
     return retval;
   }
 
-  tree_statement *do_current_statement (void) const
-  {
-    tree_statement *retval = 0;
-
-    if (! cs.empty ())
-      {
-        const call_stack_elt& elt = cs[curr_frame];
-        retval = elt.stmt;
-      }
-
-    return retval;
-  }
-
-  void do_set_statement (tree_statement *s)
+  void do_set_location (int l, int c)
   {
     if (! cs.empty ())
       {
         call_stack_elt& elt = cs.back ();
-        elt.stmt = s;
+
+        elt.line = l;
+        elt.column = c;
+      }
+  }
+
+  void do_set_line (int l)
+  {
+    if (! cs.empty ())
+      {
+        call_stack_elt& elt = cs.back ();
+
+        elt.line = l;
+      }
+  }
+
+  void do_set_column (int c)
+  {
+    if (! cs.empty ())
+      {
+        call_stack_elt& elt = cs.back ();
+
+        elt.column = c;
       }
   }
 
--- a/libinterp/parse-tree/pt-eval.cc	Thu Mar 21 07:45:04 2013 -0700
+++ b/libinterp/parse-tree/pt-eval.cc	Thu Mar 21 16:30:00 2013 -0400
@@ -557,9 +557,6 @@
 void
 tree_evaluator::visit_if_command (tree_if_command& cmd)
 {
-  if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
-
   tree_if_command_list *lst = cmd.cmd_list ();
 
   if (lst)
@@ -575,6 +572,9 @@
 
       tree_expression *expr = tic->condition ();
 
+      if (statement_context == function || statement_context == script)
+        octave_call_stack::set_location (tic->line (), tic->column ());
+
       if (debug_mode && ! tic->is_else_clause ())
         do_breakpoint (tic->is_breakpoint ());
 
@@ -703,7 +703,7 @@
           // the state of the program we are debugging.
 
           if (! Vdebugging)
-            octave_call_stack::set_statement (&stmt);
+            octave_call_stack::set_location (stmt.line (), stmt.column ());
 
           // FIXME -- we need to distinguish functions from scripts to
           // get this right.
@@ -865,9 +865,6 @@
             {
               tree_switch_case *t = *p;
 
-              if (debug_mode && ! t->is_default_case ())
-                do_breakpoint (t->is_breakpoint ());
-
               if (t->is_default_case () || t->label_matches (val))
                 {
                   if (error_state)
@@ -946,10 +943,12 @@
   frame.protect_var (error_state);
   error_state = 0;
 
-  // We want to preserve the last statement indicator for possible
+  // We want to preserve the last location info for possible
   // backtracking.
-  frame.add_fcn (octave_call_stack::set_statement,
-                 octave_call_stack::current_statement ());
+  frame.add_fcn (octave_call_stack::set_line,
+                 octave_call_stack::current_line ());
+  frame.add_fcn (octave_call_stack::set_column,
+                 octave_call_stack::current_column ());
 
   // Similarly, if we have seen a return or break statement, allow all
   // the cleanup code to run before returning or handling the break.