mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Added function call's flexibility with splats to array literals, factoring out splat compiling, and adjusted tests
This commit is contained in:
parent
b72641693d
commit
fe04f8ce6b
3 changed files with 108 additions and 72 deletions
93
lib/nodes.js
93
lib/nodes.js
|
@ -419,6 +419,11 @@
|
||||||
exports.CallNode = (function() {
|
exports.CallNode = (function() {
|
||||||
CallNode = function CallNode(variable, args) {
|
CallNode = function CallNode(variable, args) {
|
||||||
this.children = flatten([(this.variable = variable), (this.args = (args || []))]);
|
this.children = flatten([(this.variable = variable), (this.args = (args || []))]);
|
||||||
|
this.compile_splat_arguments = (function(func, obj, args) {
|
||||||
|
return (function() {
|
||||||
|
return func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)));;
|
||||||
|
});
|
||||||
|
}(SplatNode.compile_mixed_array, this, [this.args]));
|
||||||
this.prefix = '';
|
this.prefix = '';
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
@ -473,33 +478,6 @@
|
||||||
}
|
}
|
||||||
return '' + this.prefix + (meth) + ".apply(" + obj + ", " + (this.compile_splat_arguments(o)) + ")";
|
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.substr(0, 1) === '[' && prev.substr(prev.length - 1, 1) === ']') {
|
|
||||||
args[i - 1] = '' + (prev.substr(0, prev.length - 1)) + ", " + code + "]";
|
|
||||||
continue;
|
|
||||||
} else if (i > 1 && prev.substr(0, 9) === '.concat([' && prev.substr(prev.length - 2, 2) === '])') {
|
|
||||||
args[i - 1] = '' + (prev.substr(0, prev.length - 2)) + ", " + code + "])";
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
code = "[" + code + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args.push(i === 0 ? code : ".concat(" + code + ")");
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
return args.join('');
|
|
||||||
};
|
|
||||||
return CallNode;
|
return CallNode;
|
||||||
}).call(this);
|
}).call(this);
|
||||||
//### CurryNode
|
//### CurryNode
|
||||||
|
@ -508,6 +486,11 @@
|
||||||
exports.CurryNode = (function() {
|
exports.CurryNode = (function() {
|
||||||
CurryNode = function CurryNode(meth, args) {
|
CurryNode = function CurryNode(meth, args) {
|
||||||
this.children = flatten([(this.meth = meth), (this.context = args[0]), (this.args = (args.slice(1) || []))]);
|
this.children = flatten([(this.meth = meth), (this.context = args[0]), (this.args = (args.slice(1) || []))]);
|
||||||
|
this.compile_splat_arguments = (function(func, obj, args) {
|
||||||
|
return (function() {
|
||||||
|
return func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)));;
|
||||||
|
});
|
||||||
|
}(SplatNode.compile_mixed_array, this, [this.args]));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
__extends(CurryNode, CallNode);
|
__extends(CurryNode, CallNode);
|
||||||
|
@ -725,30 +708,33 @@
|
||||||
exports.ArrayNode = (function() {
|
exports.ArrayNode = (function() {
|
||||||
ArrayNode = function ArrayNode(objects) {
|
ArrayNode = function ArrayNode(objects) {
|
||||||
this.children = (this.objects = objects || []);
|
this.children = (this.objects = objects || []);
|
||||||
|
this.compile_splat_literal = (function(func, obj, args) {
|
||||||
|
return (function() {
|
||||||
|
return func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)));;
|
||||||
|
});
|
||||||
|
}(SplatNode.compile_mixed_array, this, [this.objects]));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
__extends(ArrayNode, BaseNode);
|
__extends(ArrayNode, BaseNode);
|
||||||
ArrayNode.prototype.type = 'Array';
|
ArrayNode.prototype.type = 'Array';
|
||||||
ArrayNode.prototype.compile_node = function compile_node(o) {
|
ArrayNode.prototype.compile_node = function compile_node(o) {
|
||||||
var _a, _b, _c, code, ending, i, obj, objects;
|
var _a, _b, code, ending, i, obj, objects;
|
||||||
o.indent = this.idt(1);
|
o.indent = this.idt(1);
|
||||||
objects = (function() {
|
objects = [];
|
||||||
_a = []; _b = this.objects;
|
_a = this.objects;
|
||||||
for (i = 0, _c = _b.length; i < _c; i++) {
|
for (i = 0, _b = _a.length; i < _b; i++) {
|
||||||
obj = _b[i];
|
obj = _a[i];
|
||||||
_a.push((function() {
|
|
||||||
code = obj.compile(o);
|
code = obj.compile(o);
|
||||||
if (obj instanceof CommentNode) {
|
if (obj instanceof SplatNode) {
|
||||||
return "\n" + code + "\n" + o.indent;
|
return this.compile_splat_literal(this.objects, o);
|
||||||
|
} else if (obj instanceof CommentNode) {
|
||||||
|
objects.push("\n" + code + "\n" + o.indent);
|
||||||
} else if (i === this.objects.length - 1) {
|
} else if (i === this.objects.length - 1) {
|
||||||
return code;
|
objects.push(code);
|
||||||
} else {
|
} else {
|
||||||
return '' + code + ", ";
|
objects.push('' + code + ", ");
|
||||||
}
|
}
|
||||||
}).call(this));
|
|
||||||
}
|
}
|
||||||
return _a;
|
|
||||||
}).call(this);
|
|
||||||
objects = objects.join('');
|
objects = objects.join('');
|
||||||
ending = objects.indexOf('\n') >= 0 ? "\n" + this.tab + "]" : ']';
|
ending = objects.indexOf('\n') >= 0 ? "\n" + this.tab + "]" : ']';
|
||||||
return "[" + objects + ending;
|
return "[" + objects + ending;
|
||||||
|
@ -1074,6 +1060,33 @@
|
||||||
};
|
};
|
||||||
return SplatNode;
|
return SplatNode;
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
// Utility function that converts arbitrary number of elements, mixed with
|
||||||
|
// splats, to a proper array
|
||||||
|
SplatNode.compile_mixed_array = function compile_mixed_array(list, o) {
|
||||||
|
var _a, _b, _c, arg, args, code, i, prev;
|
||||||
|
args = [];
|
||||||
|
i = 0;
|
||||||
|
_a = list;
|
||||||
|
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.substr(0, 1) === '[' && prev.substr(prev.length - 1, 1) === ']') {
|
||||||
|
args[i - 1] = '' + (prev.substr(0, prev.length - 1)) + ", " + code + "]";
|
||||||
|
continue;
|
||||||
|
} else if (i > 1 && prev.substr(0, 9) === '.concat([' && prev.substr(prev.length - 2, 2) === '])') {
|
||||||
|
args[i - 1] = '' + (prev.substr(0, prev.length - 2)) + ", " + code + "])";
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
code = "[" + code + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args.push(i === 0 ? code : ".concat(" + code + ")");
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
return args.join('');
|
||||||
|
};
|
||||||
//### WhileNode
|
//### WhileNode
|
||||||
// A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
// A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
||||||
// it, all other loops can be manufactured. Useful in cases where you need more
|
// it, all other loops can be manufactured. Useful in cases where you need more
|
||||||
|
|
|
@ -329,6 +329,7 @@ exports.CallNode: class CallNode extends BaseNode
|
||||||
|
|
||||||
constructor: (variable, args) ->
|
constructor: (variable, args) ->
|
||||||
@children: flatten [@variable: variable, @args: (args or [])]
|
@children: flatten [@variable: variable, @args: (args or [])]
|
||||||
|
@compile_splat_arguments: SplatNode.compile_mixed_array <- @, @args
|
||||||
@prefix: ''
|
@prefix: ''
|
||||||
|
|
||||||
# Tag this invocation as creating a new instance.
|
# Tag this invocation as creating a new instance.
|
||||||
|
@ -365,27 +366,6 @@ exports.CallNode: class CallNode extends BaseNode
|
||||||
meth: "($temp = ${ @variable.source })${ @variable.last }"
|
meth: "($temp = ${ @variable.source })${ @variable.last }"
|
||||||
"$@prefix${meth}.apply($obj, ${ @compile_splat_arguments(o) })"
|
"$@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
|
|
||||||
if not (arg instanceof SplatNode)
|
|
||||||
prev: args[i - 1]
|
|
||||||
if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']'
|
|
||||||
args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
|
|
||||||
continue
|
|
||||||
else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])'
|
|
||||||
args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])"
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
code: "[$code]"
|
|
||||||
args.push(if i is 0 then code else ".concat($code)")
|
|
||||||
i += 1
|
|
||||||
args.join('')
|
|
||||||
|
|
||||||
|
|
||||||
#### CurryNode
|
#### CurryNode
|
||||||
|
|
||||||
|
@ -398,6 +378,7 @@ exports.CurryNode: class CurryNode extends CallNode
|
||||||
|
|
||||||
constructor: (meth, args) ->
|
constructor: (meth, args) ->
|
||||||
@children: flatten [@meth: meth, @context: args[0], @args: (args.slice(1) or [])]
|
@children: flatten [@meth: meth, @context: args[0], @args: (args.slice(1) or [])]
|
||||||
|
@compile_splat_arguments: SplatNode.compile_mixed_array <- @, @args
|
||||||
|
|
||||||
arguments: (o) ->
|
arguments: (o) ->
|
||||||
for arg in @args
|
for arg in @args
|
||||||
|
@ -567,17 +548,21 @@ exports.ArrayNode: class ArrayNode extends BaseNode
|
||||||
|
|
||||||
constructor: (objects) ->
|
constructor: (objects) ->
|
||||||
@children: @objects: objects or []
|
@children: @objects: objects or []
|
||||||
|
@compile_splat_literal: SplatNode.compile_mixed_array <- @, @objects
|
||||||
|
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
o.indent: @idt(1)
|
o.indent: @idt(1)
|
||||||
objects: for obj, i in @objects
|
objects: []
|
||||||
|
for obj, i in @objects
|
||||||
code: obj.compile(o)
|
code: obj.compile(o)
|
||||||
if obj instanceof CommentNode
|
if obj instanceof SplatNode
|
||||||
"\n$code\n$o.indent"
|
return @compile_splat_literal(@objects, o)
|
||||||
|
else if obj instanceof CommentNode
|
||||||
|
objects.push "\n$code\n$o.indent"
|
||||||
else if i is @objects.length - 1
|
else if i is @objects.length - 1
|
||||||
code
|
objects.push code
|
||||||
else
|
else
|
||||||
"$code, "
|
objects.push "$code, "
|
||||||
objects: objects.join('')
|
objects: objects.join('')
|
||||||
ending: if objects.indexOf('\n') >= 0 then "\n$@tab]" else ']'
|
ending: if objects.indexOf('\n') >= 0 then "\n$@tab]" else ']'
|
||||||
"[$objects$ending"
|
"[$objects$ending"
|
||||||
|
@ -815,6 +800,27 @@ exports.SplatNode: class SplatNode extends BaseNode
|
||||||
compile_value: (o, name, index) ->
|
compile_value: (o, name, index) ->
|
||||||
"Array.prototype.slice.call($name, $index)"
|
"Array.prototype.slice.call($name, $index)"
|
||||||
|
|
||||||
|
# Utility function that converts arbitrary number of elements, mixed with
|
||||||
|
# splats, to a proper array
|
||||||
|
SplatNode.compile_mixed_array: (list, o) ->
|
||||||
|
args: []
|
||||||
|
i: 0
|
||||||
|
for arg in list
|
||||||
|
code: arg.compile o
|
||||||
|
if not (arg instanceof SplatNode)
|
||||||
|
prev: args[i - 1]
|
||||||
|
if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']'
|
||||||
|
args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
|
||||||
|
continue
|
||||||
|
else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])'
|
||||||
|
args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])"
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
code: "[$code]"
|
||||||
|
args.push(if i is 0 then code else ".concat($code)")
|
||||||
|
i += 1
|
||||||
|
args.join('')
|
||||||
|
|
||||||
#### WhileNode
|
#### WhileNode
|
||||||
|
|
||||||
# A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
# A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
||||||
|
|
|
@ -59,3 +59,20 @@ obj: {
|
||||||
}
|
}
|
||||||
|
|
||||||
ok obj.getNames() is 'bob jane ted'
|
ok obj.getNames() is 'bob jane ted'
|
||||||
|
|
||||||
|
|
||||||
|
crowd: [
|
||||||
|
contenders...
|
||||||
|
"Mighty Mouse"
|
||||||
|
]
|
||||||
|
|
||||||
|
bests: [
|
||||||
|
"Mighty Mouse"
|
||||||
|
contenders[0..3]...
|
||||||
|
]
|
||||||
|
|
||||||
|
ok crowd[0] is contenders[0]
|
||||||
|
ok crowd[10] is "Mighty Mouse"
|
||||||
|
|
||||||
|
ok bests[1] is contenders[0]
|
||||||
|
ok bests[4] is contenders[3]
|
Loading…
Reference in a new issue