Bugfix for #50. I'm slowly starting to take a shine to this.
This commit is contained in:
parent
936d1bcec7
commit
1d01d8874a
@ -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)
|
||||
|
34
hy/mangle.py
34
hy/mangle.py
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user