1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

Wrapping all soaked chains that are involved in operations.

This commit is contained in:
Tim Jones 2010-05-04 01:04:26 +12:00 committed by Jeremy Ashkenas
parent 4d935efd09
commit ac05f62f2f
2 changed files with 57 additions and 35 deletions

View file

@ -71,8 +71,11 @@
var closure, top;
this.options = merge(o || {});
this.tab = o.indent;
if (!(this instanceof ValueNode)) {
if (!(this instanceof ValueNode || this instanceof CallNode)) {
del(this.options, 'operation');
if (!(this instanceof AccessorNode || this instanceof IndexNode)) {
del(this.options, 'chain_root');
}
}
top = this.top_sensitive() ? this.options.top : del(this.options, 'top');
closure = this.is_statement() && !this.is_pure_statement() && !top && !this.options.as_statement && !(this instanceof CommentNode) && !this.contains_pure_statement();
@ -427,11 +430,13 @@
// operators `?.` interspersed. Then we have to take care not to accidentally
// evaluate a anything twice when building the soak chain.
ValueNode.prototype.compile_node = function compile_node(o) {
var _b, _c, _d, baseline, complete, only, op, part, prop, props, soaked, temp;
soaked = false;
var _b, _c, _d, baseline, complete, only, op, part, prop, props, temp;
only = del(o, 'only_first');
op = del(o, 'operation');
props = only ? this.properties.slice(0, this.properties.length - 1) : this.properties;
if (!(o.chain_root)) {
o.chain_root = this;
}
baseline = this.base.compile(o);
if (this.base instanceof ObjectNode && this.has_properties()) {
baseline = ("(" + baseline + ")");
@ -442,7 +447,6 @@
prop = _c[_b];
this.source = baseline;
if (prop.soak_node) {
soaked = true;
if (this.base instanceof CallNode && prop === props[0]) {
temp = o.scope.free_variable();
complete = ("(" + temp + " = " + complete + ")" + this.SOAK) + (baseline = temp + prop.compile(o));
@ -456,7 +460,8 @@
this.last = part;
}
}
if (op && soaked) {
del(o, 'chain_root');
if (op && this.wrapped) {
return "(" + complete + ")";
} else {
return complete;
@ -525,26 +530,32 @@
};
// Compile a vanilla function call.
CallNode.prototype.compile_node = function compile_node(o) {
var _b, _c, _d, _e, _f, _g, _h, arg, args;
var _b, _c, _d, _e, _f, _g, _h, arg, args, compilation;
if (!(o.chain_root)) {
o.chain_root = this;
}
_c = this.args;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
arg = _c[_b];
if (arg instanceof SplatNode) {
return this.compile_splat(o);
}
arg instanceof SplatNode ? (compilation = this.compile_splat(o)) : null;
}
args = (function() {
_e = []; _g = this.args;
for (_f = 0, _h = _g.length; _f < _h; _f++) {
arg = _g[_f];
_e.push(arg.compile(o));
}
return _e;
}).call(this).join(', ');
if (this.is_super) {
return this.compile_super(args, o);
if (!(compilation)) {
args = (function() {
_e = []; _g = this.args;
for (_f = 0, _h = _g.length; _f < _h; _f++) {
arg = _g[_f];
_e.push(arg.compile(o));
}
return _e;
}).call(this).join(', ');
compilation = this.is_super ? this.compile_super(args, o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + args + ")");
}
del(o, 'chain_root');
if (o.operation && this.wrapped) {
return "(" + compilation + ")";
} else {
return compilation;
}
return "" + (this.prefix()) + (this.variable.compile(o)) + "(" + args + ")";
};
// `super()` is converted into a call against the superclass's implementation
// of the current function.
@ -628,6 +639,7 @@
__extends(AccessorNode, BaseNode);
AccessorNode.prototype.compile_node = function compile_node(o) {
var proto_part;
o.chain_root.wrapped = o.chain_root.wrapped || this.soak_node;
proto_part = this.prototype ? 'prototype.' : '';
return "." + proto_part + (this.name.compile(o));
};
@ -644,6 +656,7 @@
__extends(IndexNode, BaseNode);
IndexNode.prototype.compile_node = function compile_node(o) {
var idx;
o.chain_root.wrapped = this.soak_node;
idx = this.index.compile(o);
return "[" + idx + "]";
};

View file

@ -50,7 +50,9 @@ exports.BaseNode: class BaseNode
compile: (o) ->
@options: merge o or {}
@tab: o.indent
del @options, 'operation' unless this instanceof ValueNode
unless this instanceof ValueNode or this instanceof CallNode
del @options, 'operation'
del @options, 'chain_root' unless this instanceof AccessorNode or this instanceof IndexNode
top: if @top_sensitive() then @options.top else del @options, 'top'
closure: @is_statement() and not @is_pure_statement() and not top and
not @options.as_statement and not (this instanceof CommentNode) and
@ -302,18 +304,17 @@ exports.ValueNode: class ValueNode extends BaseNode
# operators `?.` interspersed. Then we have to take care not to accidentally
# evaluate a anything twice when building the soak chain.
compile_node: (o) ->
soaked: false
only: del(o, 'only_first')
op: del(o, 'operation')
props: if only then @properties[0...@properties.length - 1] else @properties
baseline: @base.compile o
baseline: "($baseline)" if @base instanceof ObjectNode and @has_properties()
complete: @last: baseline
only: del(o, 'only_first')
op: del(o, 'operation')
props: if only then @properties[0...@properties.length - 1] else @properties
o.chain_root: this unless o.chain_root
baseline: @base.compile o
baseline: "($baseline)" if @base instanceof ObjectNode and @has_properties()
complete: @last: baseline
for prop in props
@source: baseline
if prop.soak_node
soaked: true
if @base instanceof CallNode and prop is props[0]
temp: o.scope.free_variable()
complete: "($temp = $complete)$@SOAK" + (baseline: temp + prop.compile(o))
@ -324,8 +325,10 @@ exports.ValueNode: class ValueNode extends BaseNode
baseline: + part
complete: + part
@last: part
del o, 'chain_root'
if op and soaked then "($complete)" else complete
if op and @wrapped then "($complete)" else complete
#### CommentNode
@ -377,11 +380,15 @@ exports.CallNode: class CallNode extends BaseNode
# Compile a vanilla function call.
compile_node: (o) ->
for arg in @args
return @compile_splat(o) if arg instanceof SplatNode
args: (arg.compile(o) for arg in @args).join(', ')
return @compile_super(args, o) if @is_super
"${@prefix()}${@variable.compile(o)}($args)"
o.chain_root: this unless o.chain_root
for arg in @args when arg instanceof SplatNode
compilation: @compile_splat(o)
unless compilation
args: (arg.compile(o) for arg in @args).join(', ')
compilation: if @is_super then @compile_super(args, o)
else "${@prefix()}${@variable.compile(o)}($args)"
del o, 'chain_root'
if o.operation and @wrapped then "($compilation)" else compilation
# `super()` is converted into a call against the superclass's implementation
# of the current function.
@ -449,6 +456,7 @@ exports.AccessorNode: class AccessorNode extends BaseNode
this
compile_node: (o) ->
o.chain_root.wrapped: or @soak_node
proto_part: if @prototype then 'prototype.' else ''
".$proto_part${@name.compile(o)}"
@ -462,6 +470,7 @@ exports.IndexNode: class IndexNode extends BaseNode
@soak_node: tag is 'soak'
compile_node: (o) ->
o.chain_root.wrapped: @soak_node
idx: @index.compile o
"[$idx]"