Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix a bug in which autocb's were being dropped in loops that return

  • Loading branch information...
commit d4fe65b51e2e23cc266ebde1aa21f4a5428aed33 1 parent 0795b7d
@maxtaco authored
Showing with 42 additions and 11 deletions.
  1. +12 −3 lib/coffee-script/nodes.js
  2. +30 −8 src/nodes.coffee
View
15 lib/coffee-script/nodes.js
@@ -2000,14 +2000,16 @@
};
While.prototype.tameWrap = function(d) {
- var body, break_assign, break_id, cond, condition, continue_assign, continue_block, continue_body, continue_id, k, k_id, outStatements, top_assign, top_block, top_body, top_call, top_func, top_id, top_statements;
+ var acb_id, body, break_assign, break_id, break_rhs, cond, condition, continue_assign, continue_block, continue_body, continue_id, k, k_id, outStatements, top_assign, top_block, top_body, top_call, top_func, top_id, top_statements;
condition = d.condition;
body = d.body;
outStatements = [];
top_id = new Value(new Literal(tame["const"].t_while));
k_id = new Value(new Literal(tame["const"].k));
+ acb_id = new Value(new Literal(tame["const"].autocb));
break_id = new Value(new Literal(tame["const"].b_while));
- break_assign = new Assign(break_id, k_id);
+ break_rhs = this.returns && this.tameHasAutocbFlag ? acb_id : k_id;
+ break_assign = new Assign(break_id, break_rhs);
continue_id = new Value(new Literal(tame["const"].c_while));
continue_block = new Block([new Call(top_id, [k_id])]);
if (d.step) continue_block.unshift(d.step);
@@ -2065,7 +2067,14 @@
body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab;
}
code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}");
- if (this.returns) code += "\n" + this.tab + "return " + rvar + ";";
+ if (this.returns) {
+ if (this.tameHasAutocbFlag) {
+ code += "\n" + this.tab + tame["const"].autocb + "(" + rvar + ");";
+ code += "\n" + this.tab + "return;";
+ } else {
+ code += "\n" + this.tab + "return " + rvar + ";";
+ }
+ }
return code;
};
View
38 src/nodes.coffee
@@ -330,8 +330,8 @@ exports.Block = class Block extends Base
expr = @expressions[len]
if expr not instanceof Comment
@expressions[len] = expr.makeReturn res
- @expressions.splice(len, 1) if expr instanceof Return and not expr.expression and
- not expr.tameHasAutocbFlag
+ @expressions.splice(len, 1) if expr instanceof Return and
+ not expr.expression and not expr.tameHasAutocbFlag
break
this
@@ -468,10 +468,10 @@ exports.Block = class Block extends Base
# 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
+ 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
@@ -1655,17 +1655,35 @@ exports.While = class While extends Base
condition = d.condition
body = d.body
outStatements = []
+
+ # Set up all of the IDs
top_id = new Value new Literal tame.const.t_while
k_id = new Value new Literal tame.const.k
+ acb_id = new Value new Literal tame.const.autocb
break_id = new Value new Literal tame.const.b_while
- break_assign = new Assign break_id, k_id
+
+ # If this loop is the last loop in the given function, then
+ # returns will be set, and we're responsible for calling out
+ # into an autocb (if one exists)
+ break_rhs = if @returns and @tameHasAutocbFlag then acb_id else k_id
+ break_assign = new Assign break_id, break_rhs
+
+ # The continue assignment is the increment at the end
+ # of the loop (if it's there), and also the recursive
+ # call back to the top.
continue_id = new Value new Literal tame.const.c_while
continue_block = new Block [ new Call top_id, [ k_id ] ]
continue_block.unshift d.step if d.step
continue_body = new Code [], continue_block, 'tamegen'
continue_assign = new Assign continue_id, continue_body
+
+ # The whole body is wrapped in an if, with the positive
+ # condition being the loop, and the negative condition
+ # being the break out of the loop
cond = new If condition, body
cond.addElse new Block [ new Call break_id, [] ]
+
+ # The top of the loop construct.
top_body = new Block [ break_assign, continue_assign, cond ]
top_func = new Code [ k_id ], top_body, 'tamegen'
top_assign = new Assign top_id, top_func
@@ -1708,7 +1726,11 @@ exports.While = class While extends Base
body = "\n#{ body.compile o, LEVEL_TOP }\n#{@tab}"
code = set + @tab + "while (#{ @condition.compile o, LEVEL_PAREN }) {#{body}}"
if @returns
- code += "\n#{@tab}return #{rvar};"
+ if @tameHasAutocbFlag
+ code += "\n#{@tab}#{tame.const.autocb}(#{rvar});"
+ code += "\n#{@tab}return;"
+ else
+ code += "\n#{@tab}return #{rvar};"
code
#### Op
Please sign in to comment.
Something went wrong with that request. Please try again.