Commits

Anonymous committed 61b9530

- added a parent attribute to AST nodes
- added a few hook examples (they will probably be used as a basis for improvements)

Comments (0)

Files changed (5)

pypy/interpreter/astcompiler/ast.py

     def __init__(self, lineno = -1):
         self.lineno = lineno
         self.filename = ""
+        self.parent = None
         #self.scope = None
         
     def getChildren(self):
     def descr_repr( self, space ):
         return space.wrap( self.__repr__() )
     
+    def fget_parent(space, self):
+        return space.wrap(self.parent)
+
+    def fset_parent(space, self, w_parent):
+        self.parent = space.interp_w(Node, w_parent, can_be_None=False)
+
     def descr_getChildNodes( self, space ):
         lst = self.getChildNodes()
         return space.newlist( [ space.wrap( it ) for it in lst ] )
                        accept = interp2app(descr_node_accept, unwrap_spec=[ ObjSpace, W_Root, W_Root ] ),
                        lineno = interp_attrproperty('lineno', cls=Node),
                        filename = interp_attrproperty('filename', cls=Node),
+                       parent=GetSetProperty(Node.fget_parent, Node.fset_parent),
                        )
 
         

pypy/interpreter/astcompiler/astgen.py

     def __init__(self, lineno = -1):
         self.lineno = lineno
         self.filename = ""
+        self.parent = None
         #self.scope = None
         
     def getChildren(self):
     def descr_repr( self, space ):
         return space.wrap( self.__repr__() )
     
+    def fget_parent(space, self):
+        return space.wrap(self.parent)
+
+    def fset_parent(space, self, w_parent):
+        self.parent = space.interp_w(Node, w_parent, can_be_None=False)
+
     def descr_getChildNodes( self, space ):
         lst = self.getChildNodes()
         return space.newlist( [ space.wrap( it ) for it in lst ] )
                        accept = interp2app(descr_node_accept, unwrap_spec=[ ObjSpace, W_Root, W_Root ] ),
                        lineno = interp_attrproperty('lineno', cls=Node),
                        filename = interp_attrproperty('filename', cls=Node),
+                       parent=GetSetProperty(Node.fget_parent, Node.fset_parent),
                        )
 
         

pypy/interpreter/pycompiler.py

 
     def __init__(self, space):
         self.space = space
-	self.w_compile_hook = space.w_None
+        self.w_compile_hook = space.w_None
 
     def compile(self, source, filename, mode, flags):
         """Compile and return an pypy.interpreter.eval.Code instance."""
             raise OperationError(space.w_SyntaxError,
                                  e.wrap_info(space, filename))
 
-	if not space.is_w(self.w_compile_hook, space.w_None):
-	    w_ast_tree = space.call_function(self.w_compile_hook,
+        if not space.is_w(self.w_compile_hook, space.w_None):
+            w_ast_tree = space.call_function(self.w_compile_hook,
                                              space.wrap(ast_tree),
                                              space.wrap(encoding))
             ast_tree = space.interp_w(Node, w_ast_tree)

pypy/module/recparser/hooksamples/constchanger.py

+class ChangeConstVisitor:
+    def visitConst(self, node):
+        if node.value == 3:
+            node.value = 2
+
+    def defaultvisit(self, node):
+        for child in node.getChildNodes():
+            child.accept(self)
+
+    def __getattr__(self, attrname):
+        if attrname.startswith('visit'):
+            return self.defaultvisit
+        raise AttributeError(attrname)
+        
+def threebecomestwo(ast, enc):
+    ast.accept(ChangeConstVisitor())
+    return ast
+
+# install the hook
+import parser
+parser.install_compiler_hook(threebecomestwo)

pypy/module/recparser/hooksamples/tracer.py

+"""this one logs simple assignments and somewhat clearly shows
+that we need a nice API to define "joinpoints". Maybe a SAX-like
+(i.e. event-based) API ?
+
+XXX: crashes on everything else than simple assignment (AssAttr, etc.)
+"""
+
+from parser import ASTPrintnl, ASTConst, ASTName
+from parser import install_compiler_hook
+
+class Tracer:
+    def visitModule(self, module):
+        module.node = module.node.accept(self)
+        return module 
+
+    def default(self, node):
+        for child in node.getChildNodes():
+            # let's cheat a bit
+            child.parent = node
+            child.accept(self)
+        return node 
+
+    def visitAssign(self, assign):
+        stmt = assign.parent
+        varname = assign.nodes[0].name
+        lognode = ASTPrintnl([ASTConst('%s <--' % varname), ASTName(varname)], None)
+        index = stmt.nodes.index(assign)
+        newstmts = stmt.nodes
+        newstmts.insert(index + 1, lognode)
+        stmt.nodes = newstmts
+        return assign
+
+    def __getattr__(self, attrname):
+        if attrname.startswith('visit'):
+            return self.default
+        raise AttributeError('No such attribute: %s' % attrname)
+
+
+def _trace(ast, enc):
+    return ast.accept(Tracer())
+
+install_compiler_hook(_trace)