This commit is contained in:
Demian Ferreiro 2013-02-28 10:37:30 -03:00
parent c0e07013e8
commit bf70b4660e
6 changed files with 196 additions and 244 deletions

View File

@ -16,7 +16,6 @@
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())"; action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
action = action.replace(/\bnew /g, '$&yy.'); action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&'); action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
action = action.replace(/\b(Op|Value\.(create|wrap))\b/g, 'yy.$&');
addLocationDataFn = function(first, last) { addLocationDataFn = function(first, last) {
if (!last) { if (!last) {
return "yy.addLocationDataFn(@" + first + ")"; return "yy.addLocationDataFn(@" + first + ")";
@ -94,12 +93,12 @@
], ],
AssignObj: [ AssignObj: [
o('ObjAssignable', function() { o('ObjAssignable', function() {
return Value.wrap($1); return new Value($1);
}), o('ObjAssignable : Expression', function() { }), o('ObjAssignable : Expression', function() {
return new Assign(LOC(1)(Value.wrap($1)), $3, 'object'); return new Assign(LOC(1)(new Value($1)), $3, 'object');
}), o('ObjAssignable :\ }), o('ObjAssignable :\
INDENT Expression OUTDENT', function() { INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(Value.wrap($1)), $4, 'object'); return new Assign(LOC(1)(new Value($1)), $4, 'object');
}), o('Comment') }), o('Comment')
], ],
ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')], ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
@ -160,27 +159,27 @@
], ],
SimpleAssignable: [ SimpleAssignable: [
o('Identifier', function() { o('Identifier', function() {
return Value.wrap($1); return new Value($1);
}), o('Value Accessor', function() { }), o('Value Accessor', function() {
return $1.add($2); return $1.add($2);
}), o('Invocation Accessor', function() { }), o('Invocation Accessor', function() {
return Value.wrap($1, [].concat($2)); return new Value($1, [].concat($2));
}), o('ThisProperty') }), o('ThisProperty')
], ],
Assignable: [ Assignable: [
o('SimpleAssignable'), o('Array', function() { o('SimpleAssignable'), o('Array', function() {
return Value.wrap($1); return new Value($1);
}), o('Object', function() { }), o('Object', function() {
return Value.wrap($1); return new Value($1);
}) })
], ],
Value: [ Value: [
o('Assignable'), o('Literal', function() { o('Assignable'), o('Literal', function() {
return Value.wrap($1); return new Value($1);
}), o('Parenthetical', function() { }), o('Parenthetical', function() {
return Value.wrap($1); return new Value($1);
}), o('Range', function() { }), o('Range', function() {
return Value.wrap($1); return new Value($1);
}), o('This') }), o('This')
], ],
Accessor: [ Accessor: [
@ -274,14 +273,14 @@
], ],
This: [ This: [
o('THIS', function() { o('THIS', function() {
return Value.wrap(new Literal('this')); return new Value(new Literal('this'));
}), o('@', function() { }), o('@', function() {
return Value.wrap(new Literal('this')); return new Value(new Literal('this'));
}) })
], ],
ThisProperty: [ ThisProperty: [
o('@ Identifier', function() { o('@ Identifier', function() {
return Value.wrap(LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'); return new Value(LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this');
}) })
], ],
Array: [ Array: [
@ -348,7 +347,7 @@
o('CATCH Identifier Block', function() { o('CATCH Identifier Block', function() {
return [$2, $3]; return [$2, $3];
}), o('CATCH Object Block', function() { }), o('CATCH Object Block', function() {
return [LOC(2)(Value.wrap($2)), $3]; return [LOC(2)(new Value($2)), $3];
}) })
], ],
Throw: [ Throw: [
@ -411,7 +410,7 @@
ForBody: [ ForBody: [
o('FOR Range', function() { o('FOR Range', function() {
return { return {
source: LOC(2)(Value.wrap($2)) source: LOC(2)(new Value($2))
}; };
}), o('ForStart ForSource', function() { }), o('ForStart ForSource', function() {
$2.own = $1.own; $2.own = $1.own;
@ -430,9 +429,9 @@
], ],
ForValue: [ ForValue: [
o('Identifier'), o('ThisProperty'), o('Array', function() { o('Identifier'), o('ThisProperty'), o('Array', function() {
return Value.wrap($1); return new Value($1);
}), o('Object', function() { }), o('Object', function() {
return Value.wrap($1); return new Value($1);
}) })
], ],
ForVariables: [ ForVariables: [
@ -533,42 +532,42 @@
], ],
Operation: [ Operation: [
o('UNARY Expression', function() { o('UNARY Expression', function() {
return Op.create($1, $2); return new Op($1, $2);
}), o('- Expression', (function() { }), o('- Expression', (function() {
return Op.create('-', $2); return new Op('-', $2);
}), { }), {
prec: 'UNARY' prec: 'UNARY'
}), o('+ Expression', (function() { }), o('+ Expression', (function() {
return Op.create('+', $2); return new Op('+', $2);
}), { }), {
prec: 'UNARY' prec: 'UNARY'
}), o('-- SimpleAssignable', function() { }), o('-- SimpleAssignable', function() {
return Op.create('--', $2); return new Op('--', $2);
}), o('++ SimpleAssignable', function() { }), o('++ SimpleAssignable', function() {
return Op.create('++', $2); return new Op('++', $2);
}), o('SimpleAssignable --', function() { }), o('SimpleAssignable --', function() {
return Op.create('--', $1, null, true); return new Op('--', $1, null, true);
}), o('SimpleAssignable ++', function() { }), o('SimpleAssignable ++', function() {
return Op.create('++', $1, null, true); return new Op('++', $1, null, true);
}), o('Expression ?', function() { }), o('Expression ?', function() {
return new Existence($1); return new Existence($1);
}), o('Expression + Expression', function() { }), o('Expression + Expression', function() {
return Op.create('+', $1, $3); return new Op('+', $1, $3);
}), o('Expression - Expression', function() { }), o('Expression - Expression', function() {
return Op.create('-', $1, $3); return new Op('-', $1, $3);
}), o('Expression MATH Expression', function() { }), o('Expression MATH Expression', function() {
return Op.create($2, $1, $3); return new Op($2, $1, $3);
}), o('Expression SHIFT Expression', function() { }), o('Expression SHIFT Expression', function() {
return Op.create($2, $1, $3); return new Op($2, $1, $3);
}), o('Expression COMPARE Expression', function() { }), o('Expression COMPARE Expression', function() {
return Op.create($2, $1, $3); return new Op($2, $1, $3);
}), o('Expression LOGIC Expression', function() { }), o('Expression LOGIC Expression', function() {
return Op.create($2, $1, $3); return new Op($2, $1, $3);
}), o('Expression RELATION Expression', function() { }), o('Expression RELATION Expression', function() {
if ($2.charAt(0) === '!') { if ($2.charAt(0) === '!') {
return Op.create($2.slice(1), $1, $3).invert(); return new Op($2.slice(1), $1, $3).invert();
} else { } else {
return Op.create($2, $1, $3); return new Op($2, $1, $3);
} }
}), o('SimpleAssignable COMPOUND_ASSIGN\ }), o('SimpleAssignable COMPOUND_ASSIGN\
Expression', function() { Expression', function() {

View File

@ -164,7 +164,7 @@
}; };
Base.prototype.invert = function() { Base.prototype.invert = function() {
return Op.create('!', this); return new Op('!', this);
}; };
Base.prototype.unwrapAll = function() { Base.prototype.unwrapAll = function() {
@ -488,7 +488,7 @@
__extends(Undefined, _super); __extends(Undefined, _super);
function Undefined() { function Undefined() {
Undefined.__super__.constructor.apply(this, arguments); return Undefined.__super__.constructor.apply(this, arguments);
} }
Undefined.prototype.isAssignable = NO; Undefined.prototype.isAssignable = NO;
@ -512,7 +512,7 @@
__extends(Null, _super); __extends(Null, _super);
function Null() { function Null() {
Null.__super__.constructor.apply(this, arguments); return Null.__super__.constructor.apply(this, arguments);
} }
Null.prototype.isAssignable = NO; Null.prototype.isAssignable = NO;
@ -587,21 +587,16 @@
__extends(Value, _super); __extends(Value, _super);
Value.wrap = function(base, props, tag) { function Value(base, props, tag) {
if (!props && base instanceof Value) { if (!props && base instanceof Value) {
return base; return base;
} else {
return new Value(base, props, tag);
} }
};
function Value(base, properties, tag) {
this.base = base; this.base = base;
this.properties = properties; this.properties = props || [];
this.properties || (this.properties = []); if (tag) {
if (tag === 'this') { this[tag] = true;
this["this"] = true;
} }
return this;
} }
Value.prototype.children = ['base', 'properties']; Value.prototype.children = ['base', 'properties'];
@ -684,10 +679,10 @@
if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) { if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) {
return [this, this]; return [this, this];
} }
base = Value.wrap(this.base, this.properties.slice(0, -1)); base = new Value(this.base, this.properties.slice(0, -1));
if (base.isComplex()) { if (base.isComplex()) {
bref = new Literal(o.scope.freeVariable('base')); bref = new Literal(o.scope.freeVariable('base'));
base = Value.wrap(new Parens(new Assign(bref, base))); base = new Value(new Parens(new Assign(bref, base)));
} }
if (!name) { if (!name) {
return [base, bref]; return [base, bref];
@ -697,7 +692,7 @@
name = new Index(new Assign(nref, name.index)); name = new Index(new Assign(nref, name.index));
nref = new Index(nref); nref = new Index(nref);
} }
return [base.add(name), Value.wrap(bref || base.base, [nref || name])]; return [base.add(name), new Value(bref || base.base, [nref || name])];
}; };
Value.prototype.compileNode = function(o) { Value.prototype.compileNode = function(o) {
@ -731,8 +726,8 @@
continue; continue;
} }
prop.soak = false; prop.soak = false;
fst = Value.wrap(_this.base, _this.properties.slice(0, i)); fst = new Value(_this.base, _this.properties.slice(0, i));
snd = Value.wrap(_this.base, _this.properties.slice(i)); snd = new Value(_this.base, _this.properties.slice(i));
if (fst.isComplex()) { if (fst.isComplex()) {
ref = new Literal(o.scope.freeVariable('ref')); ref = new Literal(o.scope.freeVariable('ref'));
fst = new Parens(new Assign(ref, fst)); fst = new Parens(new Assign(ref, fst));
@ -816,7 +811,7 @@
accesses.push(new Access(new Literal('constructor'))); accesses.push(new Access(new Literal('constructor')));
} }
accesses.push(new Access(new Literal(name))); accesses.push(new Access(new Literal(name)));
return (Value.wrap(new Literal(method.klass), accesses)).compile(o); return (new Value(new Literal(method.klass), accesses)).compile(o);
} else { } else {
return "" + name + ".__super__.constructor"; return "" + name + ".__super__.constructor";
} }
@ -835,15 +830,15 @@
if (ifn = unfoldSoak(o, this, 'variable')) { if (ifn = unfoldSoak(o, this, 'variable')) {
return ifn; return ifn;
} }
_ref2 = Value.wrap(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1];
} else { } else {
left = new Literal(this.superReference(o)); left = new Literal(this.superReference(o));
rite = Value.wrap(left); rite = new Value(left);
} }
rite = new Call(rite, this.args); rite = new Call(rite, this.args);
rite.isNew = this.isNew; rite.isNew = this.isNew;
left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); left = new Literal("typeof " + (left.compile(o)) + " === \"function\"");
return new If(left, Value.wrap(rite), { return new If(left, new Value(rite), {
soak: true soak: true
}); });
} }
@ -912,7 +907,7 @@
idt = this.tab + TAB; idt = this.tab + TAB;
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 Object(result) === result ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_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 Object(result) === result ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function(){})";
} }
base = Value.wrap(this.variable); base = new Value(this.variable);
if ((name = base.properties.pop()) && base.isComplex()) { if ((name = base.properties.pop()) && base.isComplex()) {
ref = o.scope.freeVariable('ref'); ref = o.scope.freeVariable('ref');
fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o)); fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o));
@ -947,7 +942,7 @@
Extends.prototype.children = ['child', 'parent']; Extends.prototype.children = ['child', 'parent'];
Extends.prototype.compile = function(o) { Extends.prototype.compile = function(o) {
return new Call(Value.wrap(new Literal(utility('extends'))), [this.child, this.parent]).compile(o); return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
}; };
return Extends; return Extends;
@ -1302,7 +1297,7 @@
_ref2 = this.boundFuncs; _ref2 = this.boundFuncs;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) { for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
bvar = _ref2[_i]; bvar = _ref2[_i];
lhs = (Value.wrap(new Literal("this"), [new Access(bvar)])).compile(o); lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)")); this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"));
} }
}; };
@ -1338,7 +1333,7 @@
func.context = name; func.context = name;
} }
} else { } else {
assign.variable = Value.wrap(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
if (func instanceof Code && func.bound) { if (func instanceof Code && func.bound) {
this.boundFuncs.push(base); this.boundFuncs.push(base);
func.bound = false; func.bound = false;
@ -1383,8 +1378,7 @@
return this.directives = expressions.splice(0, index); return this.directives = expressions.splice(0, index);
}; };
Class.prototype.ensureConstructor = function(name, o) { Class.prototype.ensureConstructor = function(name) {
var returnExpr;
if (!this.ctor) { if (!this.ctor) {
this.ctor = new Code; this.ctor = new Code;
if (this.parent) { if (this.parent) {
@ -1393,20 +1387,12 @@
if (this.externalCtor) { if (this.externalCtor) {
this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)")); this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)"));
} }
this.ctor.body.makeReturn();
this.body.expressions.unshift(this.ctor); this.body.expressions.unshift(this.ctor);
} }
this.ctor.ctor = this.ctor.name = name; this.ctor.ctor = this.ctor.name = name;
this.ctor.klass = null; this.ctor.klass = null;
this.ctor.noReturn = true; return this.ctor.noReturn = true;
returnExpr = null;
this.ctor.body.traverseChildren(false, function(node) {
if (node instanceof Return && (returnExpr = node.expression)) {
return false;
}
});
if (returnExpr) {
throw SyntaxError("cannot return a value from a constructor: \"" + (returnExpr.compileNode(o)) + "\" in class " + name);
}
}; };
Class.prototype.compileNode = function(o) { Class.prototype.compileNode = function(o) {
@ -1420,7 +1406,7 @@
this.hoistDirectivePrologue(); this.hoistDirectivePrologue();
this.setContext(name); this.setContext(name);
this.walkBody(name, o); this.walkBody(name, o);
this.ensureConstructor(name, o); this.ensureConstructor(name);
this.body.spaced = true; this.body.spaced = true;
if (!(this.ctor instanceof Code)) { if (!(this.ctor instanceof Code)) {
this.body.expressions.unshift(this.ctor); this.body.expressions.unshift(this.ctor);
@ -1543,7 +1529,7 @@
idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0);
} }
acc = IDENTIFIER.test(idx.unwrap().value || 0); acc = IDENTIFIER.test(idx.unwrap().value || 0);
value = Value.wrap(value); value = new Value(value);
value.properties.push(new (acc ? Access : Index)(idx)); value.properties.push(new (acc ? Access : Index)(idx));
if (_ref4 = obj.unwrap().value, __indexOf.call(RESERVED, _ref4) >= 0) { if (_ref4 = obj.unwrap().value, __indexOf.call(RESERVED, _ref4) >= 0) {
throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o))); throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o)));
@ -1567,7 +1553,7 @@
_ref5 = obj, (_ref6 = _ref5.variable, idx = _ref6.base), obj = _ref5.value; _ref5 = obj, (_ref6 = _ref5.variable, idx = _ref6.base), obj = _ref5.value;
} else { } else {
if (obj.base instanceof Parens) { if (obj.base instanceof Parens) {
_ref7 = Value.wrap(obj.unwrapAll()).cacheReference(o), obj = _ref7[0], idx = _ref7[1]; _ref7 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref7[0], idx = _ref7[1];
} else { } else {
idx = obj["this"] ? obj.properties[0].name : obj; idx = obj["this"] ? obj.properties[0].name : obj;
} }
@ -1597,7 +1583,7 @@
} else { } else {
acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0); acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0);
} }
val = Value.wrap(new Literal(vvar), [new (acc ? Access : Index)(idx)]); val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);
} }
if ((name != null) && __indexOf.call(RESERVED, name) >= 0) { if ((name != null) && __indexOf.call(RESERVED, name) >= 0) {
throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o))); throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o)));
@ -1627,7 +1613,7 @@
if (__indexOf.call(this.context, "?") >= 0) { if (__indexOf.call(this.context, "?") >= 0) {
o.isExistentialEquals = true; o.isExistentialEquals = true;
} }
return Op.create(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o); return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o);
}; };
Assign.prototype.compileSplice = function(o) { Assign.prototype.compileSplice = function(o) {
@ -1716,7 +1702,7 @@
o.scope.add(p.value, 'var', true); o.scope.add(p.value, 'var', true);
} }
} }
splats = new Assign(Value.wrap(new Arr((function() { splats = new Assign(new Value(new Arr((function() {
var _l, _len3, _ref5, _results; var _l, _len3, _ref5, _results;
_ref5 = this.params; _ref5 = this.params;
_results = []; _results = [];
@ -1725,7 +1711,7 @@
_results.push(p.asReference(o)); _results.push(p.asReference(o));
} }
return _results; return _results;
}).call(this))), Value.wrap(new Literal('arguments'))); }).call(this))), new Value(new Literal('arguments')));
break; break;
} }
_ref5 = this.params; _ref5 = this.params;
@ -1734,16 +1720,16 @@
if (param.isComplex()) { if (param.isComplex()) {
val = ref = param.asReference(o); val = ref = param.asReference(o);
if (param.value) { if (param.value) {
val = Op.create('?', ref, param.value); val = new Op('?', ref, param.value);
} }
exprs.push(new Assign(Value.wrap(param.name), val, '=', { exprs.push(new Assign(new Value(param.name), val, '=', {
param: true param: true
})); }));
} else { } else {
ref = param; ref = param;
if (param.value) { if (param.value) {
lit = new Literal(ref.name.value + ' == null'); lit = new Literal(ref.name.value + ' == null');
val = new Assign(Value.wrap(param.name), param.value, '='); val = new Assign(new Value(param.name), param.value, '=');
exprs.push(new If(lit, val)); exprs.push(new If(lit, val));
} }
} }
@ -1856,7 +1842,7 @@
} else if (node.isComplex()) { } else if (node.isComplex()) {
node = new Literal(o.scope.freeVariable('arg')); node = new Literal(o.scope.freeVariable('arg'));
} }
node = Value.wrap(node); node = new Value(node);
if (this.splat) { if (this.splat) {
node = new Splat(node); node = new Splat(node);
} }
@ -2065,7 +2051,7 @@
__extends(Op, _super); __extends(Op, _super);
Op.create = function(op, first, second, flip) { function Op(op, first, second, flip) {
if (op === 'in') { if (op === 'in') {
return new In(first, second); return new In(first, second);
} }
@ -2080,14 +2066,11 @@
first = new Parens(first); first = new Parens(first);
} }
} }
return new Op(op, first, second, flip); this.operator = CONVERSIONS[op] || op;
};
function Op(op, first, second, flip) {
this.first = first; this.first = first;
this.second = second; this.second = second;
this.operator = CONVERSIONS[op] || op;
this.flip = !!flip; this.flip = !!flip;
return this;
} }
CONVERSIONS = { CONVERSIONS = {
@ -2149,7 +2132,7 @@
} else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) { } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) {
return fst; return fst;
} else { } else {
return Op.create('!', this); return new Op('!', this);
} }
}; };
@ -2158,7 +2141,7 @@
return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first'); return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first');
}; };
Op.generateDo = function(exp) { Op.prototype.generateDo = function(exp) {
var call, func, param, passedParams, ref, _i, _len, _ref2; var call, func, param, passedParams, ref, _i, _len, _ref2;
passedParams = []; passedParams = [];
func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp;
@ -2654,7 +2637,7 @@
} }
fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val; fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val;
ref = new Literal(o.scope.freeVariable('fn')); ref = new Literal(o.scope.freeVariable('fn'));
base = Value.wrap(ref); base = new Value(ref);
if (val.base) { if (val.base) {
_ref7 = [base, val], val.base = _ref7[0], base = _ref7[1]; _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1];
} }
@ -2885,7 +2868,7 @@
if (mentionsArgs) { if (mentionsArgs) {
args.push(new Literal('arguments')); args.push(new Literal('arguments'));
} }
func = Value.wrap(func, [new Access(meth)]); func = new Value(func, [new Access(meth)]);
} }
func.noReturn = noReturn; func.noReturn = noReturn;
call = new Call(func, args); call = new Call(func, args);
@ -2909,7 +2892,7 @@
return; return;
} }
parent[name] = ifn.body; parent[name] = ifn.body;
ifn.body = Value.wrap(parent); ifn.body = new Value(parent);
return ifn; return ifn;
}; };

View File

@ -1,4 +1,4 @@
/* Jison generated parser */ /* parser generated by jison 0.4.2 */
var parser = (function(){ var parser = (function(){
var parser = {trace: function trace() { }, var parser = {trace: function trace() { },
yy: {}, yy: {},
@ -85,11 +85,11 @@ case 37:this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Assign($$[$0-3],
break; break;
case 38:this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign($$[$0-4], $$[$0-1])); case 38:this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign($$[$0-4], $$[$0-1]));
break; break;
case 39:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 39:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 40:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Assign(yy.addLocationDataFn(_$[$0-2])(yy.Value.wrap($$[$0-2])), $$[$0], 'object')); case 40:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Assign(yy.addLocationDataFn(_$[$0-2])(new yy.Value($$[$0-2])), $$[$0], 'object'));
break; break;
case 41:this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign(yy.addLocationDataFn(_$[$0-4])(yy.Value.wrap($$[$0-4])), $$[$0-1], 'object')); case 41:this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign(yy.addLocationDataFn(_$[$0-4])(new yy.Value($$[$0-4])), $$[$0-1], 'object'));
break; break;
case 42:this.$ = $$[$0]; case 42:this.$ = $$[$0];
break; break;
@ -143,27 +143,27 @@ case 66:this.$ = $$[$0];
break; break;
case 67:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Splat($$[$0-1])); case 67:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Splat($$[$0-1]));
break; break;
case 68:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 68:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 69:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0-1].add($$[$0])); case 69:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0-1].add($$[$0]));
break; break;
case 70:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Value.wrap($$[$0-1], [].concat($$[$0]))); case 70:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Value($$[$0-1], [].concat($$[$0])));
break; break;
case 71:this.$ = $$[$0]; case 71:this.$ = $$[$0];
break; break;
case 72:this.$ = $$[$0]; case 72:this.$ = $$[$0];
break; break;
case 73:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 73:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 74:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 74:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 75:this.$ = $$[$0]; case 75:this.$ = $$[$0];
break; break;
case 76:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 76:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 77:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 77:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 78:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 78:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 79:this.$ = $$[$0]; case 79:this.$ = $$[$0];
break; break;
@ -231,11 +231,11 @@ case 109:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])([]);
break; break;
case 110:this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])($$[$0-2]); case 110:this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])($$[$0-2]);
break; break;
case 111:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap(new yy.Literal('this'))); case 111:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value(new yy.Literal('this')));
break; break;
case 112:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap(new yy.Literal('this'))); case 112:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value(new yy.Literal('this')));
break; break;
case 113:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Value.wrap(yy.addLocationDataFn(_$[$0-1])(new yy.Literal('this')), [yy.addLocationDataFn(_$[$0])(new yy.Access($$[$0]))], 'this')); case 113:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Value(yy.addLocationDataFn(_$[$0-1])(new yy.Literal('this')), [yy.addLocationDataFn(_$[$0])(new yy.Access($$[$0]))], 'this'));
break; break;
case 114:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Arr([])); case 114:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Arr([]));
break; break;
@ -283,7 +283,7 @@ case 135:this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Try($$[$0-3], $$
break; break;
case 136:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([$$[$0-1], $$[$0]]); case 136:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([$$[$0-1], $$[$0]]);
break; break;
case 137:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([yy.addLocationDataFn(_$[$0-1])(yy.Value.wrap($$[$0-1])), $$[$0]]); case 137:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([new yy.Value($$[$0-1]), $$[$0]]);
break; break;
case 138:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Throw($$[$0])); case 138:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Throw($$[$0]));
break; break;
@ -325,7 +325,7 @@ break;
case 153:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.For($$[$0], $$[$0-1])); case 153:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.For($$[$0], $$[$0-1]));
break; break;
case 154:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])({ case 154:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])({
source: yy.addLocationDataFn(_$[$0])(yy.Value.wrap($$[$0])) source: new yy.Value($$[$0])
}); });
break; break;
case 155:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])((function () { case 155:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])((function () {
@ -346,9 +346,9 @@ case 158:this.$ = $$[$0];
break; break;
case 159:this.$ = $$[$0]; case 159:this.$ = $$[$0];
break; break;
case 160:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 160:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 161:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Value.wrap($$[$0])); case 161:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0]));
break; break;
case 162:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])([$$[$0]]); case 162:this.$ = yy.addLocationDataFn(_$[$0], _$[$0])([$$[$0]]);
break; break;
@ -429,39 +429,39 @@ case 184:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.If($$[$0], yy.ad
statement: true statement: true
})); }));
break; break;
case 185:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create($$[$0-1], $$[$0])); case 185:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op($$[$0-1], $$[$0]));
break; break;
case 186:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create('-', $$[$0])); case 186:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('-', $$[$0]));
break; break;
case 187:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create('+', $$[$0])); case 187:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('+', $$[$0]));
break; break;
case 188:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create('--', $$[$0])); case 188:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('--', $$[$0]));
break; break;
case 189:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create('++', $$[$0])); case 189:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('++', $$[$0]));
break; break;
case 190:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create('--', $$[$0-1], null, true)); case 190:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('--', $$[$0-1], null, true));
break; break;
case 191:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.Op.create('++', $$[$0-1], null, true)); case 191:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('++', $$[$0-1], null, true));
break; break;
case 192:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Existence($$[$0-1])); case 192:this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Existence($$[$0-1]));
break; break;
case 193:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(yy.Op.create('+', $$[$0-2], $$[$0])); case 193:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op('+', $$[$0-2], $$[$0]));
break; break;
case 194:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(yy.Op.create('-', $$[$0-2], $$[$0])); case 194:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op('-', $$[$0-2], $$[$0]));
break; break;
case 195:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(yy.Op.create($$[$0-1], $$[$0-2], $$[$0])); case 195:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op($$[$0-1], $$[$0-2], $$[$0]));
break; break;
case 196:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(yy.Op.create($$[$0-1], $$[$0-2], $$[$0])); case 196:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op($$[$0-1], $$[$0-2], $$[$0]));
break; break;
case 197:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(yy.Op.create($$[$0-1], $$[$0-2], $$[$0])); case 197:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op($$[$0-1], $$[$0-2], $$[$0]));
break; break;
case 198:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(yy.Op.create($$[$0-1], $$[$0-2], $$[$0])); case 198:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op($$[$0-1], $$[$0-2], $$[$0]));
break; break;
case 199:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])((function () { case 199:this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])((function () {
if ($$[$0-1].charAt(0) === '!') { if ($$[$0-1].charAt(0) === '!') {
return yy.Op.create($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert(); return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert();
} else { } else {
return yy.Op.create($$[$0-1], $$[$0-2], $$[$0]); return new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
} }
}())); }()));
break; break;
@ -591,19 +591,16 @@ return new Parser;
if (typeof require !== 'undefined' && typeof exports !== 'undefined') { if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
exports.parser = parser; exports.parser = parser;
exports.Parser = parser.Parser; exports.Parser = parser.Parser;
exports.parse = function () { return parser.parse.apply(parser, arguments); } exports.parse = function () { return parser.parse.apply(parser, arguments); };
exports.main = function commonjsMain(args) { exports.main = function commonjsMain(args) {
if (!args[1]) if (!args[1]) {
throw new Error('Usage: '+args[0]+' FILE'); console.log('Usage: '+args[0]+' FILE');
var source, cwd; process.exit(1);
if (typeof process !== 'undefined') {
source = require('fs').readFileSync(require('path').resolve(args[1]), "utf8");
} else {
source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
} }
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
return exports.parser.parse(source); return exports.parser.parse(source);
} };
if (typeof module !== 'undefined' && require.main === module) { if (typeof module !== 'undefined' && require.main === module) {
exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); exports.main(process.argv.slice(1));
} }
} }

View File

@ -39,7 +39,6 @@ o = (patternString, action, options) ->
# All runtime functions we need are defined on "yy" # All runtime functions we need are defined on "yy"
action = action.replace /\bnew /g, '$&yy.' action = action.replace /\bnew /g, '$&yy.'
action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&' action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&'
action = action.replace /\b(Op|Value\.(create|wrap))\b/g, 'yy.$&'
# Returns a function which adds location data to the first parameter passed # Returns a function which adds location data to the first parameter passed
# in, and returns the parameter. If the parameter is not a node, it will # in, and returns the parameter. If the parameter is not a node, it will
@ -159,10 +158,10 @@ grammar =
# Assignment when it happens within an object literal. The difference from # Assignment when it happens within an object literal. The difference from
# the ordinary **Assign** is that these allow numbers and strings as keys. # the ordinary **Assign** is that these allow numbers and strings as keys.
AssignObj: [ AssignObj: [
o 'ObjAssignable', -> Value.wrap $1 o 'ObjAssignable', -> new Value $1
o 'ObjAssignable : Expression', -> new Assign LOC(1)(Value.wrap($1)), $3, 'object' o 'ObjAssignable : Expression', -> new Assign LOC(1)(new Value($1)), $3, 'object'
o 'ObjAssignable : o 'ObjAssignable :
INDENT Expression OUTDENT', -> new Assign LOC(1)(Value.wrap($1)), $4, 'object' INDENT Expression OUTDENT', -> new Assign LOC(1)(new Value($1)), $4, 'object'
o 'Comment' o 'Comment'
] ]
@ -236,26 +235,26 @@ grammar =
# Variables and properties that can be assigned to. # Variables and properties that can be assigned to.
SimpleAssignable: [ SimpleAssignable: [
o 'Identifier', -> Value.wrap $1 o 'Identifier', -> new Value $1
o 'Value Accessor', -> $1.add $2 o 'Value Accessor', -> $1.add $2
o 'Invocation Accessor', -> Value.wrap $1, [].concat $2 o 'Invocation Accessor', -> new Value $1, [].concat $2
o 'ThisProperty' o 'ThisProperty'
] ]
# Everything that can be assigned to. # Everything that can be assigned to.
Assignable: [ Assignable: [
o 'SimpleAssignable' o 'SimpleAssignable'
o 'Array', -> Value.wrap $1 o 'Array', -> new Value $1
o 'Object', -> Value.wrap $1 o 'Object', -> new Value $1
] ]
# The types of things that can be treated as values -- assigned to, invoked # The types of things that can be treated as values -- assigned to, invoked
# as functions, indexed into, named as a class, etc. # as functions, indexed into, named as a class, etc.
Value: [ Value: [
o 'Assignable' o 'Assignable'
o 'Literal', -> Value.wrap $1 o 'Literal', -> new Value $1
o 'Parenthetical', -> Value.wrap $1 o 'Parenthetical', -> new Value $1
o 'Range', -> Value.wrap $1 o 'Range', -> new Value $1
o 'This' o 'This'
] ]
@ -330,13 +329,13 @@ grammar =
# A reference to the *this* current object. # A reference to the *this* current object.
This: [ This: [
o 'THIS', -> Value.wrap new Literal 'this' o 'THIS', -> new Value new Literal 'this'
o '@', -> Value.wrap new Literal 'this' o '@', -> new Value new Literal 'this'
] ]
# A reference to a property on *this*. # A reference to a property on *this*.
ThisProperty: [ ThisProperty: [
o '@ Identifier', -> Value.wrap LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this' o '@ Identifier', -> new Value LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'
] ]
# The array literal. # The array literal.
@ -400,7 +399,7 @@ grammar =
# A catch clause names its error and runs a block of code. # A catch clause names its error and runs a block of code.
Catch: [ Catch: [
o 'CATCH Identifier Block', -> [$2, $3] o 'CATCH Identifier Block', -> [$2, $3]
o 'CATCH Object Block', -> [LOC(2)(Value.wrap($2)), $3] o 'CATCH Object Block', -> [LOC(2)(new Value($2)), $3]
] ]
# Throw an exception object. # Throw an exception object.
@ -449,7 +448,7 @@ grammar =
] ]
ForBody: [ ForBody: [
o 'FOR Range', -> source: LOC(2) Value.wrap($2) o 'FOR Range', -> source: LOC(2) new Value($2)
o 'ForStart ForSource', -> $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; $2 o 'ForStart ForSource', -> $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; $2
] ]
@ -463,8 +462,8 @@ grammar =
ForValue: [ ForValue: [
o 'Identifier' o 'Identifier'
o 'ThisProperty' o 'ThisProperty'
o 'Array', -> Value.wrap $1 o 'Array', -> new Value $1
o 'Object', -> Value.wrap $1 o 'Object', -> new Value $1
] ]
# An array or range comprehension has variables for the current element # An array or range comprehension has variables for the current element
@ -530,30 +529,30 @@ grammar =
# -type rule, but in order to make the precedence binding possible, separate # -type rule, but in order to make the precedence binding possible, separate
# rules are necessary. # rules are necessary.
Operation: [ Operation: [
o 'UNARY Expression', -> Op.create $1 , $2 o 'UNARY Expression', -> new Op $1 , $2
o '- Expression', (-> Op.create '-', $2), prec: 'UNARY' o '- Expression', (-> new Op '-', $2), prec: 'UNARY'
o '+ Expression', (-> Op.create '+', $2), prec: 'UNARY' o '+ Expression', (-> new Op '+', $2), prec: 'UNARY'
o '-- SimpleAssignable', -> Op.create '--', $2 o '-- SimpleAssignable', -> new Op '--', $2
o '++ SimpleAssignable', -> Op.create '++', $2 o '++ SimpleAssignable', -> new Op '++', $2
o 'SimpleAssignable --', -> Op.create '--', $1, null, true o 'SimpleAssignable --', -> new Op '--', $1, null, true
o 'SimpleAssignable ++', -> Op.create '++', $1, null, true o 'SimpleAssignable ++', -> new Op '++', $1, null, true
# [The existential operator](http://jashkenas.github.com/coffee-script/#existence). # [The existential operator](http://jashkenas.github.com/coffee-script/#existence).
o 'Expression ?', -> new Existence $1 o 'Expression ?', -> new Existence $1
o 'Expression + Expression', -> Op.create '+' , $1, $3 o 'Expression + Expression', -> new Op '+' , $1, $3
o 'Expression - Expression', -> Op.create '-' , $1, $3 o 'Expression - Expression', -> new Op '-' , $1, $3
o 'Expression MATH Expression', -> Op.create $2, $1, $3 o 'Expression MATH Expression', -> new Op $2, $1, $3
o 'Expression SHIFT Expression', -> Op.create $2, $1, $3 o 'Expression SHIFT Expression', -> new Op $2, $1, $3
o 'Expression COMPARE Expression', -> Op.create $2, $1, $3 o 'Expression COMPARE Expression', -> new Op $2, $1, $3
o 'Expression LOGIC Expression', -> Op.create $2, $1, $3 o 'Expression LOGIC Expression', -> new Op $2, $1, $3
o 'Expression RELATION Expression', -> o 'Expression RELATION Expression', ->
if $2.charAt(0) is '!' if $2.charAt(0) is '!'
Op.create($2[1..], $1, $3).invert() new Op($2[1..], $1, $3).invert()
else else
Op.create $2, $1, $3 new Op $2, $1, $3
o 'SimpleAssignable COMPOUND_ASSIGN o 'SimpleAssignable COMPOUND_ASSIGN
Expression', -> new Assign $1, $3, $2 Expression', -> new Assign $1, $3, $2

View File

@ -123,7 +123,7 @@ exports.Base = class Base
child.traverseChildren crossScope, func child.traverseChildren crossScope, func
invert: -> invert: ->
Op.create '!', this new Op '!', this
unwrapAll: -> unwrapAll: ->
node = this node = this
@ -384,15 +384,12 @@ exports.Return = class Return extends Base
# A value, variable or literal or parenthesized, indexed or dotted into, # A value, variable or literal or parenthesized, indexed or dotted into,
# or vanilla. # or vanilla.
exports.Value = class Value extends Base exports.Value = class Value extends Base
@wrap: (base, props, tag) -> constructor: (base, props, tag) ->
if not props and base instanceof Value return base if not props and base instanceof Value
base @base = base
else @properties = props or []
new Value base, props, tag @[tag] = true if tag
return this
constructor: (@base, @properties, tag) ->
@properties or= []
@this = true if tag is 'this'
children: ['base', 'properties'] children: ['base', 'properties']
@ -438,16 +435,16 @@ exports.Value = class Value extends Base
name = last @properties name = last @properties
if @properties.length < 2 and not @base.isComplex() and not name?.isComplex() if @properties.length < 2 and not @base.isComplex() and not name?.isComplex()
return [this, this] # `a` `a.b` return [this, this] # `a` `a.b`
base = Value.wrap @base, @properties[...-1] base = new Value @base, @properties[...-1]
if base.isComplex() # `a().b` if base.isComplex() # `a().b`
bref = new Literal o.scope.freeVariable 'base' bref = new Literal o.scope.freeVariable 'base'
base = Value.wrap new Parens new Assign bref, base base = new Value new Parens new Assign bref, base
return [base, bref] unless name # `a()` return [base, bref] unless name # `a()`
if name.isComplex() # `a[b()]` if name.isComplex() # `a[b()]`
nref = new Literal o.scope.freeVariable 'name' nref = new Literal o.scope.freeVariable 'name'
name = new Index new Assign nref, name.index name = new Index new Assign nref, name.index
nref = new Index nref nref = new Index nref
[base.add(name), Value.wrap(bref or base.base, [nref or name])] [base.add(name), new Value(bref or base.base, [nref or name])]
# We compile a value to JavaScript by compiling and joining each property. # We compile a value to JavaScript by compiling and joining each property.
# Things get much more interesting if the chain of properties has *soak* # Things get much more interesting if the chain of properties has *soak*
@ -469,8 +466,8 @@ exports.Value = class Value extends Base
return ifn return ifn
for prop, i in @properties when prop.soak for prop, i in @properties when prop.soak
prop.soak = off prop.soak = off
fst = Value.wrap @base, @properties[...i] fst = new Value @base, @properties[...i]
snd = Value.wrap @base, @properties[i..] snd = new Value @base, @properties[i..]
if fst.isComplex() if fst.isComplex()
ref = new Literal o.scope.freeVariable 'ref' ref = new Literal o.scope.freeVariable 'ref'
fst = new Parens new Assign ref, fst fst = new Parens new Assign ref, fst
@ -525,7 +522,7 @@ exports.Call = class Call extends Base
accesses = [new Access(new Literal '__super__')] accesses = [new Access(new Literal '__super__')]
accesses.push new Access new Literal 'constructor' if method.static accesses.push new Access new Literal 'constructor' if method.static
accesses.push new Access new Literal name accesses.push new Access new Literal name
(Value.wrap (new Literal method.klass), accesses).compile o (new Value (new Literal method.klass), accesses).compile o
else else
"#{name}.__super__.constructor" "#{name}.__super__.constructor"
@ -539,14 +536,14 @@ exports.Call = class Call extends Base
if @soak if @soak
if @variable if @variable
return ifn if ifn = unfoldSoak o, this, 'variable' return ifn if ifn = unfoldSoak o, this, 'variable'
[left, rite] = Value.wrap(@variable).cacheReference o [left, rite] = new Value(@variable).cacheReference o
else else
left = new Literal @superReference o left = new Literal @superReference o
rite = Value.wrap left rite = new Value left
rite = new Call rite, @args rite = new Call rite, @args
rite.isNew = @isNew rite.isNew = @isNew
left = new Literal "typeof #{ left.compile o } === \"function\"" left = new Literal "typeof #{ left.compile o } === \"function\""
return new If left, Value.wrap(rite), soak: yes return new If left, new Value(rite), soak: yes
call = this call = this
list = [] list = []
loop loop
@ -592,7 +589,7 @@ exports.Call = class Call extends Base
#{idt}return Object(result) === result ? result : child; #{idt}return Object(result) === result ? result : child;
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function(){}) #{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function(){})
""" """
base = Value.wrap @variable base = new Value @variable
if (name = base.properties.pop()) and base.isComplex() if (name = base.properties.pop()) and base.isComplex()
ref = o.scope.freeVariable 'ref' ref = o.scope.freeVariable 'ref'
fun = "(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }" fun = "(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }"
@ -618,7 +615,7 @@ exports.Extends = class Extends extends Base
# Hooks one constructor into another's prototype chain. # Hooks one constructor into another's prototype chain.
compile: (o) -> compile: (o) ->
new Call(Value.wrap(new Literal utility 'extends'), [@child, @parent]).compile o new Call(new Value(new Literal utility 'extends'), [@child, @parent]).compile o
#### Access #### Access
@ -873,7 +870,7 @@ exports.Class = class Class extends Base
# constructor. # constructor.
addBoundFunctions: (o) -> addBoundFunctions: (o) ->
for bvar in @boundFuncs for bvar in @boundFuncs
lhs = (Value.wrap (new Literal "this"), [new Access bvar]).compile o lhs = (new Value (new Literal "this"), [new Access bvar]).compile o
@ctor.body.unshift new Literal "#{lhs} = #{utility 'bind'}(#{lhs}, this)" @ctor.body.unshift new Literal "#{lhs} = #{utility 'bind'}(#{lhs}, this)"
return return
@ -902,7 +899,7 @@ exports.Class = class Class extends Base
if func.bound if func.bound
func.context = name func.context = name
else else
assign.variable = Value.wrap(new Literal(name), [(new Access new Literal 'prototype'), new Access base ]) assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ])
if func instanceof Code and func.bound if func instanceof Code and func.bound
@boundFuncs.push base @boundFuncs.push base
func.bound = no func.bound = no
@ -931,23 +928,17 @@ exports.Class = class Class extends Base
# Make sure that a constructor is defined for the class, and properly # Make sure that a constructor is defined for the class, and properly
# configured. # configured.
ensureConstructor: (name, o) -> ensureConstructor: (name) ->
if not @ctor if not @ctor
@ctor = new Code @ctor = new Code
@ctor.body.push new Literal "#{name}.__super__.constructor.apply(this, arguments)" if @parent @ctor.body.push new Literal "#{name}.__super__.constructor.apply(this, arguments)" if @parent
@ctor.body.push new Literal "#{@externalCtor}.apply(this, arguments)" if @externalCtor @ctor.body.push new Literal "#{@externalCtor}.apply(this, arguments)" if @externalCtor
@ctor.body.makeReturn()
@body.expressions.unshift @ctor @body.expressions.unshift @ctor
@ctor.ctor = @ctor.name = name @ctor.ctor = @ctor.name = name
@ctor.klass = null @ctor.klass = null
@ctor.noReturn = yes @ctor.noReturn = yes
# Prevent constructor from returning a value.
returnExpr = null
@ctor.body.traverseChildren no, (node) ->
return no if node instanceof Return and (returnExpr = node.expression)
if returnExpr
throw SyntaxError "cannot return a value from a constructor: \"#{returnExpr.compileNode o}\" in class #{name}"
# Instead of generating the JavaScript string directly, we build up the # Instead of generating the JavaScript string directly, we build up the
# equivalent syntax tree and compile that, in pieces. You can see the # equivalent syntax tree and compile that, in pieces. You can see the
# constructor, property assignments, and inheritance getting built out below. # constructor, property assignments, and inheritance getting built out below.
@ -960,7 +951,7 @@ exports.Class = class Class extends Base
@hoistDirectivePrologue() @hoistDirectivePrologue()
@setContext name @setContext name
@walkBody name, o @walkBody name, o
@ensureConstructor name, o @ensureConstructor name
@body.spaced = yes @body.spaced = yes
@body.expressions.unshift @ctor unless @ctor instanceof Code @body.expressions.unshift @ctor unless @ctor instanceof Code
@body.expressions.push lname @body.expressions.push lname
@ -1051,7 +1042,7 @@ exports.Assign = class Assign extends Base
else else
new Literal 0 new Literal 0
acc = IDENTIFIER.test idx.unwrap().value or 0 acc = IDENTIFIER.test idx.unwrap().value or 0
value = Value.wrap value value = new Value value
value.properties.push new (if acc then Access else Index) idx value.properties.push new (if acc then Access else Index) idx
if obj.unwrap().value in RESERVED if obj.unwrap().value in RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{value.compile o}" throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{value.compile o}"
@ -1072,7 +1063,7 @@ exports.Assign = class Assign extends Base
else else
# A shorthand `{a, b, @c} = val` pattern-match. # A shorthand `{a, b, @c} = val` pattern-match.
if obj.base instanceof Parens if obj.base instanceof Parens
[obj, idx] = Value.wrap(obj.unwrapAll()).cacheReference o [obj, idx] = new Value(obj.unwrapAll()).cacheReference o
else else
idx = if obj.this then obj.properties[0].name else obj idx = if obj.this then obj.properties[0].name else obj
if not splat and obj instanceof Splat if not splat and obj instanceof Splat
@ -1097,7 +1088,7 @@ exports.Assign = class Assign extends Base
acc = no acc = no
else else
acc = isObject and IDENTIFIER.test idx.unwrap().value or 0 acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
val = Value.wrap new Literal(vvar), [new (if acc then Access else Index) idx] val = new Value new Literal(vvar), [new (if acc then Access else Index) idx]
if name? and name in RESERVED if name? and name in RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{val.compile o}" throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{val.compile o}"
assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compile o, LEVEL_LIST assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compile o, LEVEL_LIST
@ -1115,7 +1106,7 @@ exports.Assign = class Assign extends Base
left.base.value != "this" and not o.scope.check left.base.value left.base.value != "this" and not o.scope.check left.base.value
throw new Error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been defined." throw new Error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been defined."
if "?" in @context then o.isExistentialEquals = true if "?" in @context then o.isExistentialEquals = true
Op.create(@context[...-1], left, new Assign(right, @value, '=') ).compile o new Op(@context[...-1], left, new Assign(right, @value, '=') ).compile o
# Compile the assignment from an array splice literal, using JavaScript's # Compile the assignment from an array splice literal, using JavaScript's
# `Array#splice` method. # `Array#splice` method.
@ -1173,19 +1164,19 @@ exports.Code = class Code extends Base
for {name: p} in @params for {name: p} in @params
if p.this then p = p.properties[0].name if p.this then p = p.properties[0].name
if p.value then o.scope.add p.value, 'var', yes if p.value then o.scope.add p.value, 'var', yes
splats = new Assign Value.wrap(new Arr(p.asReference o for p in @params)), splats = new Assign new Value(new Arr(p.asReference o for p in @params)),
Value.wrap new Literal 'arguments' new Value new Literal 'arguments'
break break
for param in @params for param in @params
if param.isComplex() if param.isComplex()
val = ref = param.asReference o val = ref = param.asReference o
val = Op.create '?', ref, param.value if param.value val = new Op '?', ref, param.value if param.value
exprs.push new Assign Value.wrap(param.name), val, '=', param: yes exprs.push new Assign new Value(param.name), val, '=', param: yes
else else
ref = param ref = param
if param.value if param.value
lit = new Literal ref.name.value + ' == null' lit = new Literal ref.name.value + ' == null'
val = new Assign Value.wrap(param.name), param.value, '=' val = new Assign new Value(param.name), param.value, '='
exprs.push new If lit, val exprs.push new If lit, val
params.push ref unless splats params.push ref unless splats
wasEmpty = @body.isEmpty() wasEmpty = @body.isEmpty()
@ -1246,7 +1237,7 @@ exports.Param = class Param extends Base
node = new Literal o.scope.freeVariable node.value node = new Literal o.scope.freeVariable node.value
else if node.isComplex() else if node.isComplex()
node = new Literal o.scope.freeVariable 'arg' node = new Literal o.scope.freeVariable 'arg'
node = Value.wrap node node = new Value node
node = new Splat node if @splat node = new Splat node if @splat
@reference = node @reference = node
@ -1390,19 +1381,18 @@ exports.While = class While extends Base
# Simple Arithmetic and logical operations. Performs some conversion from # Simple Arithmetic and logical operations. Performs some conversion from
# CoffeeScript operations into their JavaScript equivalents. # CoffeeScript operations into their JavaScript equivalents.
exports.Op = class Op extends Base exports.Op = class Op extends Base
@create: (op, first, second, flip) -> constructor: (op, first, second, flip ) ->
if op is 'in' return new In first, second if op is 'in'
return new In first, second
if op is 'do' if op is 'do'
return @generateDo first return @generateDo first
if op is 'new' if op is 'new'
return first.newInstance() if first instanceof Call and not first.do and not first.isNew return first.newInstance() if first instanceof Call and not first.do and not first.isNew
first = new Parens first if first instanceof Code and first.bound or first.do first = new Parens first if first instanceof Code and first.bound or first.do
return new Op op, first, second, flip
constructor: (op, @first, @second, flip ) ->
@operator = CONVERSIONS[op] or op @operator = CONVERSIONS[op] or op
@first = first
@second = second
@flip = !!flip @flip = !!flip
return this
# The map of conversions from CoffeeScript to JavaScript symbols. # The map of conversions from CoffeeScript to JavaScript symbols.
CONVERSIONS = CONVERSIONS =
@ -1455,12 +1445,12 @@ exports.Op = class Op extends Base
fst.operator in ['!', 'in', 'instanceof'] fst.operator in ['!', 'in', 'instanceof']
fst fst
else else
Op.create '!', this new Op '!', this
unfoldSoak: (o) -> unfoldSoak: (o) ->
@operator in ['++', '--', 'delete'] and unfoldSoak o, this, 'first' @operator in ['++', '--', 'delete'] and unfoldSoak o, this, 'first'
@generateDo: (exp) -> generateDo: (exp) ->
passedParams = [] passedParams = []
func = if exp instanceof Assign and (ref = exp.value.unwrap()) instanceof Code func = if exp instanceof Assign and (ref = exp.value.unwrap()) instanceof Code
ref ref
@ -1789,7 +1779,7 @@ exports.For = class For extends While
val.properties[0].name?.value in ['call', 'apply']) val.properties[0].name?.value in ['call', 'apply'])
fn = val.base?.unwrapAll() or val fn = val.base?.unwrapAll() or val
ref = new Literal o.scope.freeVariable 'fn' ref = new Literal o.scope.freeVariable 'fn'
base = Value.wrap ref base = new Value ref
if val.base if val.base
[val.base, base] = [base, val] [val.base, base] = [base, val]
body.expressions[idx] = new Call base, expr.args body.expressions[idx] = new Call base, expr.args
@ -1937,7 +1927,7 @@ Closure =
meth = new Literal if mentionsArgs then 'apply' else 'call' meth = new Literal if mentionsArgs then 'apply' else 'call'
args = [new Literal 'this'] args = [new Literal 'this']
args.push new Literal 'arguments' if mentionsArgs args.push new Literal 'arguments' if mentionsArgs
func = Value.wrap func, [new Access meth] func = new Value func, [new Access meth]
func.noReturn = noReturn func.noReturn = noReturn
call = new Call func, args call = new Call func, args
if statement then Block.wrap [call] else call if statement then Block.wrap [call] else call
@ -1954,7 +1944,7 @@ Closure =
unfoldSoak = (o, parent, name) -> unfoldSoak = (o, parent, name) ->
return unless ifn = parent[name].unfoldSoak o return unless ifn = parent[name].unfoldSoak o
parent[name] = ifn.body parent[name] = ifn.body
ifn.body = Value.wrap parent ifn.body = new Value parent
ifn ifn
# Constants # Constants

View File

@ -595,6 +595,11 @@ test "#1813: Passing class definitions as expressions", ->
eq result, B eq result, B
test "#1966: external constructors should produce their return value", ->
ctor = -> {}
class A then constructor: ctor
ok (new A) not instanceof A
test "#1980: regression with an inherited class with static function members", -> test "#1980: regression with an inherited class with static function members", ->
class A class A
@ -676,27 +681,6 @@ test "#2630: class bodies can't reference arguments", ->
throws -> throws ->
CoffeeScript.compile('class Test then arguments') CoffeeScript.compile('class Test then arguments')
test "#2359: instanceof should work when extending native objects", ->
class MyError extends Error
ok new MyError instanceof MyError
test '#2359: external constructors returning "other typed" objets', ->
ctor = -> {}
class A then constructor: ctor
ok new A instanceof A
ok new ctor not instanceof A
ok new ctor not instanceof ctor
test "#2359: constructors should not return an explicit value", ->
throws -> CoffeeScript.run "class then constructor: -> return 5"
throws -> CoffeeScript.run """
class
constructor: ->
if foo
return bar: 7
baz()
"""
test "#2319: fn class n extends o.p [INDENT] x = 123", -> test "#2319: fn class n extends o.p [INDENT] x = 123", ->
first = -> first = ->
@ -706,4 +690,4 @@ test "#2319: fn class n extends o.p [INDENT] x = 123", ->
one = 1 one = 1
one: -> one one: -> one
eq new OneKeeper().one(), 1 eq new OneKeeper().one(), 1