var types = require("../lib/types");
var def = types.Type.def;
var or = types.Type.or;
var builtin = types.builtInTypes;
var isBoolean = builtin.boolean;
var defaults = require("../lib/shared").defaults;

// 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)
    // 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")
    .field("argument", or(def("Expression"), null));

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("ModuleDeclaration")
    .bases("Declaration")
    .build("id", "from", "body")
    .field("id", or(def("Literal"), def("Identifier")))
    .field("from", or(def("Path"), null))
    .field("body", or(def("BlockStatement"), null));

def("Path")
    .bases("Node")
    .build("body")
    // TODO This really ought be a recursive type.
    .field("body", [def("Identifier")]);

def("MethodDefinition")
    .bases("Declaration")
    .build("kind", "key", "value")
    .field("kind", or("init", "get", "set"))
    .field("key", or(def("Literal"), def("Identifier")))
    .field("value", def("Function"));

def("SpreadElement")
    .bases("Pattern")
    .build("argument")
    .field("argument", def("Pattern"));

types.finalize();

@@ -1985,16 +1985,26 @@
  %22value%22
+, %22static%22
 )%0A    .f
@@ -2039,16 +2039,20 @@
 %22, %22set%22
+, %22%22
 ))%0A    .
@@ -2139,16 +2139,70 @@
 ction%22))
+%0A    .field(%22static%22, builtin.boolean, defaults.false)
 ;%0A%0Adef(%22
@@ -2303,16 +2303,615 @@
 rn%22));%0A%0A
+def(%22ClassBody%22)%0A    .bases(%22Declaration%22)%0A    .build(%22body%22)%0A    .field(%22body%22, %5Bdef(%22MethodDefinition%22)%5D);%0A%0Adef(%22ClassDeclaration%22)%0A    .bases(%22Declaration%22)%0A    .build(%22id%22, %22body%22, %22superClass%22)%0A    .field(%22id%22, def(%22Identifier%22))%0A    .field(%22body%22, def(%22ClassBody%22))%0A    .field(%22superClass%22, or(def(%22Expression%22), null), defaults.null);%0A%0Adef(%22ClassExpression%22)%0A    .bases(%22Expression%22)%0A    .build(%22id%22, %22body%22, %22superClass%22)%0A    .field(%22id%22, or(def(%22Identifier%22), null), defaults.null)%0A    .field(%22body%22, def(%22ClassBody%22))%0A    .field(%22superClass%22, or(def(%22Expression%22), null), defaults.null);%0A%0A
 types.fi

Define ClassBody, ClassDeclaration, and ClassExpression types.