diff --git a/hy/mangle.py b/hy/mangle.py index a0f2051..999d18b 100644 --- a/hy/mangle.py +++ b/hy/mangle.py @@ -35,38 +35,55 @@ class Mangle(object): """ 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 def _mangle(self, tree): - # Things that force a scope push to go into: - # - # - Functions - # - If - scopable = ["fn", "if"] - scoped = False + """ + Main function of self.mangle, which is called over and over. This + is used to beat the tree until it stops moving. + """ + scopable = ["fn", "if"] + # Not actually scope, more like code branch. + + scoped = False self.push_stack(tree) 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] if what in scopable: self.push_scope(tree) scoped = True if isinstance(tree, list): + # If it's a list, let's mangle all the elements of the list. for i, element in enumerate(tree): nel = self.visit(element) if nel: + # if the subclass returned an object, we replace the + # current node. tree[i] = nel - self.tree_changed() - - self._mangle(element) + self.tree_changed() # auto-raise a changed notice. + self._mangle(element) # recurse down, unwind on change. if scoped: self.pop_scope() self.pop_stack() 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 for point, el in enumerate(scope): if el in self.stack: @@ -77,6 +94,7 @@ class Mangle(object): return self.scopes[0] def tree_changed(self): + """ Invoke this if you alter the tree in any way """ raise self.TreeChanged() @property @@ -96,6 +114,12 @@ class Mangle(object): return self.stack.pop(0) 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 while unfinished: self.root = tree