Added the ability for function declaration to have a splat at an arbitrary position, not just at the end. Still restrict their number to 1. Adjusted tests accordingly.
This commit is contained in:
parent
fa6f1c2fb1
commit
7129f518a4
50
lib/nodes.js
50
lib/nodes.js
|
@ -918,7 +918,7 @@
|
|||
// arrow, generates a wrapper that saves the current value of `this` through
|
||||
// a closure.
|
||||
CodeNode.prototype.compile_node = function compile_node(o) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, code, func, inner, name_part, param, params, shared_scope, splat, top;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, code, func, i, inner, name_part, param, params, shared_scope, splat, top;
|
||||
shared_scope = del(o, 'shared_scope');
|
||||
top = del(o, 'top');
|
||||
o.scope = shared_scope || new Scope(o.scope, this.body, this);
|
||||
|
@ -927,22 +927,35 @@
|
|||
o.indent = this.idt(this.bound ? 2 : 1);
|
||||
del(o, 'no_wrap');
|
||||
del(o, 'globals');
|
||||
if (this.params[this.params.length - 1] instanceof SplatNode) {
|
||||
splat = this.params.pop();
|
||||
splat.index = this.params.length;
|
||||
this.body.unshift(splat);
|
||||
i = 0;
|
||||
splat = undefined;
|
||||
params = [];
|
||||
_a = this.params;
|
||||
for (_b = 0, _c = _a.length; _b < _c; _b++) {
|
||||
param = _a[_b];
|
||||
if (param instanceof SplatNode && !(typeof splat !== "undefined" && splat !== null)) {
|
||||
splat = param;
|
||||
splat.index = i;
|
||||
this.body.unshift(splat);
|
||||
splat.trailings = [];
|
||||
} else if ((typeof splat !== "undefined" && splat !== null)) {
|
||||
splat.trailings.push(param);
|
||||
} else {
|
||||
params.push(param);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
params = (function() {
|
||||
_a = []; _b = this.params;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
param = _b[_c];
|
||||
_a.push(param.compile(o));
|
||||
_d = []; _e = params;
|
||||
for (_f = 0, _g = _e.length; _f < _g; _f++) {
|
||||
param = _e[_f];
|
||||
_d.push(param.compile(o));
|
||||
}
|
||||
return _a;
|
||||
return _d;
|
||||
}).call(this);
|
||||
_e = params;
|
||||
for (_f = 0, _g = _e.length; _f < _g; _f++) {
|
||||
param = _e[_f];
|
||||
_h = params;
|
||||
for (_i = 0, _j = _h.length; _i < _j; _i++) {
|
||||
param = _h[_i];
|
||||
(o.scope.parameter(param));
|
||||
}
|
||||
code = this.body.expressions.length ? "\n" + (this.body.compile_with_declarations(o)) + "\n" : '';
|
||||
|
@ -1011,10 +1024,17 @@
|
|||
// Compiling a parameter splat means recovering the parameters that succeed
|
||||
// the splat in the parameter list, by slicing the arguments object.
|
||||
SplatNode.prototype.compile_param = function compile_param(o) {
|
||||
var name;
|
||||
var _a, _b, _c, i, name, trailing;
|
||||
name = this.name.compile(o);
|
||||
o.scope.find(name);
|
||||
return '' + name + " = Array.prototype.slice.call(arguments, " + this.index + ")";
|
||||
i = 0;
|
||||
_a = this.trailings;
|
||||
for (_b = 0, _c = _a.length; _b < _c; _b++) {
|
||||
trailing = _a[_b];
|
||||
o.scope.assign(trailing.compile(o), "arguments[arguments.length - " + this.trailings.length + " + " + i + "]");
|
||||
i += 1;
|
||||
}
|
||||
return '' + name + " = Array.prototype.slice.call(arguments, " + this.index + ", arguments.length - " + (this.trailings.length) + ")";
|
||||
};
|
||||
// A compiling a splat as a destructuring assignment means slicing arguments
|
||||
// from the right-hand-side's corresponding array.
|
||||
|
|
|
@ -717,11 +717,21 @@ exports.CodeNode: class CodeNode extends BaseNode
|
|||
o.indent: @idt(if @bound then 2 else 1)
|
||||
del o, 'no_wrap'
|
||||
del o, 'globals'
|
||||
if @params[@params.length - 1] instanceof SplatNode
|
||||
splat: @params.pop()
|
||||
splat.index: @params.length
|
||||
@body.unshift(splat)
|
||||
params: (param.compile(o) for param in @params)
|
||||
i: 0
|
||||
splat: undefined
|
||||
params: []
|
||||
for param in @params
|
||||
if param instanceof SplatNode and not splat?
|
||||
splat: param
|
||||
splat.index: i
|
||||
@body.unshift(splat)
|
||||
splat.trailings: []
|
||||
else if splat?
|
||||
splat.trailings.push(param)
|
||||
else
|
||||
params.push(param)
|
||||
i += 1
|
||||
params: (param.compile(o) for param in params)
|
||||
(o.scope.parameter(param)) for param in params
|
||||
code: if @body.expressions.length then "\n${ @body.compile_with_declarations(o) }\n" else ''
|
||||
name_part: if @name then ' ' + @name else ''
|
||||
|
@ -768,8 +778,12 @@ exports.SplatNode: class SplatNode extends BaseNode
|
|||
compile_param: (o) ->
|
||||
name: @name.compile(o)
|
||||
o.scope.find name
|
||||
"$name = Array.prototype.slice.call(arguments, $@index)"
|
||||
|
||||
i: 0
|
||||
for trailing in @trailings
|
||||
o.scope.assign(trailing.compile(o), "arguments[arguments.length - $@trailings.length + $i]")
|
||||
i += 1
|
||||
"$name = Array.prototype.slice.call(arguments, $@index, arguments.length - ${@trailings.length})"
|
||||
|
||||
# A compiling a splat as a destructuring assignment means slicing arguments
|
||||
# from the right-hand-side's corresponding array.
|
||||
compile_value: (o, name, index) ->
|
||||
|
|
|
@ -6,13 +6,14 @@ result: func 1, 2, 3, 4, 5
|
|||
ok result is "3 4 5"
|
||||
|
||||
|
||||
gold: silver: bronze: the_field: null
|
||||
gold: silver: bronze: the_field: last: null
|
||||
|
||||
medalists: (first, second, third, rest...) ->
|
||||
medalists: (first, second, third, rest..., unlucky) ->
|
||||
gold: first
|
||||
silver: second
|
||||
bronze: third
|
||||
the_field: rest
|
||||
the_field: rest.concat([last])
|
||||
last: unlucky
|
||||
|
||||
contenders: [
|
||||
"Michael Phelps"
|
||||
|
@ -32,6 +33,7 @@ medalists "Mighty Mouse", contenders...
|
|||
ok gold is "Mighty Mouse"
|
||||
ok silver is "Michael Phelps"
|
||||
ok bronze is "Liu Xiang"
|
||||
ok last is "Usain Bolt"
|
||||
ok the_field.length is 8
|
||||
|
||||
contenders.reverse()
|
||||
|
@ -40,6 +42,7 @@ 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 last is "Michael Phelps"
|
||||
ok the_field.length is 8
|
||||
|
||||
obj: {
|
||||
|
|
Loading…
Reference in New Issue