mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-18 11:31:20 -05:00
#733: streamlined soak compilations and improved reference cachings
This commit is contained in:
424
lib/nodes.js
424
lib/nodes.js
@@ -26,7 +26,7 @@
|
||||
};
|
||||
BaseNode.prototype.compile = function(o) {
|
||||
var closure, code, top;
|
||||
this.options = merge(o || {});
|
||||
this.options = o ? merge(o) : {};
|
||||
this.tab = o.indent;
|
||||
if (!(this instanceof AccessorNode || this instanceof IndexNode)) {
|
||||
del(this.options, 'chainRoot');
|
||||
@@ -48,21 +48,22 @@
|
||||
return ClosureNode.wrap(this).compile(o);
|
||||
};
|
||||
BaseNode.prototype.compileReference = function(o, options) {
|
||||
var compiled, pair, reference;
|
||||
options || (options = {});
|
||||
var _len, _ref2, compiled, i, node, pair, reference;
|
||||
pair = (function() {
|
||||
if (!this.isComplex()) {
|
||||
if (!(this.isComplex())) {
|
||||
return [this, this];
|
||||
} else if (this instanceof ValueNode && options.assignment) {
|
||||
return this.cacheIndexes(o);
|
||||
} else {
|
||||
reference = literal(o.scope.freeVariable('ref'));
|
||||
compiled = new AssignNode(reference, this);
|
||||
return [compiled, reference];
|
||||
}
|
||||
}).call(this);
|
||||
if (options.precompile) {
|
||||
return [pair[0].compile(o), pair[1].compile(o)];
|
||||
if (((options != null) ? options.precompile : null)) {
|
||||
_ref2 = pair;
|
||||
for (i = 0, _len = _ref2.length; i < _len; i++) {
|
||||
node = _ref2[i];
|
||||
(pair[i] = node.compile(o));
|
||||
}
|
||||
}
|
||||
return pair;
|
||||
};
|
||||
@@ -96,7 +97,7 @@
|
||||
};
|
||||
BaseNode.prototype.containsPureStatement = function() {
|
||||
return this.isPureStatement() || this.contains(function(n) {
|
||||
return n.isPureStatement && n.isPureStatement();
|
||||
return (typeof n.isPureStatement !== "function" ? undefined : n.isPureStatement());
|
||||
});
|
||||
};
|
||||
BaseNode.prototype.traverse = function(block) {
|
||||
@@ -146,8 +147,10 @@
|
||||
};
|
||||
BaseNode.prototype.traverseChildren = function(crossScope, func) {
|
||||
return this.eachChild(function(child) {
|
||||
func.apply(this, arguments);
|
||||
return child instanceof BaseNode ? child.traverseChildren(crossScope, func) : null;
|
||||
if (func(child) === false) {
|
||||
return false;
|
||||
}
|
||||
return child instanceof BaseNode && (crossScope || !(child instanceof CodeNode)) ? child.traverseChildren(crossScope, func) : null;
|
||||
});
|
||||
};
|
||||
BaseNode.prototype["class"] = 'BaseNode';
|
||||
@@ -319,10 +322,10 @@
|
||||
return !!this.properties.length;
|
||||
};
|
||||
ValueNode.prototype.isArray = function() {
|
||||
return this.base instanceof ArrayNode && !this.hasProperties();
|
||||
return this.base instanceof ArrayNode && !this.properties.length;
|
||||
};
|
||||
ValueNode.prototype.isObject = function() {
|
||||
return this.base instanceof ObjectNode && !this.hasProperties();
|
||||
return this.base instanceof ObjectNode && !this.properties.length;
|
||||
};
|
||||
ValueNode.prototype.isSplice = function() {
|
||||
return last(this.properties) instanceof SliceNode;
|
||||
@@ -331,7 +334,7 @@
|
||||
return this.base.isComplex() || this.hasProperties();
|
||||
};
|
||||
ValueNode.prototype.makeReturn = function() {
|
||||
return this.hasProperties() ? ValueNode.__super__.makeReturn.call(this) : this.base.makeReturn();
|
||||
return this.properties.length ? ValueNode.__super__.makeReturn.call(this) : this.base.makeReturn();
|
||||
};
|
||||
ValueNode.prototype.unwrap = function() {
|
||||
return this.properties.length ? this : this.base;
|
||||
@@ -342,76 +345,95 @@
|
||||
ValueNode.prototype.isNumber = function() {
|
||||
return this.base instanceof LiteralNode && NUMBER.test(this.base.value);
|
||||
};
|
||||
ValueNode.prototype.cacheIndexes = function(o) {
|
||||
var _len, _ref2, _ref3, copy, first, i, index, indexVar, prop;
|
||||
copy = new ValueNode(this.base, this.properties.slice(0));
|
||||
if (this.base.isComplex()) {
|
||||
_ref2 = this.base.compileReference(o), this.base = _ref2[0], copy.base = _ref2[1];
|
||||
ValueNode.prototype.cacheReference = function(o) {
|
||||
var base, bref, name, nref;
|
||||
name = last(this.properties);
|
||||
if (!this.base.isComplex() && this.properties.length < 2 && !((name != null) ? name.isComplex() : null)) {
|
||||
return [this, this];
|
||||
}
|
||||
_ref2 = copy.properties;
|
||||
for (i = 0, _len = _ref2.length; i < _len; i++) {
|
||||
prop = _ref2[i];
|
||||
if (prop instanceof IndexNode && prop.index.isComplex()) {
|
||||
_ref3 = prop.index.compileReference(o), index = _ref3[0], indexVar = _ref3[1];
|
||||
this.properties[i] = (first = new IndexNode(index));
|
||||
copy.properties[i] = new IndexNode(indexVar);
|
||||
if (prop.soakNode) {
|
||||
first.soakNode = true;
|
||||
}
|
||||
}
|
||||
base = new ValueNode(this.base, this.properties.slice(0, -1));
|
||||
if (base.isComplex()) {
|
||||
bref = literal(o.scope.freeVariable('base'));
|
||||
base = new ValueNode(new ParentheticalNode(new AssignNode(bref, base)));
|
||||
}
|
||||
return [this, copy];
|
||||
if (!(name)) {
|
||||
return [base, bref];
|
||||
}
|
||||
if (name.isComplex()) {
|
||||
nref = literal(o.scope.freeVariable('name'));
|
||||
name = new IndexNode(new AssignNode(nref, name.index));
|
||||
nref = new IndexNode(nref);
|
||||
}
|
||||
return [base.push(name), new ValueNode(bref || base.base, [nref || name])];
|
||||
};
|
||||
ValueNode.prototype.compile = function(o) {
|
||||
return !o.top || this.properties.length ? ValueNode.__super__.compile.call(this, o) : this.base.compile(o);
|
||||
};
|
||||
ValueNode.prototype.compileNode = function(o) {
|
||||
var _i, _len, _ref2, baseline, complete, copy, hasSoak, i, me, only, op, part, prop, props, temp;
|
||||
only = del(o, 'onlyFirst');
|
||||
op = this.tags.operation;
|
||||
props = only ? this.properties.slice(0, -1) : this.properties;
|
||||
var _i, _len, _ref2, code, ex, prop, props;
|
||||
if (ex = this.unfoldSoak(o)) {
|
||||
return ex.compile(o);
|
||||
}
|
||||
props = this.properties;
|
||||
o.chainRoot || (o.chainRoot = this);
|
||||
_ref2 = props;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
prop = _ref2[_i];
|
||||
if (prop.soakNode) {
|
||||
hasSoak = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasSoak && this.isComplex()) {
|
||||
_ref2 = this.cacheIndexes(o), me = _ref2[0], copy = _ref2[1];
|
||||
}
|
||||
if (this.parenthetical && !props.length) {
|
||||
this.base.parenthetical = true;
|
||||
}
|
||||
baseline = this.base.compile(o);
|
||||
if (this.hasProperties() && (this.base instanceof ObjectNode || this.isNumber())) {
|
||||
baseline = ("(" + (baseline) + ")");
|
||||
code = this.base.compile(o);
|
||||
if (props[0] instanceof AccessorNode && this.isNumber() || o.top && this.base instanceof ObjectNode) {
|
||||
code = ("(" + (code) + ")");
|
||||
}
|
||||
complete = (this.last = baseline);
|
||||
_ref2 = props;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
prop = _ref2[_i];
|
||||
(code += prop.compile(o));
|
||||
}
|
||||
return code;
|
||||
};
|
||||
ValueNode.prototype.unfoldSoak = function(o) {
|
||||
var _len, _ref2, fst, i, ifn, prop, ref, snd;
|
||||
if (this.base.soakNode) {
|
||||
Array.prototype.push.apply(this.base.body.properties, this.properties);
|
||||
return this.base;
|
||||
}
|
||||
_ref2 = this.properties;
|
||||
for (i = 0, _len = _ref2.length; i < _len; i++) {
|
||||
prop = _ref2[i];
|
||||
this.source = baseline;
|
||||
if (prop.soakNode) {
|
||||
if (i === 0 && this.base.isComplex()) {
|
||||
temp = o.scope.freeVariable('ref');
|
||||
complete = ("(" + (baseline = temp) + " = (" + (complete) + "))");
|
||||
prop.soakNode = false;
|
||||
fst = new ValueNode(this.base, this.properties.slice(0, i));
|
||||
snd = new ValueNode(this.base, this.properties.slice(i));
|
||||
if (fst.isComplex()) {
|
||||
ref = literal(o.scope.freeVariable('ref'));
|
||||
fst = new ParentheticalNode(new AssignNode(ref, fst));
|
||||
snd.base = ref;
|
||||
}
|
||||
complete = i === 0 && !o.scope.check(complete) ? ("(typeof " + (complete) + " === \"undefined\" || " + (baseline) + " === null)") : ("" + (complete) + " == null");
|
||||
complete += ' ? undefined : ' + (baseline += prop.compile(o));
|
||||
} else {
|
||||
part = prop.compile(o);
|
||||
baseline += (hasSoak && prop.isComplex() ? copy.properties[i].compile(o) : part);
|
||||
complete += part;
|
||||
this.last = part;
|
||||
ifn = new IfNode(new ExistenceNode(fst), snd, {
|
||||
operation: true
|
||||
});
|
||||
ifn.soakNode = true;
|
||||
return ifn;
|
||||
}
|
||||
}
|
||||
return op && this.wrapped ? ("(" + (complete) + ")") : complete;
|
||||
return null;
|
||||
};
|
||||
ValueNode.unfoldSoak = function(o, parent, name) {
|
||||
var ifnode, node;
|
||||
node = parent[name];
|
||||
if (node instanceof IfNode && node.soakNode) {
|
||||
ifnode = node;
|
||||
} else if (node instanceof ValueNode) {
|
||||
ifnode = node.unfoldSoak(o);
|
||||
}
|
||||
if (!(ifnode)) {
|
||||
return null;
|
||||
}
|
||||
parent[name] = ifnode.body;
|
||||
ifnode.body = new ValueNode(parent);
|
||||
return ifnode;
|
||||
};
|
||||
return ValueNode;
|
||||
})();
|
||||
}).call(this);
|
||||
exports.CommentNode = (function() {
|
||||
CommentNode = function(_arg) {
|
||||
this.comment = _arg;
|
||||
@@ -436,15 +458,14 @@
|
||||
this.isSuper = variable === 'super';
|
||||
this.variable = this.isSuper ? null : variable;
|
||||
this.args || (this.args = []);
|
||||
this.first = (this.last = '');
|
||||
this.compileSplatArguments = function(o) {
|
||||
return SplatNode.compileSplattedArray.call(this, this.args, o);
|
||||
};
|
||||
return this;
|
||||
};
|
||||
__extends(CallNode, BaseNode);
|
||||
CallNode.prototype["class"] = 'CallNode';
|
||||
CallNode.prototype.children = ['variable', 'args'];
|
||||
CallNode.prototype.compileSplatArguments = function(o) {
|
||||
return SplatNode.compileSplattedArray(this.args, o);
|
||||
};
|
||||
CallNode.prototype.newInstance = function() {
|
||||
this.isNew = true;
|
||||
return this;
|
||||
@@ -453,97 +474,128 @@
|
||||
return this.isNew ? 'new ' : '';
|
||||
};
|
||||
CallNode.prototype.superReference = function(o) {
|
||||
var meth, methname;
|
||||
if (!(o.scope.method)) {
|
||||
throw new Error("cannot call super outside of a function");
|
||||
var method, name;
|
||||
method = o.scope.method;
|
||||
if (!(method)) {
|
||||
throw Error("cannot call super outside of a function");
|
||||
}
|
||||
methname = o.scope.method.name;
|
||||
return (meth = (function() {
|
||||
if (o.scope.method.proto) {
|
||||
return "" + (o.scope.method.proto) + ".__super__." + (methname);
|
||||
} else if (methname) {
|
||||
return "" + (methname) + ".__super__.constructor";
|
||||
} else {
|
||||
throw new Error("cannot call super on an anonymous function.");
|
||||
name = method.name;
|
||||
if (!(name)) {
|
||||
throw Error("cannot call super on an anonymous function.");
|
||||
}
|
||||
return method.klass ? ("" + (method.klass) + ".__super__." + (name)) : ("" + (name) + ".__super__.constructor");
|
||||
};
|
||||
CallNode.prototype.unfoldSoak = function(o) {
|
||||
var _i, _len, _ref2, call, list, node;
|
||||
call = this;
|
||||
list = [];
|
||||
while (true) {
|
||||
if (call.variable instanceof CallNode) {
|
||||
list.push(call);
|
||||
call = call.variable;
|
||||
continue;
|
||||
}
|
||||
})());
|
||||
if (!(call.variable instanceof ValueNode)) {
|
||||
break;
|
||||
}
|
||||
list.push(call);
|
||||
if (!((call = call.variable.base) instanceof CallNode)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ref2 = list.reverse();
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
call = _ref2[_i];
|
||||
if (node) {
|
||||
if (call.variable instanceof CallNode) {
|
||||
call.variable = node;
|
||||
} else {
|
||||
call.variable.base = node;
|
||||
}
|
||||
}
|
||||
node = ValueNode.unfoldSoak(o, call, 'variable');
|
||||
}
|
||||
return node;
|
||||
};
|
||||
CallNode.prototype.compileNode = function(o) {
|
||||
var _i, _len, _ref2, _result, arg, args, code, first, meth, methodAccessor, op;
|
||||
if (!(o.chainRoot)) {
|
||||
o.chainRoot = this;
|
||||
var _i, _len, _ref2, _result, arg, args, left, node, rite, val;
|
||||
if (node = this.unfoldSoak(o)) {
|
||||
return node.compile(o);
|
||||
}
|
||||
op = this.tags.operation;
|
||||
o.chainRoot || (o.chainRoot = this);
|
||||
if (this.exist) {
|
||||
if (this.variable instanceof ValueNode && last(this.variable.properties) instanceof AccessorNode) {
|
||||
methodAccessor = this.variable.properties.pop();
|
||||
_ref2 = this.variable.compileReference(o), first = _ref2[0], meth = _ref2[1];
|
||||
this.first = new ValueNode(first, [methodAccessor]).compile(o);
|
||||
this.meth = new ValueNode(meth, [methodAccessor]).compile(o);
|
||||
if (val = this.variable) {
|
||||
if (!(val instanceof ValueNode)) {
|
||||
val = new ValueNode(val);
|
||||
}
|
||||
_ref2 = val.cacheReference(o), left = _ref2[0], rite = _ref2[1];
|
||||
rite = new CallNode(rite, this.args);
|
||||
} else {
|
||||
_ref2 = this.variable.compileReference(o, {
|
||||
precompile: true
|
||||
}), this.first = _ref2[0], this.meth = _ref2[1];
|
||||
left = literal(this.superReference(o));
|
||||
rite = new CallNode(new ValueNode(left), this.args);
|
||||
rite.isNew = this.isNew;
|
||||
}
|
||||
this.first = ("(typeof " + (this.first) + " === \"function\" ? ");
|
||||
this.last = " : undefined)";
|
||||
} else if (this.variable) {
|
||||
this.meth = this.variable.compile(o);
|
||||
left = ("typeof " + (left.compile(o)) + " !== \"function\"");
|
||||
rite = rite.compile(o);
|
||||
return ("(" + (left) + " ? undefined : " + (rite) + ")");
|
||||
}
|
||||
_ref2 = this.args;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
arg = _ref2[_i];
|
||||
if (arg instanceof SplatNode) {
|
||||
code = this.compileSplat(o);
|
||||
return this.compileSplat(o);
|
||||
}
|
||||
}
|
||||
if (!code) {
|
||||
args = (function() {
|
||||
_result = []; _ref2 = this.args;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
arg = _ref2[_i];
|
||||
_result.push((function() {
|
||||
arg.parenthetical = true;
|
||||
return arg.compile(o);
|
||||
})());
|
||||
}
|
||||
return _result;
|
||||
}).call(this);
|
||||
code = this.isSuper ? this.compileSuper(args.join(', '), o) : ("" + (this.first) + (this.prefix()) + (this.meth) + "(" + (args.join(', ')) + ")" + (this.last));
|
||||
}
|
||||
return op && this.variable && this.variable.wrapped ? ("(" + (code) + ")") : code;
|
||||
args = (function() {
|
||||
_result = []; _ref2 = this.args;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
arg = _ref2[_i];
|
||||
_result.push((arg.parenthetical = true) && arg.compile(o));
|
||||
}
|
||||
return _result;
|
||||
}).call(this).join(', ');
|
||||
return this.isSuper ? this.compileSuper(args, o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + (args) + ")");
|
||||
};
|
||||
CallNode.prototype.compileSuper = function(args, o) {
|
||||
return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + (args) + ")";
|
||||
};
|
||||
CallNode.prototype.compileSplat = function(o) {
|
||||
var _i, _len, _ref2, a, b, c, mentionsArgs, meth, obj, temp;
|
||||
meth = this.meth || this.superReference(o);
|
||||
obj = this.variable && this.variable.source || 'this';
|
||||
if (!(IDENTIFIER.test(obj) || NUMBER.test(obj))) {
|
||||
temp = o.scope.freeVariable('ref');
|
||||
obj = temp;
|
||||
meth = ("(" + (temp) + " = " + (this.variable.source) + ")" + (this.variable.last));
|
||||
var _i, _len, _ref2, a, arg, argvar, b, base, c, call, fun, idt, name, ref, splatargs;
|
||||
splatargs = this.compileSplatArguments(o);
|
||||
if (this.isSuper) {
|
||||
return ("" + (this.superReference(o)) + ".apply(this, " + (splatargs) + ")");
|
||||
}
|
||||
if (this.isNew) {
|
||||
mentionsArgs = false;
|
||||
_ref2 = this.args;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
(function() {
|
||||
var arg = _ref2[_i];
|
||||
return arg.contains(function(n) {
|
||||
return mentionsArgs || (mentionsArgs = (n instanceof LiteralNode && (n.value === 'arguments')));
|
||||
});
|
||||
})();
|
||||
if (!(this.isNew)) {
|
||||
if (!((base = this.variable) instanceof ValueNode)) {
|
||||
base = new ValueNode(base);
|
||||
}
|
||||
utility('extends');
|
||||
a = o.scope.freeVariable('ctor');
|
||||
b = o.scope.freeVariable('ref');
|
||||
c = o.scope.freeVariable('result');
|
||||
return "" + (this.first) + "(function() {\n" + (this.idt(1)) + "var ctor = function(){};\n" + (this.idt(1)) + "__extends(ctor, " + (a) + " = " + (meth) + ");\n" + (this.idt(1)) + "return typeof (" + (c) + " = " + (a) + ".apply(" + (b) + " = new ctor, " + (this.compileSplatArguments(o)) + ")) === \"object\" ? " + (c) + " : " + (b) + ";\n" + (this.tab) + "})." + (mentionsArgs ? 'apply(this, arguments)' : 'call(this)') + (this.last);
|
||||
} else {
|
||||
return "" + (this.first) + (meth) + ".apply(" + (obj) + ", " + (this.compileSplatArguments(o)) + ")" + (this.last);
|
||||
if ((name = base.properties.pop()) && base.isComplex()) {
|
||||
ref = o.scope.freeVariable('this');
|
||||
fun = ("(" + (ref) + " = " + (base.compile(o)) + ")" + (name.compile(o)));
|
||||
} else {
|
||||
fun = (ref = base.compile(o));
|
||||
if (name) {
|
||||
fun += name.compile(o);
|
||||
}
|
||||
}
|
||||
return ("" + (fun) + ".apply(" + (ref) + ", " + (splatargs) + ")");
|
||||
}
|
||||
call = 'call(this)';
|
||||
argvar = function(n) {
|
||||
return n instanceof LiteralNode && n.value === 'arguments';
|
||||
};
|
||||
_ref2 = this.args;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
arg = _ref2[_i];
|
||||
if (arg.contains(argvar)) {
|
||||
call = 'apply(this, arguments)';
|
||||
break;
|
||||
}
|
||||
}
|
||||
a = o.scope.freeVariable('ctor');
|
||||
b = o.scope.freeVariable('ref');
|
||||
c = o.scope.freeVariable('result');
|
||||
return "(function() {\n" + (idt = this.idt(1)) + "var ctor = function() {};\n" + (idt) + (utility('extends')) + "(ctor, " + (a) + " = " + (this.variable.compile(o)) + ");\n" + (idt) + "return typeof (" + (c) + " = " + (a) + ".apply(" + (b) + " = new ctor, " + (splatargs) + ")) === \"object\" ? " + (c) + " : " + (b) + ";\n" + (this.tab) + "})." + (call);
|
||||
};
|
||||
return CallNode;
|
||||
})();
|
||||
@@ -576,9 +628,9 @@
|
||||
AccessorNode.prototype["class"] = 'AccessorNode';
|
||||
AccessorNode.prototype.children = ['name'];
|
||||
AccessorNode.prototype.compileNode = function(o) {
|
||||
var name, namePart;
|
||||
var _base, name, namePart;
|
||||
name = this.name.compile(o);
|
||||
o.chainRoot.wrapped || (o.chainRoot.wrapped = this.soakNode);
|
||||
(_base = o.chainRoot).wrapped || (_base.wrapped = this.soakNode);
|
||||
namePart = name.match(IS_STRING) ? ("[" + (name) + "]") : ("." + (name));
|
||||
return this.prototype + namePart;
|
||||
};
|
||||
@@ -595,8 +647,8 @@
|
||||
IndexNode.prototype["class"] = 'IndexNode';
|
||||
IndexNode.prototype.children = ['index'];
|
||||
IndexNode.prototype.compileNode = function(o) {
|
||||
var idx, prefix;
|
||||
o.chainRoot.wrapped || (o.chainRoot.wrapped = this.soakNode);
|
||||
var _base, idx, prefix;
|
||||
(_base = o.chainRoot).wrapped || (_base.wrapped = this.soakNode);
|
||||
idx = this.index.compile(o);
|
||||
prefix = this.proto ? '.prototype' : '';
|
||||
return "" + (prefix) + "[" + (idx) + "]";
|
||||
@@ -774,14 +826,14 @@
|
||||
this.objects = _arg;
|
||||
ArrayNode.__super__.constructor.call(this);
|
||||
this.objects || (this.objects = []);
|
||||
this.compileSplatLiteral = function(o) {
|
||||
return SplatNode.compileSplattedArray.call(this, this.objects, o);
|
||||
};
|
||||
return this;
|
||||
};
|
||||
__extends(ArrayNode, BaseNode);
|
||||
ArrayNode.prototype["class"] = 'ArrayNode';
|
||||
ArrayNode.prototype.children = ['objects'];
|
||||
ArrayNode.prototype.compileSplatLiteral = function(o) {
|
||||
return SplatNode.compileSplattedArray(this.objects, o);
|
||||
};
|
||||
ArrayNode.prototype.compileNode = function(o) {
|
||||
var _len, _ref2, code, i, obj, objects;
|
||||
o.indent = this.idt(1);
|
||||
@@ -898,8 +950,7 @@
|
||||
return this;
|
||||
};
|
||||
__extends(AssignNode, BaseNode);
|
||||
AssignNode.prototype.PROTO_ASSIGN = /^(\S+)\.prototype/;
|
||||
AssignNode.prototype.LEADING_DOT = /^\.(?:prototype\.)?/;
|
||||
AssignNode.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/;
|
||||
AssignNode.prototype["class"] = 'AssignNode';
|
||||
AssignNode.prototype.children = ['variable', 'value'];
|
||||
AssignNode.prototype.topSensitive = YES;
|
||||
@@ -907,7 +958,7 @@
|
||||
return this.variable instanceof ValueNode;
|
||||
};
|
||||
AssignNode.prototype.compileNode = function(o) {
|
||||
var end, isValue, match, name, proto, stmt, top, val;
|
||||
var isValue, match, name, node, stmt, top, val;
|
||||
if (isValue = this.isValue()) {
|
||||
if (this.variable.isArray() || this.variable.isObject()) {
|
||||
return this.compilePatternMatch(o);
|
||||
@@ -915,20 +966,16 @@
|
||||
if (this.variable.isSplice()) {
|
||||
return this.compileSplice(o);
|
||||
}
|
||||
if (node = ValueNode.unfoldSoak(o, this, 'variable')) {
|
||||
return node.compile(o);
|
||||
}
|
||||
}
|
||||
top = del(o, 'top');
|
||||
stmt = del(o, 'asStatement');
|
||||
name = this.variable.compile(o);
|
||||
end = isValue ? this.variable.last.replace(this.LEADING_DOT, '') : name;
|
||||
match = name.match(this.PROTO_ASSIGN);
|
||||
proto = match && match[1];
|
||||
if (this.value instanceof CodeNode) {
|
||||
if (IDENTIFIER.test(end)) {
|
||||
this.value.name = end;
|
||||
}
|
||||
if (proto) {
|
||||
this.value.proto = proto;
|
||||
}
|
||||
if (this.value instanceof CodeNode && (match = this.METHOD_DEF.exec(name))) {
|
||||
this.value.name = match[2];
|
||||
this.value.klass = match[1];
|
||||
}
|
||||
val = this.value.compile(o);
|
||||
if (this.context === 'object') {
|
||||
@@ -1005,17 +1052,15 @@
|
||||
return top || this.parenthetical ? code : ("(" + (code) + ")");
|
||||
};
|
||||
AssignNode.prototype.compileSplice = function(o) {
|
||||
var from, l, name, plus, range, to, val;
|
||||
name = this.variable.compile(merge(o, {
|
||||
onlyFirst: true
|
||||
}));
|
||||
l = this.variable.properties.length;
|
||||
range = this.variable.properties[l - 1].range;
|
||||
var from, name, plus, range, ref, to, val;
|
||||
range = this.variable.properties.pop().range;
|
||||
name = this.variable.compile(o);
|
||||
plus = range.exclusive ? '' : ' + 1';
|
||||
from = range.from ? range.from.compile(o) : '0';
|
||||
to = range.to ? range.to.compile(o) + ' - ' + from + plus : ("" + (name) + ".length");
|
||||
ref = o.scope.freeVariable('ref');
|
||||
val = this.value.compile(o);
|
||||
return "[].splice.apply(" + (name) + ", [" + (from) + ", " + (to) + "].concat(" + (val) + "))";
|
||||
return "([].splice.apply(" + (name) + ", [" + (from) + ", " + (to) + "].concat(" + (ref) + " = " + (val) + ")), " + (ref) + ")";
|
||||
};
|
||||
return AssignNode;
|
||||
})();
|
||||
@@ -1025,7 +1070,7 @@
|
||||
this.params = _arg;
|
||||
CodeNode.__super__.constructor.call(this);
|
||||
this.params || (this.params = []);
|
||||
this.body || (this.body = (new Expressions));
|
||||
this.body || (this.body = new Expressions);
|
||||
this.bound = tag === 'boundfunc';
|
||||
if (this.bound) {
|
||||
this.context = 'this';
|
||||
@@ -1143,8 +1188,7 @@
|
||||
SplatNode.prototype["class"] = 'SplatNode';
|
||||
SplatNode.prototype.children = ['name'];
|
||||
SplatNode.prototype.compileNode = function(o) {
|
||||
var _ref2;
|
||||
return (typeof (_ref2 = this.index) !== "undefined" && _ref2 !== null) ? this.compileParam(o) : this.name.compile(o);
|
||||
return (this.index != null) ? this.compileParam(o) : this.name.compile(o);
|
||||
};
|
||||
SplatNode.prototype.compileParam = function(o) {
|
||||
var _len, _ref2, assign, end, idx, len, name, pos, trailing, variadic;
|
||||
@@ -1205,14 +1249,14 @@
|
||||
exports.WhileNode = (function() {
|
||||
WhileNode = function(condition, opts) {
|
||||
WhileNode.__super__.constructor.call(this);
|
||||
if (opts == null ? undefined : opts.invert) {
|
||||
if (((opts != null) ? opts.invert : null)) {
|
||||
if (condition instanceof OpNode) {
|
||||
condition = new ParentheticalNode(condition);
|
||||
}
|
||||
condition = new OpNode('!', condition);
|
||||
}
|
||||
this.condition = condition;
|
||||
this.guard = opts == null ? undefined : opts.guard;
|
||||
this.guard = ((opts != null) ? opts.guard : null);
|
||||
return this;
|
||||
};
|
||||
__extends(WhileNode, BaseNode);
|
||||
@@ -1315,6 +1359,10 @@
|
||||
return OpNode.__super__.toString.call(this, idt, this["class"] + ' ' + this.operator);
|
||||
};
|
||||
OpNode.prototype.compileNode = function(o) {
|
||||
var node;
|
||||
if (node = ValueNode.unfoldSoak(o, this, 'first')) {
|
||||
return node.compile(o);
|
||||
}
|
||||
if (this.isChainable() && this.first.unwrap() instanceof OpNode && this.first.unwrap().isChainable()) {
|
||||
return this.compileChain(o);
|
||||
}
|
||||
@@ -1343,7 +1391,10 @@
|
||||
return "(" + (first) + ") && (" + (shared) + " " + (this.operator) + " " + (second) + ")";
|
||||
};
|
||||
OpNode.prototype.compileAssignment = function(o) {
|
||||
var _ref2, first, firstVar, second;
|
||||
var _ref2, first, firstVar, left, rite, second;
|
||||
_ref2 = this.first.cacheReference(o), left = _ref2[0], rite = _ref2[1];
|
||||
rite = new AssignNode(rite, this.second);
|
||||
return new OpNode(this.operator.slice(0, -1), left, rite).compile(o);
|
||||
_ref2 = this.first.compileReference(o, {
|
||||
precompile: true,
|
||||
assignment: true
|
||||
@@ -1361,9 +1412,15 @@
|
||||
return "" + (first) + " " + (this.operator.substr(0, 2)) + " (" + (firstVar) + " = " + (second) + ")";
|
||||
};
|
||||
OpNode.prototype.compileExistence = function(o) {
|
||||
var _ref2, ref, test;
|
||||
_ref2 = ExistenceNode.compileTest(o, this.first), test = _ref2[0], ref = _ref2[1];
|
||||
return "" + (test) + " ? " + (ref) + " : " + (this.second.compile(o));
|
||||
var fst, ref;
|
||||
if (this.first.isComplex()) {
|
||||
ref = o.scope.freeVariable('ref');
|
||||
fst = new ParentheticalNode(new AssignNode(literal(ref), this.first));
|
||||
} else {
|
||||
fst = this.first;
|
||||
ref = fst.compile(o);
|
||||
}
|
||||
return new ExistenceNode(fst).compile(o) + (" ? " + (ref) + " : " + (this.second.compile(o)));
|
||||
};
|
||||
OpNode.prototype.compileUnary = function(o) {
|
||||
var parts, space;
|
||||
@@ -1479,20 +1536,13 @@
|
||||
ExistenceNode.prototype["class"] = 'ExistenceNode';
|
||||
ExistenceNode.prototype.children = ['expression'];
|
||||
ExistenceNode.prototype.compileNode = function(o) {
|
||||
var test;
|
||||
test = ExistenceNode.compileTest(o, this.expression)[0];
|
||||
return this.parenthetical ? test.slice(1, -1) : test;
|
||||
};
|
||||
ExistenceNode.compileTest = function(o, variable) {
|
||||
var _ref2, first, second;
|
||||
_ref2 = variable.compileReference(o, {
|
||||
precompile: true
|
||||
}), first = _ref2[0], second = _ref2[1];
|
||||
first = first === second && o.scope.check(first) ? ("(" + (first) + " != null)") : ("(typeof " + (first) + " !== \"undefined\" && " + (second) + " !== null)");
|
||||
return [first, second];
|
||||
var code;
|
||||
code = this.expression.compile(o);
|
||||
code = IDENTIFIER.test(code) && !o.scope.check(code) ? ("typeof " + (code) + " !== \"undefined\" && " + (code) + " !== null") : ("" + (code) + " != null");
|
||||
return this.parenthetical ? code : ("(" + (code) + ")");
|
||||
};
|
||||
return ExistenceNode;
|
||||
}).call(this);
|
||||
})();
|
||||
exports.ParentheticalNode = (function() {
|
||||
ParentheticalNode = function(_arg) {
|
||||
this.expression = _arg;
|
||||
@@ -1742,10 +1792,12 @@
|
||||
IfNode.prototype.children = ['condition', 'body', 'elseBody', 'assigner'];
|
||||
IfNode.prototype.topSensitive = YES;
|
||||
IfNode.prototype.bodyNode = function() {
|
||||
return this.body == null ? undefined : this.body.unwrap();
|
||||
var _ref2;
|
||||
return (((_ref2 = this.body) != null) ? _ref2.unwrap() : null);
|
||||
};
|
||||
IfNode.prototype.elseBodyNode = function() {
|
||||
return this.elseBody == null ? undefined : this.elseBody.unwrap();
|
||||
var _ref2;
|
||||
return (((_ref2 = this.elseBody) != null) ? _ref2.unwrap() : null);
|
||||
};
|
||||
IfNode.prototype.addElse = function(elseBody, statement) {
|
||||
if (this.isChain) {
|
||||
@@ -1757,7 +1809,7 @@
|
||||
return this;
|
||||
};
|
||||
IfNode.prototype.isStatement = function(o) {
|
||||
return this.statement || (this.statement = (!!((o && o.top) || this.bodyNode().isStatement(o) || (this.elseBody && this.elseBodyNode().isStatement(o)))));
|
||||
return this.statement || (this.statement = !!((o && o.top) || this.bodyNode().isStatement(o) || (this.elseBody && this.elseBodyNode().isStatement(o))));
|
||||
};
|
||||
IfNode.prototype.compileCondition = function(o) {
|
||||
var _i, _len, _ref2, _result, cond, conditions;
|
||||
|
||||
Reference in New Issue
Block a user