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
101
lib/nodes.js
101
lib/nodes.js
|
@ -419,6 +419,11 @@
|
|||
exports.CallNode = (function() {
|
||||
CallNode = function CallNode(variable, 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 = '';
|
||||
return this;
|
||||
};
|
||||
|
@ -473,33 +478,6 @@
|
|||
}
|
||||
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;
|
||||
}).call(this);
|
||||
//### CurryNode
|
||||
|
@ -508,6 +486,11 @@
|
|||
exports.CurryNode = (function() {
|
||||
CurryNode = function CurryNode(meth, args) {
|
||||
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;
|
||||
};
|
||||
__extends(CurryNode, CallNode);
|
||||
|
@ -725,30 +708,33 @@
|
|||
exports.ArrayNode = (function() {
|
||||
ArrayNode = function ArrayNode(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;
|
||||
};
|
||||
__extends(ArrayNode, BaseNode);
|
||||
ArrayNode.prototype.type = 'Array';
|
||||
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);
|
||||
objects = (function() {
|
||||
_a = []; _b = this.objects;
|
||||
for (i = 0, _c = _b.length; i < _c; i++) {
|
||||
obj = _b[i];
|
||||
_a.push((function() {
|
||||
code = obj.compile(o);
|
||||
if (obj instanceof CommentNode) {
|
||||
return "\n" + code + "\n" + o.indent;
|
||||
} else if (i === this.objects.length - 1) {
|
||||
return code;
|
||||
} else {
|
||||
return '' + code + ", ";
|
||||
}
|
||||
}).call(this));
|
||||
objects = [];
|
||||
_a = this.objects;
|
||||
for (i = 0, _b = _a.length; i < _b; i++) {
|
||||
obj = _a[i];
|
||||
code = obj.compile(o);
|
||||
if (obj instanceof SplatNode) {
|
||||
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) {
|
||||
objects.push(code);
|
||||
} else {
|
||||
objects.push('' + code + ", ");
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
}
|
||||
objects = objects.join('');
|
||||
ending = objects.indexOf('\n') >= 0 ? "\n" + this.tab + "]" : ']';
|
||||
return "[" + objects + ending;
|
||||
|
@ -1074,6 +1060,33 @@
|
|||
};
|
||||
return SplatNode;
|
||||
}).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
|
||||
// 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
|
||||
|
|
|
@ -329,6 +329,7 @@ exports.CallNode: class CallNode extends BaseNode
|
|||
|
||||
constructor: (variable, args) ->
|
||||
@children: flatten [@variable: variable, @args: (args or [])]
|
||||
@compile_splat_arguments: SplatNode.compile_mixed_array <- @, @args
|
||||
@prefix: ''
|
||||
|
||||
# Tag this invocation as creating a new instance.
|
||||
|
@ -365,27 +366,6 @@ exports.CallNode: class CallNode extends BaseNode
|
|||
meth: "($temp = ${ @variable.source })${ @variable.last }"
|
||||
"$@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
|
||||
|
||||
|
@ -398,6 +378,7 @@ exports.CurryNode: class CurryNode extends CallNode
|
|||
|
||||
constructor: (meth, args) ->
|
||||
@children: flatten [@meth: meth, @context: args[0], @args: (args.slice(1) or [])]
|
||||
@compile_splat_arguments: SplatNode.compile_mixed_array <- @, @args
|
||||
|
||||
arguments: (o) ->
|
||||
for arg in @args
|
||||
|
@ -567,17 +548,21 @@ exports.ArrayNode: class ArrayNode extends BaseNode
|
|||
|
||||
constructor: (objects) ->
|
||||
@children: @objects: objects or []
|
||||
@compile_splat_literal: SplatNode.compile_mixed_array <- @, @objects
|
||||
|
||||
compile_node: (o) ->
|
||||
o.indent: @idt(1)
|
||||
objects: for obj, i in @objects
|
||||
objects: []
|
||||
for obj, i in @objects
|
||||
code: obj.compile(o)
|
||||
if obj instanceof CommentNode
|
||||
"\n$code\n$o.indent"
|
||||
if obj instanceof SplatNode
|
||||
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
|
||||
code
|
||||
objects.push code
|
||||
else
|
||||
"$code, "
|
||||
objects.push "$code, "
|
||||
objects: objects.join('')
|
||||
ending: if objects.indexOf('\n') >= 0 then "\n$@tab]" else ']'
|
||||
"[$objects$ending"
|
||||
|
@ -815,6 +800,27 @@ exports.SplatNode: class SplatNode extends BaseNode
|
|||
compile_value: (o, 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
|
||||
|
||||
# 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'
|
||||
|
||||
|
||||
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 New Issue