added 'yield return'

This commit is contained in:
Andreas Lubbe 2014-09-06 15:40:53 +02:00
parent c72556619f
commit 437b9ed65c
7 changed files with 79 additions and 40 deletions

View File

@ -552,6 +552,8 @@
return new Op('+', $2);
}), {
prec: 'UNARY_MATH'
}), o('YIELD Statement', function() {
return new Op($1, $2);
}), o('YIELD Expression', function() {
return new Op($1, $2);
}), o('YIELD FROM Expression', function() {

View File

@ -777,7 +777,7 @@
Lexer.prototype.unfinished = function() {
var _ref2;
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === 'UNARY_MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === '**' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === 'UNARY_MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'YIELD' || _ref2 === '**' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
};
Lexer.prototype.removeNewlines = function(str) {

View File

@ -1817,14 +1817,10 @@
this.params = params || [];
this.body = body || new Block;
this.bound = tag === 'boundfunc';
this.isGenerator = false;
this.body.traverseChildren(false, (function(_this) {
return function(child) {
if (child.operator === 'yield') {
return _this.isGenerator = true;
}
};
})(this));
this.isGenerator = this.body.contains(function(node) {
var _ref2;
return node instanceof Op && ((_ref2 = node.operator) === 'yield' || _ref2 === 'yield*');
});
}
Code.prototype.children = ['params', 'body'];
@ -2297,6 +2293,11 @@
Op.prototype.isSimpleNumber = NO;
Op.prototype.isYield = function() {
var _ref2;
return (_ref2 = this.operator) === 'yield' || _ref2 === 'yield*';
};
Op.prototype.isUnary = function() {
return !this.second;
};
@ -2381,6 +2382,9 @@
if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) {
this.error("cannot increment/decrement \"" + (this.first.unwrapAll().value) + "\"");
}
if (this.isYield()) {
return this.compileYield(o);
}
if (this.isUnary()) {
return this.compileUnary(o);
}
@ -2434,9 +2438,6 @@
var op, parts, plusMinus;
parts = [];
op = this.operator;
if ((op === 'yield' || op === 'yield*') && (o.scope.parent == null)) {
this.error('yield statements must occur within a function generator.');
}
parts.push([this.makeCode(op)]);
if (op === '!' && this.first instanceof Existence) {
this.first.negated = !this.first.negated;
@ -2446,7 +2447,7 @@
return (new Parens(this)).compileToFragments(o);
}
plusMinus = op === '+' || op === '-';
if ((op === 'new' || op === 'typeof' || op === 'delete' || op === 'yield' || op === 'yield*') || plusMinus && this.first instanceof Op && this.first.operator === op) {
if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) {
parts.push([this.makeCode(' ')]);
}
if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) {
@ -2459,6 +2460,25 @@
return this.joinFragmentArrays(parts, '');
};
Op.prototype.compileYield = function(o) {
var op, parts;
parts = [];
op = this.operator;
if (o.scope.parent == null) {
this.error('yield statements must occur within a function generator.');
}
if (__indexOf.call(Object.keys(this.first), 'expression') >= 0) {
if (this.first.expression != null) {
parts.push(this.first.expression.compileToFragments(o, LEVEL_OP));
}
} else {
parts.push([this.makeCode(op)]);
parts.push([this.makeCode(' ')]);
parts.push(this.first.compileToFragments(o, LEVEL_OP));
}
return this.joinFragmentArrays(parts, '');
};
Op.prototype.compilePower = function(o) {
var pow;
pow = new Value(new Literal('Math'), [new Access(new Literal('pow'))]);

File diff suppressed because one or more lines are too long

View File

@ -536,6 +536,7 @@ grammar =
o 'UNARY_MATH Expression', -> new Op $1 , $2
o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH'
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH'
o 'YIELD Statement', -> new Op $1 , $2
o 'YIELD Expression', -> new Op $1 , $2
o 'YIELD FROM Expression', -> new Op $1.concat($2) , $3

View File

@ -691,7 +691,7 @@ exports.Lexer = class Lexer
# Are we in the midst of an unfinished expression?
unfinished: ->
LINE_CONTINUER.test(@chunk) or
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-',
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', 'YIELD',
'**', 'SHIFT', 'RELATION', 'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
# Remove newlines from beginning and (non escaped) from end of string literals.

View File

@ -1314,12 +1314,11 @@ exports.Assign = class Assign extends Base
# has no *children* -- they're within the inner scope.
exports.Code = class Code extends Base
constructor: (params, body, tag) ->
@params = params or []
@body = body or new Block
@bound = tag is 'boundfunc'
@isGenerator = false
@body.traverseChildren false, (child) =>
@isGenerator = true if child.operator is 'yield'
@params = params or []
@body = body or new Block
@bound = tag is 'boundfunc'
@isGenerator = @body.contains (node) ->
node instanceof Op and node.operator in ['yield', 'yield*']
children: ['params', 'body']
@ -1629,6 +1628,9 @@ exports.Op = class Op extends Base
isSimpleNumber: NO
isYield: ->
@operator in ['yield', 'yield*']
isUnary: ->
not @second
@ -1695,6 +1697,7 @@ exports.Op = class Op extends Base
@error 'delete operand may not be argument or var'
if @operator in ['--', '++'] and @first.unwrapAll().value in STRICT_PROSCRIBED
@error "cannot increment/decrement \"#{@first.unwrapAll().value}\""
return @compileYield o if @isYield()
return @compileUnary o if @isUnary()
return @compileChain o if isChain
switch @operator
@ -1734,8 +1737,6 @@ exports.Op = class Op extends Base
compileUnary: (o) ->
parts = []
op = @operator
if op in ['yield', 'yield*'] and not o.scope.parent?
@error 'yield statements must occur within a function generator.'
parts.push [@makeCode op]
if op is '!' and @first instanceof Existence
@first.negated = not @first.negated
@ -1743,7 +1744,7 @@ exports.Op = class Op extends Base
if o.level >= LEVEL_ACCESS
return (new Parens this).compileToFragments o
plusMinus = op in ['+', '-']
parts.push [@makeCode(' ')] if op in ['new', 'typeof', 'delete', 'yield', 'yield*'] or
parts.push [@makeCode(' ')] if op in ['new', 'typeof', 'delete'] or
plusMinus and @first instanceof Op and @first.operator is op
if (plusMinus and @first instanceof Op) or (op is 'new' and @first.isStatement o)
@first = new Parens @first
@ -1751,6 +1752,19 @@ exports.Op = class Op extends Base
parts.reverse() if @flip
@joinFragmentArrays parts, ''
compileYield: (o) ->
parts = []
op = @operator
if not o.scope.parent?
@error 'yield statements must occur within a function generator.'
if 'expression' in Object.keys @first
parts.push @first.expression.compileToFragments o, LEVEL_OP if @first.expression?
else
parts.push [@makeCode op]
parts.push [@makeCode(' ')]
parts.push @first.compileToFragments o, LEVEL_OP
@joinFragmentArrays parts, ''
compilePower: (o) ->
# Make a Math.pow call
pow = new Value new Literal('Math'), [new Access new Literal 'pow']