expand parameters

Conflicts:
	test/compress/harmony.js
This commit is contained in:
Fábio Santos
2015-04-13 01:26:26 +01:00
committed by Richard van Velzen
parent e8664e63ef
commit 9863f0efa3
5 changed files with 89 additions and 7 deletions

View File

@@ -363,10 +363,27 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
} }
}, AST_Scope); }, AST_Scope);
// TODO besides parameters and function calls, expansions can go in
// arrays, array destructuring parameters, and array destructuring
// assignment. But I'm not adding this right now because I'm trying
// to do the most minimal and independent changesets.
var AST_Expansion = DEFNODE("AST_Expansion", "symbol", {
$documentation: "An expandible argument, such as ...rest",
$propdoc: {
symbol: "AST_SymbolFunarg the name of the argument as a SymbolFunarg"
},
_walk: function(visitor) {
var self = this;
return visitor._visit(this, function(){
self.symbol.walk(visitor);
});
}
});
var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", { var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
$documentation: "A set of arrow function parameters or a sequence expression. This is used because when the parser sees a \"(\" it could be the start of a seq, or the start of a parameter list of an arrow function.", $documentation: "A set of arrow function parameters or a sequence expression. This is used because when the parser sees a \"(\" it could be the start of a seq, or the start of a parameter list of an arrow function.",
$propdoc: { $propdoc: {
expressions: "[AST_Expression|AST_Destructuring*] array of expressions or argument names or destructurings." expressions: "[AST_Expression|AST_Destructuring|AST_Expansion*] array of expressions or argument names or destructurings."
}, },
as_params: function (croak) { as_params: function (croak) {
// We don't want anything which doesn't belong in a destructuring // We don't want anything which doesn't belong in a destructuring
@@ -398,6 +415,8 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
start: ex.start, start: ex.start,
end: ex.end end: ex.end
}); });
} else if (ex instanceof AST_Expansion) {
return ex;
} else if (ex instanceof AST_Array) { } else if (ex instanceof AST_Array) {
if (ex.elements.length === 0) if (ex.elements.length === 0)
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col); croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
@@ -421,7 +440,7 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
$documentation: "Base class for functions", $documentation: "Base class for functions",
$propdoc: { $propdoc: {
name: "[AST_SymbolDeclaration?] the name of this function", name: "[AST_SymbolDeclaration?] the name of this function",
argnames: "[AST_SymbolFunarg|AST_Destructuring*] array of function arguments or destructurings", argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion*] array of function arguments, destructurings, or expanding arguments",
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
}, },
args_as_names: function () { args_as_names: function () {
@@ -431,6 +450,9 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
if (parm instanceof AST_SymbolFunarg) { if (parm instanceof AST_SymbolFunarg) {
out.push(parm); out.push(parm);
} }
if (parm instanceof AST_Expansion) {
out.push(parm.symbol);
}
})); }));
return out; return out;
}, },

View File

@@ -1107,6 +1107,9 @@ merge(Compressor.prototype, {
break; break;
} else { } else {
var sym = a[i]; var sym = a[i];
if (sym instanceof AST_Expansion) {
sym = sym.symbol;
}
if (sym.unreferenced()) { if (sym.unreferenced()) {
a.pop(); a.pop();
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {

View File

@@ -607,6 +607,11 @@ function OutputStream(options) {
output.semicolon(); output.semicolon();
}); });
DEFPRINT(AST_Expansion, function (self, output) {
output.print('...');
self.symbol.print(output);
});
DEFPRINT(AST_Destructuring, function (self, output) { DEFPRINT(AST_Destructuring, function (self, output) {
output.print(self.is_array ? "[" : "{"); output.print(self.is_array ? "[" : "{");
var first = true; var first = true;

View File

@@ -526,9 +526,16 @@ function tokenizer($TEXT, filename, html5_comments) {
function handle_dot() { function handle_dot() {
next(); next();
return is_digit(peek().charCodeAt(0)) if (is_digit(peek().charCodeAt(0))) {
? read_num(".") return read_num(".");
: token("punc", "."); }
if (peek() === ".") {
next(); // Consume second dot
next(); // Consume third dot
return token("expand", "...");
}
return token("punc", ".");
}; };
function read_word() { function read_word() {
@@ -1034,7 +1041,16 @@ function parse($TEXT, options) {
S.in_parameters = true; S.in_parameters = true;
while (!is("punc", ")")) { while (!is("punc", ")")) {
if (first) first = false; else expect(","); if (first) first = false; else expect(",");
a.push(expression(false)); if (is("expand", "...")) {
next();
a.push(new AST_Expansion({
start: prev(),
symbol: as_symbol(AST_SymbolFunarg),
end: S.token,
}));
} else {
a.push(expression(false));
}
} }
S.in_parameters = false; S.in_parameters = false;
var end = S.token var end = S.token
@@ -1475,13 +1491,32 @@ function parse($TEXT, options) {
return subscripts(new AST_Call({ return subscripts(new AST_Call({
start : start, start : start,
expression : expr, expression : expr,
args : expr_list(")"), args : call_args(),
end : prev() end : prev()
}), true); }), true);
} }
return expr; return expr;
}; };
var call_args = embed_tokens(function call_args() {
var first = true;
var args = [];
while (!is("punc", ")")) {
if (first) first = false; else expect(",");
if (is("expand", "...")) {
next();
args.push(new AST_Expansion({
start: prev(),
symbol: as_symbol(AST_SymbolFunarg)
}));
} else {
args.push(expression(false));
}
}
next();
return args;
});
var maybe_unary = function(allow_calls) { var maybe_unary = function(allow_calls) {
var start = S.token; var start = S.token;
if (is("operator") && UNARY_PREFIX(start.value)) { if (is("operator") && UNARY_PREFIX(start.value)) {

View File

@@ -0,0 +1,17 @@
expand_arguments: {
input: {
func(a, ...rest);
func(...all);
}
expect_exact: "func(a,...rest);func(...all);"
}
expand_parameters: {
input: {
(function (a, ...b){});
(function (...args){});
}
expect_exact: "(function(a,...b){});(function(...args){});"
}