Browse files

more progress on getting rotations to work with expressions.

  • Loading branch information...
1 parent 09c286f commit f73eb0e56ce6e3aae9a953b480379ab8f61dd2b2 @maxtaco committed Jan 2, 2012
Showing with 90 additions and 79 deletions.
  1. +31 −32 lib/coffee-script/nodes.js
  2. +59 −47 src/nodes.coffee
View
63 lib/coffee-script/nodes.js
@@ -321,11 +321,13 @@
Base.prototype.tameCpsExprRotate = function(v) {
var doRotate;
doRotate = v.tameIsTamedExpr();
+ if (doRotate) v.tameCallContinuation();
v.tameCpsRotate();
- if (v.tameIsTamedExpr()) {
- v.tameCallContinuation();
+ if (doRotate) {
this.tameNestPrequelBlock(v);
return this.tameReturnValue = new TameReturnValue();
+ } else {
+ return null;
}
};
@@ -584,39 +586,36 @@
};
Block.prototype.tameCpsRotate = function() {
- var child, e, i, pivot, rest, _i, _j, _len, _len2, _ref2;
+ var child, e, i, pivot, rest, _i, _len, _len2, _ref2;
pivot = null;
- child = null;
- if (this.tameIsCpsPivot()) {
- i = 0;
- _ref2 = this.expressions;
- for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
- e = _ref2[_i];
- if (e.tameIsCpsPivot()) {
- pivot = e;
- break;
- }
- i++;
- }
- }
- if (pivot) {
- rest = this.expressions.slice(i + 1);
- this.expressions = this.expressions.slice(0, i + 1);
- if (rest.length) {
- child = new Block(rest);
- pivot.tameNestContinuationBlock(child);
- for (_j = 0, _len2 = rest.length; _j < _len2; _j++) {
- e = rest[_j];
- if (e.tameNodeFlag) child.tameNodeFlag = true;
- if (e.tameLoopFlag) child.tameLoopFlag = true;
- if (e.tameCpsPivotFlag) child.tameCpsPivotFlag = true;
- if (e.tameHasAutocbFlag) child.tameHasAutocbFlag = true;
- }
- child.tameCpsRotate();
+ _ref2 = this.expressions;
+ for (i = 0, _len = _ref2.length; i < _len; i++) {
+ e = _ref2[i];
+ if (e.tameIsCpsPivot()) {
+ pivot = e;
+ pivot.tameCallContinuation();
+ }
+ e.tameCpsRotate();
+ if (pivot) break;
+ }
+ if (!pivot) return this;
+ if (pivot.tameContinuationBlock) {
+ throw SyntaxError("unexpected continuation block in node");
+ }
+ rest = this.expressions.slice(i + 1);
+ this.expressions = this.expressions.slice(0, i + 1);
+ if (rest.length) {
+ child = new Block(rest);
+ pivot.tameNestContinuationBlock(child);
+ for (_i = 0, _len2 = rest.length; _i < _len2; _i++) {
+ e = rest[_i];
+ if (e.tameNodeFlag) child.tameNodeFlag = true;
+ if (e.tameLoopFlag) child.tameLoopFlag = true;
+ if (e.tameCpsPivotFlag) child.tameCpsPivotFlag = true;
+ if (e.tameHasAutocbFlag) child.tameHasAutocbFlag = true;
}
- pivot.tameCallContinuation();
+ child.tameCpsRotate();
}
- Block.__super__.tameCpsRotate.call(this);
return this;
};
View
106 src/nodes.coffee
@@ -280,9 +280,10 @@ exports.Base = class Base
# A CPS Rotation routine for expressions
tameCpsExprRotate : (v) ->
doRotate = v.tameIsTamedExpr()
- v.tameCpsRotate() # do our children first, regardless...
if doRotate
v.tameCallContinuation()
+ v.tameCpsRotate() # do our children first, regardless...
+ if doRotate
@tameNestPrequelBlock v
@tameReturnValue = new TameReturnValue()
else
@@ -490,53 +491,64 @@ exports.Block = class Block extends Base
#
tameCpsRotate : ->
pivot = null
- child = null
-
- # If this Block has taming, then we go ahead and look for a pivot
- if @tameIsCpsPivot()
- i = 0
- for e in @expressions
- if e.tameIsCpsPivot()
- pivot = e
- break
- i++
-
+
+ # Go ahead an look for a pivot
+ for e,i in @expressions
+ if e.tameIsCpsPivot()
+ pivot = e
+ # The pivot value needs to call the currently active continuation
+ # after it's all done. For things like if..else.. this does something
+ # interesting and pushes the continuation down both branches.
+ # Note that it's convenient to do this **before** anything is
+ # rotated.
+ pivot.tameCallContinuation()
+
+ # Recursively rotate the children, in depth-first order.
+ e.tameCpsRotate()
+
+ # If we've found a pivot, then we break out of here, and then
+ # handle the rest of these children
+ break if pivot
+
+ # If there's no pivot, then the above should be as in the base
+ # class, and it's safe to return out of here.
+ #
# We find a pivot if this node has taming, and it's not an Await
- # itself
- if pivot
- rest = @expressions.slice(i+1)
-
- # Leave the pivot in the list of expressions
- @expressions = @expressions.slice(0,i+1)
-
- # If there are elements in rest, then we need to nest a continuation block
- if rest.length
- child = new Block rest
- pivot.tameNestContinuationBlock child
-
- # Pass our node bits onto our new children
- for e in rest
- child.tameNodeFlag = true if e.tameNodeFlag
- child.tameLoopFlag = true if e.tameLoopFlag
- child.tameCpsPivotFlag = true if e.tameCpsPivotFlag
- child.tameHasAutocbFlag = true if e.tameHasAutocbFlag
-
- # now recursive apply the transformation to the new child,
- # this being especially import in blocks that have multiple
- # awaits on the same level
- child.tameCpsRotate()
-
- # The pivot value needs to call the currently active continuation
- # after it's all done. For things like if..else.. this does something
- # interesting and pushes the continuation down both branches.
- pivot.tameCallContinuation()
-
- # After we have pivoted this guy, we still need to walk all of the
- # expressions, because maybe the expressions that we left still have
- # embedded functions that need the rotation run on them. Thus,
- # tameNodeFlag will be 0, but children might have blocks that still
- # need to be tamed
- super()
+ # itself.
+ return this unless pivot
+
+ # We should never have a continuation here, even though we rotated
+ # this guy above. This is true for one of two cases:
+ # 1. If pivot is a statement, then the continuation will be in the
+ # grandchild Block node
+ # 2. If pivot is an expression, the pivoted code will be a prequel
+ # and not a continuation (since we can't replace nodes as we
+ # walk).
+ if pivot.tameContinuationBlock
+ throw SyntaxError "unexpected continuation block in node"
+
+ # These are the expressions on the RHS of the pivot split
+ rest = @expressions.slice(i+1)
+
+ # Leave the pivot in the list of expressions
+ @expressions = @expressions.slice(0,i+1)
+
+ # If there are elements in rest, then we need to nest a continuation block
+ if rest.length
+ child = new Block rest
+ pivot.tameNestContinuationBlock child
+
+ # Pass our node bits onto our new children
+ for e in rest
+ child.tameNodeFlag = true if e.tameNodeFlag
+ child.tameLoopFlag = true if e.tameLoopFlag
+ child.tameCpsPivotFlag = true if e.tameCpsPivotFlag
+ child.tameHasAutocbFlag = true if e.tameHasAutocbFlag
+
+ # now recursive apply the transformation to the new child,
+ # this being especially important in blocks that have multiple
+ # awaits on the same level
+ child.tameCpsRotate()
# return this for chaining
this

0 comments on commit f73eb0e

Please sign in to comment.