starting to move over isPureStatement to Coco style jumps()

This commit is contained in:
Jeremy Ashkenas
2010-12-22 12:00:46 -05:00
parent d01b7ac682
commit df8dafc5ca
2 changed files with 91 additions and 2 deletions

View File

@@ -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);

View File

@@ -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