/** * AST Node Types for MEL Parser * Based on MEL SPEC v0.3.3 Section 4 */ import type { SourceLocation } from "../lexer/source-location.js"; /** * Base interface for all AST nodes */ export interface ASTNode { location: SourceLocation; } /** * Root node of a MEL program */ export interface ProgramNode extends ASTNode { kind: "program"; imports: ImportNode[]; domain: DomainNode; } /** * Import declaration */ export interface ImportNode extends ASTNode { kind: "import"; names: string[]; from: string; } /** * Domain declaration */ export interface DomainNode extends ASTNode { kind: "domain"; name: string; annotations?: AnnotationNode[]; /** v0.3.3: Named type declarations */ types: TypeDeclNode[]; members: DomainMember[]; } /** * Structural annotation declaration. */ export interface AnnotationNode extends ASTNode { kind: "annotation"; tag: string; payload?: ExprNode; } /** * Domain member types */ export type DomainMember = StateNode | ContextNode | ComputedNode | ActionNode | FlowDeclNode; /** * Type declaration (v0.3.3) * Syntax: type Name = TypeExpr */ export interface TypeDeclNode extends ASTNode { kind: "typeDecl"; name: string; annotations?: AnnotationNode[]; typeExpr: TypeExprNode; } /** * State block declaration */ export interface StateNode extends ASTNode { kind: "state"; fields: StateFieldNode[]; } /** * State field declaration */ export interface StateFieldNode extends ASTNode { kind: "stateField"; name: string; annotations?: AnnotationNode[]; typeExpr: TypeExprNode; initializer?: ExprNode; } /** * Context block declaration. * * Declares the shape of direct-injected external context. Values are supplied * by the runtime, so context fields do not carry initializers. */ export interface ContextNode extends ASTNode { kind: "context"; fields: ContextFieldNode[]; } /** * Context field declaration. */ export interface ContextFieldNode extends ASTNode { kind: "contextField"; name: string; typeExpr: TypeExprNode; } /** * Computed value declaration */ export interface ComputedNode extends ASTNode { kind: "computed"; name: string; annotations?: AnnotationNode[]; expression: ExprNode; } /** * Action declaration */ export interface ActionNode extends ASTNode { kind: "action"; name: string; annotations?: AnnotationNode[]; params: ParamNode[]; /** v0.3.2: Optional availability condition */ available?: ExprNode; /** v0.9.0: Optional dispatchability condition */ dispatchable?: ExprNode; body: GuardedStmtNode[]; } /** * Flow declaration (v0.7.0 / ADR-013a) * Raw AST preserves flow declarations until the expansion pass removes them. */ export interface FlowDeclNode extends ASTNode { kind: "flow"; name: string; params: ParamNode[]; body: FlowStmtNode[]; } /** * Parameter declaration */ export interface ParamNode extends ASTNode { kind: "param"; name: string; annotations?: AnnotationNode[]; typeExpr: TypeExprNode; } /** * Guarded statement types (top-level in action body) */ export type GuardedStmtNode = WhenStmtNode | OnceStmtNode | OnceIntentStmtNode | IncludeStmtNode | FailStmtNode | StopStmtNode; /** * Raw flow statement types (top-level in flow body). * Parser stays permissive; validation narrows the allowed subset. */ export type FlowStmtNode = WhenStmtNode | IncludeStmtNode | OnceStmtNode | OnceIntentStmtNode | PatchStmtNode | EffectStmtNode; /** * Inner statement types (inside guards) */ export type InnerStmtNode = PatchStmtNode | EffectStmtNode | WhenStmtNode | OnceStmtNode | OnceIntentStmtNode | IncludeStmtNode | FailStmtNode | StopStmtNode; /** * When guard statement */ export interface WhenStmtNode extends ASTNode { kind: "when"; condition: ExprNode; body: InnerStmtNode[]; } /** * Once guard statement (per-intent idempotency) */ export interface OnceStmtNode extends ASTNode { kind: "once"; marker: PathNode; condition?: ExprNode; body: InnerStmtNode[]; } /** * Once-intent guard statement (per-intent idempotency sugar) */ export interface OnceIntentStmtNode extends ASTNode { kind: "onceIntent"; condition?: ExprNode; body: InnerStmtNode[]; } /** * Include statement (v0.7.0 / ADR-013a) * Raw AST preserves include sites until the expansion pass inlines them. */ export interface IncludeStmtNode extends ASTNode { kind: "include"; flowName: string; args: ExprNode[]; } /** * Patch statement */ export interface PatchStmtNode extends ASTNode { kind: "patch"; path: PathNode; op: "set" | "unset" | "merge"; value?: ExprNode; } /** * Effect statement */ export interface EffectStmtNode extends ASTNode { kind: "effect"; effectType: string; args: EffectArgNode[]; } /** * Effect argument */ export interface EffectArgNode extends ASTNode { kind: "effectArg"; name: string; value: ExprNode | PathNode; isPath: boolean; } /** * Fail statement (v0.3.2) - terminates flow with error * Compiles to FlowNode { kind: "fail", code, message } */ export interface FailStmtNode extends ASTNode { kind: "fail"; code: string; message?: ExprNode; } /** * Stop statement (v0.3.2) - early exit, no error * Compiles to FlowNode { kind: "halt", reason } */ export interface StopStmtNode extends ASTNode { kind: "stop"; reason: string; } /** * Type expression node */ export type TypeExprNode = SimpleTypeNode | UnionTypeNode | ArrayTypeNode | RecordTypeNode | LiteralTypeNode | ObjectTypeNode; export interface SimpleTypeNode extends ASTNode { kind: "simpleType"; name: string; } export interface UnionTypeNode extends ASTNode { kind: "unionType"; types: TypeExprNode[]; } export interface ArrayTypeNode extends ASTNode { kind: "arrayType"; elementType: TypeExprNode; } export interface RecordTypeNode extends ASTNode { kind: "recordType"; keyType: TypeExprNode; valueType: TypeExprNode; } export interface LiteralTypeNode extends ASTNode { kind: "literalType"; value: string | number | boolean | null; } /** * Object type node (v0.3.3) * Represents inline object types: { field: Type, ... } * Note: In state fields, this triggers W012 warning (use named type instead) */ export interface ObjectTypeNode extends ASTNode { kind: "objectType"; fields: TypeFieldNode[]; } /** * Type field within an object type */ export interface TypeFieldNode extends ASTNode { kind: "typeField"; name: string; annotations?: AnnotationNode[]; typeExpr: TypeExprNode; optional: boolean; } /** * All expression types */ export type ExprNode = LiteralExprNode | IdentifierExprNode | SystemIdentExprNode | IterationVarExprNode | PropertyAccessExprNode | IndexAccessExprNode | FunctionCallExprNode | UnaryExprNode | BinaryExprNode | TernaryExprNode | ObjectLiteralExprNode | ArrayLiteralExprNode; /** * Literal expression (number, string, boolean, null) */ export interface LiteralExprNode extends ASTNode { kind: "literal"; value: unknown; literalType: "number" | "string" | "boolean" | "null"; } /** * Identifier expression */ export interface IdentifierExprNode extends ASTNode { kind: "identifier"; name: string; } /** * Dollar namespace identifier expression ($runtime.*, $context.*, $input.*, * retired $system/$meta). */ export interface SystemIdentExprNode extends ASTNode { kind: "systemIdent"; path: string[]; } /** * Iteration variable expression ($item only) * v0.3.2: $acc removed - reduce pattern deprecated */ export interface IterationVarExprNode extends ASTNode { kind: "iterationVar"; name: "item"; } /** * Property access expression (a.b) */ export interface PropertyAccessExprNode extends ASTNode { kind: "propertyAccess"; object: ExprNode; property: string; } /** * Index access expression (a[b]) */ export interface IndexAccessExprNode extends ASTNode { kind: "indexAccess"; object: ExprNode; index: ExprNode; } /** * Function call expression */ export interface FunctionCallExprNode extends ASTNode { kind: "functionCall"; name: string; args: ExprNode[]; } /** * Unary expression (!a, -a) */ export interface UnaryExprNode extends ASTNode { kind: "unary"; operator: "!" | "-"; operand: ExprNode; } /** * Binary operators */ export type BinaryOperator = "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "&&" | "||" | "??"; /** * Binary expression (a + b, a && b, etc.) */ export interface BinaryExprNode extends ASTNode { kind: "binary"; operator: BinaryOperator; left: ExprNode; right: ExprNode; } /** * Ternary expression (a ? b : c) */ export interface TernaryExprNode extends ASTNode { kind: "ternary"; condition: ExprNode; consequent: ExprNode; alternate: ExprNode; } /** * Object literal expression ({ a: 1, b: 2 }) */ export interface ObjectLiteralExprNode extends ASTNode { kind: "objectLiteral"; properties: ObjectLiteralEntryNode[]; } export type ObjectLiteralEntryNode = ObjectPropertyNode | ObjectSpreadNode; export interface ObjectPropertyNode extends ASTNode { kind: "objectProperty"; key: string; value: ExprNode; } export interface ObjectSpreadNode extends ASTNode { kind: "objectSpread"; expr: ExprNode; } /** * Array literal expression ([1, 2, 3]) */ export interface ArrayLiteralExprNode extends ASTNode { kind: "arrayLiteral"; elements: ExprNode[]; } /** * Path node for patch targets and effect destinations */ export interface PathNode extends ASTNode { kind: "path"; segments: PathSegmentNode[]; } export type PathSegmentNode = PropertySegmentNode | IndexSegmentNode; export interface PropertySegmentNode extends ASTNode { kind: "propertySegment"; name: string; } export interface IndexSegmentNode extends ASTNode { kind: "indexSegment"; index: ExprNode; } /** * Check if a node is an expression */ export declare function isExprNode(node: ASTNode): node is ExprNode; /** * Check if a node is a statement */ export declare function isStmtNode(node: ASTNode): node is InnerStmtNode;