Skip to content

Commit

Permalink
replace some leave methods with delayed methods; further small fixes
Browse files Browse the repository at this point in the history
--HG--
branch : rebuild
  • Loading branch information
Emile Anclin committed Dec 14, 2009
1 parent 77db55d commit 1117640
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 34 deletions.
6 changes: 3 additions & 3 deletions _nodes_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@


def _init_set_doc(node, newnode):
node.doc = None
newnode.doc = None
try:
if isinstance(node.body[0], Discard) and isinstance(node.body[0].value, _Str):
newnode.tolineno = node.body[0].lineno
Expand All @@ -121,7 +121,6 @@ def _init_set_doc(node, newnode):
except IndexError:
pass # ast built from scratch


def native_repr_tree(node, indent='', _done=None):
if _done is None:
_done = set()
Expand Down Expand Up @@ -356,7 +355,7 @@ def visit_from(self, node):
newnode = new.From(node.module, names)
return newnode

def visit_function(self, node):
def _visit_function(self, node):
"""visit a Function node by returning a fresh instance of it"""
newnode = new.Function()
_init_set_doc(node, newnode)
Expand Down Expand Up @@ -483,6 +482,7 @@ def visit_pass(self, node):
def visit_print(self, node):
"""visit a Print node by returning a fresh instance of it"""
newnode = new.Print()
newnode.nl = node.nl
newnode.dest = self.visit(node.dest, node)
newnode.values = [self.visit(child, node) for child in node.values]
return newnode
Expand Down
2 changes: 1 addition & 1 deletion _nodes_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ def visit_from(self, node):
return newnode


def visit_function(self, node):
def _visit_function(self, node):
"""visit a Function node by returning a fresh instance of it"""
newnode = new.Function()
newnode.decorators = self.visit(node.decorators, node)
Expand Down
68 changes: 38 additions & 30 deletions rebuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ def __init__(self, set_line_info = True):
self.asscontext = None
self._metaclass = None
self._global_names = None
self._delayed = []
self._delayed = dict((name, []) for name in ('class', 'function', 'assattr'))
self.set_line_info = set_line_info
self._asscontext = None

def visit(self, node, parent):
if node is None: # some attributes of some nodes are just None
print "node with parent %s is None" % parent
print "node with parent %s is None" % parent
return None
node.parent = parent # XXX it seems that we need it sometimes
self.set_asscontext(node, parent) # XXX
Expand All @@ -58,20 +59,17 @@ def visit(self, node, parent):
if newnode is None:
return
for child in newnode.get_children():
child.parent = newnode
if child is not None:
child.parent = newnode
else:
print indent + "newnode %s has None as child" % newnode
newnode.set_line_info(child)
_leave = getattr(self, "leave_%s" % _method_suffix, None )
if _leave:
_leave(newnode)
return newnode


def _push(self, node):
"""update the stack and init some parts of the Function or Class node
"""
node.locals = {}
node.parent.frame().set_local(node.name, node)

def set_asscontext(self, node, childnode):
"""set assignment /delete context needed later on by the childnode"""
# XXX refactor this method at least, but killing .asscontext would be better
Expand Down Expand Up @@ -103,20 +101,21 @@ def set_asscontext(self, node, childnode):

# take node arguments to be usable as visit/leave methods
def push_asscontext(self, node=None):
self.__asscontext = self.asscontext
self._asscontext = self.asscontext
self.asscontext = None
return True
def pop_asscontext(self, node=None):
self.asscontext = self.__asscontext
self.__asscontext = None
self.asscontext = self._asscontext
self._asscontext = None

def walk(self, node):
node = self.visit(node, None)
newnode = self.visit(node, None)
delayed = self._delayed
while delayed:
dnode = delayed.pop(0)
self.delayed_visit_assattr(dnode)
return node
for name, nodes in self._delayed.items():
delay_method = getattr(self, 'delayed_' + name)
for node in nodes:
delay_method(node)
return newnode

# general visit_<node> methods ############################################

Expand All @@ -127,7 +126,8 @@ def visit_arguments(self, node): # XXX parent...
node.parent.set_local(node.kwarg, node)

def visit_assign(self, node):
newnode = self._visit_assign(node)
return self._visit_assign(node)
# XXX call leave_assign here ?

def xxx_leave_assign(self, newnode): #XXX parent...
klass = newnode.parent.frame()
Expand Down Expand Up @@ -155,7 +155,7 @@ def xxx_leave_assign(self, newnode): #XXX parent...
def visit_class(self, node): # TODO
"""visit an Class node to become astng"""
newnode = self._visit_class(node)
self._push(newnode)
newnode.name = node.name
self._metaclass.append(self._metaclass[-1])
metaclass = self._metaclass.pop()
if not newnode.bases:
Expand All @@ -164,6 +164,9 @@ def visit_class(self, node): # TODO
node._newstyle = metaclass == 'type'
return newnode

def delayed_class(self, node):
node.parent.frame().set_local(node.name, node)

def visit_decorators(self, node): # TODO
"""visiting an Decorators node"""
return self._visit_decorators(node)
Expand Down Expand Up @@ -195,24 +198,30 @@ def visit_from(self, node): # TODO XXX root !
def visit_function(self, node): # XXX parent
"""visit an Function node to become astng"""
self._global_names.append({})
if isinstance(node.parent.frame(), nodes.Class):
if node.name == '__new__':
node.type = 'classmethod'
else:
node.type = 'method'
self._push(node)
return True
newnode = self._visit_function(node)
self._delayed['function'].append(newnode)
newnode.name = node.name
return newnode

def leave_function(self, node): # TODO
"""leave a Function node -> pop the last item on the stack"""
self._global_names.pop()

def delayed_function(self, newnode):
frame = newnode.parent.frame()
if isinstance(frame, nodes.Class):
if newnode.name == '__new__':
newnode.type = 'classmethod'
else:
newnode.type = 'method'
frame.set_local(newnode.name, newnode)

def visit_assattr(self, node): # TODO
"""visit an Getattr node to become astng"""
self._delayed.append(node) # FIXME
self._delayed['assattr'].append(node) # FIXME
self.push_asscontext()
return True
visit_delattr = visit_assattr
# XXX visit_delattr = visit_assattr

def leave_assattr(self, node): # TODO
"""visit an Getattr node to become astng"""
Expand All @@ -224,7 +233,6 @@ def visit_global(self, node):
"""visit an Global node to become astng"""
newnode = nodes.Global(node.names)
if self._global_names: # global at the module level, no effect
return nodes.Global(node.names)
for name in node.names:
self._global_names[-1].setdefault(name, []).append(newnode)
return newnode
Expand Down Expand Up @@ -259,7 +267,7 @@ def visit_assname(self, node): # XXX parent
visit_subscript = push_asscontext
leave_subscript = pop_asscontext

def delayed_visit_assattr(self, node):
def delayed_assattr(self, node):
"""visit a AssAttr node -> add name to locals, handle members
definition
"""
Expand Down
2 changes: 2 additions & 0 deletions scoped_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ class Function(StmtMixIn, Lambda):
def __init__(self):
self.starargs = None
self.kwargs = None
self.locals = {}

special_attributes = set(('__name__', '__doc__', '__dict__'))
# attributes below are set by the builder module or by raw factories
Expand Down Expand Up @@ -785,6 +786,7 @@ class Class(StmtMixIn, LocalsDictNodeNG):

def __init__(self):
self.instance_attrs = {}
self.locals = {}

def _newstyle_impl(self, context=None):
if context is None:
Expand Down

0 comments on commit 1117640

Please sign in to comment.