nodes: refactored and removed the notion of o.top in favor of LVL_TOP

This commit is contained in:
satyr
2010-10-23 18:06:04 +09:00
parent b82f495ec7
commit 2bc2c4717e
7 changed files with 365 additions and 431 deletions

View File

@@ -1,5 +1,5 @@
(function() {
var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, LVL_ACCESS, LVL_ASSIGN, 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, starts, utility;
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 __extends = function(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
@@ -31,14 +31,14 @@
return Base;
})();
Base.prototype.compile = function(o, lvl) {
var top;
var node;
o = o ? extend({}, o) : {};
if (lvl) {
if (lvl != null) {
o.level = lvl;
}
top = this.topSensitive ? o.top : del(o, 'top');
this.tab = o.indent;
return top || o.asStatement || this instanceof Comment || this.isPureStatement() || !this.isStatement(o) ? this.compileNode(o) : this.compileClosure(o);
node = this.unfoldSoak(o) || this;
node.tab = o.indent;
return o.level === LVL_TOP || node.isPureStatement() || !node.isStatement(o) ? node.compileNode(o) : node.compileClosure(o);
};
Base.prototype.compileClosure = function(o) {
if (this.containsPureStatement()) {
@@ -60,7 +60,7 @@
};
Base.prototype.compileLoopReference = function(o, name) {
var src, tmp;
src = tmp = this.compile(o, LVL_ASSIGN);
src = tmp = this.compile(o, LVL_LIST);
if (!(NUMBER.test(src) || IDENTIFIER.test(src) && o.scope.check(src, {
immediate: true
}))) {
@@ -98,7 +98,7 @@
Base.prototype.toString = function(idt, override) {
var _i, _len, _ref2, _result, child, children, klass;
idt || (idt = '');
children = (function() {
children = ((function() {
_ref2 = this.collectChildren();
_result = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
@@ -106,7 +106,7 @@
_result.push(child.toString(idt + TAB));
}
return _result;
}).call(this).join('');
}).call(this)).join('');
klass = override || this.constructor.name + (this.soakNode ? '?' : '');
return '\n' + idt + klass + children;
};
@@ -155,7 +155,6 @@
Base.prototype.isPureStatement = NO;
Base.prototype.isComplex = YES;
Base.prototype.isChainable = NO;
Base.prototype.topSensitive = false;
Base.prototype.unfoldSoak = NO;
Base.prototype.assigns = NO;
return Base;
@@ -204,15 +203,16 @@
};
Expressions.prototype.compileNode = function(o) {
var _i, _len, _ref2, _result, node;
return (function() {
this.tab = o.indent;
return ((function() {
_ref2 = this.expressions;
_result = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
node = _ref2[_i];
_result.push(this.compileExpression(node, merge(o)));
_result.push(this.compileExpression(node, o));
}
return _result;
}).call(this).join('\n');
}).call(this)).join('\n');
};
Expressions.prototype.compileRoot = function(o) {
var code;
@@ -224,20 +224,25 @@
return o.bare ? code : "(function() {\n" + code + "\n}).call(this);\n";
};
Expressions.prototype.compileWithDeclarations = function(o) {
var code;
var code, scope;
code = this.compileNode(o);
if (o.scope.hasAssignments(this)) {
code = "" + this.tab + "var " + (o.scope.compiledAssignments().replace(/\n/g, '$&' + this.tab)) + ";\n" + code;
scope = o.scope;
if (scope.hasAssignments(this)) {
code = "" + this.tab + "var " + (multident(scope.compiledAssignments(), this.tab)) + ";\n" + code;
}
if (!o.globals && o.scope.hasDeclarations(this)) {
code = "" + this.tab + "var " + (o.scope.compiledDeclarations()) + ";\n" + code;
code = "" + this.tab + "var " + (scope.compiledDeclarations()) + ";\n" + code;
}
return code;
};
Expressions.prototype.compileExpression = function(node, o) {
var code;
o.top = node.tags.front = true;
this.tab = o.indent;
while (node !== (node = node.unwrap())) {
}
node = node.unfoldSoak(o) || node;
node.tags.front = true;
o.level = LVL_TOP;
code = node.compile(o);
return node.isStatement(o) ? code : this.tab + code + ';';
};
@@ -262,19 +267,16 @@
Literal.prototype.makeReturn = function() {
return this.isStatement() ? this : Literal.__super__.makeReturn.call(this);
};
Literal.prototype.isStatement = function() {
Literal.prototype.isPureStatement = function() {
var _ref2;
return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger';
};
Literal.prototype.isPureStatement = Literal.prototype.isStatement;
Literal.prototype.isComplex = NO;
Literal.prototype.assigns = function(name) {
return name === this.value;
};
Literal.prototype.compileNode = function() {
var val;
val = this.value.reserved ? "\"" + this.value + "\"" : this.value;
return this.isStatement() ? this.tab + val + ';' : val;
Literal.prototype.compile = function() {
return this.value.reserved ? "\"" + this.value + "\"" : this.value;
};
Literal.prototype.toString = function() {
return ' "' + this.value + '"';
@@ -301,15 +303,8 @@
return expr && !(expr instanceof Return) ? expr.compile(o, lvl) : Return.__super__.compile.call(this, o, lvl);
};
Return.prototype.compileNode = function(o) {
var expr;
expr = '';
if (this.expression) {
if (this.expression.isStatement(o)) {
o.asStatement = true;
}
expr = ' ' + this.expression.compile(o, LVL_PAREN);
}
return this.tab + 'return' + expr + ';';
o.level = LVL_PAREN;
return this.tab + ("return" + (this.expression ? ' ' + this.expression.compile(o) : '') + ";");
};
return Return;
})();
@@ -365,7 +360,7 @@
return this.properties.length ? this : this.base;
};
Value.prototype.isStatement = function(o) {
return this.base.isStatement(o) && !this.properties.length;
return !this.properties.length && this.base.isStatement(o);
};
Value.prototype.isSimpleNumber = function() {
return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
@@ -391,23 +386,17 @@
}
return [base.push(name), new Value(bref || base.base, [nref || name])];
};
Value.prototype.compile = function(o, lvl) {
this.base.tags.front = this.tags.front;
return !o.top || this.properties.length ? Value.__super__.compile.call(this, o, lvl) : this.base.compile(o, lvl);
};
Value.prototype.compileNode = function(o) {
var _i, _len, code, ifn, prop, props;
if (ifn = this.unfoldSoak(o)) {
return ifn.compile(o);
}
var _i, _len, code, prop, props;
this.base.tags.front = this.tags.front;
props = this.properties;
code = this.base.compile(o, props.length && LVL_ACCESS);
code = this.base.compile(o, props.length ? LVL_ACCESS : null);
if (props[0] instanceof Accessor && this.isSimpleNumber()) {
code = "(" + code + ")";
}
for (_i = 0, _len = props.length; _i < _len; _i++) {
prop = props[_i];
(code += prop.compileNode(o));
code += prop.compile(o);
}
return code;
};
@@ -451,10 +440,10 @@
return Comment;
})();
__extends(Comment, Base);
Comment.prototype.isStatement = YES;
Comment.prototype.isPureStatement = YES;
Comment.prototype.makeReturn = THIS;
Comment.prototype.compileNode = function(o) {
return this.tab + '/*' + this.comment.replace(/\n/g, '\n' + this.tab) + '*/';
return this.tab + '/*' + multident(this.comment, this.tab) + '*/';
};
return Comment;
})();
@@ -543,11 +532,10 @@
return ifn;
};
Call.prototype.compileNode = function(o) {
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _result, arg, args, ifn;
if (ifn = this.unfoldSoak(o)) {
return ifn.compile(o);
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _result, arg, args;
if ((_ref2 = this.variable) != null) {
_ref2.tags.front = this.tags.front;
}
(_ref2 = this.variable) != null ? _ref2.tags.front = this.tags.front : undefined;
_ref3 = this.args;
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
arg = _ref3[_i];
@@ -555,7 +543,7 @@
return this.compileSplat(o);
}
}
args = (function() {
args = ((function() {
_ref4 = this.args;
_result = [];
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
@@ -563,7 +551,7 @@
_result.push(arg.compile(o, LVL_LIST));
}
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 + ")");
};
Call.prototype.compileSuper = function(args, o) {
@@ -579,11 +567,11 @@
base = Value.wrap(this.variable);
if ((name = base.properties.pop()) && base.isComplex()) {
ref = o.scope.freeVariable('this');
fun = "(" + ref + " = " + (base.compile(o, LVL_ASSIGN)) + ")" + (name.compileNode(o));
fun = "(" + ref + " = " + (base.compile(o, LVL_LIST)) + ")" + (name.compile(o));
} else {
fun = ref = base.compile(o, LVL_ACCESS);
if (name) {
fun += name.compileNode(o);
fun += name.compile(o);
}
}
return "" + fun + ".apply(" + ref + ", " + splatargs + ")";
@@ -605,7 +593,7 @@
})();
__extends(Extends, Base);
Extends.prototype.children = ['child', 'parent'];
Extends.prototype.compileNode = function(o) {
Extends.prototype.compile = function(o) {
return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
};
return Extends;
@@ -623,7 +611,7 @@
})();
__extends(Accessor, Base);
Accessor.prototype.children = ['name'];
Accessor.prototype.compileNode = function(o) {
Accessor.prototype.compile = function(o) {
var name;
name = this.name.compile(o);
return this.proto + (IS_STRING.test(name) ? "[" + name + "]" : "." + name);
@@ -642,7 +630,7 @@
})();
__extends(Index, Base);
Index.prototype.children = ['index'];
Index.prototype.compileNode = function(o) {
Index.prototype.compile = function(o) {
return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LVL_PAREN)) + "]");
};
Index.prototype.isComplex = function() {
@@ -662,8 +650,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;
top = del(o, 'top');
var _i, _len, _ref2, _result, i, indent, join, lastNoncom, nonComments, obj, prop, props;
o.indent = this.idt(1);
nonComments = (function() {
_ref2 = this.properties;
@@ -779,14 +766,13 @@
return this;
};
Class.prototype.compileNode = function(o) {
var _i, _len, _ref2, _ref3, access, applied, apply, className, constScope, construct, constructor, extension, func, me, pname, prop, props, pvar, ref, returns, val, variable;
var _i, _len, _ref2, _ref3, access, applied, apply, className, constScope, construct, constructor, extension, func, me, pname, prop, props, pvar, ref, val, variable;
variable = this.variable;
if (variable.value === '__temp__') {
variable = new Literal(o.scope.freeVariable('ctor'));
}
extension = this.parent && new Extends(variable, this.parent);
props = new Expressions;
o.top = true;
me = null;
className = variable.compile(o);
constScope = null;
@@ -847,13 +833,18 @@
if (me) {
constructor.body.unshift(new Literal("" + me + " = this"));
}
construct = this.idt() + new Assign(variable, constructor).compile(merge(o, {
sharedScope: constScope
})) + ';';
props = !props.empty() ? '\n' + props.compile(o) : '';
extension = extension ? '\n' + this.idt() + extension.compile(o) + ';' : '';
returns = this.returns ? '\n' + new Return(variable).compile(o) : '';
return construct + extension + props + returns;
o.sharedScope = constScope;
construct = this.tab + new Assign(variable, constructor).compile(o) + ';';
if (extension) {
construct += '\n' + this.tab + extension.compile(o) + ';';
}
if (!props.empty()) {
construct += '\n' + props.compile(o);
}
if (this.returns) {
construct += '\n' + new Return(variable).compile(o);
}
return construct;
};
return Class;
})();
@@ -872,29 +863,28 @@
Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/;
Assign.prototype.CONDITIONAL = ['||=', '&&=', '?='];
Assign.prototype.children = ['variable', 'value'];
Assign.prototype.topSensitive = true;
Assign.prototype.assigns = function(name) {
return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
};
Assign.prototype.unfoldSoak = function(o) {
return If.unfoldSoak(o, this, 'variable');
};
Assign.prototype.compileNode = function(o) {
var _ref2, ifn, isValue, match, name, stmt, top, val;
var _ref2, isValue, match, name, val;
if (isValue = this.variable instanceof Value) {
if (this.variable.isArray() || this.variable.isObject()) {
return this.compilePatternMatch(o);
}
if (ifn = If.unfoldSoak(o, this, 'variable')) {
delete o.top;
return ifn.compile(o);
}
if (_ref2 = this.context, __indexOf.call(this.CONDITIONAL, _ref2) >= 0) {
return this.compileConditional(o);
}
}
top = del(o, 'top');
stmt = del(o, 'asStatement');
name = this.variable.compile(o, LVL_ASSIGN);
name = this.variable.compile(o, LVL_LIST);
if (this.value instanceof Code && (match = this.METHOD_DEF.exec(name))) {
this.value.name = match[2];
this.value.klass = match[1];
}
val = this.value.compile(o, LVL_ASSIGN);
val = this.value.compile(o, LVL_LIST);
if (this.context === 'object') {
return "" + name + ": " + val;
}
@@ -902,17 +892,11 @@
o.scope.find(name);
}
val = name + (" " + (this.context || '=') + " ") + val;
if (stmt) {
return "" + this.tab + val + ";";
}
return top || o.level <= LVL_ASSIGN ? val : "(" + val + ")";
return o.level <= LVL_LIST ? 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;
top = del(o, 'top');
otop = merge(o, {
top: true
});
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;
value = this.value;
objects = this.variable.base.objects;
if (!(olength = objects.length)) {
@@ -921,15 +905,15 @@
isObject = this.variable.isObject();
if (top && olength === 1 && !((obj = objects[0]) instanceof Splat)) {
if (obj instanceof Assign) {
_ref2 = obj, idx = _ref2.variable.base, obj = _ref2.value;
_ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base, _ref3), obj = _ref2.value;
} else {
idx = isObject ? obj.tags["this"] ? obj.properties[0].name : obj : new Literal(0);
}
accessClass = IDENTIFIER.test(idx.value) ? Accessor : Index;
(value = Value.wrap(value)).properties.push(new accessClass(idx));
return new Assign(obj, value).compile(otop);
return new Assign(obj, value).compile(o);
}
valVar = value.compile(o);
valVar = value.compile(o, LVL_LIST);
assigns = [];
splat = false;
if (!IDENTIFIER.test(valVar) || this.variable.assigns(valVar)) {
@@ -941,7 +925,7 @@
idx = i;
if (isObject) {
if (obj instanceof Assign) {
_ref3 = obj, idx = _ref3.variable.base, obj = _ref3.value;
_ref4 = obj, (_ref5 = _ref4.variable, idx = _ref5.base, _ref5), obj = _ref4.value;
} else {
idx = obj.tags["this"] ? obj.properties[0].name : obj;
}
@@ -959,22 +943,19 @@
}
val = new Value(new Literal(valVar), [new accessClass(idx)]);
}
assigns.push(new Assign(obj, val).compile(otop));
assigns.push(new Assign(obj, val).compile(o, LVL_LIST));
}
if (!top) {
assigns.push(valVar);
}
code = assigns.join(', ');
return top || o.level <= LVL_PAREN ? code : "(" + code + ")";
return o.level < LVL_LIST ? code : "(" + code + ")";
};
Assign.prototype.compileConditional = function(o) {
var _ref2, left, rite;
_ref2 = this.variable.cacheReference(o), left = _ref2[0], rite = _ref2[1];
return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value)).compile(o);
};
Assign.prototype.assigns = function(name) {
return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
};
return Assign;
})();
exports.Code = (function() {
@@ -996,11 +977,9 @@
__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, _len, _len2, _ref2, _ref3, _result, close, code, comm, empty, func, i, idt, open, param, params, scope, sharedScope, splat, value;
sharedScope = del(o, 'sharedScope');
top = del(o, 'top');
o.scope = sharedScope || new Scope(o.scope, this.body, this);
o.top = true;
o.scope = scope = sharedScope || new Scope(o.scope, this.body, this);
o.indent = this.idt(1);
empty = this.body.expressions.length === 0;
delete o.bare;
@@ -1019,7 +998,7 @@
} else {
if (param.attach) {
value = param.value;
_ref3 = [new Literal(o.scope.freeVariable('arg')), param.splat], param = _ref3[0], param.splat = _ref3[1];
_ref3 = [new Literal(scope.freeVariable('arg')), param.splat], param = _ref3[0], param.splat = _ref3[1];
this.body.unshift(new Assign(new Value(new Literal('this'), [new Accessor(value)]), param));
}
if (param.splat) {
@@ -1033,31 +1012,36 @@
}
}
}
o.scope.startLevel();
scope.startLevel();
if (!(empty || this.noReturn)) {
this.body.makeReturn();
}
params = (function() {
_result = [];
for (_i = 0, _len2 = params.length; _i < _len2; _i++) {
param = params[_i];
_result.push(param.compile(o));
_result.push((function() {
scope.parameter(param = param.compile(o));
return param;
})());
}
return _result;
})();
if (!(empty || this.noReturn)) {
this.body.makeReturn();
}
for (_i = 0, _len2 = params.length; _i < _len2; _i++) {
param = params[_i];
o.scope.parameter(param);
}
comm = this.comment ? this.comment.compile(o) + '\n' : '';
if (this.className) {
o.indent = this.idt(2);
}
idt = this.idt(1);
code = this.body.expressions.length ? "\n" + (this.body.compileWithDeclarations(o)) + "\n" : '';
open = this.className ? "(function() {\n" + comm + (this.idt(1)) + "function " + this.className + "(" : "function(";
close = this.className ? "" + (code && this.idt(1)) + "};\n" + (this.idt(1)) + "return " + this.className + ";\n" + this.tab + "})()" : "" + (code && this.tab) + "}";
if (this.className) {
open = "(function() {\n" + comm + idt + "function " + this.className + "(";
close = "" + (code && idt) + "};\n" + idt + "return " + this.className + ";\n" + this.tab + "})()";
} else {
open = "function(";
close = "" + (code && this.tab) + "}";
}
func = "" + open + (params.join(', ')) + ") {" + code + close;
o.scope.endLevel();
scope.endLevel();
if (this.bound) {
return "" + (utility('bind')) + "(" + func + ", " + this.context + ")";
}
@@ -1082,7 +1066,7 @@
})();
__extends(Param, Base);
Param.prototype.children = ['name'];
Param.prototype.compileNode = function(o) {
Param.prototype.compile = function(o) {
return this.value.compile(o, LVL_LIST);
};
Param.prototype.toString = function() {
@@ -1112,7 +1096,7 @@
Splat.prototype.assigns = function(name) {
return this.name.assigns(name);
};
Splat.prototype.compileNode = function(o) {
Splat.prototype.compile = function(o) {
return this.index != null ? this.compileParam(o) : this.name.compile(o);
};
Splat.prototype.compileParam = function(o) {
@@ -1182,7 +1166,6 @@
})();
__extends(While, Base);
While.prototype.children = ['condition', 'guard', 'body'];
While.prototype.topSensitive = true;
While.prototype.isStatement = YES;
While.prototype.addBody = function(body) {
this.body = body;
@@ -1193,31 +1176,26 @@
return this;
};
While.prototype.compileNode = function(o) {
var cond, post, pre, rvar, set, top;
top = del(o, 'top') && !this.returns;
var body, code, rvar, set;
o.indent = this.idt(1);
cond = this.condition.compile(o, LVL_PAREN);
o.top = true;
set = '';
if (!top) {
body = this.body;
if (o.level > LVL_TOP || this.returns) {
rvar = o.scope.freeVariable('result');
set = "" + this.tab + rvar + " = [];\n";
if (this.body) {
this.body = Push.wrap(rvar, this.body);
if (body) {
body = Push.wrap(rvar, body);
}
}
pre = "" + set + this.tab + "while (" + cond + ")";
if (this.guard) {
this.body = Expressions.wrap([new If(this.guard, this.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 + "}");
if (this.returns) {
post = '\n' + new Return(new Literal(rvar)).compile(merge(o, {
indent: this.idt()
}));
} else {
post = '';
o.indent = this.tab;
code += '\n' + new Return(new Literal(rvar)).compile(o);
}
return "" + pre + " {\n" + (this.body.compile(o)) + "\n" + this.tab + "}" + post;
return code;
};
return While;
})();
@@ -1278,12 +1256,12 @@
Op.prototype.toString = function(idt) {
return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
};
Op.prototype.unfoldSoak = function(o) {
var _ref2;
return (_ref2 = this.operator, __indexOf.call(this.MUTATORS, _ref2) >= 0) && If.unfoldSoak(o, this, 'first');
};
Op.prototype.compileNode = function(o) {
var _ref2, ifn;
if (this.isUnary()) {
if ((_ref2 = this.operator, __indexOf.call(this.MUTATORS, _ref2) >= 0) && (ifn = If.unfoldSoak(o, this, 'first'))) {
return ifn.compile(o);
}
return this.compileUnary(o);
}
if (this.isChainable() && this.first.unwrap().isChainable()) {
@@ -1309,7 +1287,7 @@
fst = this.first;
ref = fst.compile(o);
}
return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o, LVL_ASSIGN)));
return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o, LVL_LIST)));
};
Op.prototype.compileUnary = function(o) {
var _ref2, parts, space;
@@ -1394,14 +1372,11 @@
return this;
};
Try.prototype.compileNode = function(o) {
var attemptPart, catchPart, errorPart, finallyPart;
var catchPart, errorPart;
o.indent = this.idt(1);
o.top = true;
attemptPart = this.attempt.compile(o);
errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' ';
catchPart = this.recovery ? " catch" + errorPart + "{\n" + (this.recovery.compile(o)) + "\n" + this.tab + "}" : !(this.ensure || this.recovery) ? ' catch (_e) {}' : '';
finallyPart = (this.ensure || '') && ' finally {\n' + this.ensure.compile(merge(o)) + ("\n" + this.tab + "}");
return "" + this.tab + "try {\n" + attemptPart + "\n" + this.tab + "}" + catchPart + finallyPart;
catchPart = this.recovery ? " catch" + errorPart + "{\n" + (this.recovery.compile(o, LVL_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 Try;
})();
@@ -1419,7 +1394,7 @@
Throw.prototype.isStatement = YES;
Throw.prototype.makeReturn = THIS;
Throw.prototype.compileNode = function(o) {
return "" + this.tab + "throw " + (this.expression.compile(o)) + ";";
return this.tab + ("throw " + (this.expression.compile(o)) + ";");
};
return Throw;
})();
@@ -1453,9 +1428,8 @@
})();
__extends(Parens, Base);
Parens.prototype.children = ['expression'];
Parens.prototype.topSensitive = true;
Parens.prototype.isStatement = function(o) {
return this.expression.isStatement(o);
Parens.prototype.unwrap = function() {
return this.expression;
};
Parens.prototype.isComplex = function() {
return this.expression.isComplex();
@@ -1464,21 +1438,15 @@
return this.expression.makeReturn();
};
Parens.prototype.compileNode = function(o) {
var code, expr, top;
top = del(o, 'top');
var bare, code, expr;
expr = this.expression;
if (expr instanceof Value && expr.isAtomic()) {
expr.tags.front = this.tags.front;
return expr.compile(o);
}
bare = o.level < LVL_OP && (expr instanceof Op || expr instanceof Call);
code = expr.compile(o, LVL_PAREN);
if (o.level < LVL_OP && (expr instanceof Op || expr instanceof Call)) {
return code;
}
if (expr.isStatement(o)) {
return (top ? this.tab + code + ';' : code);
}
return "(" + code + ")";
return bare ? code : "(" + code + ")";
};
return Parens;
})();
@@ -1505,7 +1473,6 @@
})();
__extends(For, Base);
For.prototype.children = ['body', 'source', 'guard', 'step', 'from', 'to'];
For.prototype.topSensitive = true;
For.prototype.isStatement = YES;
For.prototype.makeReturn = function() {
this.returns = true;
@@ -1521,9 +1488,8 @@
return '';
};
For.prototype.compileNode = function(o) {
var _ref2, _ref3, _ref4, _ref5, _ref6, body, cond, defPart, forPart, guardPart, idt, index, ivar, lvar, name, namePart, pvar, resultRet, rvar, scope, sourcePart, step, svar, tail, top, tvar, varPart, vars;
var _ref2, _ref3, _ref4, _ref5, _ref6, body, cond, defPart, forPart, guardPart, idt, index, ivar, lvar, name, namePart, pvar, resultRet, rvar, scope, sourcePart, step, svar, tail, tvar, varPart, vars;
scope = o.scope;
top = del(o, 'top') && !this.returns;
name = !this.pattern && ((_ref2 = this.name) != null ? _ref2.compile(o) : undefined);
index = (_ref3 = this.index) != null ? _ref3.compile(o) : undefined;
ivar = !index ? scope.freeVariable('i') : index;
@@ -1554,11 +1520,9 @@
if (name) {
_ref6 = this.source.compileLoopReference(o, 'ref'), sourcePart = _ref6[0], svar = _ref6[1];
} else {
sourcePart = svar = this.source.compile(o);
sourcePart = svar = this.source.compile(o, LVL_PAREN);
}
namePart = this.pattern ? new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")).compile(merge(o, {
top: true
})) : name ? "" + name + " = " + svar + "[" + ivar + "]" : undefined;
namePart = this.pattern ? new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")).compile(o, LVL_TOP) : name ? "" + name + " = " + svar + "[" + ivar + "]" : undefined;
if (!this.object) {
if (0 > pvar && (pvar | 0) === +pvar) {
vars = "" + ivar + " = " + svar + ".length - 1";
@@ -1581,18 +1545,18 @@
if (svar !== sourcePart) {
defPart = "" + this.tab + sourcePart + ";\n";
}
forPart = ("" + vars + "; " + cond + "; ") + (function() {
forPart = ("" + vars + "; " + cond + "; ") + ivar + (function() {
switch (+pvar) {
case 1:
return ivar + '++';
return '++';
case -1:
return ivar + '--';
return '--';
default:
return ivar + (pvar < 0 ? ' -= ' + pvar.slice(1) : ' += ' + pvar);
return pvar < 0 ? ' -= ' + pvar.slice(1) : ' += ' + pvar;
}
})();
}
if (!top) {
if (o.level > LVL_TOP || this.returns) {
rvar = scope.freeVariable('result');
defPart += "" + this.tab + rvar + " = [];\n";
resultRet = this.compileReturnValue(rvar, o);
@@ -1604,10 +1568,8 @@
if (namePart) {
varPart = "" + idt + namePart + ";\n";
}
return "" + (defPart || '') + this.tab + "for (" + forPart + ") {\n" + (guardPart || '') + varPart + (body.compile(merge(o, {
indent: idt,
top: true
}))) + "\n" + this.tab + "}" + (resultRet || '');
o.indent = idt;
return "" + (defPart || '') + this.tab + "for (" + forPart + ") {\n" + (guardPart || '') + varPart + (body.compile(o, LVL_TOP)) + "\n" + this.tab + "}" + (resultRet || '');
};
return For;
})();
@@ -1626,43 +1588,51 @@
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
Switch.prototype.isStatement = YES;
Switch.prototype.makeReturn = function() {
var _i, _len, _ref2, pair;
var _i, _len, _ref2, _ref3, pair;
_ref2 = this.cases;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
pair = _ref2[_i];
pair[1].makeReturn();
}
if (this.otherwise) {
this.otherwise.makeReturn();
if ((_ref3 = this.otherwise) != null) {
_ref3.makeReturn();
}
return this;
};
Switch.prototype.compileNode = function(o) {
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, block, code, condition, conditions, idt1, idt2;
var _i, _j, _len, _len2, _ref2, _ref3, _ref4, _ref5, block, code, cond, conditions, expr, i, idt1, idt2;
idt1 = this.idt(1);
idt2 = o.indent = this.idt(2);
o.top = true;
code = "" + this.tab + "switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o) : undefined) || true) + ") {";
for (_i = 0, _len = this.cases.length; _i < _len; _i++) {
_ref3 = this.cases[_i], conditions = _ref3[0], block = _ref3[1];
code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LVL_PAREN) : undefined) || true) + ") {\n");
for (i = 0, _len = this.cases.length; i < _len; i++) {
_ref3 = this.cases[i], conditions = _ref3[0], block = _ref3[1];
_ref4 = flatten([conditions]);
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
condition = _ref4[_j];
for (_i = 0, _len2 = _ref4.length; _i < _len2; _i++) {
cond = _ref4[_i];
if (!this.subject) {
condition = condition.invert().invert();
cond = cond.invert().invert();
}
code += "\n" + idt1 + "case " + (condition.compile(o)) + ":";
code += idt1 + ("case " + (cond.compile(o, LVL_PAREN)) + ":\n");
}
code += "\n" + (block.compile(o));
if (!(last(block.expressions) instanceof Return)) {
code += "\n" + idt2 + "break;";
code += block.compile(o, LVL_TOP) + '\n';
if (i === this.cases.length - 1 && !this.otherwise) {
break;
}
_ref5 = block.expressions;
for (_j = _ref5.length - 1; _j >= 0; _j--) {
expr = _ref5[_j];
if (!(expr instanceof Comment)) {
if (!(expr instanceof Return)) {
code += idt2 + 'break;\n';
}
break;
}
}
}
if (this.otherwise) {
code += "\n" + idt1 + "default:\n" + (this.otherwise.compile(o));
code += idt1 + ("default:\n" + (this.otherwise.compile(o, LVL_TOP)) + "\n");
}
code += "\n" + this.tab + "}";
return code;
return code + this.tab + '}';
};
return Switch;
})();
@@ -1681,7 +1651,6 @@
})();
__extends(If, Base);
If.prototype.children = ['condition', 'body', 'elseBody'];
If.prototype.topSensitive = true;
If.prototype.bodyNode = function() {
var _ref2;
return (_ref2 = this.body) != null ? _ref2.unwrap() : undefined;
@@ -1701,7 +1670,7 @@
};
If.prototype.isStatement = function(o) {
var _ref2;
return this.statement || (this.statement = (o != null ? o.top : undefined) || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : undefined));
return (o != null ? o.level : undefined) === LVL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : undefined);
};
If.prototype.compileNode = function(o) {
return this.isStatement(o) ? this.compileStatement(o) : this.compileExpression(o);
@@ -1719,13 +1688,12 @@
return node instanceof Expressions ? node : new Expressions([node]);
};
If.prototype.compileStatement = function(o) {
var child, condO, ifPart, top;
top = del(o, 'top');
var body, child, cond, ifPart;
child = del(o, 'chainChild');
condO = merge(o);
cond = this.condition.compile(o, LVL_PAREN);
o.indent = this.idt(1);
o.top = true;
ifPart = "if (" + (this.condition.compile(condO, LVL_PAREN)) + ") {\n" + (this.body.compile(o)) + "\n" + this.tab + "}";
body = this.ensureExpressions(this.body).compile(o);
ifPart = "if (" + cond + ") {\n" + body + "\n" + this.tab + "}";
if (!child) {
ifPart = this.tab + ifPart;
}
@@ -1735,11 +1703,11 @@
return ifPart + ' else ' + (this.isChain ? this.elseBodyNode().compile(merge(o, {
indent: this.tab,
chainChild: true
})) : "{\n" + (this.elseBody.compile(o)) + "\n" + this.tab + "}");
})) : "{\n" + (this.elseBody.compile(o, LVL_TOP)) + "\n" + this.tab + "}");
};
If.prototype.compileExpression = function(o) {
var _ref2, code;
code = this.condition.compile(o, LVL_COND) + ' ? ' + this.bodyNode().compile(o, LVL_ASSIGN) + ' : ' + ((_ref2 = this.elseBodyNode()) != null ? _ref2.compile(o, LVL_ASSIGN) : undefined);
code = this.condition.compile(o, LVL_COND) + ' ? ' + this.bodyNode().compile(o, LVL_LIST) + ' : ' + ((_ref2 = this.elseBodyNode()) != null ? _ref2.compile(o, LVL_LIST) : undefined);
return o.level >= LVL_COND ? "(" + code + ")" : code;
};
If.prototype.unfoldSoak = function() {
@@ -1801,10 +1769,9 @@
LVL_TOP = 0;
LVL_PAREN = 1;
LVL_LIST = 2;
LVL_ASSIGN = 3;
LVL_COND = 4;
LVL_OP = 5;
LVL_ACCESS = 6;
LVL_COND = 3;
LVL_OP = 4;
LVL_ACCESS = 5;
TAB = ' ';
TRAILING_WHITESPACE = /[ \t]+$/gm;
IDENTIFIER = /^[$A-Za-z_][$\w]*$/;
@@ -1817,4 +1784,7 @@
Scope.root.assign(ref, UTILITIES[name]);
return ref;
};
multident = function(code, tab) {
return code.replace(/\n/g, '$&' + tab);
};
}).call(this);