Permalink
Browse files

lots of progress on the jump situation, i think this is getting close…

… to solving it
  • Loading branch information...
1 parent d80638c commit 628bebd755b0f642ffa8466162377d2b7769ce20 @maxtaco committed with Nov 24, 2011
Showing with 90 additions and 52 deletions.
  1. +46 −23 lib/coffee-script/nodes.js
  2. +0 −1 lib/coffee-script/parser.js
  3. +44 −28 src/nodes.coffee
View
69 lib/coffee-script/nodes.js
@@ -136,7 +136,8 @@
if (name == null) name = this.constructor.name;
extras = "";
if (this.tameNodeFlag) extras += "T";
- if (this.cpsNodeFlag) extras += "C";
+ if (this.tameLoopFlag) extras += "L";
+ if (this.cpsPivotFlag) extras += "P";
if (extras.length) extras = " (" + extras + ")";
tree = '\n' + idt + name;
if (this.soak) tree += '?';
@@ -216,17 +217,29 @@
return this.tameNodeFlag;
};
- Base.prototype.walkAstCps = function(flood) {
+ Base.prototype.walkAstTamedLoop = function(flood) {
var child, _i, _len, _ref2;
if (this.isLoop() && this.tameNodeFlag) flood = true;
- if (this.isAwait()) flood = false;
- this.cpsNodeFlag = flood;
+ this.tameLoopFlag = flood;
_ref2 = this.flattenChildren();
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
child = _ref2[_i];
- if (child.walkAstCps(flood)) this.cpsNodeFlag = true;
+ if (child.walkAstTamedLoop(flood)) this.tameLoopFlag = true;
}
- return this.cpsNodeFlag;
+ return this.tameLoopFlag;
+ };
+
+ Base.prototype.walkCpsPivots = function() {
+ var child, _i, _len, _ref2;
+ if (this.tameNodeFlag || (this.tameLoopFlag && this.isJump())) {
+ this.cpsPivotFlag = true;
+ }
+ _ref2 = this.flattenChildren();
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ child = _ref2[_i];
+ if (child.walkCpsPivots()) this.cpsPivotFlag = true;
+ }
+ return this.cpsPivotFlag;
};
Base.prototype.children = [];
@@ -243,12 +256,8 @@
return this;
};
- Base.prototype.needsCpsRotation = function() {
- return this.tameNodeFlag || this.cpsNodeFlag;
- };
-
Base.prototype.isCpsPivot = function() {
- return this.tameNodeFlag || this.cpsNodeFlag;
+ return this.cpsPivotFlag;
};
Base.prototype.tameNestContinuationBlock = function(b) {
@@ -281,12 +290,14 @@
Base.prototype.isJump = NO;
- Base.prototype.cpsNodeFlag = false;
+ Base.prototype.tameLoopFlag = false;
Base.prototype.tameNodeFlag = false;
Base.prototype.gotCpsSplit = false;
+ Base.prototype.cpsPivotFlag = false;
+
Base.prototype.unwrap = THIS;
Base.prototype.unfoldSoak = NO;
@@ -469,7 +480,7 @@
var child, e, i, pivot, rest, _i, _j, _len, _len2, _ref2;
pivot = null;
child = null;
- if (this.needsCpsRotation()) {
+ if (this.isCpsPivot()) {
i = 0;
_ref2 = this.expressions;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
@@ -481,9 +492,7 @@
i++;
}
}
- console.log("CPS Rotate " + this.expressions.length + " " + pivot + " " + i);
if (pivot) {
- console.log(" --> doing the pivot");
rest = this.expressions.slice(i + 1);
this.expressions = this.expressions.slice(0, i + 1);
if (rest.length) {
@@ -492,7 +501,8 @@
for (_j = 0, _len2 = rest.length; _j < _len2; _j++) {
e = rest[_j];
if (e.tameNodeFlag) child.tameNodeFlag = true;
- if (e.cpsNodeFlag) child.cpsNodeFlag = true;
+ if (e.tameLoopFlag) child.tameLoopFlag = true;
+ if (e.cpsPivotFlag) child.cpsPivotFlag = true;
}
child.cpsRotate();
}
@@ -513,7 +523,8 @@
Block.prototype.tameTransform = function() {
this.walkAstTame();
- this.walkAstCps(false);
+ this.walkAstTamedLoop(false);
+ this.walkCpsPivots();
return this.cpsRotate();
};
@@ -557,8 +568,13 @@
};
Literal.prototype.compileTame = function(o) {
- var call, func;
- func = new Value(new Literal(tame["const"].c_while));
+ var call, d, func, l;
+ d = {
+ 'continue': tame["const"].c_while,
+ 'break': tame["const"].b_while
+ };
+ l = d[this.value];
+ func = new Value(new Literal(l));
call = new Call(func, []);
return call.compile(o);
};
@@ -574,7 +590,7 @@
Literal.prototype.compileNode = function(o) {
var code, _ref2, _ref3;
- code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved && ((_ref3 = "" + this.value) !== 'eval' && _ref3 !== 'arguments') ? "\"" + this.value + "\"" : this.cpsNodeFlag && this.isJump() ? this.compileTame(o) : this.value;
+ code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved && ((_ref3 = "" + this.value) !== 'eval' && _ref3 !== 'arguments') ? "\"" + this.value + "\"" : this.tameLoopFlag && this.isJump() ? this.compileTame(o) : this.value;
if (this.isStatement()) {
return "" + this.tab + code + ";";
} else {
@@ -1713,8 +1729,15 @@
return false;
};
- Code.prototype.walkAstCps = function(flood) {
- if (Code.__super__.walkAstCps.call(this, false)) this.cpsNodeFlag = true;
+ Code.prototype.walkAstTamedLoop = function(flood) {
+ if (Code.__super__.walkAstTamedLoop.call(this, false)) {
+ this.tameLoopFlag = true;
+ }
+ return false;
+ };
+
+ Code.prototype.walkAstPivots = function() {
+ if (Code.__super__.walkAstPivots.call(this)) this.cpsPivotFlag = true;
return false;
};
@@ -2603,7 +2626,7 @@
};
If.prototype.compileNode = function(o) {
- if (this.isStatement(o || this.needsCpsRotation())) {
+ if (this.isStatement(o || this.isCpsPivot())) {
return this.compileStatement(o);
} else {
return this.compileExpression(o);
View
1 lib/coffee-script/parser.js
@@ -1,6 +1,5 @@
/* Jison generated parser */
var parser = (function(){
-undefined
var parser = {trace: function trace() { },
yy: {},
<<<<<<< HEAD
View
72 src/nodes.coffee
@@ -125,8 +125,10 @@ exports.Base = class Base
extras = ""
if @tameNodeFlag
extras += "T"
- if @cpsNodeFlag
- extras += "C"
+ if @tameLoopFlag
+ extras += "L"
+ if @cpsPivotFlag
+ extras += "P"
if extras.length
extras = " (" + extras + ")"
tree = '\n' + idt + name
@@ -178,13 +180,23 @@ exports.Base = class Base
@tameNodeFlag = true if child.walkAstTame()
@tameNodeFlag
- walkAstCps : (flood) ->
- flood = true if @isLoop() and @tameNodeFlag
- flood = false if @isAwait()
- @cpsNodeFlag = flood
+ # Walk all loops that are marked as "tamed" and mark their children
+ # as being children in a tamed loop. They'll need more translations
+ # than other nodes. Eventually, "switch" statements might also be "loops
+ walkAstTamedLoop : (flood) ->
+ flood = true if @isLoop() and @tameNodeFlag
+ @tameLoopFlag = flood
for child in @flattenChildren()
- @cpsNodeFlag = true if child.walkAstCps(flood)
- @cpsNodeFlag
+ @tameLoopFlag = true if child.walkAstTamedLoop (flood)
+ @tameLoopFlag
+
+ # A node is marked as a "cpsPivot" of it is (a) a 'tamed' node,
+ # (b) a jump node in a tamed while loop; or (c) an ancestor of (a) or (b).
+ walkCpsPivots : ->
+ @cpsPivotFlag = true if @tameNodeFlag or (@tameLoopFlag and @isJump())
+ for child in @flattenChildren()
+ @cpsPivotFlag = true if child.walkCpsPivots()
+ @cpsPivotFlag
# Default implementations of the common node properties and methods. Nodes
# will override these with custom logic, if needed.
@@ -199,11 +211,7 @@ exports.Base = class Base
child.cpsRotate()
this
- needsCpsRotation : ->
- return @tameNodeFlag or @cpsNodeFlag
-
- isCpsPivot : ->
- return @tameNodeFlag or @cpsNodeFlag
+ isCpsPivot : -> @cpsPivotFlag
tameNestContinuationBlock : (b) ->
@tameContinuationBlock = b
@@ -223,9 +231,10 @@ exports.Base = class Base
isAwait : NO
isJump : NO
- cpsNodeFlag : false
+ tameLoopFlag : false
tameNodeFlag : false
gotCpsSplit : false
+ cpsPivotFlag : false
unwrap : THIS
unfoldSoak : NO
@@ -390,32 +399,30 @@ exports.Block = class Block extends Base
child = null
# If this Block has taming, then we go ahead and look for a pivot
- if @needsCpsRotation()
+ if @isCpsPivot()
i = 0
for e in @expressions
if e.isCpsPivot()
pivot = e
break
i++
- console.log "CPS Rotate #{@expressions.length} #{pivot} #{i}"
-
# We find a pivot if this node has taming, and it's not an Await
# itself
if pivot
- console.log " --> doing the pivot"
# include the pivot in this slice!
rest = @expressions.slice(i+1)
@expressions = @expressions.slice(0,i+1)
if rest.length
child = new Block rest
pivot.tameNestContinuationBlock child
-
+
# we have to set the taming bit on the new Block
for e in rest
child.tameNodeFlag = true if e.tameNodeFlag
- child.cpsNodeFlag = true if e.cpsNodeFlag
-
+ child.tameLoopFlag = true if e.tameLoopFlag
+ child.cpsPivotFlag = true if e.cpsPivotFlag
+
# now recursive apply the transformation to the new child,
# this being especially import in blocks that have multiple
# awaits on the same level
@@ -444,7 +451,8 @@ exports.Block = class Block extends Base
# Perform all steps of the Tame transform
tameTransform : ->
@walkAstTame()
- @walkAstCps(false)
+ @walkAstTamedLoop(false)
+ @walkCpsPivots()
@cpsRotate()
#### Literal
@@ -471,7 +479,11 @@ exports.Literal = class Literal extends Base
name is @value
compileTame: (o) ->
- func = new Value new Literal tame.const.c_while
+ d =
+ 'continue' : tame.const.c_while
+ 'break' : tame.const.b_while
+ l = d[@value]
+ func = new Value new Literal l
call = new Call func, []
return call.compile o
@@ -486,7 +498,7 @@ exports.Literal = class Literal extends Base
if o.scope.method?.bound then o.scope.method.context else @value
else if @value.reserved
"\"#{@value}\""
- else if @cpsNodeFlag and @isJump()
+ else if @tameLoopFlag and @isJump()
@compileTame o
else
@value
@@ -515,7 +527,7 @@ exports.Return = class Return extends Base
compileNode: (o) ->
@tab + "return#{[" #{@expression.compile o, LEVEL_PAREN}" if @expression]};"
-
+
#### Value
# A value, variable or literal or parenthesized, indexed or dotted into,
@@ -1387,8 +1399,12 @@ exports.Code = class Code extends Base
@tameNodeFlag = true if super()
false
- walkAstCps : (flood) ->
- @cpsNodeFlag = true if super(false)
+ walkAstTamedLoop : (flood) ->
+ @tameLoopFlag = true if super(false)
+ false
+
+ walkAstPivots: () ->
+ @cpsPivotFlag = true if super()
false
#### Param
@@ -2089,7 +2105,7 @@ exports.If = class If extends Base
jumps: (o) -> @body.jumps(o) or @elseBody?.jumps(o)
compileNode: (o) ->
- if @isStatement o or @needsCpsRotation() then @compileStatement o else @compileExpression o
+ if @isStatement o or @isCpsPivot() then @compileStatement o else @compileExpression o
makeReturn: (res) ->
@elseBody or= new Block [new Literal 'void 0'] if res

0 comments on commit 628bebd

Please sign in to comment.