Permalink
Browse files

A few more test cases. fix a bug with TameTailCalls. Clean up that

code a bit.
  • Loading branch information...
1 parent 32b2ced commit 82b79cf0fb50a72ded40bd210f456ff2b132cb1e @maxtaco committed Jan 5, 2012
Showing with 41 additions and 9 deletions.
  1. +13 −2 lib/coffee-script/nodes.js
  2. +12 −7 src/nodes.coffee
  3. +16 −0 test/tame.coffee
View
15 lib/coffee-script/nodes.js
@@ -488,7 +488,7 @@
foundReturn = false;
while (len--) {
expr = this.expressions[len];
- if (expr.isStatement() || expr.tameIsCpsPivot()) break;
+ if (expr.isStatement()) break;
if (!(expr instanceof Comment) && !(expr instanceof Return)) {
call.assignValue(expr);
this.expressions[len] = call;
@@ -3513,7 +3513,7 @@
args.push(returnValue);
}
block = Block.wrap([rest]);
- if ((e = block.getSingle()) && e instanceof TameTailCall && !e.value) {
+ if ((e = block.getSingle()) && e instanceof TameTailCall && e.canInline()) {
cont = e.extractFunc();
} else {
cont = new Code(args, block, 'tamegen');
@@ -3543,6 +3543,10 @@
return this.value = v;
};
+ TameTailCall.prototype.canInline = function() {
+ return !this.value || this.value instanceof TameReturnValue;
+ };
+
TameTailCall.prototype.literalFunc = function() {
return new Literal(this.func);
};
@@ -3551,6 +3555,13 @@
return new Value(this.literalFunc());
};
+ TameTailCall.prototype.tameCpsRotate = function() {
+ var nv;
+ if (this.value) {
+ if ((nv = this.tameCpsExprRotate(this.value))) return this.value = nv;
+ }
+ };
+
TameTailCall.prototype.compileNode = function(o) {
var args, f, out;
f = this.literalFunc();
View
19 src/nodes.coffee
@@ -408,12 +408,12 @@ exports.Block = class Block extends Base
# If the last expression in the block is either a bonafide statement
# or if it's going to be pivoted, then don't thread the return value
# through the TameTailCall, just bolt it onto the end.
- if expr.isStatement() or expr.tameIsCpsPivot()
+ if expr.isStatement()
break
# In this case, we have a value that we're going to return out
# of the block, so apply the TameTamilCall onto the value
- if expr not instanceof Comment and expr not instanceof Return
+ if expr not instanceof Comment and expr not instanceof Return
call.assignValue expr
@expressions[len] = call
return
@@ -2853,11 +2853,9 @@ CpsCascade =
block = Block.wrap [ rest ]
- # This is both for optimization and for correctness. If the continuation
- # block is just a tail call to another continuation, then we just pass
- # that call directly. This will also thread values through the
- # call chain.
- if (e = block.getSingle()) and e instanceof TameTailCall and not e.value
+ # Optimization! If the block is just a tail call to another continuation
+ # that can be inlined, then we just call that call directly.
+ if (e = block.getSingle()) and e instanceof TameTailCall and e.canInline()
cont = e.extractFunc()
else
cont = new Code args, block, 'tamegen'
@@ -2881,9 +2879,16 @@ class TameTailCall extends Base
assignValue : (v) ->
@value = v
+ canInline : ->
+ return not @value or @value instanceof TameReturnValue
+
literalFunc: -> new Literal @func
extractFunc: -> new Value @literalFunc()
+ tameCpsRotate : ->
+ if @value
+ @value = nv if (nv = @tameCpsExprRotate @value)
+
compileNode : (o) ->
f = @literalFunc()
out = if o.level is LEVEL_TOP
View
16 test/tame.coffee
@@ -466,3 +466,19 @@ atest 'expressions + loops', (cb) ->
lunch = ((await eat food, defer _) for food in ['toast', 'wine', 'pea'])
ok = (lunch[0] is 5 and lunch[1] is 4 and lunch[2] is 3)
cb(ok, {})
+
+atest 'expressions + ops + if', (cb) ->
+ parrot = (n, cb) ->
+ await delay defer()
+ cb n
+ y = if true
+ (await parrot 10, defer _) + 1
+ cb(y == 11, {})
+
+atest 'expressions + ops + if (2)', (cb) ->
+ parrot = (n, cb) ->
+ await delay defer()
+ cb n
+ y = if true
+ (await parrot 10, defer _) + 1 + (await parrot 12, defer _)
+ cb(y == 23, {})

0 comments on commit 82b79cf

Please sign in to comment.