Fixing for magic scoping issues. Small steps at a time.

This commit is contained in:
Timothy Jones
2010-10-20 02:51:52 +13:00
parent c8b9c5a54e
commit cb6be74851
12 changed files with 111 additions and 86 deletions

View File

@@ -37,10 +37,13 @@
};
Base.prototype.compileClosure = function(o) {
o.sharedScope = o.scope;
return Closure.wrap(this, false, true).compile(o);
if (this.containsPureStatement()) {
throw new Error('cannot include a pure statement in an expression.');
}
return Closure.wrap(this).compile(o);
};
Base.prototype.compileReference = function(o, options) {
var _len, compiled, i, node, pair, reference;
var _i, _len, compiled, i, node, pair, reference;
pair = (function() {
if (!this.isComplex()) {
return [this, this];
@@ -95,7 +98,7 @@
return this.traverseChildren(true, block);
};
Base.prototype.toString = function(idt, override) {
var _i, _len, _ref2, _result, child, children, klass;
var _i, _j, _len, _ref2, _result, child, children, klass;
idt || (idt = '');
children = (function() {
_result = [];
@@ -109,7 +112,7 @@
return '\n' + idt + klass + children;
};
Base.prototype.eachChild = function(func) {
var _i, _j, _len, _len2, _ref2, _ref3, _result, attr, child;
var _i, _j, _k, _l, _len, _len2, _ref2, _ref3, _result, attr, child;
if (!this.children) {
return;
}
@@ -117,8 +120,8 @@
for (_i = 0, _len = (_ref2 = this.children).length; _i < _len; _i++) {
attr = _ref2[_i];
if (this[attr]) {
for (_j = 0, _len2 = (_ref3 = flatten([this[attr]])).length; _j < _len2; _j++) {
child = _ref3[_j];
for (_k = 0, _len2 = (_ref3 = flatten([this[attr]])).length; _k < _len2; _k++) {
child = _ref3[_k];
if (func(child) === false) {
return;
}
@@ -198,7 +201,7 @@
return o.scope ? Expressions.__super__.compile.call(this, o) : this.compileRoot(o);
};
Expressions.prototype.compileNode = function(o) {
var _i, _len, _ref2, _result, node;
var _i, _j, _len, _ref2, _result, node;
return (function() {
_result = [];
for (_i = 0, _len = (_ref2 = this.expressions).length; _i < _len; _i++) {
@@ -392,7 +395,7 @@
return !o.top || this.properties.length ? Value.__super__.compile.call(this, o) : this.base.compile(o);
};
Value.prototype.compileNode = function(o) {
var _i, _len, code, ifn, prop, props;
var _i, _j, _len, code, ifn, prop, props;
if (ifn = this.unfoldSoak(o)) {
return ifn.compile(o);
}
@@ -411,7 +414,7 @@
return code;
};
Value.prototype.unfoldSoak = function(o) {
var _len, _ref2, fst, i, ifn, prop, ref, snd;
var _i, _len, _ref2, fst, i, ifn, prop, ref, snd;
if (ifn = this.base.unfoldSoak(o)) {
Array.prototype.push.apply(ifn.body.properties, this.properties);
return ifn;
@@ -493,7 +496,7 @@
return method.klass ? ("" + (method.klass) + ".__super__." + name) : ("" + name + ".__super__.constructor");
};
Call.prototype.unfoldSoak = function(o) {
var _i, _len, _ref2, _ref3, call, ifn, left, list, rite, val;
var _i, _j, _len, _ref2, _ref3, call, ifn, left, list, rite, val;
if (this.soakNode) {
if (val = this.variable) {
if (!(val instanceof Value)) {
@@ -542,7 +545,7 @@
return ifn;
};
Call.prototype.compileNode = function(o) {
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _result, arg, args, ifn;
var _i, _j, _k, _l, _len, _len2, _ref2, _ref3, _ref4, _result, arg, args, ifn;
if (ifn = this.unfoldSoak(o)) {
return ifn.compile(o);
}
@@ -555,8 +558,8 @@
}
args = (function() {
_result = [];
for (_j = 0, _len2 = (_ref4 = this.args).length; _j < _len2; _j++) {
arg = _ref4[_j];
for (_k = 0, _len2 = (_ref4 = this.args).length; _k < _len2; _k++) {
arg = _ref4[_k];
_result.push((arg.parenthetical = true) && arg.compile(o));
}
return _result;
@@ -778,7 +781,7 @@
__extends(ObjectLiteral, Base);
ObjectLiteral.prototype.children = ['properties'];
ObjectLiteral.prototype.compileNode = function(o) {
var _i, _len, _ref2, _result, i, indent, join, lastNoncom, nonComments, obj, prop, props, top;
var _i, _j, _len, _ref2, _result, i, indent, join, lastNoncom, nonComments, obj, prop, props, top;
top = del(o, 'top');
o.indent = this.idt(1);
nonComments = (function() {
@@ -814,7 +817,7 @@
return this.tags.front ? ("(" + obj + ")") : obj;
};
ObjectLiteral.prototype.assigns = function(name) {
var _i, _len, _ref2, prop;
var _i, _j, _len, _ref2, prop;
for (_i = 0, _len = (_ref2 = this.properties).length; _i < _len; _i++) {
prop = _ref2[_i];
if (prop.assigns(name)) {
@@ -841,7 +844,7 @@
return Splat.compileSplattedArray(this.objects, o);
};
ArrayLiteral.prototype.compileNode = function(o) {
var _i, _len, _len2, _ref2, _ref3, code, i, obj, objects;
var _i, _j, _k, _len, _len2, _ref2, _ref3, code, i, obj, objects;
o.indent = this.idt(1);
for (_i = 0, _len = (_ref2 = this.objects).length; _i < _len; _i++) {
obj = _ref2[_i];
@@ -859,7 +862,7 @@
return 0 < objects.indexOf('\n') ? ("[\n" + (o.indent) + objects + "\n" + (this.tab) + "]") : ("[" + objects + "]");
};
ArrayLiteral.prototype.assigns = function(name) {
var _i, _len, _ref2, obj;
var _i, _j, _len, _ref2, obj;
for (_i = 0, _len = (_ref2 = this.objects).length; _i < _len; _i++) {
obj = _ref2[_i];
if (obj.assigns(name)) {
@@ -891,7 +894,7 @@
return this;
};
Class.prototype.compileNode = function(o) {
var _i, _len, _ref2, _ref3, _ref4, access, applied, apply, className, constScope, construct, constructor, extension, func, me, pname, prop, props, pvar, ref, returns, val, variable;
var _i, _j, _len, _ref2, _ref3, _ref4, access, applied, apply, className, constScope, construct, constructor, extension, func, me, pname, prop, props, pvar, ref, returns, val, variable;
variable = this.variable;
if (variable.value === '__temp__') {
variable = new Literal(o.scope.freeVariable('ctor'));
@@ -1021,7 +1024,7 @@
return top || this.parenthetical ? val : ("(" + val + ")");
};
Assign.prototype.compilePatternMatch = function(o) {
var _len, _ref2, _ref3, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, otop, ref, splat, top, val, valVar, value;
var _i, _len, _ref2, _ref3, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, otop, ref, splat, top, val, valVar, value;
if ((value = this.value).isStatement(o)) {
value = Closure.wrap(value);
}
@@ -1120,7 +1123,7 @@
__extends(Code, Base);
Code.prototype.children = ['params', 'body'];
Code.prototype.compileNode = function(o) {
var _i, _len, _len2, _ref2, _ref3, _result, close, code, comm, empty, func, i, open, param, params, sharedScope, splat, top, value;
var _i, _j, _k, _len, _len2, _ref2, _ref3, _result, close, code, comm, 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);
@@ -1159,8 +1162,8 @@
o.scope.startLevel();
params = (function() {
_result = [];
for (_i = 0, _len2 = params.length; _i < _len2; _i++) {
param = params[_i];
for (_j = 0, _len2 = params.length; _j < _len2; _j++) {
param = params[_j];
_result.push(param.compile(o));
}
return _result;
@@ -1168,8 +1171,8 @@
if (!empty) {
this.body.makeReturn();
}
for (_i = 0, _len2 = params.length; _i < _len2; _i++) {
param = params[_i];
for (_j = 0, _len2 = params.length; _j < _len2; _j++) {
param = params[_j];
(o.scope.parameter(param));
}
comm = this.comment ? this.comment.compile(o) + '\n' : '';
@@ -1239,7 +1242,7 @@
return (this.index != null) ? this.compileParam(o) : this.name.compile(o);
};
Splat.prototype.compileParam = function(o) {
var _len, _ref2, assign, end, idx, len, name, pos, trailing, variadic;
var _i, _len, _ref2, assign, end, idx, len, name, pos, trailing, variadic;
name = this.name.compile(o);
o.scope.find(name);
end = '';
@@ -1268,7 +1271,7 @@
return "" + (utility('slice')) + ".call(" + name + ", " + index + trail + ")";
};
Splat.compileSplattedArray = function(list, o) {
var _len, arg, args, code, end, i, prev;
var _i, _len, arg, args, code, end, i, prev;
args = [];
end = -1;
for (i = 0, _len = list.length; i < _len; i++) {
@@ -1482,7 +1485,7 @@
return this.isArray() ? this.compileOrTest(o) : this.compileLoopTest(o);
};
In.prototype.compileOrTest = function(o) {
var _len, _ref2, _result, i, item, tests;
var _i, _len, _ref2, _result, i, item, tests;
tests = (function() {
_result = [];
for (i = 0, _len = (_ref2 = this.array.base.objects).length; i < _len; i++) {
@@ -1654,7 +1657,7 @@
return '';
};
For.prototype.compileNode = function(o) {
var body, codeInBody, forPart, guardPart, idt1, index, ivar, lvar, name, namePart, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars;
var body, codeInBody, forPart, guardPart, idt1, index, ivar, lvar, name, namePart, nvar, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars;
topLevel = del(o, 'top') && !this.returns;
range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length;
source = range ? this.source.base : this.source;
@@ -1681,6 +1684,9 @@
if (!ivar || codeInBody) {
ivar = scope.freeVariable('i');
}
if (name && !range) {
nvar = scope.freeVariable('i');
}
varPart = '';
guardPart = '';
body = Expressions.wrap([this.body]);
@@ -1728,7 +1734,19 @@
if (index) {
body.unshift(new Literal("var " + index + " = " + ivar));
}
if (index) {
body.push(new Assign(new Literal(ivar), new Literal(index)));
}
if (nvar) {
body.push(new Assign(new Literal(nvar), new Literal(name)));
}
body = Closure.wrap(body, true);
if (index) {
body.push(new Assign(new Literal(index), new Literal(ivar)));
}
if (name) {
body.push(new Assign(new Literal(name), new Literal(nvar || ivar)));
}
} else {
if (namePart) {
varPart = ("" + idt1 + namePart + ";\n");
@@ -1766,7 +1784,7 @@
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
Switch.prototype.isStatement = YES;
Switch.prototype.makeReturn = function() {
var _i, _len, _ref2, pair;
var _i, _j, _len, _ref2, pair;
for (_i = 0, _len = (_ref2 = this.cases).length; _i < _len; _i++) {
pair = _ref2[_i];
pair[1].makeReturn();
@@ -1777,7 +1795,7 @@
return this;
};
Switch.prototype.compileNode = function(o) {
var _i, _j, _len, _len2, _ref2, _ref3, block, code, condition, conditions, exprs, idt, pair;
var _i, _j, _k, _l, _len, _len2, _ref2, _ref3, block, code, condition, conditions, exprs, idt, pair;
idt = (o.indent = this.idt(2));
o.top = true;
code = ("" + (this.tab) + "switch (" + (this.subject.compile(o)) + ") {");
@@ -1785,8 +1803,8 @@
pair = _ref2[_i];
conditions = pair[0], block = pair[1];
exprs = block.expressions;
for (_j = 0, _len2 = (_ref3 = flatten([conditions])).length; _j < _len2; _j++) {
condition = _ref3[_j];
for (_k = 0, _len2 = (_ref3 = flatten([conditions])).length; _k < _len2; _k++) {
condition = _ref3[_k];
if (this.tags.subjectless) {
condition = new Op('!!', new Parens(condition));
}
@@ -1914,14 +1932,8 @@
}
};
Closure = {
wrap: function(expressions, statement, force) {
wrap: function(expressions, statement) {
var args, call, func, mentionsArgs, meth;
if (expressions.containsPureStatement()) {
if (!force) {
return expressions;
}
throw new Error('cannot include a pure statement in an expression.');
}
if (expressions.containsPureStatement()) {
return expressions;
}