Making the LEVEL constants a bit more readable.

This commit is contained in:
Jeremy Ashkenas
2010-10-23 10:34:22 -04:00
parent b60afdb619
commit 6058910b49
2 changed files with 120 additions and 117 deletions

View File

@@ -1,5 +1,5 @@
(function() { (function() {
var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, LVL_ACCESS, LVL_COND, LVL_LIST, LVL_OP, LVL_PAREN, LVL_TOP, Literal, NO, NUMBER, ObjectLiteral, Op, Param, Parens, Push, Return, SIMPLENUM, Scope, Splat, Switch, TAB, THIS, TRAILING_WHITESPACE, Throw, Try, UTILITIES, Value, While, YES, _ref, compact, del, ends, extend, flatten, last, merge, multident, starts, utility; var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, LEVEL, Literal, NO, NUMBER, ObjectLiteral, Op, Param, Parens, Push, Return, SIMPLENUM, Scope, Splat, Switch, TAB, THIS, TRAILING_WHITESPACE, Throw, Try, UTILITIES, Value, While, YES, _ref, compact, del, ends, extend, flatten, last, merge, multident, starts, utility;
var __extends = function(child, parent) { var __extends = function(child, parent) {
function ctor() { this.constructor = child; } function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype; ctor.prototype = parent.prototype;
@@ -38,7 +38,7 @@
} }
node = this.unfoldSoak(o) || this; node = this.unfoldSoak(o) || this;
node.tab = o.indent; node.tab = o.indent;
return o.level === LVL_TOP || node.isPureStatement() || !node.isStatement(o) ? node.compileNode(o) : node.compileClosure(o); return o.level === LEVEL.TOP || node.isPureStatement() || !node.isStatement(o) ? node.compileNode(o) : node.compileClosure(o);
}; };
Base.prototype.compileClosure = function(o) { Base.prototype.compileClosure = function(o) {
if (this.containsPureStatement()) { if (this.containsPureStatement()) {
@@ -60,7 +60,7 @@
}; };
Base.prototype.compileLoopReference = function(o, name) { Base.prototype.compileLoopReference = function(o, name) {
var src, tmp; var src, tmp;
src = tmp = this.compile(o, LVL_LIST); src = tmp = this.compile(o, LEVEL.LIST);
if (!(NUMBER.test(src) || IDENTIFIER.test(src) && o.scope.check(src, { if (!(NUMBER.test(src) || IDENTIFIER.test(src) && o.scope.check(src, {
immediate: true immediate: true
}))) { }))) {
@@ -218,7 +218,7 @@
var code; var code;
o.indent = this.tab = o.bare ? '' : TAB; o.indent = this.tab = o.bare ? '' : TAB;
o.scope = new Scope(null, this, null); o.scope = new Scope(null, this, null);
o.level = LVL_TOP; o.level = LEVEL.TOP;
code = this.compileWithDeclarations(o); code = this.compileWithDeclarations(o);
code = code.replace(TRAILING_WHITESPACE, ''); code = code.replace(TRAILING_WHITESPACE, '');
return o.bare ? code : "(function() {\n" + code + "\n}).call(this);\n"; return o.bare ? code : "(function() {\n" + code + "\n}).call(this);\n";
@@ -242,7 +242,7 @@
} }
node = node.unfoldSoak(o) || node; node = node.unfoldSoak(o) || node;
node.tags.front = true; node.tags.front = true;
o.level = LVL_TOP; o.level = LEVEL.TOP;
code = node.compile(o); code = node.compile(o);
return node.isStatement(o) ? code : this.tab + code + ';'; return node.isStatement(o) ? code : this.tab + code + ';';
}; };
@@ -303,7 +303,7 @@
return expr && !(expr instanceof Return) ? expr.compile(o, lvl) : Return.__super__.compile.call(this, o, lvl); return expr && !(expr instanceof Return) ? expr.compile(o, lvl) : Return.__super__.compile.call(this, o, lvl);
}; };
Return.prototype.compileNode = function(o) { Return.prototype.compileNode = function(o) {
o.level = LVL_PAREN; o.level = LEVEL.PAREN;
return this.tab + ("return" + (this.expression ? ' ' + this.expression.compile(o) : '') + ";"); return this.tab + ("return" + (this.expression ? ' ' + this.expression.compile(o) : '') + ";");
}; };
return Return; return Return;
@@ -390,7 +390,7 @@
var _i, _len, code, prop, props; var _i, _len, code, prop, props;
this.base.tags.front = this.tags.front; this.base.tags.front = this.tags.front;
props = this.properties; props = this.properties;
code = this.base.compile(o, props.length ? LVL_ACCESS : null); code = this.base.compile(o, props.length ? LEVEL.ACCESS : null);
if (props[0] instanceof Accessor && this.isSimpleNumber()) { if (props[0] instanceof Accessor && this.isSimpleNumber()) {
code = "(" + code + ")"; code = "(" + code + ")";
} }
@@ -548,11 +548,11 @@
_result = []; _result = [];
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) { for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
arg = _ref4[_j]; arg = _ref4[_j];
_result.push(arg.compile(o, LVL_LIST)); _result.push(arg.compile(o, LEVEL.LIST));
} }
return _result; return _result;
}).call(this)).join(', '); }).call(this)).join(', ');
return this.isSuper ? this.compileSuper(args, o) : (this.isNew ? 'new ' : '') + this.variable.compile(o, LVL_ACCESS) + ("(" + args + ")"); return this.isSuper ? this.compileSuper(args, o) : (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL.ACCESS) + ("(" + args + ")");
}; };
Call.prototype.compileSuper = function(args, o) { Call.prototype.compileSuper = function(args, o) {
return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")"; return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")";
@@ -567,9 +567,9 @@
base = Value.wrap(this.variable); base = Value.wrap(this.variable);
if ((name = base.properties.pop()) && base.isComplex()) { if ((name = base.properties.pop()) && base.isComplex()) {
ref = o.scope.freeVariable('this'); ref = o.scope.freeVariable('this');
fun = "(" + ref + " = " + (base.compile(o, LVL_LIST)) + ")" + (name.compile(o)); fun = "(" + ref + " = " + (base.compile(o, LEVEL.LIST)) + ")" + (name.compile(o));
} else { } else {
fun = ref = base.compile(o, LVL_ACCESS); fun = ref = base.compile(o, LEVEL.ACCESS);
if (name) { if (name) {
fun += name.compile(o); fun += name.compile(o);
} }
@@ -577,7 +577,7 @@
return "" + fun + ".apply(" + ref + ", " + splatargs + ")"; return "" + fun + ".apply(" + ref + ", " + splatargs + ")";
} }
idt = this.idt(1); idt = this.idt(1);
return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LVL_LIST)) + ", " + splatargs + ", function() {})"; return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL.LIST)) + ", " + splatargs + ", function() {})";
}; };
return Call; return Call;
})(); })();
@@ -631,7 +631,7 @@
__extends(Index, Base); __extends(Index, Base);
Index.prototype.children = ['index']; Index.prototype.children = ['index'];
Index.prototype.compile = function(o) { Index.prototype.compile = function(o) {
return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LVL_PAREN)) + "]"); return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LEVEL.PAREN)) + "]");
}; };
Index.prototype.isComplex = function() { Index.prototype.isComplex = function() {
return this.index.isComplex(); return this.index.isComplex();
@@ -727,7 +727,7 @@
_ref3 = this.objects; _ref3 = this.objects;
for (i = 0, _len2 = _ref3.length; i < _len2; i++) { for (i = 0, _len2 = _ref3.length; i < _len2; i++) {
obj = _ref3[i]; obj = _ref3[i];
code = obj.compile(o, LVL_LIST); code = obj.compile(o, LEVEL.LIST);
objects.push((obj instanceof Comment ? "\n" + code + "\n" + o.indent : i === this.objects.length - 1 ? code : code + ', ')); objects.push((obj instanceof Comment ? "\n" + code + "\n" + o.indent : i === this.objects.length - 1 ? code : code + ', '));
} }
objects = objects.join(''); objects = objects.join('');
@@ -879,12 +879,12 @@
return this.compileConditional(o); return this.compileConditional(o);
} }
} }
name = this.variable.compile(o, LVL_LIST); name = this.variable.compile(o, LEVEL.LIST);
if (this.value instanceof Code && (match = this.METHOD_DEF.exec(name))) { if (this.value instanceof Code && (match = this.METHOD_DEF.exec(name))) {
this.value.name = match[2]; this.value.name = match[2];
this.value.klass = match[1]; this.value.klass = match[1];
} }
val = this.value.compile(o, LVL_LIST); val = this.value.compile(o, LEVEL.LIST);
if (this.context === 'object') { if (this.context === 'object') {
return "" + name + ": " + val; return "" + name + ": " + val;
} }
@@ -892,11 +892,11 @@
o.scope.find(name); o.scope.find(name);
} }
val = name + (" " + (this.context || '=') + " ") + val; val = name + (" " + (this.context || '=') + " ") + val;
return o.level <= LVL_LIST ? val : "(" + val + ")"; return o.level <= LEVEL.LIST ? val : "(" + val + ")";
}; };
Assign.prototype.compilePatternMatch = function(o) { Assign.prototype.compilePatternMatch = function(o) {
var _len, _ref2, _ref3, _ref4, _ref5, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, ref, splat, top, val, valVar, value; var _len, _ref2, _ref3, _ref4, _ref5, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, ref, splat, top, val, valVar, value;
top = o.level === LVL_TOP; top = o.level === LEVEL.TOP;
value = this.value; value = this.value;
objects = this.variable.base.objects; objects = this.variable.base.objects;
if (!(olength = objects.length)) { if (!(olength = objects.length)) {
@@ -913,7 +913,7 @@
(value = Value.wrap(value)).properties.push(new accessClass(idx)); (value = Value.wrap(value)).properties.push(new accessClass(idx));
return new Assign(obj, value).compile(o); return new Assign(obj, value).compile(o);
} }
valVar = value.compile(o, LVL_LIST); valVar = value.compile(o, LEVEL.LIST);
assigns = []; assigns = [];
splat = false; splat = false;
if (!IDENTIFIER.test(valVar) || this.variable.assigns(valVar)) { if (!IDENTIFIER.test(valVar) || this.variable.assigns(valVar)) {
@@ -943,13 +943,13 @@
} }
val = new Value(new Literal(valVar), [new accessClass(idx)]); val = new Value(new Literal(valVar), [new accessClass(idx)]);
} }
assigns.push(new Assign(obj, val).compile(o, LVL_LIST)); assigns.push(new Assign(obj, val).compile(o, LEVEL.LIST));
} }
if (!top) { if (!top) {
assigns.push(valVar); assigns.push(valVar);
} }
code = assigns.join(', '); code = assigns.join(', ');
return o.level < LVL_LIST ? code : "(" + code + ")"; return o.level < LEVEL.LIST ? code : "(" + code + ")";
}; };
Assign.prototype.compileConditional = function(o) { Assign.prototype.compileConditional = function(o) {
var _ref2, left, rite; var _ref2, left, rite;
@@ -1067,7 +1067,7 @@
__extends(Param, Base); __extends(Param, Base);
Param.prototype.children = ['name']; Param.prototype.children = ['name'];
Param.prototype.compile = function(o) { Param.prototype.compile = function(o) {
return this.value.compile(o, LVL_LIST); return this.value.compile(o, LEVEL.LIST);
}; };
Param.prototype.toString = function() { Param.prototype.toString = function() {
var name; var name;
@@ -1135,7 +1135,7 @@
end = -1; end = -1;
for (i = 0, _len = list.length; i < _len; i++) { for (i = 0, _len = list.length; i < _len; i++) {
arg = list[i]; arg = list[i];
code = arg.compile(o, LVL_LIST); code = arg.compile(o, LEVEL.LIST);
prev = args[end]; prev = args[end];
if (!(arg instanceof Splat)) { if (!(arg instanceof Splat)) {
if (prev && starts(prev, '[') && ends(prev, ']')) { if (prev && starts(prev, '[') && ends(prev, ']')) {
@@ -1180,7 +1180,7 @@
o.indent = this.idt(1); o.indent = this.idt(1);
set = ''; set = '';
body = this.body; body = this.body;
if (o.level > LVL_TOP || this.returns) { if (o.level > LEVEL.TOP || this.returns) {
rvar = o.scope.freeVariable('result'); rvar = o.scope.freeVariable('result');
set = "" + this.tab + rvar + " = [];\n"; set = "" + this.tab + rvar + " = [];\n";
if (body) { if (body) {
@@ -1190,7 +1190,7 @@
if (this.guard) { if (this.guard) {
body = Expressions.wrap([new If(this.guard, body)]); body = Expressions.wrap([new If(this.guard, body)]);
} }
code = set + this.tab + ("while (" + (this.condition.compile(o, LVL_PAREN)) + ") {\n" + (body.compile(o, LVL_TOP)) + "\n" + this.tab + "}"); code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL.PAREN)) + ") {\n" + (body.compile(o, LEVEL.TOP)) + "\n" + this.tab + "}");
if (this.returns) { if (this.returns) {
o.indent = this.tab; o.indent = this.tab;
code += '\n' + new Return(new Literal(rvar)).compile(o); code += '\n' + new Return(new Literal(rvar)).compile(o);
@@ -1271,12 +1271,12 @@
return this.compileExistence(o); return this.compileExistence(o);
} }
this.first.tags.front = this.tags.front; this.first.tags.front = this.tags.front;
return "" + (this.first.compile(o, LVL_OP)) + " " + this.operator + " " + (this.second.compile(o, LVL_OP)); return "" + (this.first.compile(o, LEVEL.OP)) + " " + this.operator + " " + (this.second.compile(o, LEVEL.OP));
}; };
Op.prototype.compileChain = function(o) { Op.prototype.compileChain = function(o) {
var _ref2, shared; var _ref2, shared;
_ref2 = this.first.unwrap().second.cache(o), this.first.second = _ref2[0], shared = _ref2[1]; _ref2 = this.first.unwrap().second.cache(o), this.first.second = _ref2[0], shared = _ref2[1];
return "" + (this.first.compile(o, LVL_OP)) + " && " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LVL_OP)); return "" + (this.first.compile(o, LEVEL.OP)) + " && " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL.OP));
}; };
Op.prototype.compileExistence = function(o) { Op.prototype.compileExistence = function(o) {
var fst, ref; var fst, ref;
@@ -1287,12 +1287,12 @@
fst = this.first; fst = this.first;
ref = fst.compile(o); ref = fst.compile(o);
} }
return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o, LVL_LIST))); return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o, LEVEL.LIST)));
}; };
Op.prototype.compileUnary = function(o) { Op.prototype.compileUnary = function(o) {
var _ref2, _ref3, parts, space; var _ref2, _ref3, parts, space;
space = (_ref2 = this.operator, __indexOf.call(this.PREFIX_OPERATORS, _ref2) >= 0) || this.first instanceof Op && this.first.operator === this.operator && ((_ref3 = this.operator) === '+' || _ref3 === '-') ? ' ' : ''; space = (_ref2 = this.operator, __indexOf.call(this.PREFIX_OPERATORS, _ref2) >= 0) || this.first instanceof Op && this.first.operator === this.operator && ((_ref3 = this.operator) === '+' || _ref3 === '-') ? ' ' : '';
parts = [this.operator, space, this.first.compile(o, LVL_OP)]; parts = [this.operator, space, this.first.compile(o, LEVEL.OP)];
return (this.flip ? parts.reverse() : parts).join(''); return (this.flip ? parts.reverse() : parts).join('');
}; };
return Op; return Op;
@@ -1318,7 +1318,7 @@
}; };
In.prototype.compileOrTest = function(o) { In.prototype.compileOrTest = function(o) {
var _len, _ref2, _ref3, _ref4, _result, cmp, cnj, i, item, ref, sub, tests; var _len, _ref2, _ref3, _ref4, _result, cmp, cnj, i, item, ref, sub, tests;
_ref2 = this.object.cache(o, LVL_OP), sub = _ref2[0], ref = _ref2[1]; _ref2 = this.object.cache(o, LEVEL.OP), sub = _ref2[0], ref = _ref2[1];
_ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1]; _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1];
tests = (function() { tests = (function() {
_ref4 = this.array.base.objects; _ref4 = this.array.base.objects;
@@ -1330,17 +1330,17 @@
return _result; return _result;
}).call(this); }).call(this);
tests = tests.join(cnj); tests = tests.join(cnj);
return o.level < LVL_OP ? tests : "(" + tests + ")"; return o.level < LEVEL.OP ? tests : "(" + tests + ")";
}; };
In.prototype.compileLoopTest = function(o) { In.prototype.compileLoopTest = function(o) {
var _ref2, code, ref, sub; var _ref2, code, ref, sub;
_ref2 = this.object.cache(o, LVL_LIST), sub = _ref2[0], ref = _ref2[1]; _ref2 = this.object.cache(o, LEVEL.LIST), sub = _ref2[0], ref = _ref2[1];
code = utility('indexOf') + (".call(" + (this.array.compile(o)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0'); code = utility('indexOf') + (".call(" + (this.array.compile(o)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0');
if (sub === ref) { if (sub === ref) {
return code; return code;
} }
code = sub + ', ' + code; code = sub + ', ' + code;
return o.level < LVL_LIST ? code : "(" + code + ")"; return o.level < LEVEL.LIST ? code : "(" + code + ")";
}; };
In.prototype.toString = function(idt) { In.prototype.toString = function(idt) {
return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : '')); return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));
@@ -1375,8 +1375,8 @@
var catchPart, errorPart; var catchPart, errorPart;
o.indent = this.idt(1); o.indent = this.idt(1);
errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' '; errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' ';
catchPart = this.recovery ? " catch" + errorPart + "{\n" + (this.recovery.compile(o, LVL_TOP)) + "\n" + this.tab + "}" : !(this.ensure || this.recovery) ? ' catch (_e) {}' : undefined; catchPart = this.recovery ? " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL.TOP)) + "\n" + this.tab + "}" : !(this.ensure || this.recovery) ? ' catch (_e) {}' : undefined;
return ("" + this.tab + "try {\n" + (this.attempt.compile(o, LVL_TOP)) + "\n" + this.tab + "}" + (catchPart || '')) + (this.ensure ? " finally {\n" + (this.ensure.compile(o, LVL_TOP)) + "\n" + this.tab + "}" : ''); return ("" + this.tab + "try {\n" + (this.attempt.compile(o, LEVEL.TOP)) + "\n" + this.tab + "}" + (catchPart || '')) + (this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL.TOP)) + "\n" + this.tab + "}" : '');
}; };
return Try; return Try;
})(); })();
@@ -1413,7 +1413,7 @@
var code; var code;
code = this.expression.compile(o); code = this.expression.compile(o);
code = IDENTIFIER.test(code) && !o.scope.check(code) ? "typeof " + code + " !== \"undefined\" && " + code + " !== null" : "" + code + " != null"; code = IDENTIFIER.test(code) && !o.scope.check(code) ? "typeof " + code + " !== \"undefined\" && " + code + " !== null" : "" + code + " != null";
return o.level <= LVL_COND ? code : "(" + code + ")"; return o.level <= LEVEL.COND ? code : "(" + code + ")";
}; };
return Existence; return Existence;
})(); })();
@@ -1444,8 +1444,8 @@
expr.tags.front = this.tags.front; expr.tags.front = this.tags.front;
return expr.compile(o); return expr.compile(o);
} }
bare = o.level < LVL_OP && (expr instanceof Op || expr instanceof Call); bare = o.level < LEVEL.OP && (expr instanceof Op || expr instanceof Call);
code = expr.compile(o, LVL_PAREN); code = expr.compile(o, LEVEL.PAREN);
return bare ? code : "(" + code + ")"; return bare ? code : "(" + code + ")";
}; };
return Parens; return Parens;
@@ -1517,9 +1517,9 @@
if (name || this.object && !this.raw) { if (name || this.object && !this.raw) {
_ref6 = this.source.compileLoopReference(o, 'ref'), sourcePart = _ref6[0], svar = _ref6[1]; _ref6 = this.source.compileLoopReference(o, 'ref'), sourcePart = _ref6[0], svar = _ref6[1];
} else { } else {
sourcePart = svar = this.source.compile(o, LVL_PAREN); sourcePart = svar = this.source.compile(o, LEVEL.PAREN);
} }
namePart = this.pattern ? new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")).compile(o, LVL_TOP) : name ? "" + name + " = " + svar + "[" + ivar + "]" : undefined; namePart = this.pattern ? new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")).compile(o, LEVEL.TOP) : name ? "" + name + " = " + svar + "[" + ivar + "]" : undefined;
if (!this.object) { if (!this.object) {
if (0 > pvar && (pvar | 0) === +pvar) { if (0 > pvar && (pvar | 0) === +pvar) {
vars = "" + ivar + " = " + svar + ".length - 1"; vars = "" + ivar + " = " + svar + ".length - 1";
@@ -1552,7 +1552,7 @@
} }
})(); })();
} }
if (o.level > LVL_TOP || this.returns) { if (o.level > LEVEL.TOP || this.returns) {
rvar = scope.freeVariable('result'); rvar = scope.freeVariable('result');
defPart += this.tab + rvar + ' = [];\n'; defPart += this.tab + rvar + ' = [];\n';
retPart = this.compileReturnValue(rvar, o); retPart = this.compileReturnValue(rvar, o);
@@ -1565,7 +1565,7 @@
varPart = idt + namePart + ';\n'; varPart = idt + namePart + ';\n';
} }
o.indent = idt; o.indent = idt;
return defPart + ("" + this.tab + "for (" + forPart + ") {\n" + (guardPart || '') + varPart + (body.compile(o, LVL_TOP)) + "\n" + this.tab + "}") + retPart; return defPart + ("" + this.tab + "for (" + forPart + ") {\n" + (guardPart || '') + varPart + (body.compile(o, LEVEL.TOP)) + "\n" + this.tab + "}") + retPart;
}; };
return For; return For;
})(); })();
@@ -1599,7 +1599,7 @@
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _ref5, block, code, cond, conditions, expr, i, idt1, idt2; var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _ref5, block, code, cond, conditions, expr, i, idt1, idt2;
idt1 = this.idt(1); idt1 = this.idt(1);
idt2 = o.indent = this.idt(2); idt2 = o.indent = this.idt(2);
code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LVL_PAREN) : undefined) || true) + ") {\n"); code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL.PAREN) : undefined) || true) + ") {\n");
for (i = 0, _len = this.cases.length; i < _len; i++) { for (i = 0, _len = this.cases.length; i < _len; i++) {
_ref3 = this.cases[i], conditions = _ref3[0], block = _ref3[1]; _ref3 = this.cases[i], conditions = _ref3[0], block = _ref3[1];
_ref4 = flatten([conditions]); _ref4 = flatten([conditions]);
@@ -1608,9 +1608,9 @@
if (!this.subject) { if (!this.subject) {
cond = cond.invert().invert(); cond = cond.invert().invert();
} }
code += idt1 + ("case " + (cond.compile(o, LVL_PAREN)) + ":\n"); code += idt1 + ("case " + (cond.compile(o, LEVEL.PAREN)) + ":\n");
} }
code += block.compile(o, LVL_TOP) + '\n'; code += block.compile(o, LEVEL.TOP) + '\n';
if (i === this.cases.length - 1 && !this.otherwise) { if (i === this.cases.length - 1 && !this.otherwise) {
break; break;
} }
@@ -1626,7 +1626,7 @@
} }
} }
if (this.otherwise) { if (this.otherwise) {
code += idt1 + ("default:\n" + (this.otherwise.compile(o, LVL_TOP)) + "\n"); code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL.TOP)) + "\n");
} }
return code + this.tab + '}'; return code + this.tab + '}';
}; };
@@ -1666,7 +1666,7 @@
}; };
If.prototype.isStatement = function(o) { If.prototype.isStatement = function(o) {
var _ref2; var _ref2;
return (o != null ? o.level : undefined) === LVL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : undefined); return (o != null ? o.level : undefined) === LEVEL.TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : undefined);
}; };
If.prototype.compileNode = function(o) { If.prototype.compileNode = function(o) {
return this.isStatement(o) ? this.compileStatement(o) : this.compileExpression(o); return this.isStatement(o) ? this.compileStatement(o) : this.compileExpression(o);
@@ -1686,7 +1686,7 @@
If.prototype.compileStatement = function(o) { If.prototype.compileStatement = function(o) {
var body, child, cond, ifPart; var body, child, cond, ifPart;
child = del(o, 'chainChild'); child = del(o, 'chainChild');
cond = this.condition.compile(o, LVL_PAREN); cond = this.condition.compile(o, LEVEL.PAREN);
o.indent = this.idt(1); o.indent = this.idt(1);
body = this.ensureExpressions(this.body).compile(o); body = this.ensureExpressions(this.body).compile(o);
ifPart = "if (" + cond + ") {\n" + body + "\n" + this.tab + "}"; ifPart = "if (" + cond + ") {\n" + body + "\n" + this.tab + "}";
@@ -1699,12 +1699,12 @@
return ifPart + ' else ' + (this.isChain ? this.elseBodyNode().compile(merge(o, { return ifPart + ' else ' + (this.isChain ? this.elseBodyNode().compile(merge(o, {
indent: this.tab, indent: this.tab,
chainChild: true chainChild: true
})) : "{\n" + (this.elseBody.compile(o, LVL_TOP)) + "\n" + this.tab + "}"); })) : "{\n" + (this.elseBody.compile(o, LEVEL.TOP)) + "\n" + this.tab + "}");
}; };
If.prototype.compileExpression = function(o) { If.prototype.compileExpression = function(o) {
var _ref2, code; var _ref2, code;
code = this.condition.compile(o, LVL_COND) + ' ? ' + this.bodyNode().compile(o, LVL_LIST) + ' : ' + ((_ref2 = this.elseBodyNode()) != null ? _ref2.compile(o, LVL_LIST) : undefined); code = this.condition.compile(o, LEVEL.COND) + ' ? ' + this.bodyNode().compile(o, LEVEL.LIST) + ' : ' + ((_ref2 = this.elseBodyNode()) != null ? _ref2.compile(o, LEVEL.LIST) : undefined);
return o.level >= LVL_COND ? "(" + code + ")" : code; return o.level >= LEVEL.COND ? "(" + code + ")" : code;
}; };
If.prototype.unfoldSoak = function() { If.prototype.unfoldSoak = function() {
return this.soakNode && this; return this.soakNode && this;
@@ -1762,12 +1762,14 @@
hasProp: 'Object.prototype.hasOwnProperty', hasProp: 'Object.prototype.hasOwnProperty',
slice: 'Array.prototype.slice' slice: 'Array.prototype.slice'
}; };
LVL_TOP = 0; LEVEL = {
LVL_PAREN = 1; TOP: 0,
LVL_LIST = 2; PAREN: 1,
LVL_COND = 3; LIST: 2,
LVL_OP = 4; COND: 3,
LVL_ACCESS = 5; OP: 4,
ACCESS: 5
};
TAB = ' '; TAB = ' ';
TRAILING_WHITESPACE = /[ \t]+$/gm; TRAILING_WHITESPACE = /[ \t]+$/gm;
IDENTIFIER = /^[$A-Za-z_][$\w]*$/; IDENTIFIER = /^[$A-Za-z_][$\w]*$/;

View File

@@ -42,7 +42,7 @@ exports.Base = class Base
o.level = lvl if lvl? o.level = lvl if lvl?
node = @unfoldSoak(o) or this node = @unfoldSoak(o) or this
node.tab = o.indent node.tab = o.indent
if o.level is LVL_TOP or node.isPureStatement() or not node.isStatement(o) if o.level is LEVEL.TOP or node.isPureStatement() or not node.isStatement(o)
node.compileNode o node.compileNode o
else else
node.compileClosure o node.compileClosure o
@@ -69,7 +69,7 @@ exports.Base = class Base
# Compile to a source/variable pair suitable for looping. # Compile to a source/variable pair suitable for looping.
compileLoopReference: (o, name) -> compileLoopReference: (o, name) ->
src = tmp = @compile o, LVL_LIST src = tmp = @compile o, LEVEL.LIST
unless NUMBER.test(src) or IDENTIFIER.test(src) and o.scope.check(src, immediate: on) unless NUMBER.test(src) or IDENTIFIER.test(src) and o.scope.check(src, immediate: on)
src = "#{ tmp = o.scope.freeVariable name } = #{src}" src = "#{ tmp = o.scope.freeVariable name } = #{src}"
[src, tmp] [src, tmp]
@@ -205,7 +205,7 @@ exports.Expressions = class Expressions extends Base
compileRoot: (o) -> compileRoot: (o) ->
o.indent = @tab = if o.bare then '' else TAB o.indent = @tab = if o.bare then '' else TAB
o.scope = new Scope null, this, null o.scope = new Scope null, this, null
o.level = LVL_TOP o.level = LEVEL.TOP
code = @compileWithDeclarations o code = @compileWithDeclarations o
code = code.replace TRAILING_WHITESPACE, '' code = code.replace TRAILING_WHITESPACE, ''
if o.bare then code else "(function() {\n#{code}\n}).call(this);\n" if o.bare then code else "(function() {\n#{code}\n}).call(this);\n"
@@ -228,7 +228,7 @@ exports.Expressions = class Expressions extends Base
while node isnt node = node.unwrap() then while node isnt node = node.unwrap() then
node = node.unfoldSoak(o) or node node = node.unfoldSoak(o) or node
node.tags.front = on node.tags.front = on
o.level = LVL_TOP o.level = LEVEL.TOP
code = node.compile o code = node.compile o
if node.isStatement o then code else @tab + code + ';' if node.isStatement o then code else @tab + code + ';'
@@ -281,7 +281,7 @@ exports.Return = class Return extends Base
if expr and expr not instanceof Return then expr.compile o, lvl else super o, lvl if expr and expr not instanceof Return then expr.compile o, lvl else super o, lvl
compileNode: (o) -> compileNode: (o) ->
o.level = LVL_PAREN o.level = LEVEL.PAREN
@tab + "return#{ if @expression then ' ' + @expression.compile o else '' };" @tab + "return#{ if @expression then ' ' + @expression.compile o else '' };"
#### Value #### Value
@@ -365,7 +365,7 @@ exports.Value = class Value extends Base
compileNode: (o) -> compileNode: (o) ->
@base.tags.front = @tags.front @base.tags.front = @tags.front
props = @properties props = @properties
code = @base.compile o, if props.length then LVL_ACCESS else null code = @base.compile o, if props.length then LEVEL.ACCESS else null
code = "(#{code})" if props[0] instanceof Accessor and @isSimpleNumber() code = "(#{code})" if props[0] instanceof Accessor and @isSimpleNumber()
(code += prop.compile o) for prop in props (code += prop.compile o) for prop in props
code code
@@ -473,11 +473,11 @@ exports.Call = class Call extends Base
@variable?.tags.front = @tags.front @variable?.tags.front = @tags.front
for arg in @args when arg instanceof Splat for arg in @args when arg instanceof Splat
return @compileSplat o return @compileSplat o
args = (arg.compile o, LVL_LIST for arg in @args).join ', ' args = (arg.compile o, LEVEL.LIST for arg in @args).join ', '
if @isSuper if @isSuper
@compileSuper args, o @compileSuper args, o
else else
(if @isNew then 'new ' else '') + @variable.compile(o, LVL_ACCESS) + "(#{args})" (if @isNew then 'new ' else '') + @variable.compile(o, LEVEL.ACCESS) + "(#{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.
@@ -495,9 +495,9 @@ exports.Call = class Call extends Base
base = Value.wrap @variable base = Value.wrap @variable
if (name = base.properties.pop()) and base.isComplex() if (name = base.properties.pop()) and base.isComplex()
ref = o.scope.freeVariable 'this' ref = o.scope.freeVariable 'this'
fun = "(#{ref} = #{ base.compile o, LVL_LIST })#{ name.compile o }" fun = "(#{ref} = #{ base.compile o, LEVEL.LIST })#{ name.compile o }"
else else
fun = ref = base.compile o, LVL_ACCESS fun = ref = base.compile o, LEVEL.ACCESS
fun += name.compile o if name fun += name.compile o if name
return "#{fun}.apply(#{ref}, #{splatargs})" return "#{fun}.apply(#{ref}, #{splatargs})"
idt = @idt 1 idt = @idt 1
@@ -506,7 +506,7 @@ exports.Call = class Call extends Base
#{idt}ctor.prototype = func.prototype; #{idt}ctor.prototype = func.prototype;
#{idt}var child = new ctor, result = func.apply(child, args); #{idt}var child = new ctor, result = func.apply(child, args);
#{idt}return typeof result === "object" ? result : child; #{idt}return typeof result === "object" ? result : child;
#{@tab}})(#{ @variable.compile o, LVL_LIST }, #{splatargs}, function() {}) #{@tab}})(#{ @variable.compile o, LEVEL.LIST }, #{splatargs}, function() {})
""" """
#### Extends #### Extends
@@ -553,7 +553,7 @@ exports.Index = class Index extends Base
constructor: (@index) -> super() constructor: (@index) -> super()
compile: (o) -> compile: (o) ->
(if @proto then '.prototype' else '') + "[#{ @index.compile o, LVL_PAREN }]" (if @proto then '.prototype' else '') + "[#{ @index.compile o, LEVEL.PAREN }]"
isComplex: -> @index.isComplex() isComplex: -> @index.isComplex()
@@ -613,7 +613,7 @@ exports.ArrayLiteral = class ArrayLiteral extends Base
return @compileSplatLiteral o return @compileSplatLiteral o
objects = [] objects = []
for obj, i in @objects for obj, i in @objects
code = obj.compile o, LVL_LIST code = obj.compile o, LEVEL.LIST
objects.push (if obj instanceof Comment objects.push (if obj instanceof Comment
"\n#{code}\n#{o.indent}" "\n#{code}\n#{o.indent}"
else if i is @objects.length - 1 else if i is @objects.length - 1
@@ -742,22 +742,22 @@ exports.Assign = class Assign extends Base
if isValue = @variable instanceof Value if isValue = @variable instanceof Value
return @compilePatternMatch o if @variable.isArray() or @variable.isObject() return @compilePatternMatch o if @variable.isArray() or @variable.isObject()
return @compileConditional o if @context in @CONDITIONAL return @compileConditional o if @context in @CONDITIONAL
name = @variable.compile o, LVL_LIST name = @variable.compile o, LEVEL.LIST
if @value instanceof Code and match = @METHOD_DEF.exec name if @value instanceof Code and match = @METHOD_DEF.exec name
@value.name = match[2] @value.name = match[2]
@value.klass = match[1] @value.klass = match[1]
val = @value.compile o, LVL_LIST val = @value.compile o, LEVEL.LIST
return "#{name}: #{val}" if @context is 'object' return "#{name}: #{val}" if @context is 'object'
o.scope.find name unless isValue and (@variable.hasProperties() or @variable.namespaced) o.scope.find name unless isValue and (@variable.hasProperties() or @variable.namespaced)
val = name + " #{ @context or '=' } " + val val = name + " #{ @context or '=' } " + val
if o.level <= LVL_LIST then val else "(#{val})" if o.level <= LEVEL.LIST then val else "(#{val})"
# Brief implementation of recursive pattern matching, when assigning array or # Brief implementation of recursive pattern matching, when assigning array or
# object literals to a value. Peeks at their properties to assign inner names. # object literals to a value. Peeks at their properties to assign inner names.
# See the [ECMAScript Harmony Wiki](http://wiki.ecmascript.org/doku.php?id=harmony:destructuring) # See the [ECMAScript Harmony Wiki](http://wiki.ecmascript.org/doku.php?id=harmony:destructuring)
# for details. # for details.
compilePatternMatch: (o) -> compilePatternMatch: (o) ->
top = o.level is LVL_TOP top = o.level is LEVEL.TOP
{value} = this {value} = this
{objects} = @variable.base {objects} = @variable.base
return value.compile o unless olength = objects.length return value.compile o unless olength = objects.length
@@ -774,7 +774,7 @@ exports.Assign = class Assign extends Base
accessClass = if IDENTIFIER.test idx.value then Accessor else Index accessClass = if IDENTIFIER.test idx.value then Accessor else Index
(value = Value.wrap value).properties.push new accessClass idx (value = Value.wrap value).properties.push new accessClass idx
return new Assign(obj, value).compile o return new Assign(obj, value).compile o
valVar = value.compile o, LVL_LIST valVar = value.compile o, LEVEL.LIST
assigns = [] assigns = []
splat = false splat = false
if not IDENTIFIER.test(valVar) or @variable.assigns(valVar) if not IDENTIFIER.test(valVar) or @variable.assigns(valVar)
@@ -800,10 +800,10 @@ exports.Assign = class Assign extends Base
if typeof idx isnt 'object' if typeof idx isnt 'object'
idx = new Literal(if splat then "#{valVar}.length - #{ olength - idx }" else idx) idx = new Literal(if splat then "#{valVar}.length - #{ olength - idx }" else idx)
val = new Value new Literal(valVar), [new accessClass idx] val = new Value new Literal(valVar), [new accessClass idx]
assigns.push new Assign(obj, val).compile o, LVL_LIST assigns.push new Assign(obj, val).compile o, LEVEL.LIST
assigns.push valVar unless top assigns.push valVar unless top
code = assigns.join ', ' code = assigns.join ', '
if o.level < LVL_LIST then code else "(#{code})" if o.level < LEVEL.LIST then code else "(#{code})"
# When compiling a conditional assignment, take care to ensure that the # When compiling a conditional assignment, take care to ensure that the
# operands are only evaluated once, even though we have to reference them # operands are only evaluated once, even though we have to reference them
@@ -898,7 +898,7 @@ exports.Param = class Param extends Base
super() super()
@value = new Literal @name @value = new Literal @name
compile: (o) -> @value.compile o, LVL_LIST compile: (o) -> @value.compile o, LEVEL.LIST
toString: -> toString: ->
{name} = this {name} = this
@@ -957,7 +957,7 @@ exports.Splat = class Splat extends Base
args = [] args = []
end = -1 end = -1
for arg, i in list for arg, i in list
code = arg.compile o, LVL_LIST code = arg.compile o, LEVEL.LIST
prev = args[end] prev = args[end]
if arg not instanceof Splat if arg not instanceof Splat
if prev and starts(prev, '[') and ends(prev, ']') if prev and starts(prev, '[') and ends(prev, ']')
@@ -1001,14 +1001,14 @@ exports.While = class While extends Base
o.indent = @idt 1 o.indent = @idt 1
set = '' set = ''
{body} = this {body} = this
if o.level > LVL_TOP or @returns if o.level > LEVEL.TOP or @returns
rvar = o.scope.freeVariable 'result' rvar = o.scope.freeVariable 'result'
set = "#{@tab}#{rvar} = [];\n" set = "#{@tab}#{rvar} = [];\n"
body = Push.wrap rvar, body if body body = Push.wrap rvar, body if body
body = Expressions.wrap [new If @guard, body] if @guard body = Expressions.wrap [new If @guard, body] if @guard
code = set + @tab + """ code = set + @tab + """
while (#{ @condition.compile o, LVL_PAREN }) { while (#{ @condition.compile o, LEVEL.PAREN }) {
#{ body.compile o, LVL_TOP } #{ body.compile o, LEVEL.TOP }
#{@tab}} #{@tab}}
""" """
if @returns if @returns
@@ -1086,7 +1086,7 @@ exports.Op = class Op extends Base
return @compileChain o if @isChainable() and @first.unwrap().isChainable() return @compileChain o if @isChainable() and @first.unwrap().isChainable()
return @compileExistence o if @operator is '?' return @compileExistence o if @operator is '?'
@first.tags.front = @tags.front @first.tags.front = @tags.front
"#{ @first.compile o, LVL_OP } #{@operator} #{ @second.compile o, LVL_OP }" "#{ @first.compile o, LEVEL.OP } #{@operator} #{ @second.compile o, LEVEL.OP }"
# Mimic Python's chained comparisons when multiple comparison operators are # Mimic Python's chained comparisons when multiple comparison operators are
# used sequentially. For example: # used sequentially. For example:
@@ -1095,7 +1095,7 @@ exports.Op = class Op extends Base
# true # true
compileChain: (o) -> compileChain: (o) ->
[@first.second, shared] = @first.unwrap().second.cache o [@first.second, shared] = @first.unwrap().second.cache o
"#{ @first.compile o, LVL_OP } && #{ shared.compile o } #{@operator} #{ @second.compile o, LVL_OP }" "#{ @first.compile o, LEVEL.OP } && #{ shared.compile o } #{@operator} #{ @second.compile o, LEVEL.OP }"
compileExistence: (o) -> compileExistence: (o) ->
if @first.isComplex() if @first.isComplex()
@@ -1104,13 +1104,13 @@ exports.Op = class Op extends Base
else else
fst = @first fst = @first
ref = fst.compile o ref = fst.compile o
new Existence(fst).compile(o) + " ? #{ref} : #{ @second.compile o, LVL_LIST }" new Existence(fst).compile(o) + " ? #{ref} : #{ @second.compile o, LEVEL.LIST }"
# Compile a unary **Op**. # Compile a unary **Op**.
compileUnary: (o) -> compileUnary: (o) ->
space = if @operator in @PREFIX_OPERATORS or @first instanceof Op and space = if @operator in @PREFIX_OPERATORS or @first instanceof Op and
@first.operator is @operator and @operator in ['+', '-'] then ' ' else '' @first.operator is @operator and @operator in ['+', '-'] then ' ' else ''
parts = [@operator, space, @first.compile(o, LVL_OP)] parts = [@operator, space, @first.compile(o, LEVEL.OP)]
(if @flip then parts.reverse() else parts).join '' (if @flip then parts.reverse() else parts).join ''
#### In #### In
@@ -1131,20 +1131,20 @@ exports.In = class In extends Base
@compileLoopTest o @compileLoopTest o
compileOrTest: (o) -> compileOrTest: (o) ->
[sub, ref] = @object.cache o, LVL_OP [sub, ref] = @object.cache o, LEVEL.OP
[cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || '] [cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || ']
tests = for item, i in @array.base.objects tests = for item, i in @array.base.objects
(if i then ref else sub) + cmp + item.compile o (if i then ref else sub) + cmp + item.compile o
tests = tests.join cnj tests = tests.join cnj
if o.level < LVL_OP then tests else "(#{tests})" if o.level < LEVEL.OP then tests else "(#{tests})"
compileLoopTest: (o) -> compileLoopTest: (o) ->
[sub, ref] = @object.cache o, LVL_LIST [sub, ref] = @object.cache o, LEVEL.LIST
code = utility('indexOf') + ".call(#{ @array.compile o }, #{ref}) " + code = utility('indexOf') + ".call(#{ @array.compile o }, #{ref}) " +
if @negated then '< 0' else '>= 0' if @negated then '< 0' else '>= 0'
return code if sub is ref return code if sub is ref
code = sub + ', ' + code code = sub + ', ' + code
if o.level < LVL_LIST then code else "(#{code})" if o.level < LEVEL.LIST then code else "(#{code})"
toString: (idt) -> toString: (idt) ->
super idt, @constructor.name + if @negated then '!' else '' super idt, @constructor.name + if @negated then '!' else ''
@@ -1171,14 +1171,14 @@ exports.Try = class Try extends Base
o.indent = @idt 1 o.indent = @idt 1
errorPart = if @error then " (#{ @error.compile o }) " else ' ' errorPart = if @error then " (#{ @error.compile o }) " else ' '
catchPart = if @recovery catchPart = if @recovery
" catch#{errorPart}{\n#{ @recovery.compile o, LVL_TOP }\n#{@tab}}" " catch#{errorPart}{\n#{ @recovery.compile o, LEVEL.TOP }\n#{@tab}}"
else unless @ensure or @recovery else unless @ensure or @recovery
' catch (_e) {}' ' catch (_e) {}'
""" """
#{@tab}try { #{@tab}try {
#{ @attempt.compile o, LVL_TOP } #{ @attempt.compile o, LEVEL.TOP }
#{@tab}}#{ catchPart or '' } #{@tab}}#{ catchPart or '' }
""" + if @ensure then " finally {\n#{ @ensure.compile o, LVL_TOP }\n#{@tab}}" else '' """ + if @ensure then " finally {\n#{ @ensure.compile o, LEVEL.TOP }\n#{@tab}}" else ''
#### Throw #### Throw
@@ -1213,7 +1213,7 @@ exports.Existence = class Existence extends Base
"typeof #{code} !== \"undefined\" && #{code} !== null" "typeof #{code} !== \"undefined\" && #{code} !== null"
else else
"#{code} != null" "#{code} != null"
if o.level <= LVL_COND then code else "(#{code})" if o.level <= LEVEL.COND then code else "(#{code})"
#### Parens #### Parens
@@ -1237,8 +1237,8 @@ exports.Parens = class Parens extends Base
if expr instanceof Value and expr.isAtomic() if expr instanceof Value and expr.isAtomic()
expr.tags.front = @tags.front expr.tags.front = @tags.front
return expr.compile o return expr.compile o
bare = o.level < LVL_OP and (expr instanceof Op or expr instanceof Call) bare = o.level < LEVEL.OP and (expr instanceof Op or expr instanceof Call)
code = expr.compile o, LVL_PAREN code = expr.compile o, LEVEL.PAREN
if bare then code else "(#{code})" if bare then code else "(#{code})"
#### For #### For
@@ -1301,9 +1301,9 @@ exports.For = class For extends Base
if name or @object and not @raw if name or @object and not @raw
[sourcePart, svar] = @source.compileLoopReference o, 'ref' [sourcePart, svar] = @source.compileLoopReference o, 'ref'
else else
sourcePart = svar = @source.compile o, LVL_PAREN sourcePart = svar = @source.compile o, LEVEL.PAREN
namePart = if @pattern namePart = if @pattern
new Assign(@name, new Literal "#{svar}[#{ivar}]").compile o, LVL_TOP new Assign(@name, new Literal "#{svar}[#{ivar}]").compile o, LEVEL.TOP
else if name else if name
"#{name} = #{svar}[#{ivar}]" "#{name} = #{svar}[#{ivar}]"
unless @object unless @object
@@ -1325,7 +1325,7 @@ exports.For = class For extends Base
when 1 then '++' when 1 then '++'
when -1 then '--' when -1 then '--'
else (if pvar < 0 then ' -= ' + pvar.slice 1 else ' += ' + pvar) else (if pvar < 0 then ' -= ' + pvar.slice 1 else ' += ' + pvar)
if o.level > LVL_TOP or @returns if o.level > LEVEL.TOP or @returns
rvar = scope.freeVariable 'result' rvar = scope.freeVariable 'result'
defPart += @tab + rvar + ' = [];\n' defPart += @tab + rvar + ' = [];\n'
retPart = @compileReturnValue rvar, o retPart = @compileReturnValue rvar, o
@@ -1335,7 +1335,7 @@ exports.For = class For extends Base
o.indent = idt o.indent = idt
defPart + """ defPart + """
#{@tab}for (#{forPart}) { #{@tab}for (#{forPart}) {
#{ guardPart or '' }#{varPart}#{ body.compile o, LVL_TOP } #{ guardPart or '' }#{varPart}#{ body.compile o, LEVEL.TOP }
#{@tab}} #{@tab}}
""" + retPart """ + retPart
@@ -1358,17 +1358,17 @@ exports.Switch = class Switch extends Base
compileNode: (o) -> compileNode: (o) ->
idt1 = @idt 1 idt1 = @idt 1
idt2 = o.indent = @idt 2 idt2 = o.indent = @idt 2
code = @tab + "switch (#{ @subject?.compile(o, LVL_PAREN) or true }) {\n" code = @tab + "switch (#{ @subject?.compile(o, LEVEL.PAREN) or true }) {\n"
for [conditions, block], i in @cases for [conditions, block], i in @cases
for cond in flatten [conditions] for cond in flatten [conditions]
cond = cond.invert().invert() unless @subject cond = cond.invert().invert() unless @subject
code += idt1 + "case #{ cond.compile o, LVL_PAREN }:\n" code += idt1 + "case #{ cond.compile o, LEVEL.PAREN }:\n"
code += block.compile(o, LVL_TOP) + '\n' code += block.compile(o, LEVEL.TOP) + '\n'
break if i is @cases.length - 1 and not @otherwise break if i is @cases.length - 1 and not @otherwise
for expr in block.expressions by -1 when expr not instanceof Comment for expr in block.expressions by -1 when expr not instanceof Comment
code += idt2 + 'break;\n' unless expr instanceof Return code += idt2 + 'break;\n' unless expr instanceof Return
break break
code += idt1 + "default:\n#{ @otherwise.compile o, LVL_TOP }\n" if @otherwise code += idt1 + "default:\n#{ @otherwise.compile o, LEVEL.TOP }\n" if @otherwise
code + @tab + '}' code + @tab + '}'
#### If #### If
@@ -1404,7 +1404,7 @@ exports.If = class If extends Base
# The **If** only compiles into a statement if either of its bodies needs # The **If** only compiles into a statement if either of its bodies needs
# to be a statement. Otherwise a conditional operator is safe. # to be a statement. Otherwise a conditional operator is safe.
isStatement: (o) -> isStatement: (o) ->
o?.level is LVL_TOP or @bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o) o?.level is LEVEL.TOP or @bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o)
compileNode: (o) -> compileNode: (o) ->
if @isStatement o then @compileStatement o else @compileExpression o if @isStatement o then @compileStatement o else @compileExpression o
@@ -1424,7 +1424,7 @@ exports.If = class If extends Base
# force inner *else* bodies into statement form. # force inner *else* bodies into statement form.
compileStatement: (o) -> compileStatement: (o) ->
child = del o, 'chainChild' child = del o, 'chainChild'
cond = @condition.compile o, LVL_PAREN cond = @condition.compile o, LEVEL.PAREN
o.indent = @idt 1 o.indent = @idt 1
body = @ensureExpressions(@body).compile o body = @ensureExpressions(@body).compile o
ifPart = "if (#{cond}) {\n#{body}\n#{@tab}}" ifPart = "if (#{cond}) {\n#{body}\n#{@tab}}"
@@ -1433,14 +1433,14 @@ exports.If = class If extends Base
ifPart + ' else ' + if @isChain ifPart + ' else ' + if @isChain
@elseBodyNode().compile merge o, indent: @tab, chainChild: true @elseBodyNode().compile merge o, indent: @tab, chainChild: true
else else
"{\n#{ @elseBody.compile o, LVL_TOP }\n#{@tab}}" "{\n#{ @elseBody.compile o, LEVEL.TOP }\n#{@tab}}"
# Compile the If as a conditional operator. # Compile the If as a conditional operator.
compileExpression: (o) -> compileExpression: (o) ->
code = @condition .compile(o, LVL_COND) + ' ? ' + code = @condition .compile(o, LEVEL.COND) + ' ? ' +
@bodyNode().compile(o, LVL_LIST) + ' : ' + @bodyNode().compile(o, LEVEL.LIST) + ' : ' +
@elseBodyNode()?.compile o, LVL_LIST @elseBodyNode()?.compile o, LEVEL.LIST
if o.level >= LVL_COND then "(#{code})" else code if o.level >= LEVEL.COND then "(#{code})" else code
unfoldSoak: -> @soakNode and this unfoldSoak: -> @soakNode and this
@@ -1532,12 +1532,13 @@ UTILITIES =
slice : 'Array.prototype.slice' slice : 'Array.prototype.slice'
# Levels indicates a node's position in the AST. # Levels indicates a node's position in the AST.
LVL_TOP = 0 # ...; LEVEL =
LVL_PAREN = 1 # (...) TOP : 0 # ...;
LVL_LIST = 2 # [...] PAREN : 1 # (...)
LVL_COND = 3 # ... ? x : y LIST : 2 # [...]
LVL_OP = 4 # !... COND : 3 # ... ? x : y
LVL_ACCESS = 5 # ...[0] OP : 4 # !...
ACCESS : 5 # ...[0]
# Tabs are two spaces for pretty printing. # Tabs are two spaces for pretty printing.
TAB = ' ' TAB = ' '