You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
7.6 KiB
JavaScript
248 lines
7.6 KiB
JavaScript
7 years ago
|
require("./core");
|
||
|
var types = require("../lib/types");
|
||
|
var def = types.Type.def;
|
||
|
var or = types.Type.or;
|
||
|
var builtin = types.builtInTypes;
|
||
|
var isBoolean = builtin.boolean;
|
||
|
var isObject = builtin.object;
|
||
|
var isString = builtin.string;
|
||
|
var defaults = require("../lib/shared").defaults;
|
||
|
|
||
|
def("Function")
|
||
|
.field("generator", isBoolean, defaults["false"])
|
||
|
.field("expression", isBoolean, defaults["false"])
|
||
|
.field("defaults", [or(def("Expression"), null)], defaults.emptyArray)
|
||
|
// TODO This could be represented as a SpreadElementPattern in .params.
|
||
|
.field("rest", or(def("Identifier"), null), defaults["null"]);
|
||
|
|
||
|
def("FunctionDeclaration")
|
||
|
.build("id", "params", "body", "generator", "expression");
|
||
|
|
||
|
def("FunctionExpression")
|
||
|
.build("id", "params", "body", "generator", "expression");
|
||
|
|
||
|
// TODO The Parser API calls this ArrowExpression, but Esprima uses
|
||
|
// ArrowFunctionExpression.
|
||
|
def("ArrowFunctionExpression")
|
||
|
.bases("Function", "Expression")
|
||
|
.build("params", "body", "expression")
|
||
|
// The forced null value here is compatible with the overridden
|
||
|
// definition of the "id" field in the Function interface.
|
||
|
.field("id", null, defaults["null"])
|
||
|
// Arrow function bodies are allowed to be expressions.
|
||
|
.field("body", or(def("BlockStatement"), def("Expression")))
|
||
|
// The current spec forbids arrow generators, so I have taken the
|
||
|
// liberty of enforcing that. TODO Report this.
|
||
|
.field("generator", false, defaults["false"]);
|
||
|
|
||
|
def("YieldExpression")
|
||
|
.bases("Expression")
|
||
|
.build("argument", "delegate")
|
||
|
.field("argument", or(def("Expression"), null))
|
||
|
.field("delegate", isBoolean, defaults["false"]);
|
||
|
|
||
|
def("GeneratorExpression")
|
||
|
.bases("Expression")
|
||
|
.build("body", "blocks", "filter")
|
||
|
.field("body", def("Expression"))
|
||
|
.field("blocks", [def("ComprehensionBlock")])
|
||
|
.field("filter", or(def("Expression"), null));
|
||
|
|
||
|
def("ComprehensionExpression")
|
||
|
.bases("Expression")
|
||
|
.build("body", "blocks", "filter")
|
||
|
.field("body", def("Expression"))
|
||
|
.field("blocks", [def("ComprehensionBlock")])
|
||
|
.field("filter", or(def("Expression"), null));
|
||
|
|
||
|
def("ComprehensionBlock")
|
||
|
.bases("Node")
|
||
|
.build("left", "right", "each")
|
||
|
.field("left", def("Pattern"))
|
||
|
.field("right", def("Expression"))
|
||
|
.field("each", isBoolean);
|
||
|
|
||
|
def("ModuleSpecifier")
|
||
|
.bases("Literal")
|
||
|
.build("value")
|
||
|
.field("value", isString);
|
||
|
|
||
|
def("Property")
|
||
|
// Esprima extensions not mentioned in the Mozilla Parser API:
|
||
|
.field("key", or(def("Literal"), def("Identifier"), def("Expression")))
|
||
|
.field("method", isBoolean, defaults["false"])
|
||
|
.field("shorthand", isBoolean, defaults["false"])
|
||
|
.field("computed", isBoolean, defaults["false"]);
|
||
|
|
||
|
def("PropertyPattern")
|
||
|
.field("key", or(def("Literal"), def("Identifier"), def("Expression")))
|
||
|
.field("computed", isBoolean, defaults["false"]);
|
||
|
|
||
|
def("MethodDefinition")
|
||
|
.bases("Declaration")
|
||
|
.build("kind", "key", "value", "static")
|
||
|
.field("kind", or("init", "get", "set", ""))
|
||
|
.field("key", or(def("Literal"), def("Identifier"), def("Expression")))
|
||
|
.field("value", def("Function"))
|
||
|
.field("computed", isBoolean, defaults["false"])
|
||
|
.field("static", isBoolean, defaults["false"]);
|
||
|
|
||
|
def("SpreadElement")
|
||
|
.bases("Node")
|
||
|
.build("argument")
|
||
|
.field("argument", def("Expression"));
|
||
|
|
||
|
def("ArrayExpression")
|
||
|
.field("elements", [or(def("Expression"), def("SpreadElement"), null)]);
|
||
|
|
||
|
def("NewExpression")
|
||
|
.field("arguments", [or(def("Expression"), def("SpreadElement"))]);
|
||
|
|
||
|
def("CallExpression")
|
||
|
.field("arguments", [or(def("Expression"), def("SpreadElement"))]);
|
||
|
|
||
|
def("SpreadElementPattern")
|
||
|
.bases("Pattern")
|
||
|
.build("argument")
|
||
|
.field("argument", def("Pattern"));
|
||
|
|
||
|
def("ArrayPattern")
|
||
|
.field("elements", [or(
|
||
|
def("Pattern"),
|
||
|
null,
|
||
|
// used by esprima
|
||
|
def("SpreadElement")
|
||
|
)]);
|
||
|
|
||
|
var ClassBodyElement = or(
|
||
|
def("MethodDefinition"),
|
||
|
def("VariableDeclarator"),
|
||
|
def("ClassPropertyDefinition"),
|
||
|
def("ClassProperty")
|
||
|
);
|
||
|
|
||
|
def("ClassProperty")
|
||
|
.bases("Declaration")
|
||
|
.build("key")
|
||
|
.field("key", or(def("Literal"), def("Identifier"), def("Expression")))
|
||
|
.field("computed", isBoolean, defaults["false"]);
|
||
|
|
||
|
def("ClassPropertyDefinition") // static property
|
||
|
.bases("Declaration")
|
||
|
.build("definition")
|
||
|
// Yes, Virginia, circular definitions are permitted.
|
||
|
.field("definition", ClassBodyElement);
|
||
|
|
||
|
def("ClassBody")
|
||
|
.bases("Declaration")
|
||
|
.build("body")
|
||
|
.field("body", [ClassBodyElement]);
|
||
|
|
||
|
def("ClassDeclaration")
|
||
|
.bases("Declaration")
|
||
|
.build("id", "body", "superClass")
|
||
|
.field("id", or(def("Identifier"), null))
|
||
|
.field("body", def("ClassBody"))
|
||
|
.field("superClass", or(def("Expression"), null), defaults["null"]);
|
||
|
|
||
|
def("ClassExpression")
|
||
|
.bases("Expression")
|
||
|
.build("id", "body", "superClass")
|
||
|
.field("id", or(def("Identifier"), null), defaults["null"])
|
||
|
.field("body", def("ClassBody"))
|
||
|
.field("superClass", or(def("Expression"), null), defaults["null"])
|
||
|
.field("implements", [def("ClassImplements")], defaults.emptyArray);
|
||
|
|
||
|
def("ClassImplements")
|
||
|
.bases("Node")
|
||
|
.build("id")
|
||
|
.field("id", def("Identifier"))
|
||
|
.field("superClass", or(def("Expression"), null), defaults["null"]);
|
||
|
|
||
|
// Specifier and NamedSpecifier are abstract non-standard types that I
|
||
|
// introduced for definitional convenience.
|
||
|
def("Specifier").bases("Node");
|
||
|
def("NamedSpecifier")
|
||
|
.bases("Specifier")
|
||
|
// Note: this abstract type is intentionally not buildable.
|
||
|
.field("id", def("Identifier"))
|
||
|
.field("name", or(def("Identifier"), null), defaults["null"]);
|
||
|
|
||
|
// Like NamedSpecifier, except type:"ExportSpecifier" and buildable.
|
||
|
// export {<id [as name]>} [from ...];
|
||
|
def("ExportSpecifier")
|
||
|
.bases("NamedSpecifier")
|
||
|
.build("id", "name");
|
||
|
|
||
|
// export <*> from ...;
|
||
|
def("ExportBatchSpecifier")
|
||
|
.bases("Specifier")
|
||
|
.build();
|
||
|
|
||
|
// Like NamedSpecifier, except type:"ImportSpecifier" and buildable.
|
||
|
// import {<id [as name]>} from ...;
|
||
|
def("ImportSpecifier")
|
||
|
.bases("NamedSpecifier")
|
||
|
.build("id", "name");
|
||
|
|
||
|
// import <* as id> from ...;
|
||
|
def("ImportNamespaceSpecifier")
|
||
|
.bases("Specifier")
|
||
|
.build("id")
|
||
|
.field("id", def("Identifier"));
|
||
|
|
||
|
// import <id> from ...;
|
||
|
def("ImportDefaultSpecifier")
|
||
|
.bases("Specifier")
|
||
|
.build("id")
|
||
|
.field("id", def("Identifier"));
|
||
|
|
||
|
def("ExportDeclaration")
|
||
|
.bases("Declaration")
|
||
|
.build("default", "declaration", "specifiers", "source")
|
||
|
.field("default", isBoolean)
|
||
|
.field("declaration", or(
|
||
|
def("Declaration"),
|
||
|
def("Expression"), // Implies default.
|
||
|
null
|
||
|
))
|
||
|
.field("specifiers", [or(
|
||
|
def("ExportSpecifier"),
|
||
|
def("ExportBatchSpecifier")
|
||
|
)], defaults.emptyArray)
|
||
|
.field("source", or(
|
||
|
def("Literal"),
|
||
|
def("ModuleSpecifier"),
|
||
|
null
|
||
|
), defaults["null"]);
|
||
|
|
||
|
def("ImportDeclaration")
|
||
|
.bases("Declaration")
|
||
|
.build("specifiers", "source")
|
||
|
.field("specifiers", [or(
|
||
|
def("ImportSpecifier"),
|
||
|
def("ImportNamespaceSpecifier"),
|
||
|
def("ImportDefaultSpecifier")
|
||
|
)], defaults.emptyArray)
|
||
|
.field("source", or(
|
||
|
def("Literal"),
|
||
|
def("ModuleSpecifier")
|
||
|
));
|
||
|
|
||
|
def("TaggedTemplateExpression")
|
||
|
.bases("Expression")
|
||
|
.field("tag", def("Expression"))
|
||
|
.field("quasi", def("TemplateLiteral"));
|
||
|
|
||
|
def("TemplateLiteral")
|
||
|
.bases("Expression")
|
||
|
.build("quasis", "expressions")
|
||
|
.field("quasis", [def("TemplateElement")])
|
||
|
.field("expressions", [def("Expression")]);
|
||
|
|
||
|
def("TemplateElement")
|
||
|
.bases("Node")
|
||
|
.build("value", "tail")
|
||
|
.field("value", {"cooked": isString, "raw": isString})
|
||
|
.field("tail", isBoolean);
|