mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
starting to move over isPureStatement to Coco style jumps()
This commit is contained in:
62
lib/nodes.js
62
lib/nodes.js
@@ -41,7 +41,7 @@
|
||||
}
|
||||
};
|
||||
Base.prototype.compileClosure = function(o) {
|
||||
if (this.containsPureStatement()) {
|
||||
if (this.jumps()) {
|
||||
throw SyntaxError('cannot use a pure statement in an expression.');
|
||||
}
|
||||
o.sharedScope = true;
|
||||
@@ -163,6 +163,7 @@
|
||||
Base.prototype.children = [];
|
||||
Base.prototype.isStatement = NO;
|
||||
Base.prototype.isPureStatement = NO;
|
||||
Base.prototype.jumps = NO;
|
||||
Base.prototype.isComplex = YES;
|
||||
Base.prototype.isChainable = NO;
|
||||
Base.prototype.isAssignable = NO;
|
||||
@@ -209,6 +210,16 @@
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Expressions.prototype.jumps = function(o) {
|
||||
var exp, _i, _len, _ref;
|
||||
_ref = this.expressions;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
exp = _ref[_i];
|
||||
if (exp.jumps(o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
Expressions.prototype.makeReturn = function() {
|
||||
var expr, len;
|
||||
len = this.expressions.length;
|
||||
@@ -332,6 +343,9 @@
|
||||
Literal.prototype.assigns = function(name) {
|
||||
return name === this.value;
|
||||
};
|
||||
Literal.prototype.jumps = function(o) {
|
||||
return this.isPureStatement() && !(o && (o.loop || o.block && (this.value !== 'continue')));
|
||||
};
|
||||
Literal.prototype.compile = function() {
|
||||
if (this.value.reserved) {
|
||||
return "\"" + this.value + "\"";
|
||||
@@ -353,6 +367,7 @@
|
||||
Return.prototype.isStatement = YES;
|
||||
Return.prototype.isPureStatement = YES;
|
||||
Return.prototype.makeReturn = THIS;
|
||||
Return.prototype.jumps = YES;
|
||||
Return.prototype.compile = function(o, level) {
|
||||
var expr, _ref;
|
||||
expr = (_ref = this.expression) != null ? _ref.makeReturn() : void 0;
|
||||
@@ -418,6 +433,9 @@
|
||||
Value.prototype.assigns = function(name) {
|
||||
return !this.properties.length && this.base.assigns(name);
|
||||
};
|
||||
Value.prototype.jumps = function(o) {
|
||||
return !this.properties.length && this.base.jumps(o);
|
||||
};
|
||||
Value.prototype.isObject = function(onlyGenerated) {
|
||||
if (this.properties.length) {
|
||||
return false;
|
||||
@@ -1217,6 +1235,7 @@
|
||||
Code.prototype.isStatement = function() {
|
||||
return !!this.ctor;
|
||||
};
|
||||
Code.prototype.jumps = NO;
|
||||
Code.prototype.compileNode = function(o) {
|
||||
var code, exprs, i, idt, lit, p, param, ref, splats, v, val, vars, wasEmpty, _i, _j, _len, _len2, _len3, _ref, _ref2, _ref3;
|
||||
o.scope = new Scope(o.scope, this.body, this);
|
||||
@@ -1419,6 +1438,22 @@
|
||||
this.body = body;
|
||||
return this;
|
||||
};
|
||||
While.prototype.jumps = function() {
|
||||
var expressions, node, _i, _len;
|
||||
expressions = this.body.expressions;
|
||||
if (!expressions.length) {
|
||||
return false;
|
||||
}
|
||||
for (_i = 0, _len = expressions.length; _i < _len; _i++) {
|
||||
node = expressions[_i];
|
||||
if (node.jumps({
|
||||
loop: true
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
While.prototype.containsPureStatement = function() {
|
||||
var expressions, i, ret, _ref;
|
||||
expressions = this.body.expressions;
|
||||
@@ -1660,6 +1695,10 @@
|
||||
}
|
||||
Try.prototype.children = ['attempt', 'recovery', 'ensure'];
|
||||
Try.prototype.isStatement = YES;
|
||||
Try.prototype.jumps = function(o) {
|
||||
var _ref;
|
||||
return this.attempt.jumps(o) || ((_ref = this.recovery) != null ? _ref.jumps(o) : void 0);
|
||||
};
|
||||
Try.prototype.makeReturn = function() {
|
||||
if (this.attempt) {
|
||||
this.attempt = this.attempt.makeReturn();
|
||||
@@ -1685,6 +1724,7 @@
|
||||
}
|
||||
Throw.prototype.children = ['expression'];
|
||||
Throw.prototype.isStatement = YES;
|
||||
Throw.prototype.jumps = NO;
|
||||
Throw.prototype.makeReturn = THIS;
|
||||
Throw.prototype.compileNode = function(o) {
|
||||
return this.tab + ("throw " + (this.expression.compile(o)) + ";");
|
||||
@@ -1903,6 +1943,22 @@
|
||||
}
|
||||
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
|
||||
Switch.prototype.isStatement = YES;
|
||||
Switch.prototype.jumps = function(o) {
|
||||
var block, conds, _i, _len, _ref, _ref2, _ref3;
|
||||
if (o == null) {
|
||||
o = {
|
||||
block: true
|
||||
};
|
||||
}
|
||||
_ref = this.cases;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
_ref2 = _ref[_i], conds = _ref2[0], block = _ref2[1];
|
||||
if (block.jumps(o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (_ref3 = this.otherwise) != null ? _ref3.jumps(o) : void 0;
|
||||
};
|
||||
Switch.prototype.makeReturn = function() {
|
||||
var pair, _i, _len, _ref, _ref2;
|
||||
_ref = this.cases;
|
||||
@@ -1983,6 +2039,10 @@
|
||||
var _ref;
|
||||
return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref = this.elseBodyNode()) != null ? _ref.isStatement(o) : void 0);
|
||||
};
|
||||
If.prototype.jumps = function(o) {
|
||||
var _ref;
|
||||
return this.body.jumps(o) || ((_ref = this.elseBody) != null ? _ref.jumps(o) : void 0);
|
||||
};
|
||||
If.prototype.compileNode = function(o) {
|
||||
if (this.isStatement(o)) {
|
||||
return this.compileStatement(o);
|
||||
|
||||
@@ -48,7 +48,7 @@ exports.Base = class Base
|
||||
# Statements converted into expressions via closure-wrapping share a scope
|
||||
# object with their parent closure, to preserve the expected lexical scope.
|
||||
compileClosure: (o) ->
|
||||
if @containsPureStatement()
|
||||
if @jumps()
|
||||
throw SyntaxError 'cannot use a pure statement in an expression.'
|
||||
o.sharedScope = yes
|
||||
Closure.wrap(this).compileNode o
|
||||
@@ -141,6 +141,7 @@ exports.Base = class Base
|
||||
|
||||
isStatement : NO
|
||||
isPureStatement : NO
|
||||
jumps : NO
|
||||
isComplex : YES
|
||||
isChainable : NO
|
||||
isAssignable : NO
|
||||
@@ -190,6 +191,10 @@ exports.Expressions = class Expressions extends Base
|
||||
return yes
|
||||
no
|
||||
|
||||
jumps: (o) ->
|
||||
for exp in @expressions
|
||||
return true if exp.jumps o
|
||||
|
||||
# An Expressions node does not return its entire body, rather it
|
||||
# ensures that the final expression is returned.
|
||||
makeReturn: ->
|
||||
@@ -288,6 +293,9 @@ exports.Literal = class Literal extends Base
|
||||
assigns: (name) ->
|
||||
name is @value
|
||||
|
||||
jumps: (o) ->
|
||||
@isPureStatement() and not (o and (o.loop or o.block and (@value isnt 'continue')))
|
||||
|
||||
compile: ->
|
||||
if @value.reserved then "\"#{@value}\"" else @value
|
||||
|
||||
@@ -306,6 +314,7 @@ exports.Return = class Return extends Base
|
||||
isStatement: YES
|
||||
isPureStatement: YES
|
||||
makeReturn: THIS
|
||||
jumps: YES
|
||||
|
||||
compile: (o, level) ->
|
||||
expr = @expression?.makeReturn()
|
||||
@@ -349,6 +358,7 @@ exports.Value = class Value extends Base
|
||||
|
||||
isStatement : (o) -> not @properties.length and @base.isStatement o
|
||||
assigns : (name) -> not @properties.length and @base.assigns name
|
||||
jumps : (o) -> not @properties.length and @base.jumps o
|
||||
|
||||
isObject: (onlyGenerated) ->
|
||||
return no if @properties.length
|
||||
@@ -997,6 +1007,8 @@ exports.Code = class Code extends Base
|
||||
|
||||
isStatement: -> !!@ctor
|
||||
|
||||
jumps: NO
|
||||
|
||||
# Compilation creates a new scope unless explicitly asked to share with the
|
||||
# outer scope. Handles splat parameters in the parameter list by peeking at
|
||||
# the JavaScript `arguments` objects. If the function is bound with the `=>`
|
||||
@@ -1134,6 +1146,13 @@ exports.While = class While extends Base
|
||||
addBody: (@body) ->
|
||||
this
|
||||
|
||||
jumps: ->
|
||||
{expressions} = @body
|
||||
return no unless expressions.length
|
||||
for node in expressions
|
||||
return yes if node.jumps loop: yes
|
||||
no
|
||||
|
||||
containsPureStatement: ->
|
||||
{expressions} = @body
|
||||
i = expressions.length
|
||||
@@ -1317,6 +1336,8 @@ exports.Try = class Try extends Base
|
||||
|
||||
isStatement: YES
|
||||
|
||||
jumps: (o) -> @attempt.jumps(o) or @recovery?.jumps(o)
|
||||
|
||||
makeReturn: ->
|
||||
@attempt = @attempt .makeReturn() if @attempt
|
||||
@recovery = @recovery.makeReturn() if @recovery
|
||||
@@ -1346,6 +1367,7 @@ exports.Throw = class Throw extends Base
|
||||
children: ['expression']
|
||||
|
||||
isStatement: YES
|
||||
jumps: NO
|
||||
|
||||
# A **Throw** is already a return, of sorts...
|
||||
makeReturn: THIS
|
||||
@@ -1527,6 +1549,11 @@ exports.Switch = class Switch extends Base
|
||||
|
||||
isStatement: YES
|
||||
|
||||
jumps: (o = {block: yes}) ->
|
||||
for [conds, block] in @cases
|
||||
return yes if block.jumps o
|
||||
@otherwise?.jumps o
|
||||
|
||||
makeReturn: ->
|
||||
pair[1].makeReturn() for pair in @cases
|
||||
@otherwise?.makeReturn()
|
||||
@@ -1582,6 +1609,8 @@ exports.If = class If extends Base
|
||||
o?.level is LEVEL_TOP or
|
||||
@bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o)
|
||||
|
||||
jumps: (o) -> @body.jumps(o) or @elseBody?.jumps(o)
|
||||
|
||||
compileNode: (o) ->
|
||||
if @isStatement o then @compileStatement o else @compileExpression o
|
||||
|
||||
|
||||
Reference in New Issue
Block a user