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):
hoistable = ["fn"]
ignore = ["def", "decorate_with"]
def __init__(self):
self.series = 0
@ -34,19 +35,29 @@ class FunctionMangle(hy.mangle.Mangle):
self.series += 1
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):
if isinstance(tree, HyExpression):
if isinstance(tree, HyExpression) and tree != []:
call = tree[0]
if isinstance(call, HyExpression) and len(call) != 0:
what = call[0]
if what in self.hoistable:
name = self.unique_name()
call = HyExpression([HySymbol("def"), name, call])
self.hoist(call)
tree.pop(0)
entry = HySymbol(name)
entry.replace(tree)
tree.insert(0, entry)
raise self.TreeChanged()
if call == "fn" and self.should_hoist():
new_name = HySymbol(self.unique_name())
new_name.replace(tree)
fn_def = HyExpression([HySymbol("def"),
new_name,
tree])
fn_def.replace(tree)
self.hoist(fn_def)
return new_name
hy.mangle.MANGLES.append(FunctionMangle)

View File

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