hydra-0.15.0: src/main/haskell/Hydra/Sources/JavaScript/Syntax.hs
-- | A JavaScript/ECMAScript syntax model for code generation.
--
-- This model is based on the ECMAScript 2024 specification and is designed
-- to support Hydra's code generation needs. It focuses on the subset of
-- JavaScript syntax needed for generating functional, type-annotated code.
module Hydra.Sources.JavaScript.Syntax where
-- Standard imports for type-level sources outside of the kernel
import Hydra.Kernel
import Hydra.Dsl.Annotations
import Hydra.Dsl.Bootstrap
import Hydra.Dsl.Types ((>:))
import qualified Hydra.Dsl.Types as T
import qualified Hydra.Sources.Kernel.Types.Core as Core
import qualified Data.List as L
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Maybe as Y
ns :: Namespace
ns = Namespace "hydra.javaScript.syntax"
define :: String -> Type -> Binding
define = datatype ns
js :: String -> Type
js = typeref ns
module_ :: Module
module_ = Module {
moduleNamespace = ns,
moduleDefinitions = (map toTypeDef definitions),
moduleTermDependencies = [Core.ns],
moduleTypeDependencies = [Core.ns],
moduleDescription = Just "A JavaScript/ECMAScript syntax model for code generation"}
where
definitions = [
-- Identifiers and names
identifier,
qualifiedName,
-- Literals
literal,
stringLiteral,
templateLiteral,
templateElement,
numericLiteral,
-- Types (for JSDoc/TypeScript-style annotations)
typeAnnotation,
typeExpression,
functionTypeExpression,
arrayTypeExpression,
unionTypeExpression,
parameterizedTypeExpression,
objectTypeExpression,
propertySignature,
typeParameter,
-- Expressions
expression,
arrayExpression,
objectExpression,
functionExpression,
arrowFunctionExpression,
arrowFunctionBody,
callExpression,
memberExpression,
conditionalExpression,
binaryExpression,
unaryExpression,
assignmentExpression,
spreadElement,
-- Object and array components
property,
propertyKind,
arrayElement,
-- Patterns (for destructuring)
pattern_,
objectPattern,
objectPatternProperty,
arrayPattern,
assignmentPattern,
restElement,
-- Statements
statement,
labeledStatement,
blockStatement,
variableDeclaration,
variableDeclarator,
variableKind,
ifStatement,
switchStatement,
switchCase,
forStatement,
forInit,
forInStatement,
forInLeft,
forOfStatement,
whileStatement,
doWhileStatement,
tryStatement,
catchClause,
throwStatement,
returnStatement,
breakStatement,
continueStatement,
-- Declarations
functionDeclaration,
classDeclaration,
classBody,
methodDefinition,
methodKind,
-- Modules
program,
sourceType,
moduleItem,
importDeclaration,
importClause,
importSpecifier,
importDefaultSpecifier,
importNamespaceSpecifier,
exportDeclaration,
namedExport,
exportAllDeclaration,
exportSpecifier,
-- Operators
binaryOperator,
unaryOperator,
assignmentOperator,
-- Comments (including documentation comments)
comment,
documentationComment,
documentationTag,
-- Declarations with comments (for attaching JSDoc)
moduleItemWithComments,
statementWithComments,
functionDeclarationWithComments,
classDeclarationWithComments]
-- ============================================================================
-- Identifiers and Names
-- ============================================================================
identifier :: Binding
identifier = define "Identifier" $
doc "A JavaScript identifier (variable, function, class name, etc.)" $
T.wrap T.string
qualifiedName :: Binding
qualifiedName = define "QualifiedName" $
doc "A qualified name like 'module.submodule.name'" $
T.list $ js "Identifier"
-- ============================================================================
-- Literals
-- ============================================================================
literal :: Binding
literal = define "Literal" $
doc "A literal value" $
T.union [
"string">:
doc "A string literal" $
js "StringLiteral",
"number">:
doc "A numeric literal" $
js "NumericLiteral",
"boolean">:
doc "A boolean literal (true or false)"
T.boolean,
"null">:
doc "The null literal"
T.unit,
"undefined">:
doc "The undefined literal"
T.unit,
"bigInt">:
doc "A BigInt literal (e.g., 123n)"
T.bigint,
"template">:
doc "A template literal" $
js "TemplateLiteral"]
stringLiteral :: Binding
stringLiteral = define "StringLiteral" $
doc "A string literal with quote style" $
T.record [
"value">:
doc "The string value"
T.string,
"singleQuote">:
doc "Whether to use single quotes (true) or double quotes (false)"
T.boolean]
templateLiteral :: Binding
templateLiteral = define "TemplateLiteral" $
doc "A template literal (backtick string with interpolations)" $
T.record [
"quasis">:
doc "The static string parts" $
T.list $ js "TemplateElement",
"expressions">:
doc "The interpolated expressions" $
T.list $ js "Expression"]
templateElement :: Binding
templateElement = define "TemplateElement" $
doc "A static part of a template literal" $
T.record [
"value">:
doc "The raw string value"
T.string,
"tail">:
doc "Whether this is the last element"
T.boolean]
numericLiteral :: Binding
numericLiteral = define "NumericLiteral" $
doc "A numeric literal (integer or floating-point)" $
T.union [
"integer">:
doc "An integer literal"
T.int64,
"float">:
doc "A floating-point literal"
T.float64]
-- ============================================================================
-- Type Annotations (JSDoc / TypeScript-compatible)
-- ============================================================================
typeAnnotation :: Binding
typeAnnotation = define "TypeAnnotation" $
doc "A type annotation (for JSDoc comments or TypeScript)" $
T.wrap $ js "TypeExpression"
typeExpression :: Binding
typeExpression = define "TypeExpression" $
doc "A type expression" $
T.union [
"identifier">:
doc "A named type (e.g., 'string', 'number', 'MyClass')" $
js "Identifier",
"literal">:
doc "A literal type (e.g., 'hello', 42)" $
js "Literal",
"array">:
doc "An array type" $
js "ArrayTypeExpression",
"function">:
doc "A function type" $
js "FunctionTypeExpression",
"object">:
doc "An object type" $
js "ObjectTypeExpression",
"union">:
doc "A union type (A | B)" $
js "UnionTypeExpression",
"parameterized">:
doc "A parameterized type (e.g., Array<T>, Map<K, V>)" $
js "ParameterizedTypeExpression",
"optional">:
doc "An optional type (?T)" $
js "TypeExpression",
"any">:
doc "The 'any' type"
T.unit,
"void">:
doc "The 'void' type"
T.unit,
"never">:
doc "The 'never' type"
T.unit]
functionTypeExpression :: Binding
functionTypeExpression = define "FunctionTypeExpression" $
doc "A function type expression" $
T.record [
"typeParameters">:
doc "Type parameters (generics)" $
T.list $ js "TypeParameter",
"parameters">:
doc "Parameter types" $
T.list $ js "TypeExpression",
"returnType">:
doc "Return type" $
js "TypeExpression"]
arrayTypeExpression :: Binding
arrayTypeExpression = define "ArrayTypeExpression" $
doc "An array type (T[])" $
T.wrap $ js "TypeExpression"
unionTypeExpression :: Binding
unionTypeExpression = define "UnionTypeExpression" $
doc "A union type (A | B | C)" $
T.list $ js "TypeExpression"
parameterizedTypeExpression :: Binding
parameterizedTypeExpression = define "ParameterizedTypeExpression" $
doc "A parameterized type (e.g., Array<T>, Map<K, V>)" $
T.record [
"base">: js "TypeExpression",
"arguments">: T.list $ js "TypeExpression"]
objectTypeExpression :: Binding
objectTypeExpression = define "ObjectTypeExpression" $
doc "An object type with property signatures" $
T.list $ js "PropertySignature"
propertySignature :: Binding
propertySignature = define "PropertySignature" $
doc "A property signature in an object type" $
T.record [
"name">:
doc "Property name" $
js "Identifier",
"type">:
doc "Property type" $
js "TypeExpression",
"optional">:
doc "Whether the property is optional"
T.boolean,
"readonly">:
doc "Whether the property is readonly"
T.boolean]
typeParameter :: Binding
typeParameter = define "TypeParameter" $
doc "A type parameter (generic)" $
T.record [
"name">:
doc "Parameter name" $
js "Identifier",
"constraint">:
doc "Optional constraint (extends clause)" $
T.optional $ js "TypeExpression",
"default">:
doc "Optional default type" $
T.optional $ js "TypeExpression"]
-- ============================================================================
-- Expressions
-- ============================================================================
expression :: Binding
expression = define "Expression" $
doc "A JavaScript expression" $
T.union [
"identifier">:
doc "A simple identifier" $
js "Identifier",
"literal">:
doc "A literal value" $
js "Literal",
"array">:
doc "An array expression [a, b, c]" $
js "ArrayExpression",
"object">:
doc "An object expression {a: 1, b: 2}" $
js "ObjectExpression",
"function">:
doc "A function expression" $
js "FunctionExpression",
"arrow">:
doc "An arrow function expression" $
js "ArrowFunctionExpression",
"call">:
doc "A function call expression" $
js "CallExpression",
"member">:
doc "A member access expression (obj.prop or obj[prop])" $
js "MemberExpression",
"conditional">:
doc "A conditional (ternary) expression" $
js "ConditionalExpression",
"binary">:
doc "A binary operation expression" $
js "BinaryExpression",
"unary">:
doc "A unary operation expression" $
js "UnaryExpression",
"assignment">:
doc "An assignment expression" $
js "AssignmentExpression",
"sequence">:
doc "A sequence expression (a, b, c)" $
T.list $ js "Expression",
"this">:
doc "The 'this' keyword"
T.unit,
"new">:
doc "A 'new' expression" $
js "CallExpression",
"yield">:
doc "A yield expression" $
T.optional $ js "Expression",
"await">:
doc "An await expression" $
js "Expression",
"spread">:
doc "A spread expression (...x)" $
js "SpreadElement",
"parenthesized">:
doc "A parenthesized expression" $
js "Expression"]
arrayExpression :: Binding
arrayExpression = define "ArrayExpression" $
doc "An array expression [a, b, c]" $
T.list $ js "ArrayElement"
arrayElement :: Binding
arrayElement = define "ArrayElement" $
doc "An element in an array expression" $
T.union [
"expression">:
doc "A regular expression element" $
js "Expression",
"spread">:
doc "A spread element ...x" $
js "SpreadElement",
"hole">:
doc "An empty slot (elision)"
T.unit]
objectExpression :: Binding
objectExpression = define "ObjectExpression" $
doc "An object expression {a: 1, b: 2}" $
T.list $ js "Property"
property :: Binding
property = define "Property" $
doc "A property in an object expression" $
T.record [
"key">:
doc "Property key (identifier, literal, or computed)" $
js "Expression",
"value">:
doc "Property value" $
js "Expression",
"kind">:
doc "Property kind (init, get, set)" $
js "PropertyKind",
"computed">:
doc "Whether the key is computed [expr]"
T.boolean,
"shorthand">:
doc "Whether using shorthand syntax {x} for {x: x}"
T.boolean]
propertyKind :: Binding
propertyKind = define "PropertyKind" $
doc "The kind of an object property" $
T.union [
"init">:
doc "A normal property initialization"
T.unit,
"get">:
doc "A getter"
T.unit,
"set">:
doc "A setter"
T.unit]
functionExpression :: Binding
functionExpression = define "FunctionExpression" $
doc "A function expression" $
T.record [
"id">:
doc "Optional function name" $
T.optional $ js "Identifier",
"params">:
doc "Function parameters" $
T.list $ js "Pattern",
"body">:
doc "Function body" $
js "BlockStatement",
"async">:
doc "Whether the function is async"
T.boolean,
"generator">:
doc "Whether the function is a generator"
T.boolean]
arrowFunctionExpression :: Binding
arrowFunctionExpression = define "ArrowFunctionExpression" $
doc "An arrow function expression" $
T.record [
"params">:
doc "Function parameters" $
T.list $ js "Pattern",
"body">:
doc "Function body (expression or block)" $
js "ArrowFunctionBody",
"async">:
doc "Whether the function is async"
T.boolean]
arrowFunctionBody :: Binding
arrowFunctionBody = define "ArrowFunctionBody" $
doc "The body of an arrow function (expression or block)" $
T.union [
"expression">: js "Expression",
"block">: js "BlockStatement"]
callExpression :: Binding
callExpression = define "CallExpression" $
doc "A function call expression" $
T.record [
"callee">:
doc "The function being called" $
js "Expression",
"arguments">:
doc "The arguments" $
T.list $ js "Expression",
"optional">:
doc "Whether using optional chaining (?.)"
T.boolean]
memberExpression :: Binding
memberExpression = define "MemberExpression" $
doc "A member access expression" $
T.record [
"object">:
doc "The object" $
js "Expression",
"property">:
doc "The property" $
js "Expression",
"computed">:
doc "Whether using bracket notation (obj[prop])"
T.boolean,
"optional">:
doc "Whether using optional chaining (?.)"
T.boolean]
conditionalExpression :: Binding
conditionalExpression = define "ConditionalExpression" $
doc "A conditional (ternary) expression: test ? consequent : alternate" $
T.record [
"test">: js "Expression",
"consequent">: js "Expression",
"alternate">: js "Expression"]
binaryExpression :: Binding
binaryExpression = define "BinaryExpression" $
doc "A binary operation expression" $
T.record [
"operator">: js "BinaryOperator",
"left">: js "Expression",
"right">: js "Expression"]
unaryExpression :: Binding
unaryExpression = define "UnaryExpression" $
doc "A unary operation expression" $
T.record [
"operator">: js "UnaryOperator",
"argument">: js "Expression",
"prefix">:
doc "Whether the operator is prefix (true) or postfix (false)"
T.boolean]
assignmentExpression :: Binding
assignmentExpression = define "AssignmentExpression" $
doc "An assignment expression" $
T.record [
"operator">: js "AssignmentOperator",
"left">: js "Pattern",
"right">: js "Expression"]
spreadElement :: Binding
spreadElement = define "SpreadElement" $
doc "A spread element (...x)" $
T.wrap $ js "Expression"
-- ============================================================================
-- Patterns (Destructuring)
-- ============================================================================
pattern_ :: Binding
pattern_ = define "Pattern" $
doc "A binding pattern (for destructuring)" $
T.union [
"identifier">:
doc "A simple identifier binding" $
js "Identifier",
"object">:
doc "An object destructuring pattern" $
js "ObjectPattern",
"array">:
doc "An array destructuring pattern" $
js "ArrayPattern",
"assignment">:
doc "A pattern with default value" $
js "AssignmentPattern",
"rest">:
doc "A rest element (...x)" $
js "RestElement"]
objectPattern :: Binding
objectPattern = define "ObjectPattern" $
doc "An object destructuring pattern {a, b: c}" $
T.record [
"properties">:
doc "The property patterns" $
T.list $ js "ObjectPatternProperty"]
objectPatternProperty :: Binding
objectPatternProperty = define "ObjectPatternProperty" $
doc "A property in an object pattern" $
T.union [
"property">: js "Property",
"rest">: js "RestElement"]
arrayPattern :: Binding
arrayPattern = define "ArrayPattern" $
doc "An array destructuring pattern [a, b, c]" $
T.list $ T.optional $ js "Pattern"
assignmentPattern :: Binding
assignmentPattern = define "AssignmentPattern" $
doc "A pattern with default value (param = default)" $
T.record [
"left">: js "Pattern",
"right">: js "Expression"]
restElement :: Binding
restElement = define "RestElement" $
doc "A rest element pattern (...x)" $
T.wrap $ js "Pattern"
-- ============================================================================
-- Statements
-- ============================================================================
statement :: Binding
statement = define "Statement" $
doc "A JavaScript statement" $
T.union [
"expression">:
doc "An expression statement" $
js "Expression",
"block">:
doc "A block statement" $
js "BlockStatement",
"empty">:
doc "An empty statement (;)"
T.unit,
"debugger">:
doc "A debugger statement"
T.unit,
"return">:
doc "A return statement" $
js "ReturnStatement",
"break">:
doc "A break statement" $
js "BreakStatement",
"continue">:
doc "A continue statement" $
js "ContinueStatement",
"if">:
doc "An if statement" $
js "IfStatement",
"switch">:
doc "A switch statement" $
js "SwitchStatement",
"throw">:
doc "A throw statement" $
js "ThrowStatement",
"try">:
doc "A try statement" $
js "TryStatement",
"while">:
doc "A while statement" $
js "WhileStatement",
"doWhile">:
doc "A do-while statement" $
js "DoWhileStatement",
"for">:
doc "A for statement" $
js "ForStatement",
"forIn">:
doc "A for-in statement" $
js "ForInStatement",
"forOf">:
doc "A for-of statement" $
js "ForOfStatement",
"variableDeclaration">:
doc "A variable declaration" $
js "VariableDeclaration",
"functionDeclaration">:
doc "A function declaration" $
js "FunctionDeclaration",
"classDeclaration">:
doc "A class declaration" $
js "ClassDeclaration",
"labeled">:
doc "A labeled statement" $
js "LabeledStatement"]
labeledStatement :: Binding
labeledStatement = define "LabeledStatement" $
doc "A labeled statement" $
T.record [
"label">: js "Identifier",
"body">: js "Statement"]
blockStatement :: Binding
blockStatement = define "BlockStatement" $
doc "A block statement { ... }" $
T.list $ js "Statement"
variableDeclaration :: Binding
variableDeclaration = define "VariableDeclaration" $
doc "A variable declaration (var, let, const)" $
T.record [
"kind">: js "VariableKind",
"declarations">: T.list $ js "VariableDeclarator"]
variableDeclarator :: Binding
variableDeclarator = define "VariableDeclarator" $
doc "A variable declarator (id = init)" $
T.record [
"id">: js "Pattern",
"init">: T.optional $ js "Expression"]
variableKind :: Binding
variableKind = define "VariableKind" $
doc "The kind of variable declaration" $
T.union [
"var">: T.unit,
"let">: T.unit,
"const">: T.unit]
ifStatement :: Binding
ifStatement = define "IfStatement" $
doc "An if statement" $
T.record [
"test">: js "Expression",
"consequent">: js "Statement",
"alternate">: T.optional $ js "Statement"]
switchStatement :: Binding
switchStatement = define "SwitchStatement" $
doc "A switch statement" $
T.record [
"discriminant">: js "Expression",
"cases">: T.list $ js "SwitchCase"]
switchCase :: Binding
switchCase = define "SwitchCase" $
doc "A case clause in a switch statement" $
T.record [
"test">:
doc "The test expression (Nothing for default)" $
T.optional $ js "Expression",
"consequent">:
doc "The statements to execute" $
T.list $ js "Statement"]
forStatement :: Binding
forStatement = define "ForStatement" $
doc "A for statement" $
T.record [
"init">:
doc "Initialization" $
T.optional $ js "ForInit",
"test">:
doc "Test condition" $
T.optional $ js "Expression",
"update">:
doc "Update expression" $
T.optional $ js "Expression",
"body">: js "Statement"]
forInit :: Binding
forInit = define "ForInit" $
doc "Initialization clause of a for statement" $
T.union [
"variable">: js "VariableDeclaration",
"expression">: js "Expression"]
forInStatement :: Binding
forInStatement = define "ForInStatement" $
doc "A for-in statement" $
T.record [
"left">: js "ForInLeft",
"right">: js "Expression",
"body">: js "Statement"]
forInLeft :: Binding
forInLeft = define "ForInLeft" $
doc "Left-hand side of a for-in or for-of statement" $
T.union [
"variable">: js "VariableDeclaration",
"pattern">: js "Pattern"]
forOfStatement :: Binding
forOfStatement = define "ForOfStatement" $
doc "A for-of statement" $
T.record [
"await">:
doc "Whether this is a for-await-of"
T.boolean,
"left">: js "ForInLeft",
"right">: js "Expression",
"body">: js "Statement"]
whileStatement :: Binding
whileStatement = define "WhileStatement" $
doc "A while statement" $
T.record [
"test">: js "Expression",
"body">: js "Statement"]
doWhileStatement :: Binding
doWhileStatement = define "DoWhileStatement" $
doc "A do-while statement" $
T.record [
"body">: js "Statement",
"test">: js "Expression"]
tryStatement :: Binding
tryStatement = define "TryStatement" $
doc "A try statement" $
T.record [
"block">: js "BlockStatement",
"handler">: T.optional $ js "CatchClause",
"finalizer">: T.optional $ js "BlockStatement"]
catchClause :: Binding
catchClause = define "CatchClause" $
doc "A catch clause" $
T.record [
"param">:
doc "The catch parameter (can be omitted in ES2019+)" $
T.optional $ js "Pattern",
"body">: js "BlockStatement"]
throwStatement :: Binding
throwStatement = define "ThrowStatement" $
doc "A throw statement" $
T.wrap $ js "Expression"
returnStatement :: Binding
returnStatement = define "ReturnStatement" $
doc "A return statement" $
T.optional $ js "Expression"
breakStatement :: Binding
breakStatement = define "BreakStatement" $
doc "A break statement" $
T.optional $ js "Identifier"
continueStatement :: Binding
continueStatement = define "ContinueStatement" $
doc "A continue statement" $
T.optional $ js "Identifier"
-- ============================================================================
-- Declarations
-- ============================================================================
functionDeclaration :: Binding
functionDeclaration = define "FunctionDeclaration" $
doc "A function declaration" $
T.record [
"id">:
doc "Function name" $
js "Identifier",
"params">:
doc "Function parameters" $
T.list $ js "Pattern",
"body">:
doc "Function body" $
js "BlockStatement",
"async">:
doc "Whether the function is async"
T.boolean,
"generator">:
doc "Whether the function is a generator"
T.boolean]
classDeclaration :: Binding
classDeclaration = define "ClassDeclaration" $
doc "A class declaration" $
T.record [
"id">:
doc "Class name" $
js "Identifier",
"superClass">:
doc "Optional superclass" $
T.optional $ js "Expression",
"body">:
doc "Class body" $
js "ClassBody"]
classBody :: Binding
classBody = define "ClassBody" $
doc "A class body" $
T.list $ js "MethodDefinition"
methodDefinition :: Binding
methodDefinition = define "MethodDefinition" $
doc "A method definition in a class" $
T.record [
"key">:
doc "Method name" $
js "Expression",
"value">:
doc "Method function" $
js "FunctionExpression",
"kind">:
doc "Method kind" $
js "MethodKind",
"computed">:
doc "Whether the key is computed"
T.boolean,
"static">:
doc "Whether the method is static"
T.boolean]
methodKind :: Binding
methodKind = define "MethodKind" $
doc "The kind of a class method" $
T.union [
"constructor">: T.unit,
"method">: T.unit,
"get">: T.unit,
"set">: T.unit]
-- ============================================================================
-- Modules
-- ============================================================================
program :: Binding
program = define "Program" $
doc "A JavaScript program (module)" $
T.record [
"body">:
doc "The module items" $
T.list $ js "ModuleItem",
"sourceType">:
doc "Whether this is a module or script" $
js "SourceType"]
sourceType :: Binding
sourceType = define "SourceType" $
doc "Whether the program is a module or script" $
T.union [
"module">: T.unit,
"script">: T.unit]
moduleItem :: Binding
moduleItem = define "ModuleItem" $
doc "A top-level item in a module" $
T.union [
"statement">: js "Statement",
"import">: js "ImportDeclaration",
"export">: js "ExportDeclaration"]
importDeclaration :: Binding
importDeclaration = define "ImportDeclaration" $
doc "An import declaration" $
T.record [
"specifiers">:
doc "What to import" $
T.list $ js "ImportClause",
"source">:
doc "The module to import from" $
js "StringLiteral"]
importClause :: Binding
importClause = define "ImportClause" $
doc "An import clause (named, default, or namespace import)" $
T.union [
"named">: js "ImportSpecifier",
"default">: js "ImportDefaultSpecifier",
"namespace">: js "ImportNamespaceSpecifier"]
importSpecifier :: Binding
importSpecifier = define "ImportSpecifier" $
doc "A named import specifier (import {x as y} from ...)" $
T.record [
"imported">: js "Identifier",
"local">: js "Identifier"]
importDefaultSpecifier :: Binding
importDefaultSpecifier = define "ImportDefaultSpecifier" $
doc "A default import specifier (import x from ...)" $
T.wrap $ js "Identifier"
importNamespaceSpecifier :: Binding
importNamespaceSpecifier = define "ImportNamespaceSpecifier" $
doc "A namespace import specifier (import * as x from ...)" $
T.wrap $ js "Identifier"
exportDeclaration :: Binding
exportDeclaration = define "ExportDeclaration" $
doc "An export declaration" $
T.union [
"named">:
doc "Named exports (export {x, y as z})" $
js "NamedExport",
"default">:
doc "Default export (export default ...)" $
js "Expression",
"declaration">:
doc "Export a declaration (export const x = ...)" $
js "Statement",
"all">:
doc "Export all (export * from ...)" $
js "ExportAllDeclaration"]
namedExport :: Binding
namedExport = define "NamedExport" $
doc "Named exports (export {x, y as z})" $
T.record [
"specifiers">: T.list $ js "ExportSpecifier",
"source">: T.optional $ js "StringLiteral"]
exportAllDeclaration :: Binding
exportAllDeclaration = define "ExportAllDeclaration" $
doc "Export all declaration (export * from ...)" $
T.record [
"exported">: T.optional $ js "Identifier",
"source">: js "StringLiteral"]
exportSpecifier :: Binding
exportSpecifier = define "ExportSpecifier" $
doc "An export specifier (x as y)" $
T.record [
"local">: js "Identifier",
"exported">: js "Identifier"]
-- ============================================================================
-- Operators
-- ============================================================================
binaryOperator :: Binding
binaryOperator = define "BinaryOperator" $
doc "A binary operator" $
T.union [
-- Arithmetic
"add">: doc "+" T.unit,
"subtract">: doc "-" T.unit,
"multiply">: doc "*" T.unit,
"divide">: doc "/" T.unit,
"modulo">: doc "%" T.unit,
"exponentiate">: doc "**" T.unit,
-- Comparison
"equal">: doc "==" T.unit,
"notEqual">: doc "!=" T.unit,
"strictEqual">: doc "===" T.unit,
"strictNotEqual">: doc "!==" T.unit,
"lessThan">: doc "<" T.unit,
"lessThanOrEqual">: doc "<=" T.unit,
"greaterThan">: doc ">" T.unit,
"greaterThanOrEqual">: doc ">=" T.unit,
-- Logical
"and">: doc "&&" T.unit,
"or">: doc "||" T.unit,
"nullishCoalescing">: doc "??" T.unit,
-- Bitwise
"bitwiseAnd">: doc "&" T.unit,
"bitwiseOr">: doc "|" T.unit,
"bitwiseXor">: doc "^" T.unit,
"leftShift">: doc "<<" T.unit,
"rightShift">: doc ">>" T.unit,
"unsignedRightShift">: doc ">>>" T.unit,
-- Other
"in">: doc "in" T.unit,
"instanceof">: doc "instanceof" T.unit]
unaryOperator :: Binding
unaryOperator = define "UnaryOperator" $
doc "A unary operator" $
T.union [
"negate">: doc "-" T.unit,
"plus">: doc "+" T.unit,
"not">: doc "!" T.unit,
"bitwiseNot">: doc "~" T.unit,
"typeof">: doc "typeof" T.unit,
"void">: doc "void" T.unit,
"delete">: doc "delete" T.unit,
"increment">: doc "++" T.unit,
"decrement">: doc "--" T.unit]
assignmentOperator :: Binding
assignmentOperator = define "AssignmentOperator" $
doc "An assignment operator" $
T.union [
"assign">: doc "=" T.unit,
"addAssign">: doc "+=" T.unit,
"subtractAssign">: doc "-=" T.unit,
"multiplyAssign">: doc "*=" T.unit,
"divideAssign">: doc "/=" T.unit,
"moduloAssign">: doc "%=" T.unit,
"exponentiateAssign">: doc "**=" T.unit,
"leftShiftAssign">: doc "<<=" T.unit,
"rightShiftAssign">: doc ">>=" T.unit,
"unsignedRightShiftAssign">: doc ">>>=" T.unit,
"bitwiseAndAssign">: doc "&=" T.unit,
"bitwiseOrAssign">: doc "|=" T.unit,
"bitwiseXorAssign">: doc "^=" T.unit,
"andAssign">: doc "&&=" T.unit,
"orAssign">: doc "||=" T.unit,
"nullishAssign">: doc "??=" T.unit]
-- ============================================================================
-- Comments (for JSDoc)
-- ============================================================================
comment :: Binding
comment = define "Comment" $
doc "A JavaScript comment" $
T.union [
"line">:
doc "A single-line comment (// ...)"
T.string,
"block">:
doc "A block comment (/* ... */)"
T.string,
"documentation">:
doc "A documentation comment (/** ... */, i.e. JSDoc)" $
js "DocumentationComment"]
documentationComment :: Binding
documentationComment = define "DocumentationComment" $
doc "A documentation comment (JSDoc) with structured tags" $
T.record [
"description">:
doc "The main description"
T.string,
"tags">:
doc "Documentation tags (@param, @returns, etc.)" $
T.list $ js "DocumentationTag"]
documentationTag :: Binding
documentationTag = define "DocumentationTag" $
doc "A documentation tag (@param, @returns, @type, etc.)" $
T.record [
"name">:
doc "Tag name (param, returns, type, etc.)"
T.string,
"type">:
doc "Optional type expression" $
T.optional $ js "TypeExpression",
"paramName">:
doc "Optional parameter name (for @param)" $
T.optional $ js "Identifier",
"description">:
doc "Tag description"
T.string]
-- ============================================================================
-- Declarations with Comments (for JSDoc support)
-- ============================================================================
moduleItemWithComments :: Binding
moduleItemWithComments = define "ModuleItemWithComments" $
doc "A module item with optional documentation" $
T.record [
"body">:
doc "The module item" $
js "ModuleItem",
"comments">:
doc "Optional documentation comment" $
T.optional $ js "DocumentationComment"]
statementWithComments :: Binding
statementWithComments = define "StatementWithComments" $
doc "A statement with optional documentation" $
T.record [
"body">:
doc "The statement" $
js "Statement",
"comments">:
doc "Optional documentation comment" $
T.optional $ js "DocumentationComment"]
functionDeclarationWithComments :: Binding
functionDeclarationWithComments = define "FunctionDeclarationWithComments" $
doc "A function declaration with optional JSDoc" $
T.record [
"body">:
doc "The function declaration" $
js "FunctionDeclaration",
"comments">:
doc "Optional JSDoc comment" $
T.optional $ js "DocumentationComment"]
classDeclarationWithComments :: Binding
classDeclarationWithComments = define "ClassDeclarationWithComments" $
doc "A class declaration with optional JSDoc" $
T.record [
"body">:
doc "The class declaration" $
js "ClassDeclaration",
"comments">:
doc "Optional JSDoc comment" $
T.optional $ js "DocumentationComment"]