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):
|
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)
|
||||||
|
34
hy/mangle.py
34
hy/mangle.py
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user