moving the contains-a-pure-statement-means-no-closure logic into ClosureNode.wrap itself.

This commit is contained in:
Jeremy Ashkenas
2010-03-15 22:27:31 -07:00
parent 8c2b2c7f80
commit 3aeb8c6bdb
3 changed files with 22 additions and 16 deletions

View File

@@ -67,9 +67,7 @@
del(this.options, 'operation'); del(this.options, 'operation');
} }
top = this.top_sensitive() ? this.options.top : del(this.options, 'top'); top = this.top_sensitive() ? this.options.top : del(this.options, 'top');
closure = this.is_statement() && !this.is_pure_statement() && !top && !this.options.returns && !(this instanceof CommentNode) && !this.contains(function(node) { closure = this.is_statement() && !this.is_pure_statement() && !top && !this.options.returns && !(this instanceof CommentNode);
return node.is_pure_statement();
});
return closure ? this.compile_closure(this.options) : this.compile_node(this.options); return closure ? this.compile_closure(this.options) : this.compile_node(this.options);
}; };
// Statements converted into expressions via closure-wrapping share a scope // Statements converted into expressions via closure-wrapping share a scope
@@ -1346,11 +1344,11 @@
} }
set_result = rvar ? this.idt() + rvar + ' = []; ' : this.idt(); set_result = rvar ? this.idt() + rvar + ' = []; ' : this.idt();
return_result = rvar || ''; return_result = rvar || '';
top_level && !this.contains(function(n) { if (top_level && body.contains(function(n) {
return n.is_pure_statement();
}) && this.contains(function(n) {
return n instanceof CodeNode; return n instanceof CodeNode;
}) ? (body = ClosureNode.wrap(body, true)) : null; })) {
body = ClosureNode.wrap(body, true);
}
if (!(top_level)) { if (!(top_level)) {
body = PushNode.wrap(rvar, body); body = PushNode.wrap(rvar, body);
} }
@@ -1542,8 +1540,15 @@
//### ClosureNode //### ClosureNode
// A faux-node used to wrap an expressions body in a closure. // A faux-node used to wrap an expressions body in a closure.
ClosureNode = (exports.ClosureNode = { ClosureNode = (exports.ClosureNode = {
// Wrap the expressions body, unless it contains a pure statement,
// in which case, no dice.
wrap: function wrap(expressions, statement) { wrap: function wrap(expressions, statement) {
var call, func; var call, func;
if (expressions.contains(function(n) {
return n.is_pure_statement();
})) {
return expressions;
}
func = new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions]))); func = new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions])));
call = new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')]); call = new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')]);
return statement ? Expressions.wrap([call]) : call; return statement ? Expressions.wrap([call]) : call;

View File

@@ -54,8 +54,7 @@ exports.BaseNode: class BaseNode
del @options, 'operation' unless this instanceof ValueNode del @options, 'operation' unless this instanceof ValueNode
top: if @top_sensitive() then @options.top else del @options, 'top' top: if @top_sensitive() then @options.top else del @options, 'top'
closure: @is_statement() and not @is_pure_statement() and not top and closure: @is_statement() and not @is_pure_statement() and not top and
not @options.returns and not (this instanceof CommentNode) and not @options.returns and not (this instanceof CommentNode)
not @contains (node) -> node.is_pure_statement()
if closure then @compile_closure(@options) else @compile_node(@options) if closure then @compile_closure(@options) else @compile_node(@options)
# Statements converted into expressions via closure-wrapping share a scope # Statements converted into expressions via closure-wrapping share a scope
@@ -1024,8 +1023,7 @@ exports.ForNode: class ForNode extends BaseNode
for_part: "$ivar = 0, $lvar = ${svar}.length; $ivar < $lvar; $step_part" for_part: "$ivar = 0, $lvar = ${svar}.length; $ivar < $lvar; $step_part"
set_result: if rvar then @idt() + rvar + ' = []; ' else @idt() set_result: if rvar then @idt() + rvar + ' = []; ' else @idt()
return_result: rvar or '' return_result: rvar or ''
if top_level and not @contains((n) -> n.is_pure_statement()) and @contains((n) -> n instanceof CodeNode) body: ClosureNode.wrap(body, true) if top_level and body.contains (n) -> n instanceof CodeNode
body: ClosureNode.wrap(body, true)
body: PushNode.wrap(rvar, body) unless top_level body: PushNode.wrap(rvar, body) unless top_level
if o.returns if o.returns
return_result: 'return ' + return_result return_result: 'return ' + return_result
@@ -1172,7 +1170,10 @@ PushNode: exports.PushNode: {
# A faux-node used to wrap an expressions body in a closure. # A faux-node used to wrap an expressions body in a closure.
ClosureNode: exports.ClosureNode: { ClosureNode: exports.ClosureNode: {
# Wrap the expressions body, unless it contains a pure statement,
# in which case, no dice.
wrap: (expressions, statement) -> wrap: (expressions, statement) ->
return expressions if expressions.contains (n) -> n.is_pure_statement()
func: new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions]))) func: new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions])))
call: new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')]) call: new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')])
if statement then Expressions.wrap([call]) else call if statement then Expressions.wrap([call]) else call

View File

@@ -1,21 +1,21 @@
# Test with break at the top level. # Test with break at the top level.
a: [1,2,3] array: [1,2,3]
call_with_lambda: (l) -> null call_with_lambda: (l) -> null
for i in a for i in array
a: call_with_lambda(->) result: call_with_lambda(->)
if i == 2 if i == 2
puts "i = 2" puts "i = 2"
else else
break break
ok a is null ok result is null
# Test with break *not* at the top level. # Test with break *not* at the top level.
some_func: (input) -> some_func: (input) ->
takes_lambda: (l) -> null takes_lambda: (l) -> null
for i in [1,2] for i in [1,2]
arbitraty_var: takes_lambda(->) result: takes_lambda(->)
if input == 1 if input == 1
return 1 return 1
else else