Bugfix for #50. I'm slowly starting to take a shine to this.

This commit is contained in:
Paul R. Tagliamonte 2013-04-05 19:29:31 -04:00
parent 936d1bcec7
commit 1d01d8874a
2 changed files with 45 additions and 24 deletions

View File

@ -26,6 +26,7 @@ import hy.mangle
class FunctionMangle(hy.mangle.Mangle): class FunctionMangle(hy.mangle.Mangle):
hoistable = ["fn"] hoistable = ["fn"]
ignore = ["def", "decorate_with"]
def __init__(self): def __init__(self):
self.series = 0 self.series = 0
@ -34,19 +35,29 @@ class FunctionMangle(hy.mangle.Mangle):
self.series += 1 self.series += 1
return "_hy_hoisted_fn_%s" % (self.series) return "_hy_hoisted_fn_%s" % (self.series)
def should_hoist(self):
for frame in self.stack:
if frame is self.scope:
return False
if isinstance(frame, HyExpression) and frame != []:
call = frame[0]
if call in self.ignore:
continue
return True
return False
def visit(self, tree): def visit(self, tree):
if isinstance(tree, HyExpression): if isinstance(tree, HyExpression) and tree != []:
call = tree[0] call = tree[0]
if isinstance(call, HyExpression) and len(call) != 0: if call == "fn" and self.should_hoist():
what = call[0] new_name = HySymbol(self.unique_name())
if what in self.hoistable: new_name.replace(tree)
name = self.unique_name() fn_def = HyExpression([HySymbol("def"),
call = HyExpression([HySymbol("def"), name, call]) new_name,
self.hoist(call) tree])
tree.pop(0) fn_def.replace(tree)
entry = HySymbol(name) self.hoist(fn_def)
entry.replace(tree) return new_name
tree.insert(0, entry)
raise self.TreeChanged()
hy.mangle.MANGLES.append(FunctionMangle) hy.mangle.MANGLES.append(FunctionMangle)

View File

@ -45,6 +45,8 @@ class Mangle(object):
scopable = ["fn", "if"] scopable = ["fn", "if"]
scoped = False scoped = False
self.push_stack(tree)
if isinstance(tree, HyExpression): if isinstance(tree, HyExpression):
what = tree[0] what = tree[0]
if what in scopable: if what in scopable:
@ -52,30 +54,31 @@ class Mangle(object):
scoped = True scoped = True
if isinstance(tree, list): if isinstance(tree, list):
for element in tree: for i, element in enumerate(tree):
self.visit(element) nel = self.visit(element)
if nel:
tree[i] = nel
self.tree_changed()
self._mangle(element) self._mangle(element)
if scoped: if scoped:
self.pop_scope() self.pop_scope()
self.pop_stack()
def hoist(self, what): def hoist(self, what):
#print "HOIST: "
#print " --> (fro) ", what
#print " --> (to) ", self.scope
scope = self.scope scope = self.scope
point = 0 for point, el in enumerate(scope):
if el in self.stack:
if isinstance(scope, HyExpression) and len(scope): break
if scope[0] == 'fn':
point = 2
self.scope.insert(point, what) self.scope.insert(point, what)
#print " --> (aft) ", self.scope
def get_scope(self): def get_scope(self):
return self.scopes[0] return self.scopes[0]
def tree_changed(self):
raise self.TreeChanged()
@property @property
def scope(self): def scope(self):
return self.get_scope() return self.get_scope()
@ -83,14 +86,21 @@ class Mangle(object):
def push_scope(self, tree): def push_scope(self, tree):
self.scopes.insert(0, tree) self.scopes.insert(0, tree)
def push_stack(self, tree):
self.stack.insert(0, tree)
def pop_scope(self): def pop_scope(self):
return self.scopes.pop(0) return self.scopes.pop(0)
def pop_stack(self):
return self.stack.pop(0)
def mangle(self, tree): def mangle(self, tree):
unfinished = True unfinished = True
while unfinished: while unfinished:
self.root = tree self.root = tree
self.scopes = [] self.scopes = []
self.stack = []
self.push_scope(tree) self.push_scope(tree)
try: try:
self._mangle(tree) self._mangle(tree)