mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-19 03:44:23 -05:00
Wrapping all soaked chains that are involved in operations.
This commit is contained in:
committed by
Jeremy Ashkenas
parent
4d935efd09
commit
ac05f62f2f
53
lib/nodes.js
53
lib/nodes.js
@@ -71,8 +71,11 @@
|
|||||||
var closure, top;
|
var closure, top;
|
||||||
this.options = merge(o || {});
|
this.options = merge(o || {});
|
||||||
this.tab = o.indent;
|
this.tab = o.indent;
|
||||||
if (!(this instanceof ValueNode)) {
|
if (!(this instanceof ValueNode || this instanceof CallNode)) {
|
||||||
del(this.options, 'operation');
|
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');
|
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();
|
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
|
// operators `?.` interspersed. Then we have to take care not to accidentally
|
||||||
// evaluate a anything twice when building the soak chain.
|
// evaluate a anything twice when building the soak chain.
|
||||||
ValueNode.prototype.compile_node = function compile_node(o) {
|
ValueNode.prototype.compile_node = function compile_node(o) {
|
||||||
var _b, _c, _d, baseline, complete, only, op, part, prop, props, soaked, temp;
|
var _b, _c, _d, baseline, complete, only, op, part, prop, props, temp;
|
||||||
soaked = false;
|
|
||||||
only = del(o, 'only_first');
|
only = del(o, 'only_first');
|
||||||
op = del(o, 'operation');
|
op = del(o, 'operation');
|
||||||
props = only ? this.properties.slice(0, this.properties.length - 1) : this.properties;
|
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);
|
baseline = this.base.compile(o);
|
||||||
if (this.base instanceof ObjectNode && this.has_properties()) {
|
if (this.base instanceof ObjectNode && this.has_properties()) {
|
||||||
baseline = ("(" + baseline + ")");
|
baseline = ("(" + baseline + ")");
|
||||||
@@ -442,7 +447,6 @@
|
|||||||
prop = _c[_b];
|
prop = _c[_b];
|
||||||
this.source = baseline;
|
this.source = baseline;
|
||||||
if (prop.soak_node) {
|
if (prop.soak_node) {
|
||||||
soaked = true;
|
|
||||||
if (this.base instanceof CallNode && prop === props[0]) {
|
if (this.base instanceof CallNode && prop === props[0]) {
|
||||||
temp = o.scope.free_variable();
|
temp = o.scope.free_variable();
|
||||||
complete = ("(" + temp + " = " + complete + ")" + this.SOAK) + (baseline = temp + prop.compile(o));
|
complete = ("(" + temp + " = " + complete + ")" + this.SOAK) + (baseline = temp + prop.compile(o));
|
||||||
@@ -456,7 +460,8 @@
|
|||||||
this.last = part;
|
this.last = part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (op && soaked) {
|
del(o, 'chain_root');
|
||||||
|
if (op && this.wrapped) {
|
||||||
return "(" + complete + ")";
|
return "(" + complete + ")";
|
||||||
} else {
|
} else {
|
||||||
return complete;
|
return complete;
|
||||||
@@ -525,26 +530,32 @@
|
|||||||
};
|
};
|
||||||
// Compile a vanilla function call.
|
// Compile a vanilla function call.
|
||||||
CallNode.prototype.compile_node = function compile_node(o) {
|
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;
|
_c = this.args;
|
||||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||||
arg = _c[_b];
|
arg = _c[_b];
|
||||||
if (arg instanceof SplatNode) {
|
arg instanceof SplatNode ? (compilation = this.compile_splat(o)) : null;
|
||||||
return this.compile_splat(o);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
args = (function() {
|
if (!(compilation)) {
|
||||||
_e = []; _g = this.args;
|
args = (function() {
|
||||||
for (_f = 0, _h = _g.length; _f < _h; _f++) {
|
_e = []; _g = this.args;
|
||||||
arg = _g[_f];
|
for (_f = 0, _h = _g.length; _f < _h; _f++) {
|
||||||
_e.push(arg.compile(o));
|
arg = _g[_f];
|
||||||
}
|
_e.push(arg.compile(o));
|
||||||
return _e;
|
}
|
||||||
}).call(this).join(', ');
|
return _e;
|
||||||
if (this.is_super) {
|
}).call(this).join(', ');
|
||||||
return this.compile_super(args, o);
|
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
|
// `super()` is converted into a call against the superclass's implementation
|
||||||
// of the current function.
|
// of the current function.
|
||||||
@@ -628,6 +639,7 @@
|
|||||||
__extends(AccessorNode, BaseNode);
|
__extends(AccessorNode, BaseNode);
|
||||||
AccessorNode.prototype.compile_node = function compile_node(o) {
|
AccessorNode.prototype.compile_node = function compile_node(o) {
|
||||||
var proto_part;
|
var proto_part;
|
||||||
|
o.chain_root.wrapped = o.chain_root.wrapped || this.soak_node;
|
||||||
proto_part = this.prototype ? 'prototype.' : '';
|
proto_part = this.prototype ? 'prototype.' : '';
|
||||||
return "." + proto_part + (this.name.compile(o));
|
return "." + proto_part + (this.name.compile(o));
|
||||||
};
|
};
|
||||||
@@ -644,6 +656,7 @@
|
|||||||
__extends(IndexNode, BaseNode);
|
__extends(IndexNode, BaseNode);
|
||||||
IndexNode.prototype.compile_node = function compile_node(o) {
|
IndexNode.prototype.compile_node = function compile_node(o) {
|
||||||
var idx;
|
var idx;
|
||||||
|
o.chain_root.wrapped = this.soak_node;
|
||||||
idx = this.index.compile(o);
|
idx = this.index.compile(o);
|
||||||
return "[" + idx + "]";
|
return "[" + idx + "]";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ exports.BaseNode: class BaseNode
|
|||||||
compile: (o) ->
|
compile: (o) ->
|
||||||
@options: merge o or {}
|
@options: merge o or {}
|
||||||
@tab: o.indent
|
@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'
|
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.as_statement and not (this instanceof CommentNode) 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
|
# operators `?.` interspersed. Then we have to take care not to accidentally
|
||||||
# evaluate a anything twice when building the soak chain.
|
# evaluate a anything twice when building the soak chain.
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
soaked: false
|
only: del(o, 'only_first')
|
||||||
only: del(o, 'only_first')
|
op: del(o, 'operation')
|
||||||
op: del(o, 'operation')
|
props: if only then @properties[0...@properties.length - 1] else @properties
|
||||||
props: if only then @properties[0...@properties.length - 1] else @properties
|
o.chain_root: this unless o.chain_root
|
||||||
baseline: @base.compile o
|
baseline: @base.compile o
|
||||||
baseline: "($baseline)" if @base instanceof ObjectNode and @has_properties()
|
baseline: "($baseline)" if @base instanceof ObjectNode and @has_properties()
|
||||||
complete: @last: baseline
|
complete: @last: baseline
|
||||||
|
|
||||||
for prop in props
|
for prop in props
|
||||||
@source: baseline
|
@source: baseline
|
||||||
if prop.soak_node
|
if prop.soak_node
|
||||||
soaked: true
|
|
||||||
if @base instanceof CallNode and prop is props[0]
|
if @base instanceof CallNode and prop is props[0]
|
||||||
temp: o.scope.free_variable()
|
temp: o.scope.free_variable()
|
||||||
complete: "($temp = $complete)$@SOAK" + (baseline: temp + prop.compile(o))
|
complete: "($temp = $complete)$@SOAK" + (baseline: temp + prop.compile(o))
|
||||||
@@ -324,8 +325,10 @@ exports.ValueNode: class ValueNode extends BaseNode
|
|||||||
baseline: + part
|
baseline: + part
|
||||||
complete: + part
|
complete: + part
|
||||||
@last: part
|
@last: part
|
||||||
|
|
||||||
|
del o, 'chain_root'
|
||||||
|
|
||||||
if op and soaked then "($complete)" else complete
|
if op and @wrapped then "($complete)" else complete
|
||||||
|
|
||||||
#### CommentNode
|
#### CommentNode
|
||||||
|
|
||||||
@@ -377,11 +380,15 @@ exports.CallNode: class CallNode extends BaseNode
|
|||||||
|
|
||||||
# Compile a vanilla function call.
|
# Compile a vanilla function call.
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
for arg in @args
|
o.chain_root: this unless o.chain_root
|
||||||
return @compile_splat(o) if arg instanceof SplatNode
|
for arg in @args when arg instanceof SplatNode
|
||||||
args: (arg.compile(o) for arg in @args).join(', ')
|
compilation: @compile_splat(o)
|
||||||
return @compile_super(args, o) if @is_super
|
unless compilation
|
||||||
"${@prefix()}${@variable.compile(o)}($args)"
|
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
|
# `super()` is converted into a call against the superclass's implementation
|
||||||
# of the current function.
|
# of the current function.
|
||||||
@@ -449,6 +456,7 @@ exports.AccessorNode: class AccessorNode extends BaseNode
|
|||||||
this
|
this
|
||||||
|
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
|
o.chain_root.wrapped: or @soak_node
|
||||||
proto_part: if @prototype then 'prototype.' else ''
|
proto_part: if @prototype then 'prototype.' else ''
|
||||||
".$proto_part${@name.compile(o)}"
|
".$proto_part${@name.compile(o)}"
|
||||||
|
|
||||||
@@ -462,6 +470,7 @@ exports.IndexNode: class IndexNode extends BaseNode
|
|||||||
@soak_node: tag is 'soak'
|
@soak_node: tag is 'soak'
|
||||||
|
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
|
o.chain_root.wrapped: @soak_node
|
||||||
idx: @index.compile o
|
idx: @index.compile o
|
||||||
"[$idx]"
|
"[$idx]"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user