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:
matehat
2010-03-17 14:41:09 -04:00
parent fa6f1c2fb1
commit 7129f518a4
3 changed files with 62 additions and 25 deletions

View File

@@ -918,7 +918,7 @@
// arrow, generates a wrapper that saves the current value of `this` through // arrow, generates a wrapper that saves the current value of `this` through
// a closure. // a closure.
CodeNode.prototype.compile_node = function compile_node(o) { 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'); shared_scope = del(o, 'shared_scope');
top = del(o, 'top'); top = del(o, 'top');
o.scope = shared_scope || new Scope(o.scope, this.body, this); o.scope = shared_scope || new Scope(o.scope, this.body, this);
@@ -927,22 +927,35 @@
o.indent = this.idt(this.bound ? 2 : 1); o.indent = this.idt(this.bound ? 2 : 1);
del(o, 'no_wrap'); del(o, 'no_wrap');
del(o, 'globals'); del(o, 'globals');
if (this.params[this.params.length - 1] instanceof SplatNode) { i = 0;
splat = this.params.pop(); splat = undefined;
splat.index = this.params.length; params = [];
this.body.unshift(splat); _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() { params = (function() {
_a = []; _b = this.params; _d = []; _e = params;
for (_c = 0, _d = _b.length; _c < _d; _c++) { for (_f = 0, _g = _e.length; _f < _g; _f++) {
param = _b[_c]; param = _e[_f];
_a.push(param.compile(o)); _d.push(param.compile(o));
} }
return _a; return _d;
}).call(this); }).call(this);
_e = params; _h = params;
for (_f = 0, _g = _e.length; _f < _g; _f++) { for (_i = 0, _j = _h.length; _i < _j; _i++) {
param = _e[_f]; param = _h[_i];
(o.scope.parameter(param)); (o.scope.parameter(param));
} }
code = this.body.expressions.length ? "\n" + (this.body.compile_with_declarations(o)) + "\n" : ''; 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 // Compiling a parameter splat means recovering the parameters that succeed
// the splat in the parameter list, by slicing the arguments object. // the splat in the parameter list, by slicing the arguments object.
SplatNode.prototype.compile_param = function compile_param(o) { SplatNode.prototype.compile_param = function compile_param(o) {
var name; var _a, _b, _c, i, name, trailing;
name = this.name.compile(o); name = this.name.compile(o);
o.scope.find(name); 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 // A compiling a splat as a destructuring assignment means slicing arguments
// from the right-hand-side's corresponding array. // from the right-hand-side's corresponding array.

View File

@@ -717,11 +717,21 @@ exports.CodeNode: class CodeNode extends BaseNode
o.indent: @idt(if @bound then 2 else 1) o.indent: @idt(if @bound then 2 else 1)
del o, 'no_wrap' del o, 'no_wrap'
del o, 'globals' del o, 'globals'
if @params[@params.length - 1] instanceof SplatNode i: 0
splat: @params.pop() splat: undefined
splat.index: @params.length params: []
@body.unshift(splat) for param in @params
params: (param.compile(o) 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 (o.scope.parameter(param)) for param in params
code: if @body.expressions.length then "\n${ @body.compile_with_declarations(o) }\n" else '' code: if @body.expressions.length then "\n${ @body.compile_with_declarations(o) }\n" else ''
name_part: if @name then ' ' + @name else '' name_part: if @name then ' ' + @name else ''
@@ -768,7 +778,11 @@ exports.SplatNode: class SplatNode extends BaseNode
compile_param: (o) -> compile_param: (o) ->
name: @name.compile(o) name: @name.compile(o)
o.scope.find name 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 # A compiling a splat as a destructuring assignment means slicing arguments
# from the right-hand-side's corresponding array. # from the right-hand-side's corresponding array.

View File

@@ -6,13 +6,14 @@ result: func 1, 2, 3, 4, 5
ok result is "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 gold: first
silver: second silver: second
bronze: third bronze: third
the_field: rest the_field: rest.concat([last])
last: unlucky
contenders: [ contenders: [
"Michael Phelps" "Michael Phelps"
@@ -32,6 +33,7 @@ medalists "Mighty Mouse", contenders...
ok gold is "Mighty Mouse" ok gold is "Mighty Mouse"
ok silver is "Michael Phelps" ok silver is "Michael Phelps"
ok bronze is "Liu Xiang" ok bronze is "Liu Xiang"
ok last is "Usain Bolt"
ok the_field.length is 8 ok the_field.length is 8
contenders.reverse() contenders.reverse()
@@ -40,6 +42,7 @@ medalists contenders[0...2]..., "Mighty Mouse", contenders[2...contenders.length
ok gold is "Usain Bolt" ok gold is "Usain Bolt"
ok silver is "Asafa Powell" ok silver is "Asafa Powell"
ok bronze is "Mighty Mouse" ok bronze is "Mighty Mouse"
ok last is "Michael Phelps"
ok the_field.length is 8 ok the_field.length is 8
obj: { obj: {