support rest parameters (#4515)

This commit is contained in:
Alex Lam S.L
2021-01-07 02:04:09 +00:00
committed by GitHub
parent 68497d0258
commit c3d358a5b8
12 changed files with 819 additions and 135 deletions

View File

@@ -513,10 +513,11 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
}
}, AST_Scope);
var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest uses_arguments", {
$documentation: "Base class for functions",
$propdoc: {
argnames: "[(AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
argnames: "[(AST_DefaultValue|AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
rest: "[(AST_Destructured|AST_SymbolFunarg)?] rest parameter, or null if absent",
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
},
each_argname: function(visit) {
@@ -534,6 +535,7 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
this.argnames.forEach(function(argname) {
argname.walk(tw);
});
if (this.rest) this.rest.walk(tw);
},
walk: function(visitor) {
var node = this;
@@ -542,6 +544,7 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
node.argnames.forEach(function(argname) {
argname.walk(visitor);
});
if (node.rest) node.rest.walk(visitor);
walk_body(node, visitor);
});
},
@@ -551,6 +554,9 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
if (!(node instanceof AST_SymbolFunarg)) throw new Error("argnames must be AST_SymbolFunarg[]");
}, true);
});
if (this.rest != null) validate_destructured(this.rest, function(node) {
if (!(node instanceof AST_SymbolFunarg)) throw new Error("rest must be AST_SymbolFunarg");
});
},
}, AST_Scope);
@@ -576,6 +582,7 @@ var AST_Arrow = DEFNODE("Arrow", "inlined value", {
node.argnames.forEach(function(argname) {
argname.walk(visitor);
});
if (node.rest) node.rest.walk(visitor);
if (node.value) {
node.value.walk(visitor);
} else {
@@ -1155,25 +1162,31 @@ var AST_Array = DEFNODE("Array", "elements", {
},
});
var AST_Destructured = DEFNODE("Destructured", null, {
var AST_Destructured = DEFNODE("Destructured", "rest", {
$documentation: "Base class for destructured literal",
$propdoc: {
rest: "[(AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)?] rest parameter, or null if absent",
},
});
function validate_destructured(node, check, allow_default) {
if (node instanceof AST_DefaultValue && allow_default) return validate_destructured(node.name, check);
if (node instanceof AST_DestructuredArray) return node.elements.forEach(function(node) {
if (!(node instanceof AST_Hole)) validate_destructured(node, check, true);
});
if (node instanceof AST_DestructuredObject) return node.properties.forEach(function(prop) {
validate_destructured(prop.value, check, true);
});
if (node instanceof AST_Destructured) {
if (node.rest != null) validate_destructured(node.rest, check);
if (node instanceof AST_DestructuredArray) return node.elements.forEach(function(node) {
if (!(node instanceof AST_Hole)) validate_destructured(node, check, true);
});
if (node instanceof AST_DestructuredObject) return node.properties.forEach(function(prop) {
validate_destructured(prop.value, check, true);
});
}
check(node);
}
var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
$documentation: "A destructured array literal",
$propdoc: {
elements: "[AST_Node*] array of elements",
elements: "[(AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)*] array of elements",
},
walk: function(visitor) {
var node = this;
@@ -1181,6 +1194,7 @@ var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
node.elements.forEach(function(element) {
element.walk(visitor);
});
if (node.rest) node.rest.walk(visitor);
});
},
}, AST_Destructured);
@@ -1189,7 +1203,7 @@ var AST_DestructuredKeyVal = DEFNODE("DestructuredKeyVal", "key value", {
$documentation: "A key: value destructured property",
$propdoc: {
key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
value: "[AST_Node] property value",
value: "[AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef] property value",
},
walk: function(visitor) {
var node = this;
@@ -1218,6 +1232,7 @@ var AST_DestructuredObject = DEFNODE("DestructuredObject", "properties", {
node.properties.forEach(function(prop) {
prop.walk(visitor);
});
if (node.rest) node.rest.walk(visitor);
});
},
_validate: function() {