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:
parent
4d935efd09
commit
ac05f62f2f
2 changed files with 57 additions and 35 deletions
53
lib/nodes.js
53
lib/nodes.js
|
@ -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 + "]";
|
||||
};
|
||||
|
|
|
@ -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]"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue