mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
Merge branch 'issue1313'
This commit is contained in:
129
lib/nodes.js
129
lib/nodes.js
@@ -167,10 +167,10 @@
|
||||
return Base;
|
||||
})();
|
||||
exports.Block = Block = (function() {
|
||||
__extends(Block, Base);
|
||||
function Block(nodes) {
|
||||
this.expressions = compact(flatten(nodes || []));
|
||||
}
|
||||
__extends(Block, Base);
|
||||
Block.prototype.children = ['expressions'];
|
||||
Block.prototype.push = function(node) {
|
||||
this.expressions.push(node);
|
||||
@@ -319,10 +319,10 @@
|
||||
return Block;
|
||||
})();
|
||||
exports.Literal = Literal = (function() {
|
||||
__extends(Literal, Base);
|
||||
function Literal(value) {
|
||||
this.value = value;
|
||||
}
|
||||
__extends(Literal, Base);
|
||||
Literal.prototype.makeReturn = function() {
|
||||
if (this.isStatement()) {
|
||||
return this;
|
||||
@@ -366,12 +366,12 @@
|
||||
return Literal;
|
||||
})();
|
||||
exports.Return = Return = (function() {
|
||||
__extends(Return, Base);
|
||||
function Return(expr) {
|
||||
if (expr && !expr.unwrap().isUndefined) {
|
||||
this.expression = expr;
|
||||
}
|
||||
}
|
||||
__extends(Return, Base);
|
||||
Return.prototype.children = ['expression'];
|
||||
Return.prototype.isStatement = YES;
|
||||
Return.prototype.makeReturn = THIS;
|
||||
@@ -391,6 +391,7 @@
|
||||
return Return;
|
||||
})();
|
||||
exports.Value = Value = (function() {
|
||||
__extends(Value, Base);
|
||||
function Value(base, props, tag) {
|
||||
if (!props && base instanceof Value) {
|
||||
return base;
|
||||
@@ -402,7 +403,6 @@
|
||||
}
|
||||
return this;
|
||||
}
|
||||
__extends(Value, Base);
|
||||
Value.prototype.children = ['base', 'properties'];
|
||||
Value.prototype.push = function(prop) {
|
||||
this.properties.push(prop);
|
||||
@@ -536,10 +536,10 @@
|
||||
return Value;
|
||||
})();
|
||||
exports.Comment = Comment = (function() {
|
||||
__extends(Comment, Base);
|
||||
function Comment(comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
__extends(Comment, Base);
|
||||
Comment.prototype.isStatement = YES;
|
||||
Comment.prototype.makeReturn = THIS;
|
||||
Comment.prototype.compileNode = function(o, level) {
|
||||
@@ -553,6 +553,7 @@
|
||||
return Comment;
|
||||
})();
|
||||
exports.Call = Call = (function() {
|
||||
__extends(Call, Base);
|
||||
function Call(variable, args, soak) {
|
||||
this.args = args != null ? args : [];
|
||||
this.soak = soak;
|
||||
@@ -560,7 +561,6 @@
|
||||
this.isSuper = variable === 'super';
|
||||
this.variable = this.isSuper ? null : variable;
|
||||
}
|
||||
__extends(Call, Base);
|
||||
Call.prototype.children = ['variable', 'args'];
|
||||
Call.prototype.newInstance = function() {
|
||||
var base;
|
||||
@@ -720,11 +720,11 @@
|
||||
return Call;
|
||||
})();
|
||||
exports.Extends = Extends = (function() {
|
||||
__extends(Extends, Base);
|
||||
function Extends(child, parent) {
|
||||
this.child = child;
|
||||
this.parent = parent;
|
||||
}
|
||||
__extends(Extends, Base);
|
||||
Extends.prototype.children = ['child', 'parent'];
|
||||
Extends.prototype.compile = function(o) {
|
||||
utility('hasProp');
|
||||
@@ -733,13 +733,13 @@
|
||||
return Extends;
|
||||
})();
|
||||
exports.Access = Access = (function() {
|
||||
__extends(Access, Base);
|
||||
function Access(name, tag) {
|
||||
this.name = name;
|
||||
this.name.asKey = true;
|
||||
this.proto = tag === 'proto' ? '.prototype' : '';
|
||||
this.soak = tag === 'soak';
|
||||
}
|
||||
__extends(Access, Base);
|
||||
Access.prototype.children = ['name'];
|
||||
Access.prototype.compile = function(o) {
|
||||
var name;
|
||||
@@ -750,10 +750,10 @@
|
||||
return Access;
|
||||
})();
|
||||
exports.Index = Index = (function() {
|
||||
__extends(Index, Base);
|
||||
function Index(index) {
|
||||
this.index = index;
|
||||
}
|
||||
__extends(Index, Base);
|
||||
Index.prototype.children = ['index'];
|
||||
Index.prototype.compile = function(o) {
|
||||
return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LEVEL_PAREN)) + "]");
|
||||
@@ -764,8 +764,8 @@
|
||||
return Index;
|
||||
})();
|
||||
exports.Range = Range = (function() {
|
||||
Range.prototype.children = ['from', 'to'];
|
||||
__extends(Range, Base);
|
||||
Range.prototype.children = ['from', 'to'];
|
||||
function Range(from, to, tag) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
@@ -848,8 +848,8 @@
|
||||
return Range;
|
||||
})();
|
||||
exports.Slice = Slice = (function() {
|
||||
Slice.prototype.children = ['range'];
|
||||
__extends(Slice, Base);
|
||||
Slice.prototype.children = ['range'];
|
||||
function Slice(range) {
|
||||
this.range = range;
|
||||
Slice.__super__.constructor.call(this);
|
||||
@@ -867,11 +867,11 @@
|
||||
return Slice;
|
||||
})();
|
||||
exports.Obj = Obj = (function() {
|
||||
__extends(Obj, Base);
|
||||
function Obj(props, generated) {
|
||||
this.generated = generated != null ? generated : false;
|
||||
this.objects = this.properties = props || [];
|
||||
}
|
||||
__extends(Obj, Base);
|
||||
Obj.prototype.children = ['properties'];
|
||||
Obj.prototype.compileNode = function(o) {
|
||||
var i, idt, indent, join, lastNoncom, node, obj, prop, props, _i, _len;
|
||||
@@ -935,10 +935,10 @@
|
||||
return Obj;
|
||||
})();
|
||||
exports.Arr = Arr = (function() {
|
||||
__extends(Arr, Base);
|
||||
function Arr(objs) {
|
||||
this.objects = objs || [];
|
||||
}
|
||||
__extends(Arr, Base);
|
||||
Arr.prototype.children = ['objects'];
|
||||
Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects;
|
||||
Arr.prototype.compileNode = function(o) {
|
||||
@@ -980,6 +980,7 @@
|
||||
return Arr;
|
||||
})();
|
||||
exports.Class = Class = (function() {
|
||||
__extends(Class, Base);
|
||||
function Class(variable, parent, body) {
|
||||
this.variable = variable;
|
||||
this.parent = parent;
|
||||
@@ -987,7 +988,6 @@
|
||||
this.boundFuncs = [];
|
||||
this.body.classBody = true;
|
||||
}
|
||||
__extends(Class, Base);
|
||||
Class.prototype.children = ['variable', 'parent', 'body'];
|
||||
Class.prototype.determineName = function() {
|
||||
var decl, tail;
|
||||
@@ -1026,39 +1026,44 @@
|
||||
}
|
||||
};
|
||||
Class.prototype.addProperties = function(node, name) {
|
||||
var assign, base, func, props, _results;
|
||||
var assign, base, exprs, func, props;
|
||||
props = node.base.properties.slice(0);
|
||||
_results = [];
|
||||
while (assign = props.shift()) {
|
||||
if (assign instanceof Assign) {
|
||||
base = assign.variable.base;
|
||||
delete assign.context;
|
||||
func = assign.value;
|
||||
if (base.value === 'constructor') {
|
||||
if (this.ctor) {
|
||||
throw new Error('cannot define more than one constructor in a class');
|
||||
}
|
||||
if (func.bound) {
|
||||
throw new Error('cannot define a constructor as a bound function');
|
||||
}
|
||||
if (func instanceof Code) {
|
||||
assign = this.ctor = func;
|
||||
exprs = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
while (assign = props.shift()) {
|
||||
if (assign instanceof Assign) {
|
||||
base = assign.variable.base;
|
||||
delete assign.context;
|
||||
func = assign.value;
|
||||
if (base.value === 'constructor') {
|
||||
if (this.ctor) {
|
||||
throw new Error('cannot define more than one constructor in a class');
|
||||
}
|
||||
if (func.bound) {
|
||||
throw new Error('cannot define a constructor as a bound function');
|
||||
}
|
||||
if (func instanceof Code) {
|
||||
assign = this.ctor = func;
|
||||
} else {
|
||||
assign = null;
|
||||
this.ctor = new Assign(new Value(new Literal(name)), func);
|
||||
}
|
||||
} else {
|
||||
assign = this.ctor = new Assign(new Value(new Literal(name)), func);
|
||||
}
|
||||
} else {
|
||||
if (!assign.variable["this"]) {
|
||||
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]);
|
||||
}
|
||||
if (func instanceof Code && func.bound) {
|
||||
this.boundFuncs.push(base);
|
||||
func.bound = false;
|
||||
if (!assign.variable["this"]) {
|
||||
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]);
|
||||
}
|
||||
if (func instanceof Code && func.bound) {
|
||||
this.boundFuncs.push(base);
|
||||
func.bound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
_results.push(assign);
|
||||
}
|
||||
_results.push(assign);
|
||||
}
|
||||
return _results;
|
||||
return _results;
|
||||
}).call(this);
|
||||
return compact(exprs);
|
||||
};
|
||||
Class.prototype.walkBody = function(name) {
|
||||
return this.traverseChildren(false, __bind(function(child) {
|
||||
@@ -1091,15 +1096,23 @@
|
||||
return this.ctor.noReturn = true;
|
||||
};
|
||||
Class.prototype.compileNode = function(o) {
|
||||
var decl, klass, lname, name;
|
||||
var decl, extension, klass, lname, name;
|
||||
decl = this.determineName();
|
||||
name = decl || this.name || '_Class';
|
||||
lname = new Literal(name);
|
||||
this.setContext(name);
|
||||
this.walkBody(name);
|
||||
this.ensureConstructor(name);
|
||||
if (!(this.ctor instanceof Code)) {
|
||||
this.body.expressions.unshift(this.ctor);
|
||||
}
|
||||
if (this.parent) {
|
||||
this.body.expressions.splice(1, 0, new Extends(lname, this.parent));
|
||||
extension = new Extends(lname, this.parent);
|
||||
if (this.ctor instanceof Code) {
|
||||
this.body.expressions.unshift(extension);
|
||||
} else {
|
||||
this.body.expressions.splice(1, 0, extension);
|
||||
}
|
||||
}
|
||||
this.body.expressions.push(lname);
|
||||
this.addBoundFunctions(o);
|
||||
@@ -1112,13 +1125,13 @@
|
||||
return Class;
|
||||
})();
|
||||
exports.Assign = Assign = (function() {
|
||||
__extends(Assign, Base);
|
||||
function Assign(variable, value, context, options) {
|
||||
this.variable = variable;
|
||||
this.value = value;
|
||||
this.context = context;
|
||||
this.param = options && options.param;
|
||||
}
|
||||
__extends(Assign, Base);
|
||||
Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.|\S+?)?\b([$A-Za-z_][$\w\x7f-\uffff]*)$/;
|
||||
Assign.prototype.children = ['variable', 'value'];
|
||||
Assign.prototype.assigns = function(name) {
|
||||
@@ -1291,6 +1304,7 @@
|
||||
return Assign;
|
||||
})();
|
||||
exports.Code = Code = (function() {
|
||||
__extends(Code, Base);
|
||||
function Code(params, body, tag) {
|
||||
this.params = params || [];
|
||||
this.body = body || new Block;
|
||||
@@ -1299,7 +1313,6 @@
|
||||
this.context = 'this';
|
||||
}
|
||||
}
|
||||
__extends(Code, Base);
|
||||
Code.prototype.children = ['params', 'body'];
|
||||
Code.prototype.isStatement = function() {
|
||||
return !!this.ctor;
|
||||
@@ -1402,12 +1415,12 @@
|
||||
return Code;
|
||||
})();
|
||||
exports.Param = Param = (function() {
|
||||
__extends(Param, Base);
|
||||
function Param(name, value, splat) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.splat = splat;
|
||||
}
|
||||
__extends(Param, Base);
|
||||
Param.prototype.children = ['name', 'value'];
|
||||
Param.prototype.compile = function(o) {
|
||||
return this.name.compile(o, LEVEL_LIST);
|
||||
@@ -1438,8 +1451,8 @@
|
||||
return Param;
|
||||
})();
|
||||
exports.Splat = Splat = (function() {
|
||||
Splat.prototype.children = ['name'];
|
||||
__extends(Splat, Base);
|
||||
Splat.prototype.children = ['name'];
|
||||
Splat.prototype.isAssignable = YES;
|
||||
function Splat(name) {
|
||||
this.name = name.compile ? name : new Literal(name);
|
||||
@@ -1494,11 +1507,11 @@
|
||||
return Splat;
|
||||
})();
|
||||
exports.While = While = (function() {
|
||||
__extends(While, Base);
|
||||
function While(condition, options) {
|
||||
this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;
|
||||
this.guard = options != null ? options.guard : void 0;
|
||||
}
|
||||
__extends(While, Base);
|
||||
While.prototype.children = ['condition', 'guard', 'body'];
|
||||
While.prototype.isStatement = YES;
|
||||
While.prototype.makeReturn = function() {
|
||||
@@ -1555,6 +1568,7 @@
|
||||
})();
|
||||
exports.Op = Op = (function() {
|
||||
var CONVERSIONS, INVERSIONS;
|
||||
__extends(Op, Base);
|
||||
function Op(op, first, second, flip) {
|
||||
var call;
|
||||
if (op === 'in') {
|
||||
@@ -1579,7 +1593,6 @@
|
||||
this.flip = !!flip;
|
||||
return this;
|
||||
}
|
||||
__extends(Op, Base);
|
||||
CONVERSIONS = {
|
||||
'==': '===',
|
||||
'!=': '!==',
|
||||
@@ -1695,11 +1708,11 @@
|
||||
return Op;
|
||||
})();
|
||||
exports.In = In = (function() {
|
||||
__extends(In, Base);
|
||||
function In(object, array) {
|
||||
this.object = object;
|
||||
this.array = array;
|
||||
}
|
||||
__extends(In, Base);
|
||||
In.prototype.children = ['object', 'array'];
|
||||
In.prototype.invert = NEGATE;
|
||||
In.prototype.compileNode = function(o) {
|
||||
@@ -1753,13 +1766,13 @@
|
||||
return In;
|
||||
})();
|
||||
exports.Try = Try = (function() {
|
||||
__extends(Try, Base);
|
||||
function Try(attempt, error, recovery, ensure) {
|
||||
this.attempt = attempt;
|
||||
this.error = error;
|
||||
this.recovery = recovery;
|
||||
this.ensure = ensure;
|
||||
}
|
||||
__extends(Try, Base);
|
||||
Try.prototype.children = ['attempt', 'recovery', 'ensure'];
|
||||
Try.prototype.isStatement = YES;
|
||||
Try.prototype.jumps = function(o) {
|
||||
@@ -1785,10 +1798,10 @@
|
||||
return Try;
|
||||
})();
|
||||
exports.Throw = Throw = (function() {
|
||||
__extends(Throw, Base);
|
||||
function Throw(expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
__extends(Throw, Base);
|
||||
Throw.prototype.children = ['expression'];
|
||||
Throw.prototype.isStatement = YES;
|
||||
Throw.prototype.jumps = NO;
|
||||
@@ -1799,10 +1812,10 @@
|
||||
return Throw;
|
||||
})();
|
||||
exports.Existence = Existence = (function() {
|
||||
__extends(Existence, Base);
|
||||
function Existence(expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
__extends(Existence, Base);
|
||||
Existence.prototype.children = ['expression'];
|
||||
Existence.prototype.invert = NEGATE;
|
||||
Existence.prototype.compileNode = function(o) {
|
||||
@@ -1818,10 +1831,10 @@
|
||||
return Existence;
|
||||
})();
|
||||
exports.Parens = Parens = (function() {
|
||||
__extends(Parens, Base);
|
||||
function Parens(body) {
|
||||
this.body = body;
|
||||
}
|
||||
__extends(Parens, Base);
|
||||
Parens.prototype.children = ['body'];
|
||||
Parens.prototype.unwrap = function() {
|
||||
return this.body;
|
||||
@@ -1850,6 +1863,7 @@
|
||||
return Parens;
|
||||
})();
|
||||
exports.For = For = (function() {
|
||||
__extends(For, Base);
|
||||
function For(body, source) {
|
||||
var _ref2;
|
||||
this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index;
|
||||
@@ -1872,7 +1886,6 @@
|
||||
}
|
||||
this.returns = false;
|
||||
}
|
||||
__extends(For, Base);
|
||||
For.prototype.children = ['body', 'source', 'guard', 'step'];
|
||||
For.prototype.isStatement = YES;
|
||||
For.prototype.jumps = While.prototype.jumps;
|
||||
@@ -1990,12 +2003,12 @@
|
||||
return For;
|
||||
})();
|
||||
exports.Switch = Switch = (function() {
|
||||
__extends(Switch, Base);
|
||||
function Switch(subject, cases, otherwise) {
|
||||
this.subject = subject;
|
||||
this.cases = cases;
|
||||
this.otherwise = otherwise;
|
||||
}
|
||||
__extends(Switch, Base);
|
||||
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
|
||||
Switch.prototype.isStatement = YES;
|
||||
Switch.prototype.jumps = function(o) {
|
||||
@@ -2062,6 +2075,7 @@
|
||||
return Switch;
|
||||
})();
|
||||
exports.If = If = (function() {
|
||||
__extends(If, Base);
|
||||
function If(condition, body, options) {
|
||||
this.body = body;
|
||||
if (options == null) {
|
||||
@@ -2072,7 +2086,6 @@
|
||||
this.isChain = false;
|
||||
this.soak = options.soak;
|
||||
}
|
||||
__extends(If, Base);
|
||||
If.prototype.children = ['condition', 'body', 'elseBody'];
|
||||
If.prototype.bodyNode = function() {
|
||||
var _ref2;
|
||||
|
||||
@@ -819,7 +819,7 @@ exports.Class = class Class extends Base
|
||||
# on the class.
|
||||
addProperties: (node, name) ->
|
||||
props = node.base.properties.slice 0
|
||||
while assign = props.shift()
|
||||
exprs = while assign = props.shift()
|
||||
if assign instanceof Assign
|
||||
base = assign.variable.base
|
||||
delete assign.context
|
||||
@@ -832,7 +832,8 @@ exports.Class = class Class extends Base
|
||||
if func instanceof Code
|
||||
assign = @ctor = func
|
||||
else
|
||||
assign = @ctor = new Assign(new Value(new Literal name), func)
|
||||
assign = null
|
||||
@ctor = new Assign new Value(new Literal name), func
|
||||
else
|
||||
unless assign.variable.this
|
||||
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')])
|
||||
@@ -840,6 +841,7 @@ exports.Class = class Class extends Base
|
||||
@boundFuncs.push base
|
||||
func.bound = no
|
||||
assign
|
||||
compact exprs
|
||||
|
||||
# Walk the body of the class, looking for prototype properties to be converted.
|
||||
walkBody: (name) ->
|
||||
@@ -873,7 +875,13 @@ exports.Class = class Class extends Base
|
||||
@setContext name
|
||||
@walkBody name
|
||||
@ensureConstructor name
|
||||
@body.expressions.splice 1, 0, new Extends(lname, @parent) if @parent
|
||||
@body.expressions.unshift @ctor unless @ctor instanceof Code
|
||||
if @parent
|
||||
extension = new Extends lname, @parent
|
||||
if @ctor instanceof Code
|
||||
@body.expressions.unshift extension
|
||||
else
|
||||
@body.expressions.splice 1, 0, extension
|
||||
@body.expressions.push lname
|
||||
@addBoundFunctions o
|
||||
|
||||
|
||||
@@ -278,8 +278,7 @@ test "classes with value'd constructors", ->
|
||||
|
||||
counter = 0
|
||||
classMaker = ->
|
||||
counter++
|
||||
inner = counter
|
||||
inner = ++counter
|
||||
->
|
||||
@value = inner
|
||||
|
||||
@@ -438,12 +437,27 @@ test "`new` works against bare function", ->
|
||||
Date
|
||||
|
||||
|
||||
test "a subclass should be able to set its constructor to an external function", ->
|
||||
|
||||
test "#1182: a subclass should be able to set its constructor to an external function", ->
|
||||
ctor = ->
|
||||
@val = 1
|
||||
class A
|
||||
class B extends A
|
||||
constructor: ctor
|
||||
|
||||
eq (new B).val, 1
|
||||
eq (new B).val, 1
|
||||
|
||||
test "#1182: external constructors continued", ->
|
||||
ctor = ->
|
||||
class A
|
||||
class B extends A
|
||||
method: ->
|
||||
constructor: ctor
|
||||
eq ctor, B
|
||||
ok B::method
|
||||
|
||||
test "#1313: misplaced __extends", ->
|
||||
nonce = {}
|
||||
class A
|
||||
class B extends A
|
||||
prop: nonce
|
||||
constructor: ->
|
||||
eq nonce, B::prop
|
||||
|
||||
Reference in New Issue
Block a user