allowing implicit returns to be pushed down into each branch of computation, even when there's an explicit return nested more deeply. Issue #401

This commit is contained in:
Jeremy Ashkenas
2010-06-13 01:13:52 -04:00
parent 88ea66b4c9
commit 5612a59b30
3 changed files with 29 additions and 12 deletions

View File

@@ -151,23 +151,24 @@
}).call(this).join(''); }).call(this).join('');
}; };
BaseNode.prototype.eachChild = function(func) { BaseNode.prototype.eachChild = function(func) {
var _b, _c, _d, _e, _f, _g, attr, child; var _b, _c, _d, _e, _f, _g, _h, attr, child;
if (!(this.children)) { if (!(this.children)) {
return null; return null;
} }
_c = this.children; _b = []; _d = this.children;
for (_b = 0, _d = _c.length; _b < _d; _b++) { for (_c = 0, _e = _d.length; _c < _e; _c++) {
attr = _c[_b]; attr = _d[_c];
if (this[attr]) { if (this[attr]) {
_f = flatten([this[attr]]); _g = flatten([this[attr]]);
for (_e = 0, _g = _f.length; _e < _g; _e++) { for (_f = 0, _h = _g.length; _f < _h; _f++) {
child = _f[_e]; child = _g[_f];
if (func(child) === false) { if (func(child) === false) {
return null; return null;
} }
} }
} }
} }
return _b;
}; };
BaseNode.prototype.collectChildren = function() { BaseNode.prototype.collectChildren = function() {
var nodes; var nodes;
@@ -253,9 +254,8 @@
if (!last || last instanceof ReturnNode) { if (!last || last instanceof ReturnNode) {
return this; return this;
} }
if (!(last.containsPureStatement())) { this.expressions[idx] = last.makeReturn();
this.expressions[idx] = last.makeReturn(); // unless last.containsPureStatement()
}
return this; return this;
}; };
// An **Expressions** is the only node that can serve as the root. // An **Expressions** is the only node that can serve as the root.
@@ -378,6 +378,9 @@
ReturnNode.prototype.topSensitive = function() { ReturnNode.prototype.topSensitive = function() {
return true; return true;
}; };
ReturnNode.prototype.makeReturn = function() {
return this;
};
ReturnNode.prototype.compileNode = function(o) { ReturnNode.prototype.compileNode = function(o) {
var expr; var expr;
expr = this.expression.makeReturn(); expr = this.expression.makeReturn();

View File

@@ -179,7 +179,7 @@ exports.Expressions: class Expressions extends BaseNode
last: @expressions[idx] last: @expressions[idx]
last: @expressions[idx: - 1] if last instanceof CommentNode last: @expressions[idx: - 1] if last instanceof CommentNode
return this if not last or last instanceof ReturnNode return this if not last or last instanceof ReturnNode
@expressions[idx]: last.makeReturn() unless last.containsPureStatement() @expressions[idx]: last.makeReturn()
this this
# An **Expressions** is the only node that can serve as the root. # An **Expressions** is the only node that can serve as the root.
@@ -264,6 +264,9 @@ exports.ReturnNode: class ReturnNode extends BaseNode
topSensitive: -> topSensitive: ->
true true
makeReturn: ->
this
compileNode: (o) -> compileNode: (o) ->
expr: @expression.makeReturn() expr: @expression.makeReturn()
return expr.compile(o) unless expr instanceof ReturnNode return expr.compile(o) unless expr instanceof ReturnNode

View File

@@ -10,4 +10,15 @@ third: ->
ok first().join(' ') is 'do do do' ok first().join(' ') is 'do do do'
ok second()[0].join(' ') is 're re re' ok second()[0].join(' ') is 're re re'
ok third().join(' ') is 'mi mi mi' ok third().join(' ') is 'mi mi mi'
# Testing returns with multiple branches.
func: ->
if false
for a in b
return c if d
else
"word"
ok func() is 'word'