Fixing Issue 730 -- and removing garbage collection of tempvars (which was totally unsafe.)

This commit is contained in:
Jeremy Ashkenas
2010-10-06 20:54:08 -04:00
parent 69b901a5b6
commit 59d6e59f97
7 changed files with 94 additions and 101 deletions

View File

@@ -32,13 +32,7 @@
this.tab = o.indent;
top = this.topSensitive() ? this.options.top : del(this.options, 'top');
closure = this.isStatement(o) && !this.isPureStatement() && !top && !this.options.asStatement && !(this instanceof CommentNode) && !this.containsPureStatement();
if (!o.keepLevel) {
o.scope.startLevel();
}
code = closure ? this.compileClosure(this.options) : this.compileNode(this.options);
if (!o.keepLevel) {
o.scope.endLevel();
}
return code;
};
BaseNode.prototype.compileClosure = function(o) {
@@ -526,7 +520,7 @@
return node;
};
CallNode.prototype.compileNode = function(o) {
var _i, _len, _ref2, _result, arg, args, left, node, rite, val;
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _result, arg, args, left, node, rite, val;
if (node = this.unfoldSoak(o)) {
return node.compile(o);
}
@@ -546,17 +540,17 @@
rite = rite.compile(o);
return ("(" + left + " ? undefined : " + rite + ")");
}
_ref2 = this.args;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
arg = _ref2[_i];
_ref3 = this.args;
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
arg = _ref3[_i];
if (arg instanceof SplatNode) {
return this.compileSplat(o);
}
}
args = (function() {
_result = []; _ref2 = this.args;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
arg = _ref2[_i];
_result = []; _ref4 = this.args;
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
arg = _ref4[_j];
_result.push((arg.parenthetical = true) && arg.compile(o));
}
return _result;
@@ -680,17 +674,17 @@
__extends(RangeNode, BaseNode);
RangeNode.prototype.children = ['from', 'to'];
RangeNode.prototype.compileVariables = function(o) {
var _ref2, parts;
var _ref2, _ref3, _ref4, parts;
o = merge(o, {
top: true
});
_ref2 = this.from.compileReference(o, {
precompile: true
}), this.from = _ref2[0], this.fromVar = _ref2[1];
_ref2 = this.to.compileReference(o, {
_ref3 = this.to.compileReference(o, {
precompile: true
}), this.to = _ref2[0], this.toVar = _ref2[1];
_ref2 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref2[0], this.toNum = _ref2[1];
}), this.to = _ref3[0], this.toVar = _ref3[1];
_ref4 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref4[0], this.toNum = _ref4[1];
parts = [];
if (this.from !== this.fromVar) {
parts.push(this.from);
@@ -791,7 +785,7 @@
ObjectNode.prototype.children = ['properties'];
ObjectNode.prototype.topSensitive = YES;
ObjectNode.prototype.compileNode = function(o) {
var _i, _len, _ref2, _result, i, indent, join, lastNoncom, nonComments, obj, prop, props, top;
var _i, _len, _len2, _ref2, _ref3, _result, _result2, i, indent, join, lastNoncom, nonComments, obj, prop, props, top;
top = del(o, 'top');
o.indent = this.idt(1);
nonComments = (function() {
@@ -806,10 +800,10 @@
}).call(this);
lastNoncom = last(nonComments);
props = (function() {
_result = []; _ref2 = this.properties;
for (i = 0, _len = _ref2.length; i < _len; i++) {
prop = _ref2[i];
_result.push((function() {
_result2 = []; _ref3 = this.properties;
for (i = 0, _len2 = _ref3.length; i < _len2; i++) {
prop = _ref3[i];
_result2.push((function() {
join = ",\n";
if ((prop === lastNoncom) || (prop instanceof CommentNode)) {
join = "\n";
@@ -826,7 +820,7 @@
return indent + prop.compile(o) + join;
}).call(this));
}
return _result;
return _result2;
}).call(this);
props = props.join('');
obj = '{' + (props ? '\n' + props + '\n' + this.idt() : '') + '}';
@@ -891,7 +885,7 @@
return this;
};
ClassNode.prototype.compileNode = function(o) {
var _i, _len, _ref2, _ref3, access, applied, className, constScope, construct, constructor, extension, func, me, pname, prop, props, pvar, returns, val;
var _i, _len, _ref2, _ref3, _ref4, access, applied, apply, className, constScope, construct, constructor, extension, func, me, pname, prop, props, pvar, ref, returns, val;
if (this.variable === '__temp__') {
this.variable = literal(o.scope.freeVariable('ctor'));
}
@@ -911,7 +905,15 @@
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
prop = _ref2[_i];
_ref3 = [prop.variable, prop.value], pvar = _ref3[0], func = _ref3[1];
if (pvar && pvar.base.value === 'constructor' && func instanceof CodeNode) {
if (pvar && pvar.base.value === 'constructor') {
if (!(func instanceof CodeNode)) {
_ref4 = func.compileReference(o), func = _ref4[0], ref = _ref4[1];
if (func !== ref) {
props.push(func);
}
apply = new CallNode(new ValueNode(ref, [new AccessorNode(literal('apply'))]), [literal('this'), literal('arguments')]);
func = new CodeNode([], new Expressions([apply]));
}
if (func.bound) {
throw new Error("cannot define a constructor as a bound function.");
}
@@ -1008,7 +1010,7 @@
return top || this.parenthetical ? val : ("(" + val + ")");
};
AssignNode.prototype.compilePatternMatch = function(o) {
var _len, _ref2, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, otop, splat, top, val, valVar, value;
var _len, _ref2, _ref3, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, otop, splat, top, val, valVar, value;
if ((value = this.value).isStatement(o)) {
value = ClosureNode.wrap(value);
}
@@ -1042,7 +1044,7 @@
idx = i;
if (isObject) {
if (obj instanceof AssignNode) {
_ref2 = [obj.value, obj.variable.base], obj = _ref2[0], idx = _ref2[1];
_ref3 = [obj.value, obj.variable.base], obj = _ref3[0], idx = _ref3[1];
} else {
idx = obj.tags["this"] ? obj.properties[0].name : obj;
}
@@ -1099,7 +1101,7 @@
__extends(CodeNode, BaseNode);
CodeNode.prototype.children = ['params', 'body'];
CodeNode.prototype.compileNode = function(o) {
var _i, _len, _ref2, _ref3, _result, close, code, empty, func, i, open, param, params, sharedScope, splat, top, value;
var _i, _j, _len, _len2, _len3, _ref2, _ref3, _result, close, code, empty, func, i, open, param, params, sharedScope, splat, top, value;
sharedScope = del(o, 'sharedScope');
top = del(o, 'top');
o.scope = sharedScope || new Scope(o.scope, this.body, this);
@@ -1138,7 +1140,7 @@
}
params = (function() {
_result = [];
for (_i = 0, _len = params.length; _i < _len; _i++) {
for (_i = 0, _len2 = params.length; _i < _len2; _i++) {
param = params[_i];
_result.push(param.compile(o));
}
@@ -1147,8 +1149,8 @@
if (!(empty)) {
this.body.makeReturn();
}
for (_i = 0, _len = params.length; _i < _len; _i++) {
param = params[_i];
for (_j = 0, _len3 = params.length; _j < _len3; _j++) {
param = params[_j];
(o.scope.parameter(param));
}
if (this.className) {
@@ -1410,10 +1412,10 @@
return [this.first.compile(o), this.operator, this.second.compile(o)].join(' ');
};
OpNode.prototype.compileChain = function(o) {
var _ref2, first, second, shared;
var _ref2, _ref3, first, second, shared;
shared = this.first.unwrap().second;
_ref2 = shared.compileReference(o), this.first.second = _ref2[0], shared = _ref2[1];
_ref2 = [this.first.compile(o), this.second.compile(o), shared.compile(o)], first = _ref2[0], second = _ref2[1], shared = _ref2[2];
_ref3 = [this.first.compile(o), this.second.compile(o), shared.compile(o)], first = _ref3[0], second = _ref3[1], shared = _ref3[2];
return "(" + first + ") && (" + shared + " " + (this.operator) + " " + second + ")";
};
OpNode.prototype.compileAssignment = function(o) {
@@ -1478,11 +1480,11 @@
return "(" + (tests.join(' || ')) + ")";
};
InNode.prototype.compileLoopTest = function(o) {
var _ref2, i, l, prefix;
var _ref2, _ref3, i, l, prefix;
_ref2 = this.array.compileReference(o, {
precompile: true
}), this.arr1 = _ref2[0], this.arr2 = _ref2[1];
_ref2 = [o.scope.freeVariable('i'), o.scope.freeVariable('len')], i = _ref2[0], l = _ref2[1];
_ref3 = [o.scope.freeVariable('i'), o.scope.freeVariable('len')], i = _ref3[0], l = _ref3[1];
prefix = this.obj1 !== this.obj2 ? this.obj1 + '; ' : '';
return "(function(){ " + prefix + "for (var " + i + "=0, " + l + "=" + (this.arr1) + ".length; " + i + "<" + l + "; " + i + "++) { if (" + (this.arr2) + "[" + i + "] === " + (this.obj2) + ") return true; } return false; }).call(this)";
};
@@ -1761,7 +1763,7 @@
return this;
};
SwitchNode.prototype.compileNode = function(o) {
var _i, _j, _len, _len2, _ref2, _ref3, block, code, condition, conditions, exprs, idt, pair;
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, block, code, condition, conditions, exprs, idt, pair;
idt = (o.indent = this.idt(2));
o.top = true;
code = ("" + (this.tab) + "switch (" + (this.subject.compile(o)) + ") {");
@@ -1770,9 +1772,9 @@
pair = _ref2[_i];
_ref3 = pair, conditions = _ref3[0], block = _ref3[1];
exprs = block.expressions;
_ref3 = flatten([conditions]);
for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
condition = _ref3[_j];
_ref4 = flatten([conditions]);
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
condition = _ref4[_j];
if (this.tags.subjectless) {
condition = new OpNode('!!', new ParentheticalNode(condition));
}