docstrings on the mangle
This commit is contained in:
parent
049c019791
commit
23773a5117
42
hy/mangle.py
42
hy/mangle.py
@ -35,38 +35,55 @@ class Mangle(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class TreeChanged(Exception):
|
class TreeChanged(Exception):
|
||||||
|
"""
|
||||||
|
This exception gets raised whenver any code alters the tree. This is
|
||||||
|
to let the handling code re-normalize parents, etc, and make sure we
|
||||||
|
re-enter the current position in order.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _mangle(self, tree):
|
def _mangle(self, tree):
|
||||||
# Things that force a scope push to go into:
|
"""
|
||||||
#
|
Main function of self.mangle, which is called over and over. This
|
||||||
# - Functions
|
is used to beat the tree until it stops moving.
|
||||||
# - If
|
"""
|
||||||
scopable = ["fn", "if"]
|
|
||||||
scoped = False
|
|
||||||
|
|
||||||
|
scopable = ["fn", "if"]
|
||||||
|
# Not actually scope, more like code branch.
|
||||||
|
|
||||||
|
scoped = False
|
||||||
self.push_stack(tree)
|
self.push_stack(tree)
|
||||||
|
|
||||||
if isinstance(tree, HyExpression):
|
if isinstance(tree, HyExpression):
|
||||||
|
# If it's an expression, let's make sure we reset the "scope"
|
||||||
|
# (code branch) if it's a scopable object.
|
||||||
what = tree[0]
|
what = tree[0]
|
||||||
if what in scopable:
|
if what in scopable:
|
||||||
self.push_scope(tree)
|
self.push_scope(tree)
|
||||||
scoped = True
|
scoped = True
|
||||||
|
|
||||||
if isinstance(tree, list):
|
if isinstance(tree, list):
|
||||||
|
# If it's a list, let's mangle all the elements of the list.
|
||||||
for i, element in enumerate(tree):
|
for i, element in enumerate(tree):
|
||||||
nel = self.visit(element)
|
nel = self.visit(element)
|
||||||
if nel:
|
if nel:
|
||||||
|
# if the subclass returned an object, we replace the
|
||||||
|
# current node.
|
||||||
tree[i] = nel
|
tree[i] = nel
|
||||||
self.tree_changed()
|
self.tree_changed() # auto-raise a changed notice.
|
||||||
|
self._mangle(element) # recurse down, unwind on change.
|
||||||
self._mangle(element)
|
|
||||||
|
|
||||||
if scoped:
|
if scoped:
|
||||||
self.pop_scope()
|
self.pop_scope()
|
||||||
self.pop_stack()
|
self.pop_stack()
|
||||||
|
|
||||||
def hoist(self, what):
|
def hoist(self, what):
|
||||||
|
"""
|
||||||
|
Take a thing (what), and move it before whichever ancestor is in the
|
||||||
|
"scope" (code branch). This will hoist it *all* the way out of a deeply
|
||||||
|
nested statement in one pass. If it's still "invalid" (which it
|
||||||
|
shouldn't be), it'll just hoist again anyway.
|
||||||
|
"""
|
||||||
scope = self.scope
|
scope = self.scope
|
||||||
for point, el in enumerate(scope):
|
for point, el in enumerate(scope):
|
||||||
if el in self.stack:
|
if el in self.stack:
|
||||||
@ -77,6 +94,7 @@ class Mangle(object):
|
|||||||
return self.scopes[0]
|
return self.scopes[0]
|
||||||
|
|
||||||
def tree_changed(self):
|
def tree_changed(self):
|
||||||
|
""" Invoke this if you alter the tree in any way """
|
||||||
raise self.TreeChanged()
|
raise self.TreeChanged()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -96,6 +114,12 @@ class Mangle(object):
|
|||||||
return self.stack.pop(0)
|
return self.stack.pop(0)
|
||||||
|
|
||||||
def mangle(self, tree):
|
def mangle(self, tree):
|
||||||
|
"""
|
||||||
|
Magic external entry point.
|
||||||
|
|
||||||
|
We mangle until the tree stops moving (we don't get a TreeChanged
|
||||||
|
Exception during mangle)
|
||||||
|
"""
|
||||||
unfinished = True
|
unfinished = True
|
||||||
while unfinished:
|
while unfinished:
|
||||||
self.root = tree
|
self.root = tree
|
||||||
|
Loading…
Reference in New Issue
Block a user