mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Compile splats in arrays and function calls to ES2015 splats (#4353)
Rather than compiling splats to arrays built using `Array#concat`, splats are now compiled directly to ES2015 splats, e.g. f foo, arguments..., bar [ foo, arguments..., bar ] Which used to be compiled to: f.apply(null, [foo].concat(slice.call(arguments), [bar])); [foo].concat(slice.call(arguments), [bar]); Is now compiled to: f(foo, ...arguments, bar); [ foo, ...arguments, bar ];
This commit is contained in:
parent
496fd5d3d3
commit
663595ba94
7 changed files with 56 additions and 203 deletions
|
@ -47,7 +47,7 @@
|
|||
if ((ref = xhr.status) === 0 || ref === 200) {
|
||||
param = [xhr.responseText, options];
|
||||
if (!hold) {
|
||||
CoffeeScript.run.apply(CoffeeScript, param);
|
||||
CoffeeScript.run(...param);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Could not load " + url);
|
||||
|
@ -80,7 +80,7 @@
|
|||
var param;
|
||||
param = coffees[index];
|
||||
if (param instanceof Array) {
|
||||
CoffeeScript.run.apply(CoffeeScript, param);
|
||||
CoffeeScript.run(...param);
|
||||
index++;
|
||||
return execute();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// Generated by CoffeeScript 2.0.0-alpha
|
||||
(function() {
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVALID_ESCAPE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isUnassignable, key, locationDataToString, ref, ref1, repeat, starts, throwSyntaxError,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
slice = [].slice;
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
ref = require('./rewriter'), Rewriter = ref.Rewriter, INVERSES = ref.INVERSES;
|
||||
|
||||
|
@ -549,7 +548,7 @@
|
|||
}
|
||||
tag = value;
|
||||
ref2 = this.tokens, prev = ref2[ref2.length - 1];
|
||||
if (prev && indexOf.call(['='].concat(slice.call(COMPOUND_ASSIGN)), value) >= 0) {
|
||||
if (prev && indexOf.call(['=', ...COMPOUND_ASSIGN], value) >= 0) {
|
||||
skipToken = false;
|
||||
if (value === '=' && ((ref3 = prev[1]) === '||' || ref3 === '&&') && !prev.spaced) {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
|
@ -719,7 +718,7 @@
|
|||
};
|
||||
|
||||
Lexer.prototype.mergeInterpolationTokens = function(tokens, options, fn) {
|
||||
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, ref2, rparen, tag, token, tokensToPush, value;
|
||||
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, rparen, tag, token, tokensToPush, value;
|
||||
if (tokens.length > 1) {
|
||||
lparen = this.token('STRING_START', '(', 0, 0);
|
||||
}
|
||||
|
@ -761,7 +760,7 @@
|
|||
last_column: locationToken[2].first_column
|
||||
};
|
||||
}
|
||||
(ref2 = this.tokens).push.apply(ref2, tokensToPush);
|
||||
this.tokens.push(...tokensToPush);
|
||||
}
|
||||
if (lparen) {
|
||||
lastToken = tokens[tokens.length - 1];
|
||||
|
@ -934,7 +933,7 @@
|
|||
|
||||
isUnassignable = function(name, displayName = name) {
|
||||
switch (false) {
|
||||
case indexOf.call(slice.call(JS_KEYWORDS).concat(slice.call(COFFEE_KEYWORDS)), name) < 0:
|
||||
case indexOf.call([...JS_KEYWORDS, ...COFFEE_KEYWORDS], name) < 0:
|
||||
return "keyword '" + displayName + "' can't be assigned";
|
||||
case indexOf.call(STRICT_PROSCRIBED, name) < 0:
|
||||
return "'" + displayName + "' can't be assigned";
|
||||
|
|
|
@ -531,7 +531,7 @@
|
|||
};
|
||||
|
||||
Literal.prototype.toString = function() {
|
||||
return " " + (this.isStatement() ? Literal.__super__.toString.apply(this, arguments) : this.constructor.name) + ": " + this.value;
|
||||
return " " + (this.isStatement() ? Literal.__super__.toString.call(this, ...arguments) : this.constructor.name) + ": " + this.value;
|
||||
};
|
||||
|
||||
return Literal;
|
||||
|
@ -777,7 +777,7 @@
|
|||
if (o.scope.parent == null) {
|
||||
this.error('yield can only occur inside functions');
|
||||
}
|
||||
return YieldReturn.__super__.compileNode.apply(this, arguments);
|
||||
return YieldReturn.__super__.compileNode.call(this, ...arguments);
|
||||
};
|
||||
|
||||
return YieldReturn;
|
||||
|
@ -795,7 +795,7 @@
|
|||
if (o.scope.parent == null) {
|
||||
this.error('await can only occur inside functions');
|
||||
}
|
||||
return AwaitReturn.__super__.compileNode.apply(this, arguments);
|
||||
return AwaitReturn.__super__.compileNode.call(this, ...arguments);
|
||||
};
|
||||
|
||||
return AwaitReturn;
|
||||
|
@ -958,21 +958,21 @@
|
|||
}
|
||||
for (j = 0, len1 = props.length; j < len1; j++) {
|
||||
prop = props[j];
|
||||
fragments.push.apply(fragments, prop.compileToFragments(o));
|
||||
fragments.push(...prop.compileToFragments(o));
|
||||
}
|
||||
return fragments;
|
||||
};
|
||||
|
||||
Value.prototype.unfoldSoak = function(o) {
|
||||
return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (() => {
|
||||
var fst, i, ifn, j, len1, prop, ref, ref3, ref4, snd;
|
||||
var fst, i, ifn, j, len1, prop, ref, ref3, snd;
|
||||
if (ifn = this.base.unfoldSoak(o)) {
|
||||
(ref3 = ifn.body.properties).push.apply(ref3, this.properties);
|
||||
ifn.body.properties.push(...this.properties);
|
||||
return ifn;
|
||||
}
|
||||
ref4 = this.properties;
|
||||
for (i = j = 0, len1 = ref4.length; j < len1; i = ++j) {
|
||||
prop = ref4[i];
|
||||
ref3 = this.properties;
|
||||
for (i = j = 0, len1 = ref3.length; j < len1; i = ++j) {
|
||||
prop = ref3[i];
|
||||
if (!prop.soak) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1099,14 +1099,10 @@
|
|||
};
|
||||
|
||||
Call.prototype.compileNode = function(o) {
|
||||
var arg, argIndex, compiledArgs, compiledArray, fragments, j, len1, preface, ref3, ref4;
|
||||
var arg, argIndex, compiledArgs, fragments, j, len1, preface, ref3, ref4;
|
||||
if ((ref3 = this.variable) != null) {
|
||||
ref3.front = this.front;
|
||||
}
|
||||
compiledArray = Splat.compileSplattedArray(o, this.args, true);
|
||||
if (compiledArray.length) {
|
||||
return this.compileSplat(o, compiledArray);
|
||||
}
|
||||
compiledArgs = [];
|
||||
ref4 = this.args;
|
||||
for (argIndex = j = 0, len1 = ref4.length; j < len1; argIndex = ++j) {
|
||||
|
@ -1114,7 +1110,7 @@
|
|||
if (argIndex) {
|
||||
compiledArgs.push(this.makeCode(", "));
|
||||
}
|
||||
compiledArgs.push.apply(compiledArgs, arg.compileToFragments(o, LEVEL_LIST));
|
||||
compiledArgs.push(...arg.compileToFragments(o, LEVEL_LIST));
|
||||
}
|
||||
fragments = [];
|
||||
if (this instanceof SuperCall) {
|
||||
|
@ -1127,44 +1123,14 @@
|
|||
if (this.isNew) {
|
||||
fragments.push(this.makeCode('new '));
|
||||
}
|
||||
fragments.push.apply(fragments, this.variable.compileToFragments(o, LEVEL_ACCESS));
|
||||
fragments.push(...this.variable.compileToFragments(o, LEVEL_ACCESS));
|
||||
fragments.push(this.makeCode("("));
|
||||
}
|
||||
fragments.push.apply(fragments, compiledArgs);
|
||||
fragments.push(...compiledArgs);
|
||||
fragments.push(this.makeCode(")"));
|
||||
return fragments;
|
||||
};
|
||||
|
||||
Call.prototype.compileSplat = function(o, splatArgs) {
|
||||
var answer, base, fun, idt, name, ref;
|
||||
if (this instanceof SuperCall) {
|
||||
return [].concat(this.makeCode((this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", "), splatArgs, this.makeCode(")"));
|
||||
}
|
||||
if (this.isNew) {
|
||||
idt = this.tab + TAB;
|
||||
return [].concat(this.makeCode("(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return Object(result) === result ? result : child;\n" + this.tab + "})("), this.variable.compileToFragments(o, LEVEL_LIST), this.makeCode(", "), splatArgs, this.makeCode(", function(){})"));
|
||||
}
|
||||
answer = [];
|
||||
base = new Value(this.variable);
|
||||
if ((name = base.properties.pop()) && base.isComplex()) {
|
||||
ref = o.scope.freeVariable('ref');
|
||||
answer = answer.concat(this.makeCode("(" + ref + " = "), base.compileToFragments(o, LEVEL_LIST), this.makeCode(")"), name.compileToFragments(o));
|
||||
} else {
|
||||
fun = base.compileToFragments(o, LEVEL_ACCESS);
|
||||
if (SIMPLENUM.test(fragmentsToText(fun))) {
|
||||
fun = this.wrapInBraces(fun);
|
||||
}
|
||||
if (name) {
|
||||
ref = fragmentsToText(fun);
|
||||
fun.push.apply(fun, name.compileToFragments(o));
|
||||
} else {
|
||||
ref = 'null';
|
||||
}
|
||||
answer = answer.concat(fun);
|
||||
}
|
||||
return answer = answer.concat(this.makeCode(".apply(" + ref + ", "), splatArgs, this.makeCode(")"));
|
||||
};
|
||||
|
||||
return Call;
|
||||
|
||||
})(Base);
|
||||
|
@ -1262,12 +1228,12 @@
|
|||
node = this.name.unwrap();
|
||||
if (node instanceof PropertyName) {
|
||||
if (ref3 = node.value, indexOf.call(JS_FORBIDDEN, ref3) >= 0) {
|
||||
return [this.makeCode('["')].concat(slice.call(name), [this.makeCode('"]')]);
|
||||
return [this.makeCode('["'), ...name, this.makeCode('"]')];
|
||||
} else {
|
||||
return [this.makeCode('.')].concat(slice.call(name));
|
||||
return [this.makeCode('.'), ...name];
|
||||
}
|
||||
} else {
|
||||
return [this.makeCode('[')].concat(slice.call(name), [this.makeCode(']')]);
|
||||
return [this.makeCode('['), ...name, this.makeCode(']')];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1482,7 +1448,7 @@
|
|||
if (indent) {
|
||||
answer.push(this.makeCode(indent));
|
||||
}
|
||||
answer.push.apply(answer, prop.compileToFragments(o, LEVEL_TOP));
|
||||
answer.push(...prop.compileToFragments(o, LEVEL_TOP));
|
||||
if (join) {
|
||||
answer.push(this.makeCode(join));
|
||||
}
|
||||
|
@ -1528,10 +1494,6 @@
|
|||
return [this.makeCode('[]')];
|
||||
}
|
||||
o.indent += TAB;
|
||||
answer = Splat.compileSplattedArray(o, this.objects);
|
||||
if (answer.length) {
|
||||
return answer;
|
||||
}
|
||||
answer = [];
|
||||
compiledObjs = (function() {
|
||||
var j, len1, ref3, results;
|
||||
|
@ -1548,7 +1510,7 @@
|
|||
if (index) {
|
||||
answer.push(this.makeCode(", "));
|
||||
}
|
||||
answer.push.apply(answer, fragments);
|
||||
answer.push(...fragments);
|
||||
}
|
||||
if (fragmentsToText(answer).indexOf('\n') >= 0) {
|
||||
answer.unshift(this.makeCode("[\n" + o.indent));
|
||||
|
@ -1736,7 +1698,7 @@
|
|||
};
|
||||
|
||||
Class.prototype.compileNode = function(o) {
|
||||
var args, argumentsNode, func, jumpNode, klass, lname, name, ref3, superClass;
|
||||
var args, argumentsNode, func, jumpNode, klass, lname, name, superClass;
|
||||
if (jumpNode = this.body.jumps()) {
|
||||
jumpNode.error('Class bodies cannot contain pure statements');
|
||||
}
|
||||
|
@ -1763,7 +1725,7 @@
|
|||
func.params.push(new Param(superClass));
|
||||
args.push(this.parent);
|
||||
}
|
||||
(ref3 = this.body.expressions).unshift.apply(ref3, this.directives);
|
||||
this.body.expressions.unshift(...this.directives);
|
||||
klass = new Parens(new Call(func, args));
|
||||
if (this.variable) {
|
||||
klass = new Assign(this.variable, klass, null, {
|
||||
|
@ -1824,7 +1786,7 @@
|
|||
code = [];
|
||||
code.push(this.makeCode(this.tab + "import "));
|
||||
if (this.clause != null) {
|
||||
code.push.apply(code, this.clause.compileNode(o));
|
||||
code.push(...this.clause.compileNode(o));
|
||||
}
|
||||
if (((ref3 = this.source) != null ? ref3.value : void 0) != null) {
|
||||
if (this.clause !== null) {
|
||||
|
@ -1854,13 +1816,13 @@
|
|||
var code;
|
||||
code = [];
|
||||
if (this.defaultBinding != null) {
|
||||
code.push.apply(code, this.defaultBinding.compileNode(o));
|
||||
code.push(...this.defaultBinding.compileNode(o));
|
||||
if (this.namedImports != null) {
|
||||
code.push(this.makeCode(', '));
|
||||
}
|
||||
}
|
||||
if (this.namedImports != null) {
|
||||
code.push.apply(code, this.namedImports.compileNode(o));
|
||||
code.push(...this.namedImports.compileNode(o));
|
||||
}
|
||||
return code;
|
||||
};
|
||||
|
@ -1970,7 +1932,7 @@
|
|||
if (index) {
|
||||
code.push(this.makeCode(",\n" + o.indent));
|
||||
}
|
||||
code.push.apply(code, fragments);
|
||||
code.push(...fragments);
|
||||
}
|
||||
code.push(this.makeCode("\n}"));
|
||||
} else {
|
||||
|
@ -2238,7 +2200,7 @@
|
|||
assigns = [];
|
||||
expandedIdx = false;
|
||||
if (!(value.unwrap() instanceof IdentifierLiteral) || this.variable.assigns(vvarText)) {
|
||||
assigns.push([this.makeCode((ref = o.scope.freeVariable('ref')) + " = ")].concat(slice.call(vvar)));
|
||||
assigns.push([this.makeCode((ref = o.scope.freeVariable('ref')) + " = "), ...vvar]);
|
||||
vvar = [this.makeCode(ref)];
|
||||
vvarText = ref;
|
||||
}
|
||||
|
@ -2419,7 +2381,7 @@
|
|||
};
|
||||
|
||||
Code.prototype.compileNode = function(o) {
|
||||
var answer, code, condition, exprs, haveSplatParam, i, ifTrue, j, k, len1, len2, param, paramNames, params, paramsAfterSplat, ref, ref3, ref4, ref5, ref6, splatParamName, val, wasEmpty;
|
||||
var answer, code, condition, exprs, haveSplatParam, i, ifTrue, j, k, len1, len2, param, paramNames, params, paramsAfterSplat, ref, ref3, ref4, ref5, splatParamName, val, wasEmpty;
|
||||
if (this.bound) {
|
||||
if ((ref3 = o.scope.method) != null ? ref3.bound : void 0) {
|
||||
this.context = o.scope.method.context;
|
||||
|
@ -2497,7 +2459,8 @@
|
|||
}
|
||||
}
|
||||
if (paramsAfterSplat.length !== 0) {
|
||||
exprs.unshift(new Assign(new Value(new Arr([new Splat(new IdentifierLiteral(splatParamName))].concat(slice.call((function() {
|
||||
exprs.unshift(new Assign(new Value(new Arr([
|
||||
new Splat(new IdentifierLiteral(splatParamName)), ...(function() {
|
||||
var k, len2, results;
|
||||
results = [];
|
||||
for (k = 0, len2 = paramsAfterSplat.length; k < len2; k++) {
|
||||
|
@ -2505,11 +2468,12 @@
|
|||
results.push(param.asReference(o));
|
||||
}
|
||||
return results;
|
||||
})())))), new Value(new IdentifierLiteral(splatParamName))));
|
||||
})()
|
||||
])), new Value(new IdentifierLiteral(splatParamName))));
|
||||
}
|
||||
wasEmpty = this.body.isEmpty();
|
||||
if (exprs.length) {
|
||||
(ref6 = this.body.expressions).unshift.apply(ref6, exprs);
|
||||
this.body.expressions.unshift(...exprs);
|
||||
}
|
||||
if (!(wasEmpty || this.noReturn)) {
|
||||
this.body.makeReturn();
|
||||
|
@ -2537,7 +2501,7 @@
|
|||
if (haveSplatParam && i === params.length - 1) {
|
||||
answer.push(this.makeCode('...'));
|
||||
}
|
||||
answer.push.apply(answer, param.compileToFragments(o));
|
||||
answer.push(...param.compileToFragments(o));
|
||||
}
|
||||
answer.push(this.makeCode(!this.bound ? ') {' : ') => {'));
|
||||
if (!this.body.isEmpty()) {
|
||||
|
@ -2545,7 +2509,7 @@
|
|||
}
|
||||
answer.push(this.makeCode('}'));
|
||||
if (this.ctor) {
|
||||
return [this.makeCode(this.tab)].concat(slice.call(answer));
|
||||
return [this.makeCode(this.tab), ...answer];
|
||||
}
|
||||
if (this.front || (o.level >= LEVEL_ACCESS)) {
|
||||
return this.wrapInBraces(answer);
|
||||
|
@ -2682,57 +2646,13 @@
|
|||
};
|
||||
|
||||
Splat.prototype.compileToFragments = function(o) {
|
||||
return this.name.compileToFragments(o);
|
||||
return [this.makeCode('...'), ...this.name.compileToFragments(o)];
|
||||
};
|
||||
|
||||
Splat.prototype.unwrap = function() {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
Splat.compileSplattedArray = function(o, list, apply) {
|
||||
var args, base, compiledNode, concatPart, fragments, i, index, j, last, len1, node;
|
||||
index = -1;
|
||||
while ((node = list[++index]) && !(node instanceof Splat)) {
|
||||
continue;
|
||||
}
|
||||
if (index >= list.length) {
|
||||
return [];
|
||||
}
|
||||
if (list.length === 1) {
|
||||
node = list[0];
|
||||
fragments = node.compileToFragments(o, LEVEL_LIST);
|
||||
if (apply) {
|
||||
return fragments;
|
||||
}
|
||||
return [].concat(node.makeCode((utility('slice', o)) + ".call("), fragments, node.makeCode(")"));
|
||||
}
|
||||
args = list.slice(index);
|
||||
for (i = j = 0, len1 = args.length; j < len1; i = ++j) {
|
||||
node = args[i];
|
||||
compiledNode = node.compileToFragments(o, LEVEL_LIST);
|
||||
args[i] = node instanceof Splat ? [].concat(node.makeCode((utility('slice', o)) + ".call("), compiledNode, node.makeCode(")")) : [].concat(node.makeCode("["), compiledNode, node.makeCode("]"));
|
||||
}
|
||||
if (index === 0) {
|
||||
node = list[0];
|
||||
concatPart = node.joinFragmentArrays(args.slice(1), ', ');
|
||||
return args[0].concat(node.makeCode(".concat("), concatPart, node.makeCode(")"));
|
||||
}
|
||||
base = (function() {
|
||||
var k, len2, ref3, results;
|
||||
ref3 = list.slice(0, index);
|
||||
results = [];
|
||||
for (k = 0, len2 = ref3.length; k < len2; k++) {
|
||||
node = ref3[k];
|
||||
results.push(node.compileToFragments(o, LEVEL_LIST));
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
base = list[0].joinFragmentArrays(base, ', ');
|
||||
concatPart = list[index].joinFragmentArrays(args, ', ');
|
||||
last = list[list.length - 1];
|
||||
return [].concat(list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, last.makeCode(")"));
|
||||
};
|
||||
|
||||
return Splat;
|
||||
|
||||
})(Base);
|
||||
|
@ -2774,7 +2694,7 @@
|
|||
|
||||
While.prototype.makeReturn = function(res) {
|
||||
if (res) {
|
||||
return While.__super__.makeReturn.apply(this, arguments);
|
||||
return While.__super__.makeReturn.call(this, ...arguments);
|
||||
} else {
|
||||
this.returns = !this.jumps({
|
||||
loop: true
|
||||
|
@ -3588,7 +3508,7 @@
|
|||
fragments.push(cond.makeCode(idt2 + 'break;\n'));
|
||||
}
|
||||
if (this.otherwise && this.otherwise.expressions.length) {
|
||||
fragments.push.apply(fragments, [this.makeCode(idt1 + "default:\n")].concat(slice.call(this.otherwise.compileToFragments(o, LEVEL_TOP)), [this.makeCode("\n")]));
|
||||
fragments.push(this.makeCode(idt1 + "default:\n"), ...this.otherwise.compileToFragments(o, LEVEL_TOP), this.makeCode("\n"));
|
||||
}
|
||||
fragments.push(this.makeCode(this.tab + '}'));
|
||||
return fragments;
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
results.push(buildRule.apply(null, tuple));
|
||||
results.push(buildRule(...tuple));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// Generated by CoffeeScript 2.0.0-alpha
|
||||
(function() {
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, ref, rite,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
slice = [].slice;
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
generate = function(tag, value, origin) {
|
||||
var tok;
|
||||
|
@ -401,7 +400,7 @@
|
|||
tag = token[0];
|
||||
if (tag === 'TERMINATOR') {
|
||||
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i, 1].concat(slice.call(this.indentation())));
|
||||
tokens.splice(i, 1, ...this.indentation());
|
||||
return 1;
|
||||
}
|
||||
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
|
||||
|
@ -414,7 +413,7 @@
|
|||
if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
|
||||
continue;
|
||||
}
|
||||
tokens.splice.apply(tokens, [i + j, 0].concat(slice.call(this.indentation())));
|
||||
tokens.splice(i + j, 0, ...this.indentation());
|
||||
return 2 + j;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -690,9 +690,6 @@ exports.Call = class Call extends Base
|
|||
# Compile a vanilla function call.
|
||||
compileNode: (o) ->
|
||||
@variable?.front = @front
|
||||
compiledArray = Splat.compileSplattedArray o, @args, true
|
||||
if compiledArray.length
|
||||
return @compileSplat o, compiledArray
|
||||
compiledArgs = []
|
||||
for arg, argIndex in @args
|
||||
if argIndex then compiledArgs.push @makeCode ", "
|
||||
|
@ -711,47 +708,6 @@ exports.Call = class Call extends Base
|
|||
fragments.push @makeCode ")"
|
||||
fragments
|
||||
|
||||
# If you call a function with a splat, it's converted into a JavaScript
|
||||
# `.apply()` call to allow an array of arguments to be passed.
|
||||
# If it's a constructor, then things get real tricky. We have to inject an
|
||||
# inner constructor in order to be able to pass the varargs.
|
||||
#
|
||||
# splatArgs is an array of CodeFragments to put into the 'apply'.
|
||||
compileSplat: (o, splatArgs) ->
|
||||
if this instanceof SuperCall
|
||||
return [].concat @makeCode("#{ @superReference o }.apply(#{@superThis(o)}, "),
|
||||
splatArgs, @makeCode(")")
|
||||
|
||||
if @isNew
|
||||
idt = @tab + TAB
|
||||
return [].concat @makeCode("""
|
||||
(function(func, args, ctor) {
|
||||
#{idt}ctor.prototype = func.prototype;
|
||||
#{idt}var child = new ctor, result = func.apply(child, args);
|
||||
#{idt}return Object(result) === result ? result : child;
|
||||
#{@tab}})("""),
|
||||
(@variable.compileToFragments o, LEVEL_LIST),
|
||||
@makeCode(", "), splatArgs, @makeCode(", function(){})")
|
||||
|
||||
answer = []
|
||||
base = new Value @variable
|
||||
if (name = base.properties.pop()) and base.isComplex()
|
||||
ref = o.scope.freeVariable 'ref'
|
||||
answer = answer.concat @makeCode("(#{ref} = "),
|
||||
(base.compileToFragments o, LEVEL_LIST),
|
||||
@makeCode(")"),
|
||||
name.compileToFragments(o)
|
||||
else
|
||||
fun = base.compileToFragments o, LEVEL_ACCESS
|
||||
fun = @wrapInBraces fun if SIMPLENUM.test fragmentsToText fun
|
||||
if name
|
||||
ref = fragmentsToText fun
|
||||
fun.push (name.compileToFragments o)...
|
||||
else
|
||||
ref = 'null'
|
||||
answer = answer.concat fun
|
||||
answer = answer.concat @makeCode(".apply(#{ref}, "), splatArgs, @makeCode(")")
|
||||
|
||||
#### Super
|
||||
|
||||
# Takes care of converting `super()` calls into calls against the prototype's
|
||||
|
@ -1042,8 +998,6 @@ exports.Arr = class Arr extends Base
|
|||
compileNode: (o) ->
|
||||
return [@makeCode '[]'] unless @objects.length
|
||||
o.indent += TAB
|
||||
answer = Splat.compileSplattedArray o, @objects
|
||||
return answer if answer.length
|
||||
|
||||
answer = []
|
||||
compiledObjs = (obj.compileToFragments o, LEVEL_LIST for obj in @objects)
|
||||
|
@ -1847,37 +1801,11 @@ exports.Splat = class Splat extends Base
|
|||
@name.assigns name
|
||||
|
||||
compileToFragments: (o) ->
|
||||
@name.compileToFragments o
|
||||
[ @makeCode('...')
|
||||
@name.compileToFragments(o)... ]
|
||||
|
||||
unwrap: -> @name
|
||||
|
||||
# Utility function that converts an arbitrary number of elements, mixed with
|
||||
# splats, to a proper array.
|
||||
@compileSplattedArray: (o, list, apply) ->
|
||||
index = -1
|
||||
continue while (node = list[++index]) and node not instanceof Splat
|
||||
return [] if index >= list.length
|
||||
if list.length is 1
|
||||
node = list[0]
|
||||
fragments = node.compileToFragments o, LEVEL_LIST
|
||||
return fragments if apply
|
||||
return [].concat node.makeCode("#{ utility 'slice', o }.call("), fragments, node.makeCode(")")
|
||||
args = list[index..]
|
||||
for node, i in args
|
||||
compiledNode = node.compileToFragments o, LEVEL_LIST
|
||||
args[i] = if node instanceof Splat
|
||||
then [].concat node.makeCode("#{ utility 'slice', o }.call("), compiledNode, node.makeCode(")")
|
||||
else [].concat node.makeCode("["), compiledNode, node.makeCode("]")
|
||||
if index is 0
|
||||
node = list[0]
|
||||
concatPart = (node.joinFragmentArrays args[1..], ', ')
|
||||
return args[0].concat node.makeCode(".concat("), concatPart, node.makeCode(")")
|
||||
base = (node.compileToFragments o, LEVEL_LIST for node in list[...index])
|
||||
base = list[0].joinFragmentArrays base, ', '
|
||||
concatPart = list[index].joinFragmentArrays args, ', '
|
||||
[..., last] = list
|
||||
[].concat list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, last.makeCode(")")
|
||||
|
||||
#### Expansion
|
||||
|
||||
# Used to skip values inside an array destructuring (pattern matching) or
|
||||
|
|
|
@ -107,3 +107,10 @@ test "regex interpolation in array", ->
|
|||
eq 2, arr.length
|
||||
eq 'ab', arr[0].source
|
||||
eq 'value', arr[1].key
|
||||
|
||||
test "splat extraction from generators", ->
|
||||
gen = ->
|
||||
yield 1
|
||||
yield 2
|
||||
yield 3
|
||||
arrayEq [ gen()... ], [ 1, 2, 3 ]
|
||||
|
|
Loading…
Reference in a new issue