adding support for calling variadic functions with less than the requested number of arguments.

This commit is contained in:
Jeremy Ashkenas 2010-05-08 12:44:54 -04:00
parent be72120311
commit 9a7420ccd0
3 changed files with 32 additions and 9 deletions

View File

@ -1060,8 +1060,9 @@
if (param instanceof SplatNode && !(typeof splat !== "undefined" && splat !== null)) {
splat = param;
splat.index = i;
this.body.unshift(splat);
splat.trailings = [];
splat.arglength = this.params.length;
this.body.unshift(splat);
} else if ((typeof splat !== "undefined" && splat !== null)) {
splat.trailings.push(param);
} else {
@ -1153,15 +1154,18 @@
// 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 _b, _c, len, name, pos, trailing;
var _b, _c, idx, len, name, pos, trailing, variadic;
name = this.name.compile(o);
o.scope.find(name);
len = o.scope.free_variable();
o.scope.assign(len, "arguments.length");
variadic = o.scope.free_variable();
o.scope.assign(variadic, ("" + len + " >= " + this.arglength));
_b = this.trailings;
for (pos = 0, _c = _b.length; pos < _c; pos++) {
trailing = _b[pos];
o.scope.assign(trailing.compile(o), ("arguments[" + len + " - " + (this.trailings.length + pos) + "]"));
for (idx = 0, _c = _b.length; idx < _c; idx++) {
trailing = _b[idx];
pos = this.trailings.length - idx;
o.scope.assign(trailing.compile(o), ("arguments[" + variadic + " ? " + len + " - " + pos + " : " + (this.index + idx) + "]"));
}
return "" + name + " = " + (utility('slice')) + ".call(arguments, " + this.index + ", " + len + " - " + (this.trailings.length) + ")";
};

View File

@ -773,8 +773,9 @@ exports.CodeNode: class CodeNode extends BaseNode
if param instanceof SplatNode and not splat?
splat: param
splat.index: i
@body.unshift(splat)
splat.trailings: []
splat.arglength: @params.length
@body.unshift(splat)
else if splat?
splat.trailings.push(param)
else
@ -830,8 +831,11 @@ exports.SplatNode: class SplatNode extends BaseNode
o.scope.find name
len: o.scope.free_variable()
o.scope.assign len, "arguments.length"
for trailing, pos in @trailings
o.scope.assign(trailing.compile(o), "arguments[$len - ${@trailings.length + pos}]")
variadic: o.scope.free_variable()
o.scope.assign variadic, "$len >= $@arglength"
for trailing, idx in @trailings
pos: @trailings.length - idx
o.scope.assign(trailing.compile(o), "arguments[$variadic ? $len - $pos : ${@index + idx}]")
"$name = ${utility('slice')}.call(arguments, $@index, $len - ${@trailings.length})"
# A compiling a splat as a destructuring assignment means slicing arguments

View File

@ -89,4 +89,19 @@ class Child extends Parent
nums: [3, 2, 1]
super nums...
ok (new Child()).meth().join(' ') is '3 2 1'
ok (new Child()).meth().join(' ') is '3 2 1'
# Functions with splats being called with too few arguments.
pen: null
method: (first, variable..., penultimate, ultimate) ->
pen: penultimate
method 1, 2, 3, 4, 5, 6, 7, 8, 9
ok pen is 8
method 1, 2, 3
ok pen is 2
method 1, 2
ok pen is 2