Added the ability to put as many splats in a function call as one wants. Also optimized the assembly into static arrays. Adjusted tests accordingly.
This commit is contained in:
parent
70cfc9500e
commit
2bd1c3acca
61
lib/nodes.js
61
lib/nodes.js
|
@ -431,17 +431,21 @@
|
|||
};
|
||||
// Compile a vanilla function call.
|
||||
CallNode.prototype.compile_node = function compile_node(o) {
|
||||
var _a, _b, _c, _d, arg, args;
|
||||
if (this.args[this.args.length - 1] instanceof SplatNode) {
|
||||
return this.compile_splat(o);
|
||||
var _a, _b, _c, _d, _e, _f, _g, arg, args;
|
||||
_a = this.args;
|
||||
for (_b = 0, _c = _a.length; _b < _c; _b++) {
|
||||
arg = _a[_b];
|
||||
if (arg instanceof SplatNode) {
|
||||
return this.compile_splat(o);
|
||||
}
|
||||
}
|
||||
args = (function() {
|
||||
_a = []; _b = this.args;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
arg = _b[_c];
|
||||
_a.push(arg.compile(o));
|
||||
_d = []; _e = this.args;
|
||||
for (_f = 0, _g = _e.length; _f < _g; _f++) {
|
||||
arg = _e[_f];
|
||||
_d.push(arg.compile(o));
|
||||
}
|
||||
return _a;
|
||||
return _d;
|
||||
}).call(this).join(', ');
|
||||
if (this.variable === 'super') {
|
||||
return this.compile_super(args, o);
|
||||
|
@ -459,7 +463,7 @@
|
|||
// If you call a function with a splat, it's converted into a JavaScript
|
||||
// `.apply()` call to allow an array of arguments to be passed.
|
||||
CallNode.prototype.compile_splat = function compile_splat(o) {
|
||||
var _a, _b, _c, arg, args, code, i, meth, obj, temp;
|
||||
var meth, obj, temp;
|
||||
meth = this.variable.compile(o);
|
||||
obj = this.variable.source || 'this';
|
||||
if (obj.match(/\(/)) {
|
||||
|
@ -467,19 +471,34 @@
|
|||
obj = temp;
|
||||
meth = "(" + temp + " = " + (this.variable.source) + ")" + (this.variable.last);
|
||||
}
|
||||
args = (function() {
|
||||
_a = []; _b = this.args;
|
||||
for (i = 0, _c = _b.length; i < _c; i++) {
|
||||
arg = _b[i];
|
||||
_a.push((function() {
|
||||
code = arg.compile(o);
|
||||
code = arg instanceof SplatNode ? code : "[" + code + "]";
|
||||
return i === 0 ? code : ".concat(" + code + ")";
|
||||
}).call(this));
|
||||
return '' + this.prefix + (meth) + ".apply(" + obj + ", " + (this.compile_splat_arguments(o)) + ")";
|
||||
};
|
||||
// Converts arbitrary number of arguments, mixed with splats, to
|
||||
// a proper array to pass to an `.apply()` call
|
||||
CallNode.prototype.compile_splat_arguments = function compile_splat_arguments(o) {
|
||||
var _a, _b, _c, arg, args, code, i, prev;
|
||||
args = [];
|
||||
i = 0;
|
||||
_a = this.args;
|
||||
for (_b = 0, _c = _a.length; _b < _c; _b++) {
|
||||
arg = _a[_b];
|
||||
code = arg.compile(o);
|
||||
if (!(arg instanceof SplatNode)) {
|
||||
prev = args[i - 1];
|
||||
if (i === 1 && prev[0] === '[' && prev[prev.length - 1] === ']') {
|
||||
args[i - 1] = '' + (prev.slice(0, prev.length - 2)) + ", " + code + "]";
|
||||
continue;
|
||||
} else if (i > 1 && prev[8] === '[' && prev[prev.length - 2] === ']') {
|
||||
args[i - 1] = '' + (prev.slice(0, prev.length - 2)) + ", " + code + "])";
|
||||
continue;
|
||||
} else {
|
||||
code = "[" + code + "]";
|
||||
}
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
return '' + this.prefix + (meth) + ".apply(" + obj + ", " + (args.join('')) + ")";
|
||||
args.push(i === 0 ? code : ".concat(" + code + ")");
|
||||
i += 1;
|
||||
}
|
||||
return args.join('');
|
||||
};
|
||||
return CallNode;
|
||||
}).call(this);
|
||||
|
|
|
@ -338,7 +338,8 @@ exports.CallNode: class CallNode extends BaseNode
|
|||
|
||||
# Compile a vanilla function call.
|
||||
compile_node: (o) ->
|
||||
return @compile_splat(o) if @args[@args.length - 1] instanceof SplatNode
|
||||
for arg in @args
|
||||
return @compile_splat(o) if arg instanceof SplatNode
|
||||
args: (arg.compile(o) for arg in @args).join(', ')
|
||||
return @compile_super(args, o) if @variable is 'super'
|
||||
"$@prefix${@variable.compile(o)}($args)"
|
||||
|
@ -362,11 +363,28 @@ exports.CallNode: class CallNode extends BaseNode
|
|||
temp: o.scope.free_variable()
|
||||
obj: temp
|
||||
meth: "($temp = ${ @variable.source })${ @variable.last }"
|
||||
args: for arg, i in @args
|
||||
"$@prefix${meth}.apply($obj, ${ @compile_splat_arguments(o) })"
|
||||
|
||||
# Converts arbitrary number of arguments, mixed with splats, to
|
||||
# a proper array to pass to an `.apply()` call
|
||||
compile_splat_arguments: (o) ->
|
||||
args: []
|
||||
i: 0
|
||||
for arg in @args
|
||||
code: arg.compile o
|
||||
code: if arg instanceof SplatNode then code else "[$code]"
|
||||
if i is 0 then code else ".concat($code)"
|
||||
"$@prefix${meth}.apply($obj, ${ args.join('') })"
|
||||
if not (arg instanceof SplatNode)
|
||||
prev: args[i - 1]
|
||||
if i is 1 and prev[0] is '[' and prev[prev.length - 1] is ']'
|
||||
args[i - 1] = "${prev[0...prev.length - 2]}, $code]"
|
||||
continue
|
||||
else if i > 1 and prev[8] is '[' and prev[prev.length - 2] is ']'
|
||||
args[i - 1] = "${prev[0...prev.length - 2]}, $code])"
|
||||
continue
|
||||
else
|
||||
code: "[$code]"
|
||||
args.push(if i is 0 then code else ".concat($code)")
|
||||
i += 1
|
||||
args.join('')
|
||||
|
||||
#### ExtendsNode
|
||||
|
||||
|
|
|
@ -34,6 +34,13 @@ ok silver is "Michael Phelps"
|
|||
ok bronze is "Liu Xiang"
|
||||
ok the_field.length is 8
|
||||
|
||||
contenders.reverse()
|
||||
medalists contenders[0...2]..., "Mighty Mouse", contenders[2...contenders.length]...
|
||||
|
||||
ok gold is "Usain Bolt"
|
||||
ok silver is "Asafa Powell"
|
||||
ok bronze is "Mighty Mouse"
|
||||
ok the_field.length is 8
|
||||
|
||||
obj: {
|
||||
name: 'bob'
|
||||
|
|
Loading…
Reference in New Issue