[pypy-commit] pypy split-ast-classes: in-progress: conversion of internal trees to Python-visible AST.

amauryfa noreply at buildbot.pypy.org
Wed Jun 26 23:22:05 CEST 2013


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: split-ast-classes
Changeset: r65014:e1dff3384dde
Date: 2013-06-23 13:57 +0200
http://bitbucket.org/pypy/pypy/changeset/e1dff3384dde/

Log:	in-progress: conversion of internal trees to Python-visible AST.

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
@@ -1,6 +1,10 @@
 # Generated by tools/asdl_py.py
 from pypy.interpreter.error import OperationError
 from rpython.tool.pairtype import extendabletype
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter import typedef
+from pypy.interpreter.gateway import interp2app
+from rpython.tool.sourcetools import func_with_new_name
 
 
 class AST(object):
@@ -16,8 +20,101 @@
 class NodeVisitorNotImplemented(Exception):
     pass
 
+
+class _FieldsWrapper(W_Root):
+    "Hack around the fact we can't store tuples on a TypeDef."
+
+    def __init__(self, fields):
+        self.fields = fields
+
+    def __spacebind__(self, space):
+        return space.newtuple([space.wrap(field) for field in self.fields])
+
+
+class W_AST(W_Root):
+    w_dict = None
+
+    def getdict(self, space):
+        if self.w_dict is None:
+            self.w_dict = space.newdict(instance=True)
+        return self.w_dict
+
+    def reduce_w(self, space):
+        w_dict = self.w_dict
+        if w_dict is None:
+            w_dict = space.newdict()
+        w_type = space.type(self)
+        w_fields = w_type.getdictvalue(space, "_fields")
+        for w_name in space.fixedview(w_fields):
+            space.setitem(w_dict, w_name,
+                          space.getattr(self, w_name))
+        w_attrs = space.findattr(w_type, space.wrap("_attributes"))
+        if w_attrs:
+            for w_name in space.fixedview(w_attrs):
+                space.setitem(w_dict, w_name,
+                              space.getattr(self, w_name))
+        return space.newtuple([space.type(self),
+                               space.newtuple([]),
+                               w_dict])
+
+    def setstate_w(self, space, w_state):
+        for w_name in space.unpackiterable(w_state):
+            space.setattr(self, w_name,
+                          space.getitem(w_state, w_name))
+
+def get_W_AST_new(node_class):
+    def generic_W_AST_new(space, w_type, __args__):
+        node = space.allocate_instance(node_class, w_type)
+        return space.wrap(node)
+    return func_with_new_name(generic_W_AST_new, "new_%s" % node_class.__name__)
+
+
+def W_AST_init(space, w_self, __args__):
+    args_w, kwargs_w = __args__.unpack()
+    if args_w and len(args_w) != 0:
+        w_err = space.wrap("_ast.AST constructor takes 0 positional arguments")
+        raise OperationError(space.w_TypeError, w_err)
+    for field, w_value in kwargs_w.iteritems():
+        space.setattr(w_self, space.wrap(field), w_value)
+
+
+W_AST.typedef = typedef.TypeDef("AST",
+    _fields=_FieldsWrapper([]),
+    _attributes=_FieldsWrapper([]),
+    __module__='_ast',
+    __reduce__=interp2app(W_AST.reduce_w),
+    __setstate__=interp2app(W_AST.setstate_w),
+    __dict__ = typedef.GetSetProperty(typedef.descr_get_dict,
+                                      typedef.descr_set_dict, cls=W_AST),
+    __new__=interp2app(get_W_AST_new(W_AST)),
+    __init__=interp2app(W_AST_init),
+)
+
+class State:
+    AST_TYPES = []
+
+    @classmethod
+    def ast_type(cls, name, base):
+        cls.AST_TYPES.append((name, base))
+
+    def __init__(self, space):
+        self.w_AST = space.gettypeobject(W_AST.typedef)
+        for (name, base) in self.AST_TYPES:
+            self.make_new_type(space, name, base)
+        
+    def make_new_type(self, space, name, base):
+        w_base = getattr(self, 'w_%s' % base)
+        w_type = space.call_function(
+            space.w_type, 
+            space.wrap(name), space.newtuple([w_base]), space.newdict())
+        setattr(self, 'w_%s' % name, w_type)
+
+def get(space):
+    return space.fromcache(State)
+
 class mod(AST):
     pass
+State.ast_type('mod', 'AST')
 
 class Module(mod):
 
@@ -32,6 +129,17 @@
             visitor._mutate_sequence(self.body)
         return visitor.visit_Module(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Module)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('Module', 'mod')
+
 
 class Interactive(mod):
 
@@ -46,6 +154,17 @@
             visitor._mutate_sequence(self.body)
         return visitor.visit_Interactive(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Interactive)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('Interactive', 'mod')
+
 
 class Expression(mod):
 
@@ -59,6 +178,13 @@
         self.body = self.body.mutate_over(visitor)
         return visitor.visit_Expression(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Expression)
+        w_body = self.body.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('Expression', 'mod')
+
 
 class Suite(mod):
 
@@ -73,12 +199,24 @@
             visitor._mutate_sequence(self.body)
         return visitor.visit_Suite(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Suite)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('Suite', 'mod')
+
 
 class stmt(AST):
 
     def __init__(self, lineno, col_offset):
         self.lineno = lineno
         self.col_offset = col_offset
+State.ast_type('stmt', 'AST')
 
 class FunctionDef(stmt):
 
@@ -100,6 +238,27 @@
             visitor._mutate_sequence(self.decorator_list)
         return visitor.visit_FunctionDef(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_FunctionDef)
+        w_name = space.wrap(self.name)
+        space.setattr(w_node, space.wrap('name'), w_name)
+        w_args = self.args.to_object(space)  # arguments
+        space.setattr(w_node, space.wrap('args'), w_args)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.decorator_list is None:
+            decorator_list_w = []
+        else:
+            decorator_list_w = [node.to_object(space) for node in self.decorator_list] # expr
+        w_decorator_list = space.newlist(decorator_list_w)
+        space.setattr(w_node, space.wrap('decorator_list'), w_decorator_list)
+        return w_node
+State.ast_type('FunctionDef', 'stmt')
+
 
 class ClassDef(stmt):
 
@@ -122,6 +281,31 @@
             visitor._mutate_sequence(self.decorator_list)
         return visitor.visit_ClassDef(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_ClassDef)
+        w_name = space.wrap(self.name)
+        space.setattr(w_node, space.wrap('name'), w_name)
+        if self.bases is None:
+            bases_w = []
+        else:
+            bases_w = [node.to_object(space) for node in self.bases] # expr
+        w_bases = space.newlist(bases_w)
+        space.setattr(w_node, space.wrap('bases'), w_bases)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.decorator_list is None:
+            decorator_list_w = []
+        else:
+            decorator_list_w = [node.to_object(space) for node in self.decorator_list] # expr
+        w_decorator_list = space.newlist(decorator_list_w)
+        space.setattr(w_node, space.wrap('decorator_list'), w_decorator_list)
+        return w_node
+State.ast_type('ClassDef', 'stmt')
+
 
 class Return(stmt):
 
@@ -137,6 +321,13 @@
             self.value = self.value.mutate_over(visitor)
         return visitor.visit_Return(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Return)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Return', 'stmt')
+
 
 class Delete(stmt):
 
@@ -152,6 +343,17 @@
             visitor._mutate_sequence(self.targets)
         return visitor.visit_Delete(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Delete)
+        if self.targets is None:
+            targets_w = []
+        else:
+            targets_w = [node.to_object(space) for node in self.targets] # expr
+        w_targets = space.newlist(targets_w)
+        space.setattr(w_node, space.wrap('targets'), w_targets)
+        return w_node
+State.ast_type('Delete', 'stmt')
+
 
 class Assign(stmt):
 
@@ -169,6 +371,19 @@
         self.value = self.value.mutate_over(visitor)
         return visitor.visit_Assign(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Assign)
+        if self.targets is None:
+            targets_w = []
+        else:
+            targets_w = [node.to_object(space) for node in self.targets] # expr
+        w_targets = space.newlist(targets_w)
+        space.setattr(w_node, space.wrap('targets'), w_targets)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Assign', 'stmt')
+
 
 class AugAssign(stmt):
 
@@ -186,6 +401,17 @@
         self.value = self.value.mutate_over(visitor)
         return visitor.visit_AugAssign(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_AugAssign)
+        w_target = self.target.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('target'), w_target)
+        w_op = operator_to_class[self.op - 1]()
+        space.setattr(w_node, space.wrap('op'), w_op)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('AugAssign', 'stmt')
+
 
 class Print(stmt):
 
@@ -205,6 +431,21 @@
             visitor._mutate_sequence(self.values)
         return visitor.visit_Print(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Print)
+        w_dest = self.dest.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('dest'), w_dest)
+        if self.values is None:
+            values_w = []
+        else:
+            values_w = [node.to_object(space) for node in self.values] # expr
+        w_values = space.newlist(values_w)
+        space.setattr(w_node, space.wrap('values'), w_values)
+        w_nl = self.nl.to_object(space)  # bool
+        space.setattr(w_node, space.wrap('nl'), w_nl)
+        return w_node
+State.ast_type('Print', 'stmt')
+
 
 class For(stmt):
 
@@ -227,6 +468,27 @@
             visitor._mutate_sequence(self.orelse)
         return visitor.visit_For(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_For)
+        w_target = self.target.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('target'), w_target)
+        w_iter = self.iter.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('iter'), w_iter)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.orelse is None:
+            orelse_w = []
+        else:
+            orelse_w = [node.to_object(space) for node in self.orelse] # stmt
+        w_orelse = space.newlist(orelse_w)
+        space.setattr(w_node, space.wrap('orelse'), w_orelse)
+        return w_node
+State.ast_type('For', 'stmt')
+
 
 class While(stmt):
 
@@ -247,6 +509,25 @@
             visitor._mutate_sequence(self.orelse)
         return visitor.visit_While(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_While)
+        w_test = self.test.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('test'), w_test)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.orelse is None:
+            orelse_w = []
+        else:
+            orelse_w = [node.to_object(space) for node in self.orelse] # stmt
+        w_orelse = space.newlist(orelse_w)
+        space.setattr(w_node, space.wrap('orelse'), w_orelse)
+        return w_node
+State.ast_type('While', 'stmt')
+
 
 class If(stmt):
 
@@ -267,6 +548,25 @@
             visitor._mutate_sequence(self.orelse)
         return visitor.visit_If(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_If)
+        w_test = self.test.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('test'), w_test)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.orelse is None:
+            orelse_w = []
+        else:
+            orelse_w = [node.to_object(space) for node in self.orelse] # stmt
+        w_orelse = space.newlist(orelse_w)
+        space.setattr(w_node, space.wrap('orelse'), w_orelse)
+        return w_node
+State.ast_type('If', 'stmt')
+
 
 class With(stmt):
 
@@ -287,6 +587,21 @@
             visitor._mutate_sequence(self.body)
         return visitor.visit_With(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_With)
+        w_context_expr = self.context_expr.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('context_expr'), w_context_expr)
+        w_optional_vars = self.optional_vars.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('optional_vars'), w_optional_vars)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('With', 'stmt')
+
 
 class Raise(stmt):
 
@@ -308,6 +623,17 @@
             self.tback = self.tback.mutate_over(visitor)
         return visitor.visit_Raise(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Raise)
+        w_type = self.type.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('type'), w_type)
+        w_inst = self.inst.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('inst'), w_inst)
+        w_tback = self.tback.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('tback'), w_tback)
+        return w_node
+State.ast_type('Raise', 'stmt')
+
 
 class TryExcept(stmt):
 
@@ -329,6 +655,29 @@
             visitor._mutate_sequence(self.orelse)
         return visitor.visit_TryExcept(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_TryExcept)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.handlers is None:
+            handlers_w = []
+        else:
+            handlers_w = [node.to_object(space) for node in self.handlers] # excepthandler
+        w_handlers = space.newlist(handlers_w)
+        space.setattr(w_node, space.wrap('handlers'), w_handlers)
+        if self.orelse is None:
+            orelse_w = []
+        else:
+            orelse_w = [node.to_object(space) for node in self.orelse] # stmt
+        w_orelse = space.newlist(orelse_w)
+        space.setattr(w_node, space.wrap('orelse'), w_orelse)
+        return w_node
+State.ast_type('TryExcept', 'stmt')
+
 
 class TryFinally(stmt):
 
@@ -347,6 +696,23 @@
             visitor._mutate_sequence(self.finalbody)
         return visitor.visit_TryFinally(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_TryFinally)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        if self.finalbody is None:
+            finalbody_w = []
+        else:
+            finalbody_w = [node.to_object(space) for node in self.finalbody] # stmt
+        w_finalbody = space.newlist(finalbody_w)
+        space.setattr(w_node, space.wrap('finalbody'), w_finalbody)
+        return w_node
+State.ast_type('TryFinally', 'stmt')
+
 
 class Assert(stmt):
 
@@ -364,6 +730,15 @@
             self.msg = self.msg.mutate_over(visitor)
         return visitor.visit_Assert(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Assert)
+        w_test = self.test.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('test'), w_test)
+        w_msg = self.msg.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('msg'), w_msg)
+        return w_node
+State.ast_type('Assert', 'stmt')
+
 
 class Import(stmt):
 
@@ -379,6 +754,17 @@
             visitor._mutate_sequence(self.names)
         return visitor.visit_Import(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Import)
+        if self.names is None:
+            names_w = []
+        else:
+            names_w = [node.to_object(space) for node in self.names] # alias
+        w_names = space.newlist(names_w)
+        space.setattr(w_node, space.wrap('names'), w_names)
+        return w_node
+State.ast_type('Import', 'stmt')
+
 
 class ImportFrom(stmt):
 
@@ -396,6 +782,21 @@
             visitor._mutate_sequence(self.names)
         return visitor.visit_ImportFrom(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_ImportFrom)
+        w_module = space.wrap(self.module)
+        space.setattr(w_node, space.wrap('module'), w_module)
+        if self.names is None:
+            names_w = []
+        else:
+            names_w = [node.to_object(space) for node in self.names] # alias
+        w_names = space.newlist(names_w)
+        space.setattr(w_node, space.wrap('names'), w_names)
+        w_level = self.level.to_object(space)  # int
+        space.setattr(w_node, space.wrap('level'), w_level)
+        return w_node
+State.ast_type('ImportFrom', 'stmt')
+
 
 class Exec(stmt):
 
@@ -416,6 +817,17 @@
             self.locals = self.locals.mutate_over(visitor)
         return visitor.visit_Exec(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Exec)
+        w_body = self.body.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('body'), w_body)
+        w_globals = self.globals.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('globals'), w_globals)
+        w_locals = self.locals.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('locals'), w_locals)
+        return w_node
+State.ast_type('Exec', 'stmt')
+
 
 class Global(stmt):
 
@@ -429,6 +841,17 @@
     def mutate_over(self, visitor):
         return visitor.visit_Global(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Global)
+        if self.names is None:
+            names_w = []
+        else:
+            names_w = [node.to_object(space) for node in self.names] # identifier
+        w_names = space.newlist(names_w)
+        space.setattr(w_node, space.wrap('names'), w_names)
+        return w_node
+State.ast_type('Global', 'stmt')
+
 
 class Expr(stmt):
 
@@ -443,6 +866,13 @@
         self.value = self.value.mutate_over(visitor)
         return visitor.visit_Expr(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Expr)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Expr', 'stmt')
+
 
 class Pass(stmt):
 
@@ -455,6 +885,11 @@
     def mutate_over(self, visitor):
         return visitor.visit_Pass(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Pass)
+        return w_node
+State.ast_type('Pass', 'stmt')
+
 
 class Break(stmt):
 
@@ -467,6 +902,11 @@
     def mutate_over(self, visitor):
         return visitor.visit_Break(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Break)
+        return w_node
+State.ast_type('Break', 'stmt')
+
 
 class Continue(stmt):
 
@@ -479,12 +919,18 @@
     def mutate_over(self, visitor):
         return visitor.visit_Continue(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Continue)
+        return w_node
+State.ast_type('Continue', 'stmt')
+
 
 class expr(AST):
 
     def __init__(self, lineno, col_offset):
         self.lineno = lineno
         self.col_offset = col_offset
+State.ast_type('expr', 'AST')
 
 class BoolOp(expr):
 
@@ -501,6 +947,19 @@
             visitor._mutate_sequence(self.values)
         return visitor.visit_BoolOp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_BoolOp)
+        w_op = boolop_to_class[self.op - 1]()
+        space.setattr(w_node, space.wrap('op'), w_op)
+        if self.values is None:
+            values_w = []
+        else:
+            values_w = [node.to_object(space) for node in self.values] # expr
+        w_values = space.newlist(values_w)
+        space.setattr(w_node, space.wrap('values'), w_values)
+        return w_node
+State.ast_type('BoolOp', 'expr')
+
 
 class BinOp(expr):
 
@@ -518,6 +977,17 @@
         self.right = self.right.mutate_over(visitor)
         return visitor.visit_BinOp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_BinOp)
+        w_left = self.left.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('left'), w_left)
+        w_op = operator_to_class[self.op - 1]()
+        space.setattr(w_node, space.wrap('op'), w_op)
+        w_right = self.right.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('right'), w_right)
+        return w_node
+State.ast_type('BinOp', 'expr')
+
 
 class UnaryOp(expr):
 
@@ -533,6 +1003,15 @@
         self.operand = self.operand.mutate_over(visitor)
         return visitor.visit_UnaryOp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_UnaryOp)
+        w_op = unaryop_to_class[self.op - 1]()
+        space.setattr(w_node, space.wrap('op'), w_op)
+        w_operand = self.operand.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('operand'), w_operand)
+        return w_node
+State.ast_type('UnaryOp', 'expr')
+
 
 class Lambda(expr):
 
@@ -549,6 +1028,15 @@
         self.body = self.body.mutate_over(visitor)
         return visitor.visit_Lambda(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Lambda)
+        w_args = self.args.to_object(space)  # arguments
+        space.setattr(w_node, space.wrap('args'), w_args)
+        w_body = self.body.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('Lambda', 'expr')
+
 
 class IfExp(expr):
 
@@ -567,6 +1055,17 @@
         self.orelse = self.orelse.mutate_over(visitor)
         return visitor.visit_IfExp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_IfExp)
+        w_test = self.test.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('test'), w_test)
+        w_body = self.body.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('body'), w_body)
+        w_orelse = self.orelse.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('orelse'), w_orelse)
+        return w_node
+State.ast_type('IfExp', 'expr')
+
 
 class Dict(expr):
 
@@ -585,6 +1084,23 @@
             visitor._mutate_sequence(self.values)
         return visitor.visit_Dict(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Dict)
+        if self.keys is None:
+            keys_w = []
+        else:
+            keys_w = [node.to_object(space) for node in self.keys] # expr
+        w_keys = space.newlist(keys_w)
+        space.setattr(w_node, space.wrap('keys'), w_keys)
+        if self.values is None:
+            values_w = []
+        else:
+            values_w = [node.to_object(space) for node in self.values] # expr
+        w_values = space.newlist(values_w)
+        space.setattr(w_node, space.wrap('values'), w_values)
+        return w_node
+State.ast_type('Dict', 'expr')
+
 
 class Set(expr):
 
@@ -600,6 +1116,17 @@
             visitor._mutate_sequence(self.elts)
         return visitor.visit_Set(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Set)
+        if self.elts is None:
+            elts_w = []
+        else:
+            elts_w = [node.to_object(space) for node in self.elts] # expr
+        w_elts = space.newlist(elts_w)
+        space.setattr(w_node, space.wrap('elts'), w_elts)
+        return w_node
+State.ast_type('Set', 'expr')
+
 
 class ListComp(expr):
 
@@ -617,6 +1144,19 @@
             visitor._mutate_sequence(self.generators)
         return visitor.visit_ListComp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_ListComp)
+        w_elt = self.elt.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('elt'), w_elt)
+        if self.generators is None:
+            generators_w = []
+        else:
+            generators_w = [node.to_object(space) for node in self.generators] # comprehension
+        w_generators = space.newlist(generators_w)
+        space.setattr(w_node, space.wrap('generators'), w_generators)
+        return w_node
+State.ast_type('ListComp', 'expr')
+
 
 class SetComp(expr):
 
@@ -634,6 +1174,19 @@
             visitor._mutate_sequence(self.generators)
         return visitor.visit_SetComp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_SetComp)
+        w_elt = self.elt.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('elt'), w_elt)
+        if self.generators is None:
+            generators_w = []
+        else:
+            generators_w = [node.to_object(space) for node in self.generators] # comprehension
+        w_generators = space.newlist(generators_w)
+        space.setattr(w_node, space.wrap('generators'), w_generators)
+        return w_node
+State.ast_type('SetComp', 'expr')
+
 
 class DictComp(expr):
 
@@ -653,6 +1206,21 @@
             visitor._mutate_sequence(self.generators)
         return visitor.visit_DictComp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_DictComp)
+        w_key = self.key.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('key'), w_key)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        if self.generators is None:
+            generators_w = []
+        else:
+            generators_w = [node.to_object(space) for node in self.generators] # comprehension
+        w_generators = space.newlist(generators_w)
+        space.setattr(w_node, space.wrap('generators'), w_generators)
+        return w_node
+State.ast_type('DictComp', 'expr')
+
 
 class GeneratorExp(expr):
 
@@ -670,6 +1238,19 @@
             visitor._mutate_sequence(self.generators)
         return visitor.visit_GeneratorExp(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_GeneratorExp)
+        w_elt = self.elt.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('elt'), w_elt)
+        if self.generators is None:
+            generators_w = []
+        else:
+            generators_w = [node.to_object(space) for node in self.generators] # comprehension
+        w_generators = space.newlist(generators_w)
+        space.setattr(w_node, space.wrap('generators'), w_generators)
+        return w_node
+State.ast_type('GeneratorExp', 'expr')
+
 
 class Yield(expr):
 
@@ -685,6 +1266,13 @@
             self.value = self.value.mutate_over(visitor)
         return visitor.visit_Yield(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Yield)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Yield', 'expr')
+
 
 class Compare(expr):
 
@@ -703,6 +1291,25 @@
             visitor._mutate_sequence(self.comparators)
         return visitor.visit_Compare(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Compare)
+        w_left = self.left.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('left'), w_left)
+        if self.ops is None:
+            ops_w = []
+        else:
+            ops_w = [cmpop_to_class[node - 1]() for node in self.ops] # cmpop
+        w_ops = space.newlist(ops_w)
+        space.setattr(w_node, space.wrap('ops'), w_ops)
+        if self.comparators is None:
+            comparators_w = []
+        else:
+            comparators_w = [node.to_object(space) for node in self.comparators] # expr
+        w_comparators = space.newlist(comparators_w)
+        space.setattr(w_node, space.wrap('comparators'), w_comparators)
+        return w_node
+State.ast_type('Compare', 'expr')
+
 
 class Call(expr):
 
@@ -729,6 +1336,29 @@
             self.kwargs = self.kwargs.mutate_over(visitor)
         return visitor.visit_Call(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Call)
+        w_func = self.func.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('func'), w_func)
+        if self.args is None:
+            args_w = []
+        else:
+            args_w = [node.to_object(space) for node in self.args] # expr
+        w_args = space.newlist(args_w)
+        space.setattr(w_node, space.wrap('args'), w_args)
+        if self.keywords is None:
+            keywords_w = []
+        else:
+            keywords_w = [node.to_object(space) for node in self.keywords] # keyword
+        w_keywords = space.newlist(keywords_w)
+        space.setattr(w_node, space.wrap('keywords'), w_keywords)
+        w_starargs = self.starargs.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('starargs'), w_starargs)
+        w_kwargs = self.kwargs.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('kwargs'), w_kwargs)
+        return w_node
+State.ast_type('Call', 'expr')
+
 
 class Repr(expr):
 
@@ -743,6 +1373,13 @@
         self.value = self.value.mutate_over(visitor)
         return visitor.visit_Repr(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Repr)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Repr', 'expr')
+
 
 class Num(expr):
 
@@ -756,6 +1393,13 @@
     def mutate_over(self, visitor):
         return visitor.visit_Num(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Num)
+        w_n = self.n
+        space.setattr(w_node, space.wrap('n'), w_n)
+        return w_node
+State.ast_type('Num', 'expr')
+
 
 class Str(expr):
 
@@ -769,6 +1413,13 @@
     def mutate_over(self, visitor):
         return visitor.visit_Str(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Str)
+        w_s = self.s
+        space.setattr(w_node, space.wrap('s'), w_s)
+        return w_node
+State.ast_type('Str', 'expr')
+
 
 class Attribute(expr):
 
@@ -785,6 +1436,17 @@
         self.value = self.value.mutate_over(visitor)
         return visitor.visit_Attribute(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Attribute)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        w_attr = space.wrap(self.attr)
+        space.setattr(w_node, space.wrap('attr'), w_attr)
+        w_ctx = expr_context_to_class[self.ctx - 1]()
+        space.setattr(w_node, space.wrap('ctx'), w_ctx)
+        return w_node
+State.ast_type('Attribute', 'expr')
+
 
 class Subscript(expr):
 
@@ -802,6 +1464,17 @@
         self.slice = self.slice.mutate_over(visitor)
         return visitor.visit_Subscript(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Subscript)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        w_slice = self.slice.to_object(space)  # slice
+        space.setattr(w_node, space.wrap('slice'), w_slice)
+        w_ctx = expr_context_to_class[self.ctx - 1]()
+        space.setattr(w_node, space.wrap('ctx'), w_ctx)
+        return w_node
+State.ast_type('Subscript', 'expr')
+
 
 class Name(expr):
 
@@ -816,6 +1489,15 @@
     def mutate_over(self, visitor):
         return visitor.visit_Name(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Name)
+        w_id = space.wrap(self.id)
+        space.setattr(w_node, space.wrap('id'), w_id)
+        w_ctx = expr_context_to_class[self.ctx - 1]()
+        space.setattr(w_node, space.wrap('ctx'), w_ctx)
+        return w_node
+State.ast_type('Name', 'expr')
+
 
 class List(expr):
 
@@ -832,6 +1514,19 @@
             visitor._mutate_sequence(self.elts)
         return visitor.visit_List(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_List)
+        if self.elts is None:
+            elts_w = []
+        else:
+            elts_w = [node.to_object(space) for node in self.elts] # expr
+        w_elts = space.newlist(elts_w)
+        space.setattr(w_node, space.wrap('elts'), w_elts)
+        w_ctx = expr_context_to_class[self.ctx - 1]()
+        space.setattr(w_node, space.wrap('ctx'), w_ctx)
+        return w_node
+State.ast_type('List', 'expr')
+
 
 class Tuple(expr):
 
@@ -848,6 +1543,19 @@
             visitor._mutate_sequence(self.elts)
         return visitor.visit_Tuple(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Tuple)
+        if self.elts is None:
+            elts_w = []
+        else:
+            elts_w = [node.to_object(space) for node in self.elts] # expr
+        w_elts = space.newlist(elts_w)
+        space.setattr(w_node, space.wrap('elts'), w_elts)
+        w_ctx = expr_context_to_class[self.ctx - 1]()
+        space.setattr(w_node, space.wrap('ctx'), w_ctx)
+        return w_node
+State.ast_type('Tuple', 'expr')
+
 
 class Const(expr):
 
@@ -861,42 +1569,56 @@
     def mutate_over(self, visitor):
         return visitor.visit_Const(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Const)
+        w_value = self.value
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Const', 'expr')
+
 
 class expr_context(AST):
 
     def to_simple_int(self, space):
         w_msg = space.wrap("not a valid expr_context")
         raise OperationError(space.w_TypeError, w_msg)
+State.ast_type('expr_context', 'AST')
 
 class _Load(expr_context):
 
     def to_simple_int(self, space):
         return 1
+State.ast_type('Load', 'expr_context')
 
 class _Store(expr_context):
 
     def to_simple_int(self, space):
         return 2
+State.ast_type('Store', 'expr_context')
 
 class _Del(expr_context):
 
     def to_simple_int(self, space):
         return 3
+State.ast_type('Del', 'expr_context')
 
 class _AugLoad(expr_context):
 
     def to_simple_int(self, space):
         return 4
+State.ast_type('AugLoad', 'expr_context')
 
 class _AugStore(expr_context):
 
     def to_simple_int(self, space):
         return 5
+State.ast_type('AugStore', 'expr_context')
 
 class _Param(expr_context):
 
     def to_simple_int(self, space):
         return 6
+State.ast_type('Param', 'expr_context')
 
 Load = 1
 Store = 2
@@ -916,6 +1638,7 @@
 
 class slice(AST):
     pass
+State.ast_type('slice', 'AST')
 
 class Ellipsis(slice):
 
@@ -926,6 +1649,11 @@
     def mutate_over(self, visitor):
         return visitor.visit_Ellipsis(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Ellipsis)
+        return w_node
+State.ast_type('Ellipsis', 'slice')
+
 
 class Slice(slice):
 
@@ -946,6 +1674,17 @@
             self.step = self.step.mutate_over(visitor)
         return visitor.visit_Slice(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Slice)
+        w_lower = self.lower.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('lower'), w_lower)
+        w_upper = self.upper.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('upper'), w_upper)
+        w_step = self.step.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('step'), w_step)
+        return w_node
+State.ast_type('Slice', 'slice')
+
 
 class ExtSlice(slice):
 
@@ -960,6 +1699,17 @@
             visitor._mutate_sequence(self.dims)
         return visitor.visit_ExtSlice(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_ExtSlice)
+        if self.dims is None:
+            dims_w = []
+        else:
+            dims_w = [node.to_object(space) for node in self.dims] # slice
+        w_dims = space.newlist(dims_w)
+        space.setattr(w_node, space.wrap('dims'), w_dims)
+        return w_node
+State.ast_type('ExtSlice', 'slice')
+
 
 class Index(slice):
 
@@ -973,22 +1723,32 @@
         self.value = self.value.mutate_over(visitor)
         return visitor.visit_Index(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Index)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('Index', 'slice')
+
 
 class boolop(AST):
 
     def to_simple_int(self, space):
         w_msg = space.wrap("not a valid boolop")
         raise OperationError(space.w_TypeError, w_msg)
+State.ast_type('boolop', 'AST')
 
 class _And(boolop):
 
     def to_simple_int(self, space):
         return 1
+State.ast_type('And', 'boolop')
 
 class _Or(boolop):
 
     def to_simple_int(self, space):
         return 2
+State.ast_type('Or', 'boolop')
 
 And = 1
 Or = 2
@@ -1003,66 +1763,79 @@
     def to_simple_int(self, space):
         w_msg = space.wrap("not a valid operator")
         raise OperationError(space.w_TypeError, w_msg)
+State.ast_type('operator', 'AST')
 
 class _Add(operator):
 
     def to_simple_int(self, space):
         return 1
+State.ast_type('Add', 'operator')
 
 class _Sub(operator):
 
     def to_simple_int(self, space):
         return 2
+State.ast_type('Sub', 'operator')
 
 class _Mult(operator):
 
     def to_simple_int(self, space):
         return 3
+State.ast_type('Mult', 'operator')
 
 class _Div(operator):
 
     def to_simple_int(self, space):
         return 4
+State.ast_type('Div', 'operator')
 
 class _Mod(operator):
 
     def to_simple_int(self, space):
         return 5
+State.ast_type('Mod', 'operator')
 
 class _Pow(operator):
 
     def to_simple_int(self, space):
         return 6
+State.ast_type('Pow', 'operator')
 
 class _LShift(operator):
 
     def to_simple_int(self, space):
         return 7
+State.ast_type('LShift', 'operator')
 
 class _RShift(operator):
 
     def to_simple_int(self, space):
         return 8
+State.ast_type('RShift', 'operator')
 
 class _BitOr(operator):
 
     def to_simple_int(self, space):
         return 9
+State.ast_type('BitOr', 'operator')
 
 class _BitXor(operator):
 
     def to_simple_int(self, space):
         return 10
+State.ast_type('BitXor', 'operator')
 
 class _BitAnd(operator):
 
     def to_simple_int(self, space):
         return 11
+State.ast_type('BitAnd', 'operator')
 
 class _FloorDiv(operator):
 
     def to_simple_int(self, space):
         return 12
+State.ast_type('FloorDiv', 'operator')
 
 Add = 1
 Sub = 2
@@ -1097,26 +1870,31 @@
     def to_simple_int(self, space):
         w_msg = space.wrap("not a valid unaryop")
         raise OperationError(space.w_TypeError, w_msg)
+State.ast_type('unaryop', 'AST')
 
 class _Invert(unaryop):
 
     def to_simple_int(self, space):
         return 1
+State.ast_type('Invert', 'unaryop')
 
 class _Not(unaryop):
 
     def to_simple_int(self, space):
         return 2
+State.ast_type('Not', 'unaryop')
 
 class _UAdd(unaryop):
 
     def to_simple_int(self, space):
         return 3
+State.ast_type('UAdd', 'unaryop')
 
 class _USub(unaryop):
 
     def to_simple_int(self, space):
         return 4
+State.ast_type('USub', 'unaryop')
 
 Invert = 1
 Not = 2
@@ -1135,56 +1913,67 @@
     def to_simple_int(self, space):
         w_msg = space.wrap("not a valid cmpop")
         raise OperationError(space.w_TypeError, w_msg)
+State.ast_type('cmpop', 'AST')
 
 class _Eq(cmpop):
 
     def to_simple_int(self, space):
         return 1
+State.ast_type('Eq', 'cmpop')
 
 class _NotEq(cmpop):
 
     def to_simple_int(self, space):
         return 2
+State.ast_type('NotEq', 'cmpop')
 
 class _Lt(cmpop):
 
     def to_simple_int(self, space):
         return 3
+State.ast_type('Lt', 'cmpop')
 
 class _LtE(cmpop):
 
     def to_simple_int(self, space):
         return 4
+State.ast_type('LtE', 'cmpop')
 
 class _Gt(cmpop):
 
     def to_simple_int(self, space):
         return 5
+State.ast_type('Gt', 'cmpop')
 
 class _GtE(cmpop):
 
     def to_simple_int(self, space):
         return 6
+State.ast_type('GtE', 'cmpop')
 
 class _Is(cmpop):
 
     def to_simple_int(self, space):
         return 7
+State.ast_type('Is', 'cmpop')
 
 class _IsNot(cmpop):
 
     def to_simple_int(self, space):
         return 8
+State.ast_type('IsNot', 'cmpop')
 
 class _In(cmpop):
 
     def to_simple_int(self, space):
         return 9
+State.ast_type('In', 'cmpop')
 
 class _NotIn(cmpop):
 
     def to_simple_int(self, space):
         return 10
+State.ast_type('NotIn', 'cmpop')
 
 Eq = 1
 NotEq = 2
@@ -1227,11 +2016,27 @@
     def walkabout(self, visitor):
         visitor.visit_comprehension(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_comprehension)
+        w_target = self.target.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('target'), w_target)
+        w_iter = self.iter.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('iter'), w_iter)
+        if self.ifs is None:
+            ifs_w = []
+        else:
+            ifs_w = [node.to_object(space) for node in self.ifs] # expr
+        w_ifs = space.newlist(ifs_w)
+        space.setattr(w_node, space.wrap('ifs'), w_ifs)
+        return w_node
+State.ast_type('comprehension', 'AST')
+
 class excepthandler(AST):
 
     def __init__(self, lineno, col_offset):
         self.lineno = lineno
         self.col_offset = col_offset
+State.ast_type('excepthandler', 'AST')
 
 class ExceptHandler(excepthandler):
 
@@ -1253,6 +2058,21 @@
             visitor._mutate_sequence(self.body)
         return visitor.visit_ExceptHandler(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_ExceptHandler)
+        w_type = self.type.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('type'), w_type)
+        w_name = self.name.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('name'), w_name)
+        if self.body is None:
+            body_w = []
+        else:
+            body_w = [node.to_object(space) for node in self.body] # stmt
+        w_body = space.newlist(body_w)
+        space.setattr(w_node, space.wrap('body'), w_body)
+        return w_node
+State.ast_type('ExceptHandler', 'excepthandler')
+
 
 class arguments(AST):
 
@@ -1272,6 +2092,27 @@
     def walkabout(self, visitor):
         visitor.visit_arguments(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_arguments)
+        if self.args is None:
+            args_w = []
+        else:
+            args_w = [node.to_object(space) for node in self.args] # expr
+        w_args = space.newlist(args_w)
+        space.setattr(w_node, space.wrap('args'), w_args)
+        w_vararg = space.wrap(self.vararg)
+        space.setattr(w_node, space.wrap('vararg'), w_vararg)
+        w_kwarg = space.wrap(self.kwarg)
+        space.setattr(w_node, space.wrap('kwarg'), w_kwarg)
+        if self.defaults is None:
+            defaults_w = []
+        else:
+            defaults_w = [node.to_object(space) for node in self.defaults] # expr
+        w_defaults = space.newlist(defaults_w)
+        space.setattr(w_node, space.wrap('defaults'), w_defaults)
+        return w_node
+State.ast_type('arguments', 'AST')
+
 class keyword(AST):
 
     def __init__(self, arg, value):
@@ -1285,6 +2126,15 @@
     def walkabout(self, visitor):
         visitor.visit_keyword(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_keyword)
+        w_arg = space.wrap(self.arg)
+        space.setattr(w_node, space.wrap('arg'), w_arg)
+        w_value = self.value.to_object(space)  # expr
+        space.setattr(w_node, space.wrap('value'), w_value)
+        return w_node
+State.ast_type('keyword', 'AST')
+
 class alias(AST):
 
     def __init__(self, name, asname):
@@ -1297,6 +2147,15 @@
     def walkabout(self, visitor):
         visitor.visit_alias(self)
 
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_alias)
+        w_name = space.wrap(self.name)
+        space.setattr(w_node, space.wrap('name'), w_name)
+        w_asname = space.wrap(self.asname)
+        space.setattr(w_node, space.wrap('asname'), w_asname)
+        return w_node
+State.ast_type('alias', 'AST')
+
 class ASTVisitor(object):
 
     def visit_sequence(self, seq):
diff --git a/pypy/interpreter/astcompiler/test/test_ast.py b/pypy/interpreter/astcompiler/test/test_ast.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/astcompiler/test/test_ast.py
@@ -0,0 +1,30 @@
+from pypy.interpreter.astcompiler import ast
+class TestAstToObject:
+    def test_types(self, space):
+        assert space.is_true(space.issubtype(
+                ast.get(space).w_Module, ast.get(space).w_mod))
+                                  
+    def test_num(self, space):
+        value = space.wrap(42)
+        node = ast.Num(value, lineno=1, col_offset=1)
+        w_node = node.to_object(space)
+        assert space.getattr(w_node, space.wrap("n")) is value
+
+    def test_expr(self, space):
+        value = space.wrap(42)
+        node = ast.Num(value, lineno=1, col_offset=1)
+        expr = ast.Expr(node, lineno=1, col_offset=1)
+        w_node = expr.to_object(space)
+        # node.value.n
+        assert space.getattr(space.getattr(w_node, space.wrap("value")),
+                             space.wrap("n")) is value
+
+    def test_operation(self, space):
+        val1 = ast.Num(space.wrap(1), lineno=1, col_offset=1)
+        val2 = ast.Num(space.wrap(2), lineno=1, col_offset=1)
+        node = ast.BinOp(left=val1, right=val2, op=ast.Add,
+                         lineno=1, col_offset=1)
+        w_node = node.to_object(space)
+        w_op = space.getattr(w_node, space.wrap("op"))
+        assert space.is_true(space.issubtype(
+                ast.get(space).w_operator, w_op))
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
@@ -61,12 +61,14 @@
             self.emit("def to_simple_int(self, space):", 1)
             self.emit("w_msg = space.wrap(\"not a valid %s\")" % (base,), 2)
             self.emit("raise OperationError(space.w_TypeError, w_msg)", 2)
+            self.emit("State.ast_type('%s', 'AST')" % (base,))
             self.emit("")
             for i, cons in enumerate(sum.types):
                 self.emit("class _%s(%s):" % (cons.name, base))
                 self.emit("")
                 self.emit("def to_simple_int(self, space):", 1)
                 self.emit("return %i" % (i + 1,), 2)
+                self.emit("State.ast_type('%s', '%s')" % (cons.name, base))
                 self.emit("")
             for i, cons in enumerate(sum.types):
                 self.emit("%s = %i" % (cons.name, i + 1))
@@ -84,10 +86,10 @@
                 self.emit("def __init__(self, %s):" % (args,), 1)
                 for attr in sum.attributes:
                     self.visit(attr)
-                self.emit("")
             else:
                 self.emit("pass", 1)
-                self.emit("")
+            self.emit("State.ast_type('%r', 'AST')" % (base,))
+            self.emit("")
             for cons in sum.types:
                 self.visit(cons, base, sum.attributes)
                 self.emit("")
@@ -101,6 +103,47 @@
         self.emit("def walkabout(self, visitor):", 1)
         self.emit("visitor.visit_%s(self)" % (name,), 2)
         self.emit("")
+        self.make_converters(product.fields, name)
+        self.emit("State.ast_type('%r', 'AST')" % (name,))
+        self.emit("")
+
+    def get_field_converter(self, field):
+        if field.seq:
+            lines = []
+            lines.append("if self.%s is None:" % field.name)
+            lines.append("    %s_w = []" % field.name)
+            lines.append("else:")
+            if field.type.value in self.data.simple_types:
+                wrapper = "%s_to_class[node - 1]()" % (field.type,)
+            elif field.type.value in ("object", "string"):
+                wrapper = "node"
+            else:
+                wrapper = "node.to_object(space)"
+            lines.append("    %s_w = [%s for node in self.%s] # %s" %
+                         (field.name, wrapper, field.name, field.type))
+            lines.append("w_%s = space.newlist(%s_w)" % (field.name, field.name))
+            return lines
+        elif field.type.value in self.data.simple_types:
+            return ["w_%s = %s_to_class[self.%s - 1]()" % 
+                    (field.name, field.type, field.name)]
+        elif field.type.value in ("object", "string"):
+            return ["w_%s = self.%s" % (field.name, field.name)]
+        elif field.type.value in ("identifier",):
+            return ["w_%s = space.wrap(self.%s)" % (field.name, field.name)]
+        else:
+            return ["w_%s = self.%s.to_object(space)  # %s" %
+                    (field.name, field.name, field.type)]
+
+    def make_converters(self, fields, name):
+        self.emit("def to_object(self, space):", 1)
+        self.emit("w_node = space.call_function(get(space).w_%s)" % name, 2)
+        for field in fields:
+            wrapping_code = self.get_field_converter(field)
+            for line in wrapping_code:
+                self.emit(line, 2)
+            self.emit("space.setattr(w_node, space.wrap(%r), w_%s)" % (
+                    str(field.name), field.name), 2)
+        self.emit("return w_node", 2)
 
     def make_constructor(self, fields, node, extras=None, base=None):
         if fields or extras:
@@ -142,6 +185,9 @@
         self.emit("visitor.visit_%s(self)" % (cons.name,), 2)
         self.emit("")
         self.make_mutate_over(cons, cons.name)
+        self.make_converters(cons.fields, cons.name)
+        self.emit("State.ast_type('%r', '%s')" % (cons.name, base))
+        self.emit("")
 
     def visitField(self, field):
         self.emit("self.%s = %s" % (field.name, field.name), 2)
@@ -212,8 +258,8 @@
         self.emit("")
 
     def visitField(self, field):
-        if field.type.value not in asdl.builtin_types and \
-                field.type.value not in self.data.simple_types:
+        if (field.type.value not in asdl.builtin_types and 
+            field.type.value not in self.data.simple_types):
             level = 2
             template = "node.%s.walkabout(self)"
             if field.seq:
@@ -276,6 +322,10 @@
 HEAD = """# Generated by tools/asdl_py.py
 from pypy.interpreter.error import OperationError
 from rpython.tool.pairtype import extendabletype
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter import typedef
+from pypy.interpreter.gateway import interp2app
+from rpython.tool.sourcetools import func_with_new_name
 
 
 class AST(object):
@@ -291,6 +341,98 @@
 class NodeVisitorNotImplemented(Exception):
     pass
 
+
+class _FieldsWrapper(W_Root):
+    "Hack around the fact we can't store tuples on a TypeDef."
+
+    def __init__(self, fields):
+        self.fields = fields
+
+    def __spacebind__(self, space):
+        return space.newtuple([space.wrap(field) for field in self.fields])
+
+
+class W_AST(W_Root):
+    w_dict = None
+
+    def getdict(self, space):
+        if self.w_dict is None:
+            self.w_dict = space.newdict(instance=True)
+        return self.w_dict
+
+    def reduce_w(self, space):
+        w_dict = self.w_dict
+        if w_dict is None:
+            w_dict = space.newdict()
+        w_type = space.type(self)
+        w_fields = w_type.getdictvalue(space, "_fields")
+        for w_name in space.fixedview(w_fields):
+            space.setitem(w_dict, w_name,
+                          space.getattr(self, w_name))
+        w_attrs = space.findattr(w_type, space.wrap("_attributes"))
+        if w_attrs:
+            for w_name in space.fixedview(w_attrs):
+                space.setitem(w_dict, w_name,
+                              space.getattr(self, w_name))
+        return space.newtuple([space.type(self),
+                               space.newtuple([]),
+                               w_dict])
+
+    def setstate_w(self, space, w_state):
+        for w_name in space.unpackiterable(w_state):
+            space.setattr(self, w_name,
+                          space.getitem(w_state, w_name))
+
+def get_W_AST_new(node_class):
+    def generic_W_AST_new(space, w_type, __args__):
+        node = space.allocate_instance(node_class, w_type)
+        return space.wrap(node)
+    return func_with_new_name(generic_W_AST_new, "new_%s" % node_class.__name__)
+
+
+def W_AST_init(space, w_self, __args__):
+    args_w, kwargs_w = __args__.unpack()
+    if args_w and len(args_w) != 0:
+        w_err = space.wrap("_ast.AST constructor takes 0 positional arguments")
+        raise OperationError(space.w_TypeError, w_err)
+    for field, w_value in kwargs_w.iteritems():
+        space.setattr(w_self, space.wrap(field), w_value)
+
+
+W_AST.typedef = typedef.TypeDef("AST",
+    _fields=_FieldsWrapper([]),
+    _attributes=_FieldsWrapper([]),
+    __module__='_ast',
+    __reduce__=interp2app(W_AST.reduce_w),
+    __setstate__=interp2app(W_AST.setstate_w),
+    __dict__ = typedef.GetSetProperty(typedef.descr_get_dict,
+                                      typedef.descr_set_dict, cls=W_AST),
+    __new__=interp2app(get_W_AST_new(W_AST)),
+    __init__=interp2app(W_AST_init),
+)
+
+class State:
+    AST_TYPES = []
+
+    @classmethod
+    def ast_type(cls, name, base):
+        cls.AST_TYPES.append((name, base))
+
+    def __init__(self, space):
+        self.w_AST = space.gettypeobject(W_AST.typedef)
+        for (name, base) in self.AST_TYPES:
+            self.make_new_type(space, name, base)
+        
+    def make_new_type(self, space, name, base):
+        w_base = getattr(self, 'w_%s' % base)
+        w_type = space.call_function(
+            space.w_type, 
+            space.wrap(name), space.newtuple([w_base]), space.newdict())
+        setattr(self, 'w_%s' % name, w_type)
+
+def get(space):
+    return space.fromcache(State)
+
 """
 
 visitors = [ASTNodeVisitor, ASTVisitorVisitor, GenericASTVisitorVisitor]
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -25,7 +25,7 @@
 """
 
     ast_node = None
-    w_ast_type = space.gettypeobject(interp_ast.W_AST.typedef)
+    w_ast_type = space.gettypeobject(ast.W_AST.typedef)
     str_ = None
     if space.isinstance_w(w_source, w_ast_type):
         ast_node = space.interp_w(ast.mod, w_source)
@@ -57,7 +57,8 @@
     if ast_node is None:
         if flags & consts.PyCF_ONLY_AST:
             mod = ec.compiler.compile_to_ast(str_, filename, mode, flags)
-            return space.wrap(mod)
+            w_mod = mod.to_object(space)
+            return w_mod
         else:
             code = ec.compiler.compile(str_, filename, mode, flags)
     else:
diff --git a/pypy/module/_ast/__init__.py b/pypy/module/_ast/__init__.py
--- a/pypy/module/_ast/__init__.py
+++ b/pypy/module/_ast/__init__.py
@@ -7,14 +7,12 @@
     interpleveldefs = {
         "PyCF_ONLY_AST" : "space.wrap(%s)" % consts.PyCF_ONLY_AST,
         "__version__"   : "space.wrap('82160')",  # from CPython's svn.
-        "AST": "interp_ast.W_AST",
         }
     appleveldefs = {}
 
 
 def _setup():
     defs = Module.interpleveldefs
-    for name, cls in ast.__dict__.iteritems():
-        if isinstance(cls, type) and issubclass(cls, ast.AST):
-            defs[name.lstrip("_")] = cls.__module__ + "." + name
+    for (name, base) in ast.State.AST_TYPES:
+        defs[name] = "pypy.interpreter.astcompiler.ast.get(space).w_" + name
 _setup()


More information about the pypy-commit mailing list