import type { SourceSpan } from './source-location.js'; import type { FieldArg, RillTypeName, TypeRef } from './value-types.js'; interface BaseNode { readonly span: SourceSpan; } export interface ScriptNode extends BaseNode { readonly type: 'Script'; readonly frontmatter: FrontmatterNode | null; /** * Statements in the script. May include RecoveryErrorNode or * PartialExpressionNode when parsed with recoveryMode. */ readonly statements: (StatementNode | AnnotatedStatementNode | RecoveryErrorNode | PartialExpressionNode)[]; } export interface FrontmatterNode extends BaseNode { readonly type: 'Frontmatter'; readonly content: string; } /** * Closure: |params| body * First-class closure with optional typed parameters and defaults. * Scope rules: captures outer (read-only), local mutable. * * Body can be: * - Simple: |x| $x (postfix-expr) * - Grouped: |x| ($x * 2) (compound expression) * - Block: |x| { $a ↵ $b } (multiple statements) * * Optional postfix return type target: |params| body :type-target * Asserts the closure return value against the type target at invocation time. * `:any` is valid and equivalent to omission. */ export interface ClosureNode extends BaseNode { readonly type: 'Closure'; readonly params: ClosureParamNode[]; readonly body: BodyNode; readonly returnTypeTarget?: TypeRef | TypeConstructorNode | undefined; } /** * Function parameter with optional type and default value. * - (x) { } -- untyped * - (x: string) { } -- typed * - (x: string = "hi") { } -- typed with default * - ^(key: value) (x) { } -- with parameter annotations */ export interface ClosureParamNode extends BaseNode { readonly type: 'ClosureParam'; readonly name: string; readonly typeRef: TypeRef | null; readonly defaultValue: LiteralNode | null; readonly annotations?: AnnotationArg[] | undefined; } /** * Statement: a pipe chain expression. * Termination (capture/break/return) is now part of PipeChainNode. */ export interface StatementNode extends BaseNode { readonly type: 'Statement'; readonly expression: PipeChainNode; } /** * Recovery error node for parse error recovery mode. * Represents unparseable content that was skipped during error recovery. * Only appears in ASTs when parsing with `recoveryMode: true`. * * Text/span fidelity contract: `text` must equal the exact source slice * covered by `span`, i.e. `source.slice(span.start.offset, span.end.offset) === text`. */ export interface RecoveryErrorNode extends BaseNode { readonly type: 'RecoveryError'; /** The error message describing what went wrong */ readonly message: string; /** The raw source text that could not be parsed */ readonly text: string; } /** * Annotated statement: ^(key: value, ...) statement * Annotations modify operational parameters for statements. * They prefix statements and bind to the immediately following construct. * * Examples: * ^(limit: 100) $items @ process() * ^(timeout: 30) fetch($url) */ export interface AnnotatedStatementNode extends BaseNode { readonly type: 'AnnotatedStatement'; readonly annotations: AnnotationArg[]; readonly statement: StatementNode; } /** * Annotation argument: named or spread * Reuses similar structure to dict entries but with spread support. */ export type AnnotationArg = NamedArgNode | SpreadArgNode; /** * Named annotation argument: key: value * Example: limit: 100, timeout: 30 */ export interface NamedArgNode extends BaseNode { readonly type: 'NamedArg'; readonly name: string; readonly value: ExpressionNode; } /** * Spread annotation argument: *expr * Example: *$opts spreads tuple keys as annotations */ export interface SpreadArgNode extends BaseNode { readonly type: 'SpreadArg'; readonly expression: ExpressionNode; } export interface CaptureNode extends BaseNode { readonly type: 'Capture'; readonly name: string; /** * Optional explicit type annotation: $name:type or $name:$t */ readonly typeRef: TypeRef | null; readonly inlineShape: null; } /** * Break: exit loop with current pipe value. * Used as chain terminator: $x -> break * Or bare: break (implicit $ -> break) */ export interface BreakNode extends BaseNode { readonly type: 'Break'; } /** * Return: exit closure with current pipe value. * Used as chain terminator: $x -> return * Or bare: return (implicit $ -> return) */ export interface ReturnNode extends BaseNode { readonly type: 'Return'; } /** * Yield: emit value from a stream closure. * Used as chain terminator: $x -> yield * Or bare: yield (implicit $ -> yield) * Only valid inside a closure with :stream(T):R return type annotation. */ export interface YieldNode extends BaseNode { readonly type: 'Yield'; } /** * Pass: pass through pipe value unchanged. * Used as chain terminator: $x -> pass * Or bare: pass (implicit $ -> pass) */ export interface PassNode extends BaseNode { readonly type: 'Pass'; } /** * PassBlock: non-halting side-effect block. * Syntax: pass { body } * * Lexer emits PASS_LANGLE when `pass` is followed immediately by `<`. * The body executes in the surrounding scope. In Phase 1, only * `on_error: #IGNORE` is recognized in the options dict. */ export interface PassBlockNode extends BaseNode { readonly type: 'PassBlock'; /** Raw dict parsed from the angle-bracket head, e.g. ``. */ readonly options: DictNode; /** Block body sharing the surrounding scope. */ readonly body: BlockNode; } /** * TimeoutBlock: wall-time or inactivity bound wrapping a body. * Syntax: timeout { body } * timeout { body } * * Lexer emits TIMEOUT_LANGLE when `timeout` is followed immediately by `<`. * On expiry, produces an invalid value carrying #TIMEOUT_TOTAL (kind: 'total') * or #TIMEOUT_IDLE (kind: 'idle'). Recovery is via guard/?? */ export interface TimeoutBlockNode extends BaseNode { readonly type: 'TimeoutBlock'; /** Which bound applies: 'total' for wall-time, 'idle' for inactivity. */ readonly kind: 'total' | 'idle'; /** Duration expression evaluated at runtime. Must resolve to a duration value. */ readonly duration: ExpressionNode; /** Non-empty body block to execute under the timeout. */ readonly body: BlockNode; } /** * Assert: halt execution if condition is false. * Syntax: assert condition * Or: assert condition "custom error message" */ export interface AssertNode extends BaseNode { readonly type: 'Assert'; readonly condition: ExpressionNode; readonly message: StringLiteralNode | null; } /** * Error: explicitly raise an error with a message. * Syntax: error "message" * Or: error "interpolated {$var} message" */ export interface ErrorNode extends BaseNode { readonly type: 'Error'; readonly message: StringLiteralNode | null; } export type ExpressionNode = PipeChainNode | PartialExpressionNode; /** * Partial expression node for parser error recovery. * Represents a partially-typed (half-recognized) expression: a structured * fragment with at least one typed child, kept distinct from * `RecoveryErrorNode` (opaque skipped text) so the two recovery shapes * never collide in downstream visitors. * Only appears in ASTs produced during error recovery. */ export interface PartialExpressionNode extends BaseNode { readonly type: 'PartialExpression'; /** Human-readable description of what was expected */ readonly message: string; /** Typed child nodes recognized within the partial fragment (at least one) */ readonly children: readonly ExpressionNode[]; } /** Chain terminator: capture, break, return, or yield */ export type ChainTerminator = CaptureNode | BreakNode | ReturnNode | YieldNode; export interface PipeChainNode extends BaseNode { readonly type: 'PipeChain'; readonly head: ArithHead; /** * Pipe targets and inline captures. * Inline captures act as implicit .set() — store value and return unchanged. * Semantically: "-> $a ->" ≡ "-> $a.set($) ->" */ readonly pipes: (PipeTargetNode | CaptureNode)[]; /** * Chain terminator: final capture, break, or return. * Examples: * $x -> $y terminator = Capture($y) * $x -> break terminator = Break * $x -> return terminator = Return * $x -> .method terminator = null */ readonly terminator: ChainTerminator | null; } /** * Type guard to check if an expression node is a PipeChainNode (as opposed * to a PartialExpressionNode produced by parser error recovery). */ export declare function isPipeChainNode(node: ExpressionNode): node is PipeChainNode; export interface PostfixExprNode extends BaseNode { readonly type: 'PostfixExpr'; readonly primary: PrimaryNode; readonly methods: (MethodCallNode | InvokeNode | AnnotationAccessNode | IndexAccessNode)[]; readonly defaultValue: BodyNode | null; /** * Terminal existence check on the accumulated primary+methods chain: * expr.?field (optionally &type). Mirrors VariableNode.existenceCheck; * when set, methods after it are not collected — the check ends the * postfix chain. */ readonly existenceCheck?: ExistenceCheck | null; } export type PrimaryNode = LiteralNode | ListLiteralNode | DictLiteralNode | TupleLiteralNode | OrderedLiteralNode | VariableNode | HostCallNode | HostRefNode | AnnotatedExprNode | ClosureCallNode | MethodCallNode | ConditionalNode | WhileLoopNode | DoWhileLoopNode | BlockNode | AssertNode | ErrorNode | PassNode | PassBlockNode | TimeoutBlockNode | GroupedExprNode | TypeAssertionNode | TypeCheckNode | TypeNameExprNode | TypeConstructorNode | ClosureSigLiteralNode | UseExprNode | AtomLiteralNode | StatusProbeNode | GuardBlockNode | RetryBlockNode | RecoveryErrorNode; export type PipeTargetNode = HostCallNode | HostRefNode | ClosureCallNode | MethodCallNode | PipeInvokeNode | ConditionalNode | WhileLoopNode | DoWhileLoopNode | BlockNode | ClosureNode | StringLiteralNode | DictNode | GroupedExprNode | DestructureNode | SliceNode | TypeAssertionNode | TypeCheckNode | PostfixExprNode | VariableNode | AssertNode | ErrorNode | AnnotationAccessNode | DestructNode | ListLiteralNode | TypeNameExprNode | TypeConstructorNode | UseExprNode | PassBlockNode | TimeoutBlockNode; /** Invoke pipe value as a closure: -> $() or -> $(arg1, arg2) */ export interface PipeInvokeNode extends BaseNode { readonly type: 'PipeInvoke'; readonly args: (ExpressionNode | SpreadArgNode)[]; } export type LiteralNode = StringLiteralNode | NumberLiteralNode | BoolLiteralNode | ListLiteralNode | DictNode | ClosureNode | AtomLiteralNode | DictLiteralNode | TupleLiteralNode | OrderedLiteralNode | RecoveryErrorNode; export interface StringLiteralNode extends BaseNode { readonly type: 'StringLiteral'; readonly parts: (string | InterpolationNode)[]; readonly isMultiline: boolean; } export interface InterpolationNode extends BaseNode { readonly type: 'Interpolation'; readonly expression: ExpressionNode; } export interface NumberLiteralNode extends BaseNode { readonly type: 'NumberLiteral'; readonly value: number; } export interface BoolLiteralNode extends BaseNode { readonly type: 'BoolLiteral'; readonly value: boolean; } export interface ListSpreadNode extends BaseNode { readonly type: 'ListSpread'; readonly expression: ExpressionNode; } export interface DictNode extends BaseNode { readonly type: 'Dict'; readonly entries: DictEntryNode[]; readonly defaultValue: BodyNode | null; } export interface DictKeyVariable { readonly kind: 'variable'; readonly variableName: string; /** Source span from the opening key delimiter through the closing delimiter */ readonly span: SourceSpan; } export interface DictKeyComputed { readonly kind: 'computed'; readonly expression: ExpressionNode; /** Source span from the opening key delimiter through the closing delimiter */ readonly span: SourceSpan; } export interface DictEntryNode extends BaseNode { readonly type: 'DictEntry'; readonly key: string | number | boolean | ListLiteralNode | DictKeyVariable | DictKeyComputed; readonly value: ExpressionNode; /** * Present only for string keys that came directly from source syntax as either an * IDENTIFIER token or a quoted STRING token. Reflects the syntactic form used at the call * site: `'identifier'` for bare-identifier keys (`[name: "x"]`) and `'string'` for * quoted-string keys (`["name": "x"]` or `dict["name": "x"]`). * * Not all string-valued keys have `keyForm`; some internal or synthesized string keys * intentionally omit it (for example the `'...'` key used to encode spread entries). This * is metadata for downstream tools and does not affect runtime semantics. */ readonly keyForm?: 'identifier' | 'string'; } /** * Type constructor: list(string), dict(string, number), tuple(string, number), ordered(string) * Constructs a parameterized type expression for use in type assertions and shape constraints. * * Examples: * list(string) * dict(string, number) * tuple(string, number, boolean) * ordered(string) * list(element: string) */ export interface TypeConstructorNode extends BaseNode { readonly type: 'TypeConstructor'; readonly constructorName: 'list' | 'dict' | 'tuple' | 'ordered' | 'stream'; readonly args: FieldArg[]; } /** * Closure signature literal: |param: type, ...| :returnType * Represents a closure type signature as a first-class value. * Distinguished from a closure literal by absence of a `{` body block. * * Examples: * |x: string| :number * |a: string, b: number| :boolean */ export interface ClosureSigLiteralNode extends BaseNode { readonly type: 'ClosureSigLiteral'; readonly params: { name: string; typeExpr: ExpressionNode; annotations?: AnnotationArg[]; }[]; readonly returnType: PostfixExprNode; } export type BinaryOp = '+' | '-' | '*' | '/' | '%' | '&&' | '||' | '==' | '!=' | '<' | '>' | '<=' | '>='; /** * Named constants for the {@link BinaryOp} string literals so parser and * runtime sites reference symbols instead of repeating operator characters. */ export declare const BINARY_OPS: { readonly ADD: '+'; readonly SUB: '-'; readonly MUL: '*'; readonly DIV: '/'; readonly MOD: '%'; readonly AND: '&&'; readonly OR: '||'; readonly EQ: '=='; readonly NE: '!='; readonly LT: '<'; readonly GT: '>'; readonly LE: '<='; readonly GE: '>='; }; /** * Expression head types for binary/unary expressions. * Includes arithmetic (+, -, *, /, %) and logical (&&, ||, !) operators. */ export type ArithHead = BinaryExprNode | UnaryExprNode | PostfixExprNode; /** * Binary expression: left op right * Arithmetic: ($x + 5), ($a * $b), (2 + 3 * 4) * Logical: ($a && $b), ($x || $y) */ export interface BinaryExprNode extends BaseNode { readonly type: 'BinaryExpr'; readonly op: BinaryOp; readonly left: ArithHead; readonly right: ArithHead; } /** * Unary expression: -operand or !operand * Examples: (-5), (-$x), (!$ready) */ export interface UnaryExprNode extends BaseNode { readonly type: 'UnaryExpr'; readonly op: '-' | '!'; readonly operand: UnaryExprNode | PostfixExprNode; } /** * Grouped expression: ( expression ) * Single-expression block with () delimiters. * Provides scoping — captures inside are local and not visible outside. * * Scoping rules identical to blocks: * ("hello" -> $local) — $local is scoped to group, returns "hello" */ export interface GroupedExprNode extends BaseNode { readonly type: 'GroupedExpr'; readonly expression: PipeChainNode; } /** * Simple body: expression that can follow closure params, conditionals, or loops. * No naked compound expressions — arithmetic/pipes/booleans must be grouped. * * Valid: block, grouped, or postfix-expr (variable, literal, method, function call) * Examples: * |x| $x — postfix-expr * |x| ($x * 2) — grouped (compound) * |x| { $a ↵ $b } — block (multiple statements) */ export type BodyNode = BlockNode | GroupedExprNode | PostfixExprNode | PipeChainNode; export interface VariableNode extends BaseNode { readonly type: 'Variable'; readonly name: string | null; readonly isPipeVar: boolean; readonly isPipeTarget?: boolean; /** Ordered chain of property accesses: .name, [0], .$var, etc. */ readonly accessChain: PropertyAccess[]; /** * Default value for null-coalescing: $data.path ?? default * If property access returns null/missing, use this value instead. */ readonly defaultValue: BodyNode | null; /** * Existence check on final path element: $data.?path * Returns boolean (true if path exists). * When set, implies safe traversal (no error on missing intermediate paths). */ readonly existenceCheck: ExistenceCheck | null; } /** * Existence check configuration. * For .?path (just exists), .?path&type (exists AND type matches), or a bare * .? probe (finalAccess: null) that checks the receiver itself rather than a * field/index on it. */ export interface ExistenceCheck { /** * The final field/index being checked for existence, or null for a bare * `.?` probe that checks the validity of the receiver itself. */ readonly finalAccess: FieldAccess | null; /** Optional type check: returns true only if exists AND matches type */ readonly typeRef: TypeRef | null; } /** * Field access element in a property access chain (dot-based). * * Access forms: * - literal: .identifier (string key) * - variable: .$var (variable as key) * - computed: .(expr) (computed expression) * - block: .{block} (block returning key) * - alternatives: .(a || b) (try keys left-to-right) * * Note: Numeric indices use bracket syntax [0], [-1] instead of dot. */ export type FieldAccess = FieldAccessLiteral | FieldAccessVariable | FieldAccessComputed | FieldAccessBlock | FieldAccessAlternatives | FieldAccessAnnotation; /** Literal field access: .identifier */ export interface FieldAccessLiteral { readonly kind: 'literal'; readonly field: string; /** Source span from the . token through the field-name token */ readonly span: SourceSpan; } /** Variable as key: .$var or .$ (pipe variable) */ export interface FieldAccessVariable { readonly kind: 'variable'; readonly variableName: string | null; /** Source span from the . token through the variable-name token */ readonly span: SourceSpan; } /** Computed expression: .(expr) */ export interface FieldAccessComputed { readonly kind: 'computed'; readonly expression: ExpressionNode; /** Source span from the . token through the closing ) token */ readonly span: SourceSpan; } /** Block returning key: .{block} */ export interface FieldAccessBlock { readonly kind: 'block'; readonly block: BlockNode; } /** Alternatives (try keys left-to-right): .(a || b) */ export interface FieldAccessAlternatives { readonly kind: 'alternatives'; readonly alternatives: string[]; } /** Annotation reflection: .^key */ export interface FieldAccessAnnotation { readonly kind: 'annotation'; readonly key: string; } /** * Bracket index access: [expr] * Used for numeric indexing into lists/strings. * Expression can be positive (from start) or negative (from end). */ export interface BracketAccess { /** Discriminator for the unified PropertyAccess type */ readonly accessKind: 'bracket'; /** The index expression (evaluates to number) */ readonly expression: ExpressionNode; /** Source span from opening [ to closing ] (inclusive) */ readonly span: SourceSpan; } /** * Unified property access type. * Used to maintain order of mixed dot and bracket accesses. * e.g., $data[0].name[1] has accesses: [bracket(0), field(name), bracket(1)] */ export type PropertyAccess = FieldAccess | BracketAccess; /** * Annotated expression: ^(key: value, ...) expression * Attaches annotation data to a primary expression value. * When the expression is a closure, annotations are captured by createClosure(). * When the expression is a non-closure, annotations are ignored at runtime. * * Examples: * ^("describe it") |x| ($x * 2) -- closure gets description annotation * ^(label: "add") app::add -- host ref gets annotation (runtime: ignored) */ export interface AnnotatedExprNode extends BaseNode { readonly type: 'AnnotatedExpr'; readonly annotations: AnnotationArg[]; readonly expression: PrimaryNode; } export interface HostCallNode extends BaseNode { readonly type: 'HostCall'; readonly name: string; readonly args: (ExpressionNode | SpreadArgNode)[]; } export interface HostRefNode extends BaseNode { readonly type: 'HostRef'; readonly name: string; } export interface MethodCallNode extends BaseNode { readonly type: 'MethodCall'; readonly name: string; readonly args: ExpressionNode[]; readonly receiverSpan: SourceSpan | null; /** True when the source wrote explicit parens: `.method(...)` vs bare `.method`. */ readonly hasParens: boolean; } /** Postfix invocation: expr(args) - calls the result of expr as a closure */ export interface InvokeNode extends BaseNode { readonly type: 'Invoke'; readonly args: (ExpressionNode | SpreadArgNode)[]; } /** Postfix bracket-index access: expr[index] */ export interface IndexAccessNode extends BaseNode { readonly type: 'IndexAccess'; readonly index: ExpressionNode; } /** Annotation reflection access on expressions: expr.^key */ export interface AnnotationAccessNode extends BaseNode { readonly type: 'AnnotationAccess'; readonly key: string; } /** Call a closure stored in a variable: $fn(args) or $obj.method(args) */ export interface ClosureCallNode extends BaseNode { readonly type: 'ClosureCall'; readonly name: string; readonly accessChain: string[]; readonly args: (ExpressionNode | SpreadArgNode)[]; } /** * Conditional: ?($cond) body : else * Body can be any simple-body (block, grouped, or postfix-expr). * * Examples: * ?($x > 0) "positive" : "negative" — literals * ?($x > 0) ($x * 2) : ($x / 2) — grouped * ?($x > 0) { complex } : { other } — blocks */ export interface ConditionalNode extends BaseNode { readonly type: 'Conditional'; readonly input: ExpressionNode | null; readonly condition: BodyNode | null; readonly thenBranch: BodyNode; readonly elseBranch: BodyNode | ConditionalNode | null; } /** * While loop: `while (cond) do { body }` * * `condition` is required and evaluated as a boolean before each iteration. * Loop executes body repeatedly while condition is true. * BreakSignal exits the loop; ReturnSignal propagates upward. */ export interface WhileLoopNode extends BaseNode { readonly type: 'WhileLoop'; readonly condition: ExpressionNode; readonly body: BodyNode; readonly annotations?: AnnotationArg[] | undefined; } /** * Do-while loop: `do { body } while (cond)` * * Body executes at least once before condition is checked. * `input` carries the pipe-seed expression when present (null = implied $). * `condition` is stored as a BodyNode. The parser assigns the PipeChainNode * produced by parseExpression() directly — PipeChainNode is a member of the * BodyNode union, so no wrapping is needed. * BreakSignal exits the loop; ReturnSignal propagates upward. */ export interface DoWhileLoopNode extends BaseNode { readonly type: 'DoWhileLoop'; readonly input: ExpressionNode | null; readonly body: BodyNode; readonly condition: BodyNode; readonly annotations?: AnnotationArg[] | undefined; } export interface BlockNode extends BaseNode { readonly type: 'Block'; readonly statements: (StatementNode | AnnotatedStatementNode)[]; } /** * Guard block: guard { body } or guard { body } * Intercepts error codes raised by the body. If the body raises a code in * `onCodes` (or any code when onCodes is absent), the guard handles it and * produces a recovered value. Otherwise the error propagates. * * Lexer emits GUARD_LBRACE when `guard` is followed immediately by `{`. * Parser productions (task 1.4) populate this node. */ export interface GuardBlockNode extends BaseNode { readonly type: 'GuardBlock'; readonly body: BlockNode; /** Optional list of atom codes that this guard handles. */ readonly onCodes?: AtomLiteralNode[] | undefined; } /** * Retry block: retry { body } or retry { body } * Runs the body up to N times. On error matching `onCodes` (or any error when * onCodes is absent), the body is re-executed. The last attempt's error * propagates if all attempts fail. * * Lexer emits RETRY_LANGLE when `retry` is followed immediately by `<`. * Parser productions (task 1.4) populate this node. */ export interface RetryBlockNode extends BaseNode { readonly type: 'RetryBlock'; /** Maximum number of attempts, derived from the N in `retry`. */ readonly attempts: number; readonly body: BlockNode; /** Optional list of atom codes that trigger retry; absent = any error. */ readonly onCodes?: AtomLiteralNode[] | undefined; } /** * Atom literal: #NAME * An interned, uppercase-named symbol used as an error code identity. * * Shape rule (enforced by the atom registry at resolution time): * [A-Z][A-Z0-9_]* * * The lexer only guarantees the first character is uppercase; the registry * applies strict validation and interns the atom. */ export interface AtomLiteralNode extends BaseNode { readonly type: 'AtomLiteral'; /** Atom name, without the leading `#` sigil. */ readonly name: string; } /** * Status probe: $x.! or $x.!field * Reads the sidecar status associated with a value. Bare `.!` returns the full * status record; `.!field` projects a single field. * * Lexer emits the DOT_BANG token for `.!`. Parser productions (task 1.4) * wire this node into the AST. */ export interface StatusProbeNode extends BaseNode { readonly type: 'StatusProbe'; /** The value being probed (e.g., `$x`). */ readonly target: ExpressionNode; /** Optional field projection; `undefined` for bare `.!`. */ readonly field?: string | undefined; } /** * Destructure operator: destruct<...> * Extracts elements from tuples/dicts into variables. * * Tuple: [1, 2, 3] -> destruct<$a, $b, $c> * Dict: [name: "x"] -> destruct * Nested: [[1, 2], 3] -> destruct, $c> */ export interface DestructureNode extends BaseNode { readonly type: 'Destructure'; readonly elements: DestructPatternNode[]; } /** * Element in a destructure pattern. * Can be: typed variable, key-variable pair, skip placeholder, or nested destructure. */ export interface DestructPatternNode extends BaseNode { readonly type: 'DestructPattern'; readonly kind: 'variable' | 'keyValue' | 'skip' | 'nested'; /** Variable name (for 'variable' and 'keyValue' kinds) */ readonly name: string | null; /** Key name (for 'keyValue' kind - dict destructuring) */ readonly key: string | null; /** Type annotation (for 'variable' and 'keyValue' kinds) */ readonly typeRef: TypeRef | null; /** Nested destructure pattern (for 'nested' kind) */ readonly nested: DestructureNode | null; } /** * Slice operator: / * Extracts a portion of a tuple or string using Python-style slicing. * * Examples: * $tuple -> /<0:3> # elements 0, 1, 2 * $tuple -> /<::-1> # reversed * "hello" -> /<1:4> # "ell" */ export interface SliceNode extends BaseNode { readonly type: 'Slice'; /** Start index (null = from beginning) */ readonly start: SliceBoundNode | null; /** Stop index (null = to end) */ readonly stop: SliceBoundNode | null; /** Step (null = 1) */ readonly step: SliceBoundNode | null; } /** A slice bound: number, variable, or grouped expression */ export type SliceBoundNode = NumberLiteralNode | VariableNode | GroupedExprNode; /** * Type assertion: expr:type * Asserts that the expression evaluates to the specified type. * Returns the value unchanged if assertion passes, errors on mismatch. * * Examples: * fetchData():string # assert result is string * $val -> :number -> process() # assert pipe value is number * "hello":string # "hello" (pass) * "hello":number # Error: expected number, got string * * When operand is null, it acts on the implicit $: * :string ≡ $:string */ export interface TypeAssertionNode extends BaseNode { readonly type: 'TypeAssertion'; /** The expression to assert (null for bare :type which uses $) */ readonly operand: PostfixExprNode | null; /** The expected type reference (static or dynamic) */ readonly typeRef: TypeRef; } /** * Type check: expr:?type * Checks if the expression evaluates to the specified type. * Returns true if types match, false otherwise. * * Examples: * fetchData():?string # is result a string? * $val -> :?number -> process() # is pipe value a number? * "hello":?string # true * "hello":?number # false * * When operand is null, it checks the implicit $: * :?string ≡ $:?string */ export interface TypeCheckNode extends BaseNode { readonly type: 'TypeCheck'; /** The expression to check (null for bare :?type which uses $) */ readonly operand: PostfixExprNode | null; /** The type reference to check for (static or dynamic) */ readonly typeRef: TypeRef; } /** * Type name expression: a bare type keyword used as a first-class value. * Produces a type value that can be passed to type assertion/check operators * or stored in variables. * * Examples: * string # the type value for 'string' * number -> :type # assert the result is of kind 'type' */ export interface TypeNameExprNode extends BaseNode { readonly type: 'TypeNameExpr'; /** The rill type name this expression represents */ readonly typeName: RillTypeName; } /** * List literal: list[expr, expr, ...] * Constructs a list collection from comma-separated expressions. * * Examples: * list[1, 2, 3] * list["a", "b", $x] */ export interface ListLiteralNode extends BaseNode { readonly type: 'ListLiteral'; readonly elements: (ExpressionNode | ListSpreadNode)[]; readonly defaultValue: BodyNode | null; } /** * Dict literal: dict[key: value, ...] * Constructs a dict collection from comma-separated key-value pairs. * * Examples: * dict[name: "Alice", age: 30] * dict["x": 1, "y": 2] */ export interface DictLiteralNode extends BaseNode { readonly type: 'DictLiteral'; readonly entries: DictEntryNode[]; } /** * Tuple literal: tuple[expr, expr, ...] * Constructs a typed tuple from comma-separated expressions (mixed types allowed). * * Examples: * tuple[1, "hello", true] * tuple[$a, $b] */ export interface TupleLiteralNode extends BaseNode { readonly type: 'TupleLiteral'; readonly elements: (ExpressionNode | ListSpreadNode)[]; } /** * Ordered literal: ordered[key: value, ...] * Constructs an ordered collection from comma-separated key-value pairs. * * Examples: * ordered[name: "Alice", score: 42] */ export interface OrderedLiteralNode extends BaseNode { readonly type: 'OrderedLiteral'; readonly entries: DictEntryNode[]; } /** * Destruct operator: destruct<$a, $b, ...> * Extracts elements from collections into named captures. * Supports skip placeholders (_), typed captures, and key-value patterns. * * Examples: * $tuple -> destruct<$a, $b, $c> * $tuple -> destruct<$a, _, $c> * $dict -> destruct */ export interface DestructNode extends BaseNode { readonly type: 'Destruct'; readonly elements: DestructPatternNode[]; } /** * Discriminated union for the identifier in a use expression. * - 'static': scheme:seg1.seg2 — parsed at parse time into scheme and segments * - 'variable': $varName — resolved to string at runtime * - 'computed': (pipeChain) — expression resolved to string at runtime * * static.segments contains at minimum 1 element. */ export type UseIdentifier = { kind: 'static'; scheme: string; segments: string[]; } | { kind: 'variable'; name: string; } | { kind: 'computed'; expression: ExpressionNode; }; /** * Use expression: use or use:TypeRef * Resolves a module or resource identifier at runtime. * * Examples: * use * use<$moduleVar> * use<(computedExpr)>:TypeName * use:|param: string| */ export interface UseExprNode extends BaseNode { readonly type: 'UseExpr'; readonly identifier: UseIdentifier; readonly typeRef: TypeRef | null; readonly closureAnnotation: ReadonlyArray<{ readonly name: string; readonly typeRef: TypeRef; readonly defaultValue?: LiteralNode; }> | null; } export type SimplePrimaryNode = LiteralNode | VariableNode | HostCallNode | MethodCallNode | BlockNode | BinaryExprNode | UnaryExprNode | GroupedExprNode | PostfixExprNode | TypeAssertionNode | TypeCheckNode; export type ASTNode = ScriptNode | FrontmatterNode | ClosureNode | ClosureParamNode | StatementNode | CaptureNode | BreakNode | ReturnNode | YieldNode | PassNode | AssertNode | PipeChainNode | PostfixExprNode | MethodCallNode | InvokeNode | IndexAccessNode | AnnotationAccessNode | HostCallNode | HostRefNode | ClosureCallNode | PipeInvokeNode | VariableNode | ConditionalNode | WhileLoopNode | DoWhileLoopNode | BlockNode | StringLiteralNode | InterpolationNode | NumberLiteralNode | BoolLiteralNode | ListSpreadNode | DictNode | DictEntryNode | BinaryExprNode | UnaryExprNode | GroupedExprNode | DestructureNode | DestructPatternNode | SliceNode | TypeAssertionNode | TypeCheckNode | TypeConstructorNode | ClosureSigLiteralNode | AnnotatedStatementNode | AnnotatedExprNode | NamedArgNode | SpreadArgNode | RecoveryErrorNode | PartialExpressionNode | ErrorNode | TypeNameExprNode | ListLiteralNode | DictLiteralNode | TupleLiteralNode | OrderedLiteralNode | DestructNode | UseExprNode | GuardBlockNode | RetryBlockNode | PassBlockNode | TimeoutBlockNode | AtomLiteralNode | StatusProbeNode; export {};