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