fixed yield return producing incorrect output when used outside of the last line

This commit is contained in:
Andreas Lubbe 2015-02-15 18:57:15 +01:00
parent fea058c53a
commit feee6954a6
3 changed files with 35 additions and 7 deletions

View File

@ -652,13 +652,18 @@
};
Return.prototype.compileNode = function(o) {
var answer;
var answer, exprIsYieldReturn, ref3;
answer = [];
answer.push(this.makeCode(this.tab + ("return" + (this.expression ? " " : ""))));
exprIsYieldReturn = (ref3 = this.expression) != null ? typeof ref3.isYieldReturn === "function" ? ref3.isYieldReturn() : void 0 : void 0;
if (!exprIsYieldReturn) {
answer.push(this.makeCode(this.tab + ("return" + (this.expression ? " " : ""))));
}
if (this.expression) {
answer = answer.concat(this.expression.compileToFragments(o, LEVEL_PAREN));
}
answer.push(this.makeCode(";"));
if (!exprIsYieldReturn) {
answer.push(this.makeCode(";"));
}
return answer;
};
@ -2361,6 +2366,10 @@
return (ref3 = this.operator) === 'yield' || ref3 === 'yield*';
};
Op.prototype.isYieldReturn = function() {
return this.isYield() && this.first instanceof Return;
};
Op.prototype.isUnary = function() {
return !this.second;
};
@ -2531,7 +2540,9 @@
this.error('yield statements must occur within a function generator.');
}
if (indexOf.call(Object.keys(this.first), 'expression') >= 0 && !(this.first instanceof Throw)) {
if (this.first.expression != null) {
if (this.isYieldReturn()) {
parts.push(this.first.compileToFragments(o, LEVEL_TOP));
} else if (this.first.expression != null) {
parts.push(this.first.expression.compileToFragments(o, LEVEL_OP));
}
} else {

View File

@ -453,11 +453,13 @@ exports.Return = class Return extends Base
compileNode: (o) ->
answer = []
exprIsYieldReturn = @expression?.isYieldReturn?()
# TODO: If we call expression.compile() here twice, we'll sometimes get back different results!
answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
unless exprIsYieldReturn
answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
if @expression
answer = answer.concat @expression.compileToFragments o, LEVEL_PAREN
answer.push @makeCode ";"
answer.push @makeCode ";" unless exprIsYieldReturn
return answer
#### Value
@ -1674,6 +1676,9 @@ exports.Op = class Op extends Base
isYield: ->
@operator in ['yield', 'yield*']
isYieldReturn: ->
@isYield() and @first instanceof Return
isUnary: ->
not @second
@ -1802,7 +1807,10 @@ exports.Op = class Op extends Base
if not o.scope.parent?
@error 'yield statements must occur within a function generator.'
if 'expression' in Object.keys(@first) and not (@first instanceof Throw)
parts.push @first.expression.compileToFragments o, LEVEL_OP if @first.expression?
if @isYieldReturn()
parts.push @first.compileToFragments o, LEVEL_TOP
else if @first.expression?
parts.push @first.expression.compileToFragments o, LEVEL_OP
else
parts.push [@makeCode "(#{op} "]
parts.push @first.compileToFragments o, LEVEL_OP

View File

@ -38,6 +38,15 @@ test "last line yields are returned", ->
y = x.next 42
ok y.value is 42 and y.done is true
test "yield return can be used anywhere in the function body", ->
x = do ->
if true
yield return true
return false
y = x.next()
ok y.value is true and y.done is true
test "bound generator", ->
obj =
bound: ->