Author: Armin Rigo <ar...@tunes.org>
Branch: reverse-debugger
Changeset: r85423:0d91eaae941b
Date: 2016-06-28 14:03 +0200
http://bitbucket.org/pypy/pypy/changeset/0d91eaae941b/

Log:    astcompiler and basic interpreter support for $NUM

diff --git a/lib-python/2.7/opcode.py b/lib-python/2.7/opcode.py
--- a/lib-python/2.7/opcode.py
+++ b/lib-python/2.7/opcode.py
@@ -194,5 +194,6 @@
 def_op('CALL_METHOD', 202)            # #args not including 'self'
 def_op('BUILD_LIST_FROM_ARG', 203)
 jrel_op('JUMP_IF_NOT_DEBUG', 204)     # jump over assert statements
+def_op('LOAD_REVDB_VAR', 205)         # reverse debugger (syntax example: $5)
 
 del def_op, name_op, jrel_op, jabs_op
diff --git a/pypy/interpreter/astcompiler/assemble.py 
b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -664,6 +664,7 @@
     ops.JUMP_IF_NOT_DEBUG: 0,
 
     ops.BUILD_LIST_FROM_ARG: 1,
+    ops.LOAD_REVDB_VAR: 1,
 }
 
 
diff --git a/pypy/interpreter/astcompiler/ast.py 
b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -1534,6 +1534,8 @@
             return Num.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Str):
             return Str.from_object(space, w_node)
+        if space.isinstance_w(w_node, get(space).w_RevDBMetaVar):
+            return RevDBMetaVar.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Attribute):
             return Attribute.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Subscript):
@@ -2344,6 +2346,41 @@
 State.ast_type('Str', 'expr', ['s'])
 
 
+class RevDBMetaVar(expr):
+
+    def __init__(self, metavar, lineno, col_offset):
+        self.metavar = metavar
+        expr.__init__(self, lineno, col_offset)
+
+    def walkabout(self, visitor):
+        visitor.visit_RevDBMetaVar(self)
+
+    def mutate_over(self, visitor):
+        return visitor.visit_RevDBMetaVar(self)
+
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_RevDBMetaVar)
+        w_metavar = space.wrap(self.metavar)  # int
+        space.setattr(w_node, space.wrap('metavar'), w_metavar)
+        w_lineno = space.wrap(self.lineno)  # int
+        space.setattr(w_node, space.wrap('lineno'), w_lineno)
+        w_col_offset = space.wrap(self.col_offset)  # int
+        space.setattr(w_node, space.wrap('col_offset'), w_col_offset)
+        return w_node
+
+    @staticmethod
+    def from_object(space, w_node):
+        w_metavar = get_field(space, w_node, 'metavar', False)
+        w_lineno = get_field(space, w_node, 'lineno', False)
+        w_col_offset = get_field(space, w_node, 'col_offset', False)
+        _metavar = space.int_w(w_metavar)
+        _lineno = space.int_w(w_lineno)
+        _col_offset = space.int_w(w_col_offset)
+        return RevDBMetaVar(_metavar, _lineno, _col_offset)
+
+State.ast_type('RevDBMetaVar', 'expr', ['metavar'])
+
+
 class Attribute(expr):
 
     def __init__(self, value, attr, ctx, lineno, col_offset):
@@ -3439,6 +3476,8 @@
         return self.default_visitor(node)
     def visit_Str(self, node):
         return self.default_visitor(node)
+    def visit_RevDBMetaVar(self, node):
+        return self.default_visitor(node)
     def visit_Attribute(self, node):
         return self.default_visitor(node)
     def visit_Subscript(self, node):
@@ -3655,6 +3694,9 @@
     def visit_Str(self, node):
         pass
 
+    def visit_RevDBMetaVar(self, node):
+        pass
+
     def visit_Attribute(self, node):
         node.value.walkabout(self)
 
diff --git a/pypy/interpreter/astcompiler/astbuilder.py 
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -1160,6 +1160,11 @@
         elif first_child_type == tokens.BACKQUOTE:
             expr = self.handle_testlist(atom_node.get_child(1))
             return ast.Repr(expr, atom_node.get_lineno(), 
atom_node.get_column())
+        elif first_child_type == tokens.REVDBMETAVAR:
+            string = atom_node.get_child(0).get_value()
+            return ast.RevDBMetaVar(int(string[1:]),
+                                    atom_node.get_lineno(),
+                                    atom_node.get_column())
         else:
             raise AssertionError("unknown atom")
 
diff --git a/pypy/interpreter/astcompiler/codegen.py 
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1196,6 +1196,14 @@
             sub.value.walkabout(self)
         self._compile_slice(sub.slice, sub.ctx)
 
+    def visit_RevDBMetaVar(self, node):
+        if self.space.config.translation.reverse_debugger:
+            from pypy.interpreter.reverse_debugging import dbstate
+            if dbstate.extend_syntax_with_dollar_num:
+                self.emit_op_arg(ops.LOAD_REVDB_VAR, node.metavar)
+                return
+        self.error("$NUM is only valid in the reverse-debugger", node)
+
 
 class TopLevelCodeGenerator(PythonCodeGenerator):
 
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py 
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -940,6 +940,15 @@
         yield (self.st, "x=(lambda: (-0.0, 0.0), lambda: (0.0, -0.0))[1]()",
                         'repr(x)', '(0.0, -0.0)')
 
+    def test_revdb_metavar(self):
+        from pypy.interpreter.reverse_debugging import dbstate, setup_revdb
+        self.space.config.translation.reverse_debugger = True
+        setup_revdb(self.space)
+        dbstate.extend_syntax_with_dollar_num = True
+        dbstate.metavars = [self.space.wrap(6)]
+        self.simple_test("x = 7*$0", "x", 42)
+        dbstate.extend_syntax_with_dollar_num = False
+
 
 class AppTestCompiler:
 
diff --git a/pypy/interpreter/astcompiler/tools/Python.asdl 
b/pypy/interpreter/astcompiler/tools/Python.asdl
--- a/pypy/interpreter/astcompiler/tools/Python.asdl
+++ b/pypy/interpreter/astcompiler/tools/Python.asdl
@@ -71,6 +71,7 @@
             | Repr(expr value)
             | Num(object n) -- a number as a PyObject.
             | Str(string s) -- need to specify raw, unicode, etc?
+             | RevDBMetaVar(int metavar)
             -- other literals? bools?
 
             -- the following expression can appear in assignment context
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py 
b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -400,7 +400,7 @@
     if not (space.isinstance_w(w_obj, space.w_str) or
             space.isinstance_w(w_obj, space.w_unicode)):
         raise oefmt(space.w_TypeError,
-                   "AST string must be of type str or unicode")
+                    "AST string must be of type str or unicode")
     return w_obj
 
 def get_field(space, w_node, name, optional):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -412,6 +412,10 @@
 
     def startup(self):
         # To be called before using the space
+        if self.config.translation.reverse_debugger:
+            from pypy.interpreter.reverse_debugging import setup_revdb
+            setup_revdb(self)
+
         self.threadlocals.enter_thread(self)
 
         # Initialize already imported builtin modules
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -436,6 +436,8 @@
                 self.WITH_CLEANUP(oparg, next_instr)
             elif opcode == opcodedesc.YIELD_VALUE.index:
                 self.YIELD_VALUE(oparg, next_instr)
+            elif opcode == opcodedesc.LOAD_REVDB_VAR.index:
+                self.LOAD_REVDB_VAR(oparg, next_instr)
             else:
                 self.MISSING_OPCODE(oparg, next_instr)
 
@@ -1305,6 +1307,11 @@
         w_dict = self.peekvalue()
         self.space.setitem(w_dict, w_key, w_value)
 
+    def LOAD_REVDB_VAR(self, oparg, next_instr):
+        from pypy.interpreter.reverse_debugging import load_metavar
+        w_var = load_metavar(oparg)
+        self.pushvalue(w_var)
+
 
 ### ____________________________________________________________ ###
 
diff --git a/pypy/interpreter/pyparser/data/Grammar2.7 
b/pypy/interpreter/pyparser/data/Grammar2.7
--- a/pypy/interpreter/pyparser/data/Grammar2.7
+++ b/pypy/interpreter/pyparser/data/Grammar2.7
@@ -104,7 +104,7 @@
        '[' [listmaker] ']' |
        '{' [dictorsetmaker] '}' |
        '`' testlist1 '`' |
-       NAME | NUMBER | STRING+ | revdb_metavar)
+       NAME | NUMBER | STRING+ | '$NUM')
 listmaker: test ( list_for | (',' test)* [','] )
 testlist_comp: test ( comp_for | (',' test)* [','] )
 lambdef: 'lambda' [varargslist] ':' test
@@ -141,5 +141,3 @@
 encoding_decl: NAME
 
 yield_expr: 'yield' [testlist]
-
-revdb_metavar: '$NUM'
diff --git a/pypy/interpreter/reverse_debugging.py 
b/pypy/interpreter/reverse_debugging.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/reverse_debugging.py
@@ -0,0 +1,41 @@
+import sys
+from rpython.rlib import revdb
+from rpython.rlib.debug import make_sure_not_resized
+from pypy.interpreter.error import oefmt
+
+
+class DBState:
+    extend_syntax_with_dollar_num = False
+    metavars = []
+
+dbstate = DBState()
+
+
+def setup_revdb(space):
+    assert space.config.translation.reverse_debugger
+    dbstate.space = space
+    #make_sure_not_resized(dbstate.breakpoint_funcnames)
+    #make_sure_not_resized(dbstate.watch_progs)
+    make_sure_not_resized(dbstate.metavars)
+    #revdb.register_debug_command(revdb.CMD_PRINT, lambda_print)
+    #revdb.register_debug_command(revdb.CMD_BACKTRACE, lambda_backtrace)
+    #revdb.register_debug_command(revdb.CMD_LOCALS, lambda_locals)
+    #revdb.register_debug_command(revdb.CMD_BREAKPOINTS, lambda_breakpoints)
+    #revdb.register_debug_command(revdb.CMD_MOREINFO, lambda_moreinfo)
+    #revdb.register_debug_command("ALLOCATING", lambda_allocating)
+    #revdb.register_debug_command(revdb.CMD_ATTACHID, lambda_attachid)
+    #revdb.register_debug_command(revdb.CMD_CHECKWATCH, lambda_checkwatch)
+    #revdb.register_debug_command(revdb.CMD_WATCHVALUES, lambda_watchvalues)
+
+def load_metavar(oparg):
+    space = dbstate.space
+    metavars = dbstate.metavars
+    w_var = metavars[oparg] if oparg < len(metavars) else None
+    if w_var is None:
+        raise oefmt(space.w_NameError, "no constant object '$%d'",
+                    oparg)
+    if w_var is space.w_Ellipsis:
+        raise oefmt(space.w_RuntimeError,
+                    "'$%d' refers to an object created later in time",
+                    oparg)
+    return w_var
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to