littlewing 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/dist/index.d.ts +489 -527
  2. package/dist/index.js +2017 -817
  3. package/package.json +39 -45
  4. package/LICENSE +0 -21
  5. package/README.md +0 -586
package/dist/index.d.ts CHANGED
@@ -1,80 +1,176 @@
1
1
  declare namespace exports_ast {
2
- export { unaryOp, subtract, program, number, notEquals, negate, multiply, modulo, logicalOr, logicalNot, logicalAnd, lessThan, lessEqual, isUnaryOp, isProgram, isNumberLiteral, isIdentifier, isFunctionCall, isConditionalExpression, isBinaryOp, isAssignment, identifier, greaterThan, greaterEqual, getNodeName, functionCall, exponentiate, equals, divide, conditional, binaryOp, assign, add, UnaryOp, Program, Operator, NumberLiteral, NodeKind, Identifier, FunctionCall, ConditionalExpression, BinaryOp, Assignment, ASTNode };
2
+ export { unaryOp, subtract, string, rangeExpr, program, number, notEquals, negate, multiply, modulo, logicalOr, logicalNot, logicalAnd, lessThan, lessEqual, isUnaryOp, isStringLiteral, isRangeExpression, isProgram, isNumberLiteral, isIndexAccess, isIfExpression, isIdentifier, isFunctionCall, isForExpression, isBooleanLiteral, isBinaryOp, isAssignment, isArrayLiteral, indexAccess, ifExpr, identifier, greaterThan, greaterEqual, getNodeName, functionCall, forExpr, exponentiate, equals, divide, boolean, binaryOp, assign, array, add, UnaryOp, StringLiteral, RangeExpression, Program, Operator, NumberLiteral, NodeKind, IndexAccess, IfExpression, Identifier2 as Identifier, FunctionCall, ForExpression, BooleanLiteral, BinaryOp, Assignment, ArrayLiteral, ASTNodeBase, ASTNode };
3
3
  }
4
4
  /**
5
5
  * Binary operator types
6
6
  */
7
7
  type Operator = "+" | "-" | "*" | "/" | "%" | "^" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "&&" | "||";
8
8
  /**
9
+ * Base interface for all AST nodes.
10
+ * Optional comment metadata preserved through parse → generate roundtrips.
11
+ */
12
+ interface ASTNodeBase {
13
+ readonly leadingComments?: readonly string[];
14
+ readonly trailingComments?: readonly string[];
15
+ }
16
+ /**
9
17
  * AST Node kind discriminator (const enum for zero-cost abstraction)
10
18
  */
11
19
  declare const enum NodeKind {
12
20
  Program = 0,
13
21
  NumberLiteral = 1,
14
- Identifier = 2,
22
+ Identifier2 = 2,
15
23
  BinaryOp = 3,
16
24
  UnaryOp = 4,
17
25
  FunctionCall = 5,
18
26
  Assignment = 6,
19
- ConditionalExpression = 7
27
+ IfExpression = 7,
28
+ StringLiteral = 8,
29
+ BooleanLiteral = 9,
30
+ ArrayLiteral = 10,
31
+ ForExpression = 11,
32
+ IndexAccess = 12,
33
+ RangeExpression = 13
20
34
  }
21
35
  /**
22
36
  * Program node (multiple statements)
23
- * Tuple: [kind, statements]
24
37
  */
25
- type Program = readonly [kind: NodeKind.Program, statements: readonly ASTNode[]];
38
+ interface Program extends ASTNodeBase {
39
+ readonly kind: NodeKind.Program;
40
+ readonly statements: readonly ASTNode[];
41
+ }
26
42
  /**
27
43
  * Number literal (123, 45.67)
28
- * Tuple: [kind, value]
29
44
  */
30
- type NumberLiteral = readonly [kind: NodeKind.NumberLiteral, value: number];
45
+ interface NumberLiteral extends ASTNodeBase {
46
+ readonly kind: NodeKind.NumberLiteral;
47
+ readonly value: number;
48
+ }
49
+ /**
50
+ * String literal ("hello")
51
+ */
52
+ interface StringLiteral extends ASTNodeBase {
53
+ readonly kind: NodeKind.StringLiteral;
54
+ readonly value: string;
55
+ }
56
+ /**
57
+ * Boolean literal (true, false)
58
+ */
59
+ interface BooleanLiteral extends ASTNodeBase {
60
+ readonly kind: NodeKind.BooleanLiteral;
61
+ readonly value: boolean;
62
+ }
63
+ /**
64
+ * Array literal ([1, 2, 3])
65
+ */
66
+ interface ArrayLiteral extends ASTNodeBase {
67
+ readonly kind: NodeKind.ArrayLiteral;
68
+ readonly elements: readonly ASTNode[];
69
+ }
31
70
  /**
32
71
  * Identifier (variable or function name)
33
- * Tuple: [kind, name]
34
72
  */
35
- type Identifier = readonly [kind: NodeKind.Identifier, name: string];
73
+ interface Identifier2 extends ASTNodeBase {
74
+ readonly kind: NodeKind.Identifier2;
75
+ readonly name: string;
76
+ }
36
77
  /**
37
78
  * Binary operation (a + b, x * y, etc.)
38
- * Tuple: [kind, left, operator, right]
39
- * Note: left-to-right reading order
40
79
  */
41
- type BinaryOp = readonly [kind: NodeKind.BinaryOp, left: ASTNode, operator: Operator, right: ASTNode];
80
+ interface BinaryOp extends ASTNodeBase {
81
+ readonly kind: NodeKind.BinaryOp;
82
+ readonly left: ASTNode;
83
+ readonly operator: Operator;
84
+ readonly right: ASTNode;
85
+ }
42
86
  /**
43
87
  * Unary operation (-x, !x, etc.)
44
- * Tuple: [kind, operator, argument]
45
88
  */
46
- type UnaryOp = readonly [kind: NodeKind.UnaryOp, operator: "-" | "!", argument: ASTNode];
89
+ interface UnaryOp extends ASTNodeBase {
90
+ readonly kind: NodeKind.UnaryOp;
91
+ readonly operator: "-" | "!";
92
+ readonly argument: ASTNode;
93
+ }
47
94
  /**
48
95
  * Function call (NOW(), MAX(a, b), etc.)
49
- * Tuple: [kind, name, arguments]
50
96
  */
51
- type FunctionCall = readonly [kind: NodeKind.FunctionCall, name: string, arguments: readonly ASTNode[]];
97
+ interface FunctionCall extends ASTNodeBase {
98
+ readonly kind: NodeKind.FunctionCall;
99
+ readonly name: string;
100
+ readonly args: readonly ASTNode[];
101
+ }
52
102
  /**
53
103
  * Variable assignment (x = 5)
54
- * Tuple: [kind, name, value]
55
104
  */
56
- type Assignment = readonly [kind: NodeKind.Assignment, name: string, value: ASTNode];
105
+ interface Assignment extends ASTNodeBase {
106
+ readonly kind: NodeKind.Assignment;
107
+ readonly name: string;
108
+ readonly value: ASTNode;
109
+ }
57
110
  /**
58
- * Conditional expression (ternary operator: condition ? consequent : alternate)
59
- * Returns consequent if condition !== 0, otherwise returns alternate
60
- * Tuple: [kind, condition, consequent, alternate]
111
+ * If expression (if condition then consequent else alternate)
112
+ * Returns consequent if condition is true, otherwise returns alternate
61
113
  */
62
- type ConditionalExpression = readonly [kind: NodeKind.ConditionalExpression, condition: ASTNode, consequent: ASTNode, alternate: ASTNode];
114
+ interface IfExpression extends ASTNodeBase {
115
+ readonly kind: NodeKind.IfExpression;
116
+ readonly condition: ASTNode;
117
+ readonly consequent: ASTNode;
118
+ readonly alternate: ASTNode;
119
+ }
120
+ /**
121
+ * For expression (for variable in iterable [when guard] [into name = init] then body)
122
+ * Without `into`: maps over an array or string, optionally filtering with a guard
123
+ * With `into`: reduces/folds into a single value using an accumulator
124
+ */
125
+ interface ForExpression extends ASTNodeBase {
126
+ readonly kind: NodeKind.ForExpression;
127
+ readonly variable: string;
128
+ readonly iterable: ASTNode;
129
+ readonly guard: ASTNode | null;
130
+ readonly accumulator: {
131
+ readonly name: string;
132
+ readonly initial: ASTNode;
133
+ } | null;
134
+ readonly body: ASTNode;
135
+ }
136
+ /**
137
+ * Index access (arr[0], str[1])
138
+ */
139
+ interface IndexAccess extends ASTNodeBase {
140
+ readonly kind: NodeKind.IndexAccess;
141
+ readonly object: ASTNode;
142
+ readonly index: ASTNode;
143
+ }
144
+ /**
145
+ * Range expression (1..5, 1..=5)
146
+ */
147
+ interface RangeExpression extends ASTNodeBase {
148
+ readonly kind: NodeKind.RangeExpression;
149
+ readonly start: ASTNode;
150
+ readonly end: ASTNode;
151
+ readonly inclusive: boolean;
152
+ }
63
153
  /**
64
154
  * AST Node - discriminated union of all node types
65
155
  */
66
- type ASTNode = Program | NumberLiteral | Identifier | BinaryOp | UnaryOp | FunctionCall | Assignment | ConditionalExpression;
156
+ type ASTNode = Program | NumberLiteral | StringLiteral | BooleanLiteral | ArrayLiteral | Identifier2 | BinaryOp | UnaryOp | FunctionCall | Assignment | IfExpression | ForExpression | IndexAccess | RangeExpression;
67
157
  /**
68
158
  * Type guard functions for discriminated union narrowing
69
159
  */
70
160
  declare function isProgram(node: ASTNode): node is Program;
71
161
  declare function isNumberLiteral(node: ASTNode): node is NumberLiteral;
72
- declare function isIdentifier(node: ASTNode): node is Identifier;
162
+ declare function isStringLiteral(node: ASTNode): node is StringLiteral;
163
+ declare function isBooleanLiteral(node: ASTNode): node is BooleanLiteral;
164
+ declare function isArrayLiteral(node: ASTNode): node is ArrayLiteral;
165
+ declare function isIdentifier(node: ASTNode): node is Identifier2;
73
166
  declare function isBinaryOp(node: ASTNode): node is BinaryOp;
74
167
  declare function isUnaryOp(node: ASTNode): node is UnaryOp;
75
168
  declare function isFunctionCall(node: ASTNode): node is FunctionCall;
76
169
  declare function isAssignment(node: ASTNode): node is Assignment;
77
- declare function isConditionalExpression(node: ASTNode): node is ConditionalExpression;
170
+ declare function isIfExpression(node: ASTNode): node is IfExpression;
171
+ declare function isForExpression(node: ASTNode): node is ForExpression;
172
+ declare function isIndexAccess(node: ASTNode): node is IndexAccess;
173
+ declare function isRangeExpression(node: ASTNode): node is RangeExpression;
78
174
  /**
79
175
  * Builder functions for creating AST nodes manually
80
176
  */
@@ -87,9 +183,21 @@ declare function program(statements: readonly ASTNode[]): Program;
87
183
  */
88
184
  declare function number(value: number): NumberLiteral;
89
185
  /**
186
+ * Create a string literal node
187
+ */
188
+ declare function string(value: string): StringLiteral;
189
+ /**
190
+ * Create a boolean literal node
191
+ */
192
+ declare function boolean(value: boolean): BooleanLiteral;
193
+ /**
194
+ * Create an array literal node
195
+ */
196
+ declare function array(elements: readonly ASTNode[]): ArrayLiteral;
197
+ /**
90
198
  * Create an identifier node
91
199
  */
92
- declare function identifier(name: string): Identifier;
200
+ declare function identifier(name: string): Identifier2;
93
201
  /**
94
202
  * Create a binary operation node
95
203
  */
@@ -107,81 +215,42 @@ declare function functionCall(name: string, args?: readonly ASTNode[]): Function
107
215
  */
108
216
  declare function assign(name: string, value: ASTNode): Assignment;
109
217
  /**
110
- * Create a conditional expression node (ternary operator)
218
+ * Create an if expression node (if condition then consequent else alternate)
111
219
  */
112
- declare function conditional(condition: ASTNode, consequent: ASTNode, alternate: ASTNode): ConditionalExpression;
220
+ declare function ifExpr(condition: ASTNode, consequent: ASTNode, alternate: ASTNode): IfExpression;
113
221
  /**
114
- * Convenience functions for common operations
222
+ * Create a for expression node (for variable in iterable [when guard] [into name = init] then body)
115
223
  */
224
+ declare function forExpr(variable: string, iterable: ASTNode, guard: ASTNode | null, accumulator: {
225
+ readonly name: string;
226
+ readonly initial: ASTNode;
227
+ } | null, body: ASTNode): ForExpression;
116
228
  /**
117
- * Create an addition operation
229
+ * Create an index access node (arr[0], str[1])
118
230
  */
119
- declare function add(left: ASTNode, right: ASTNode): BinaryOp;
231
+ declare function indexAccess(object: ASTNode, index: ASTNode): IndexAccess;
120
232
  /**
121
- * Create a subtraction operation
233
+ * Create a range expression node (1..5, 1..=5)
122
234
  */
123
- declare function subtract(left: ASTNode, right: ASTNode): BinaryOp;
235
+ declare function rangeExpr(start: ASTNode, end: ASTNode, inclusive: boolean): RangeExpression;
124
236
  /**
125
- * Create a multiplication operation
237
+ * Convenience functions for common operations
126
238
  */
239
+ declare function add(left: ASTNode, right: ASTNode): BinaryOp;
240
+ declare function subtract(left: ASTNode, right: ASTNode): BinaryOp;
127
241
  declare function multiply(left: ASTNode, right: ASTNode): BinaryOp;
128
- /**
129
- * Create a division operation
130
- */
131
242
  declare function divide(left: ASTNode, right: ASTNode): BinaryOp;
132
- /**
133
- * Create a modulo operation
134
- */
135
243
  declare function modulo(left: ASTNode, right: ASTNode): BinaryOp;
136
- /**
137
- * Create an exponentiation operation
138
- */
139
244
  declare function exponentiate(left: ASTNode, right: ASTNode): BinaryOp;
140
- /**
141
- * Create a negation operation
142
- */
143
245
  declare function negate(argument: ASTNode): UnaryOp;
144
- /**
145
- * Create a logical NOT operation
146
- */
147
246
  declare function logicalNot(argument: ASTNode): UnaryOp;
148
- /**
149
- * Comparison operator convenience functions
150
- */
151
- /**
152
- * Create an equality comparison (==)
153
- */
154
247
  declare function equals(left: ASTNode, right: ASTNode): BinaryOp;
155
- /**
156
- * Create a not-equals comparison (!=)
157
- */
158
248
  declare function notEquals(left: ASTNode, right: ASTNode): BinaryOp;
159
- /**
160
- * Create a less-than comparison (<)
161
- */
162
249
  declare function lessThan(left: ASTNode, right: ASTNode): BinaryOp;
163
- /**
164
- * Create a greater-than comparison (>)
165
- */
166
250
  declare function greaterThan(left: ASTNode, right: ASTNode): BinaryOp;
167
- /**
168
- * Create a less-than-or-equal comparison (<=)
169
- */
170
251
  declare function lessEqual(left: ASTNode, right: ASTNode): BinaryOp;
171
- /**
172
- * Create a greater-than-or-equal comparison (>=)
173
- */
174
252
  declare function greaterEqual(left: ASTNode, right: ASTNode): BinaryOp;
175
- /**
176
- * Logical operator convenience functions
177
- */
178
- /**
179
- * Create a logical AND operation (&&)
180
- */
181
253
  declare function logicalAnd(left: ASTNode, right: ASTNode): BinaryOp;
182
- /**
183
- * Create a logical OR operation (||)
184
- */
185
254
  declare function logicalOr(left: ASTNode, right: ASTNode): BinaryOp;
186
255
  declare function getNodeName(node: ASTNode): string;
187
256
  /**
@@ -207,80 +276,33 @@ declare function getNodeName(node: ASTNode): string;
207
276
  */
208
277
  declare function extractInputVariables(ast: ASTNode): string[];
209
278
  /**
210
- * Generate source code from an AST node
211
- */
212
- declare function generate(node: ASTNode): string;
213
- /**
214
- * Options for customizing the humanization output
215
- */
216
- interface HumanizeOptions {
217
- /**
218
- * Enable HTML output with wrapper tags
219
- * @default false
220
- */
221
- html?: boolean;
222
- /**
223
- * CSS classes to apply to different node types when html is true
224
- */
225
- htmlClasses?: {
226
- number?: string;
227
- identifier?: string;
228
- operator?: string;
229
- function?: string;
230
- };
231
- /**
232
- * Custom phrases for function names
233
- * Maps function name to human-readable phrase
234
- * Example: { 'MAX': 'the maximum of', 'CUSTOM': 'my custom function with' }
235
- */
236
- functionPhrases?: Record<string, string>;
237
- /**
238
- * Custom phrases for operators
239
- * Overrides default operator text
240
- */
241
- operatorPhrases?: Partial<Record<Operator, string>>;
242
- /**
243
- * Use more verbose, descriptive phrasing
244
- * @default false
245
- */
246
- verbose?: boolean;
247
- }
248
- /**
249
- * Humanize an AST node into human-readable English text
279
+ * Extracts the names of all assigned variables from an AST.
250
280
  *
251
- * @param node - The AST node to humanize
252
- * @param options - Optional configuration for the output
253
- * @returns Human-readable English text
281
+ * Walks the AST and collects the left-hand side name from every
282
+ * `Assignment` node. Returns deduplicated names in definition order.
254
283
  *
255
- * @example
256
- * ```typescript
257
- * const ast = parse('price * quantity > 100 ? (price * quantity - discount) * (1 + tax_rate) : MAX(price * quantity, 50)')
258
- * const text = humanize(ast)
259
- * // "if price times quantity is greater than 100 then (price times quantity minus discount) times (1 plus tax_rate), otherwise the maximum of price times quantity and 50"
260
- * ```
284
+ * @param ast - The AST to analyze (can be a single statement or Program node)
285
+ * @returns Array of assigned variable names in definition order
261
286
  *
262
287
  * @example
263
288
  * ```typescript
264
- * // With HTML formatting
265
- * const text = humanize(ast, {
266
- * html: true,
267
- * htmlClasses: {
268
- * identifier: 'variable',
269
- * operator: 'op',
270
- * number: 'num'
271
- * }
272
- * })
289
+ * const node = parse('totalTime = hours * 60; hoursRecovered = saved / 60')
290
+ * extractAssignedVariables(node) // ['totalTime', 'hoursRecovered']
273
291
  * ```
274
292
  */
275
- declare function humanize(node: ASTNode, options?: HumanizeOptions): string;
293
+ declare function extractAssignedVariables(ast: ASTNode): string[];
294
+ /**
295
+ * Generate source code from an AST node
296
+ */
297
+ declare function generate(node: ASTNode): string;
276
298
  /**
277
- * Runtime value type - only numbers
299
+ * Runtime value type - numbers, strings, booleans, dates, times, datetimes, and homogeneous arrays
278
300
  */
279
- type RuntimeValue = number;
301
+ type RuntimeValue = number | string | boolean | Temporal.PlainDate | Temporal.PlainTime | Temporal.PlainDateTime | readonly RuntimeValue[];
280
302
  /**
281
303
  * Execution context providing global functions and variables
282
- * Functions must accept zero or more number arguments and return a number
283
- * Variables must be numbers
304
+ * Functions accept zero or more RuntimeValue arguments and return a RuntimeValue
305
+ * Variables can be any RuntimeValue
284
306
  */
285
307
  interface ExecutionContext {
286
308
  functions?: Record<string, (...args: RuntimeValue[]) => RuntimeValue>;
@@ -288,306 +310,251 @@ interface ExecutionContext {
288
310
  }
289
311
  /**
290
312
  * Evaluate source code or AST with given context
291
- * @param input - Either a source code string or an AST node
292
- * @param context - Optional execution context with variables and functions
293
- * @returns The evaluated result
294
313
  */
295
314
  declare function evaluate(input: string | ASTNode, context?: ExecutionContext): RuntimeValue;
296
315
  /**
297
- * Compiled expression that can be executed multiple times
298
- * Provides faster repeated execution compared to tree-walk interpreter
299
- */
300
- interface CompiledExpression {
301
- /**
302
- * Execute the compiled expression with optional context
303
- * @param context - Execution context with variables and functions
304
- * @returns The evaluated result
305
- */
306
- execute: (context?: ExecutionContext) => RuntimeValue;
307
- /**
308
- * Generated JavaScript source code (for debugging and inspection)
309
- */
310
- source: string;
311
- }
312
- /**
313
- * Compile source code or AST to a JavaScript function for faster repeated execution
314
- *
315
- * JIT compilation trades compilation time for execution speed:
316
- * - First call: Parse + Optimize + Compile (~10-50µs depending on size)
317
- * - Subsequent calls: Direct JavaScript execution (~1-5µs, 5-10x faster)
318
- *
319
- * The compiler automatically optimizes the AST before code generation:
320
- * - Constant folding: `2 + 3` → `5` (safe constants only)
321
- * - Dead code elimination: removes unused variable assignments
322
- * - Expression simplification: `1 ? x : y` → `x`
323
- *
324
- * Optimization is safe because:
325
- * - Constant folding errors (e.g., division by zero) propagate to compile-time
326
- * - Variables that could be external are preserved (no unsafe DCE)
327
- * - The optimizer respects ExecutionContext override semantics
328
- *
329
- * The compiler generates optimized JavaScript code:
330
- * - Uses comma operator instead of IIFEs for better performance
331
- * - Only initializes variables that are actually used
332
- * - Pre-declares temporary variables for reuse
333
- *
334
- * Best for expressions that are evaluated many times with different contexts.
335
- *
336
- * Security: Uses `new Function()` to generate executable code. Safe for trusted
337
- * input only. For untrusted input, use the tree-walk interpreter instead.
338
- *
339
- * @param input - Either a source code string or an AST node
340
- * @returns Compiled expression that can be executed multiple times
341
- * @throws {Error} If compilation fails or AST contains invalid operations (e.g., constant division by zero)
342
- *
343
- * @example
344
- * ```typescript
345
- * const expr = compile('x * 2 + y')
346
- * expr.execute({ variables: { x: 10, y: 5 } }) // 25
347
- * expr.execute({ variables: { x: 20, y: 3 } }) // 43
348
- * ```
349
- *
350
- * @example Automatic optimization
351
- * ```typescript
352
- * const expr = compile('2 + 3 * 4') // Automatically optimized to 14
353
- * expr.execute() // Fast execution of pre-folded constant
354
- * ```
316
+ * Evaluate source code or AST and return the full variable scope.
355
317
  */
356
- declare function compile(input: string | ASTNode): CompiledExpression;
318
+ declare function evaluateScope(input: string | ASTNode, context?: ExecutionContext): Record<string, RuntimeValue>;
357
319
  /**
358
- * Optimize an AST using constant folding, expression simplification, and dead code elimination.
320
+ * Optimize an AST using constant folding, constant propagation, and dead code elimination.
359
321
  *
360
- * This optimizer performs SAFE optimizations that preserve program semantics:
361
- * - Constant folding: Evaluates arithmetic with literal operands at compile-time
362
- * - Function argument pre-evaluation: Simplifies expressions passed to functions
363
- * - Conditional folding: Evaluates ternary with constant condition
364
- * - Dead code elimination: Removes unused variable assignments
365
- *
366
- * Optimizations that are NOT performed (because they're unsafe with context variables):
367
- * - Variable propagation: Variables can be overridden by ExecutionContext
368
- * - Cross-statement analysis: Each statement may affect external state
369
- *
370
- * Time complexity: O(n) where n is the number of AST nodes
371
- * Space complexity: O(d) where d is the max depth (recursion stack)
372
- *
373
- * Algorithm properties:
374
- * - Sound: Preserves program semantics exactly
375
- * - Safe: No assumptions about variable values
376
- * - Local: Only optimizes within individual expressions
377
- *
378
- * @param node - The AST node to optimize
379
- * @returns Optimized AST node
322
+ * When `externalVariables` is provided, the optimizer can safely propagate variables
323
+ * that are not in the set since they cannot be overridden by `ExecutionContext.variables`.
324
+ * Without this parameter, no variables are propagated (backward-compatible behavior).
380
325
  */
381
- declare function optimize(node: ASTNode): ASTNode;
326
+ declare function optimize(node: ASTNode, externalVariables?: ReadonlySet<string>): ASTNode;
382
327
  /**
383
328
  * Parse source code string into AST
384
- * Implements Pratt parsing (top-down operator precedence)
385
- * Uses lazy lexing - calls lexer on-demand instead of receiving all tokens upfront
386
- *
387
- * @param source - The source code to parse
388
- * @returns Parsed AST
389
329
  */
390
330
  declare function parse(source: string): ASTNode;
391
- declare namespace exports_datetime {
392
- export { START_OF_YEAR, START_OF_WEEK, START_OF_QUARTER, START_OF_MONTH, START_OF_DAY, NOW, IS_WEEKEND, IS_SAME_DAY, IS_LEAP_YEAR, GET_YEAR, GET_WEEKDAY, GET_SECOND, GET_QUARTER, GET_MONTH, GET_MINUTE, GET_MILLISECOND, GET_HOUR, GET_DAY_OF_YEAR, GET_DAY, FROM_YEARS, FROM_WEEKS, FROM_MONTHS, FROM_DAYS, END_OF_YEAR, END_OF_MONTH, END_OF_DAY, DIFFERENCE_IN_YEARS, DIFFERENCE_IN_WEEKS, DIFFERENCE_IN_SECONDS, DIFFERENCE_IN_MONTHS, DIFFERENCE_IN_MINUTES, DIFFERENCE_IN_HOURS, DIFFERENCE_IN_DAYS, DATE, ADD_YEARS, ADD_MONTHS, ADD_DAYS };
331
+ declare namespace array {
332
+ export { ARR_UNIQUE, ARR_SUM, ARR_SORT, ARR_SLICE, ARR_REVERSE, ARR_PUSH, ARR_MIN, ARR_MAX, ARR_LEN, ARR_JOIN, ARR_FLAT, ARR_CONTAINS };
393
333
  }
394
334
  /**
395
- * Date utility functions for working with timestamps
396
- * All functions work with milliseconds since Unix epoch (numbers only)
397
- *
398
- * IMPORTANT: All functions use local timezone to match the user's context.
399
- * In a browser, this reflects the user's timezone. On a server, this reflects
400
- * the server's configured timezone. This ensures date calculations align with
401
- * the user's calendar expectations.
335
+ * Get the length of an array
402
336
  */
337
+ declare const ARR_LEN: (a: RuntimeValue) => RuntimeValue;
403
338
  /**
404
- * Get current timestamp (milliseconds since Unix epoch)
339
+ * Append a value to an array, returning a new array
340
+ * Validates homogeneity
405
341
  */
406
- declare const NOW: () => RuntimeValue;
342
+ declare const ARR_PUSH: (a: RuntimeValue, value: RuntimeValue) => RuntimeValue;
407
343
  /**
408
- * Create timestamp from date components (local timezone)
409
- * Year is required, all other parameters default to minimum values
410
- * Month is 1-based (1 = January, 12 = December)
411
- * All parameters are interpreted in local timezone
344
+ * Extract a section of an array (0-based indices)
412
345
  */
413
- declare const DATE: (year: RuntimeValue, month?: number, day?: number, hour?: number, minute?: number, second?: number) => RuntimeValue;
346
+ declare const ARR_SLICE: (a: RuntimeValue, start: RuntimeValue, end?: RuntimeValue) => RuntimeValue;
414
347
  /**
415
- * Convert days to milliseconds
348
+ * Check if an array contains a value (using deep equality)
349
+ * Returns boolean
416
350
  */
417
- declare const FROM_DAYS: (d: RuntimeValue) => RuntimeValue;
351
+ declare const ARR_CONTAINS: (a: RuntimeValue, value: RuntimeValue) => RuntimeValue;
418
352
  /**
419
- * Convert weeks to milliseconds
353
+ * Reverse an array, returning a new array
420
354
  */
421
- declare const FROM_WEEKS: (w: RuntimeValue) => RuntimeValue;
355
+ declare const ARR_REVERSE: (a: RuntimeValue) => RuntimeValue;
422
356
  /**
423
- * Convert months to milliseconds (approximate: 30 days per month)
424
- * WARNING: This is an approximation. Not all months have 30 days.
425
- * For accurate month arithmetic, use ADD_MONTHS() instead.
357
+ * Sort an array in ascending order, returning a new array.
358
+ * Numbers sort numerically, strings lexicographically,
359
+ * dates/times/datetimes by temporal comparison.
360
+ * All elements must be the same type.
426
361
  */
427
- declare const FROM_MONTHS: (months: RuntimeValue) => RuntimeValue;
362
+ declare const ARR_SORT: (a: RuntimeValue) => RuntimeValue;
428
363
  /**
429
- * Convert years to milliseconds (approximate: 365 days per year)
430
- * WARNING: This is an approximation. Leap years have 366 days.
431
- * For accurate year arithmetic, use ADD_YEARS() instead.
364
+ * Remove duplicate elements using deep equality, preserving first occurrence order.
432
365
  */
433
- declare const FROM_YEARS: (years: RuntimeValue) => RuntimeValue;
366
+ declare const ARR_UNIQUE: (a: RuntimeValue) => RuntimeValue;
434
367
  /**
435
- * Get the year from a timestamp (local timezone)
368
+ * Flatten one level of nested arrays.
369
+ * Each element must be an array. Result is validated for homogeneity.
436
370
  */
437
- declare const GET_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
371
+ declare const ARR_FLAT: (a: RuntimeValue) => RuntimeValue;
438
372
  /**
439
- * Get the month from a timestamp (1-based: 1 = January, 12 = December, local timezone)
373
+ * Join a string array with a separator into a single string.
374
+ * All elements must be strings.
440
375
  */
441
- declare const GET_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
376
+ declare const ARR_JOIN: (a: RuntimeValue, sep: RuntimeValue) => RuntimeValue;
442
377
  /**
443
- * Get the day of month from a timestamp (1-31, local timezone)
378
+ * Sum all elements of a numeric array. Empty array returns 0.
444
379
  */
445
- declare const GET_DAY: (timestamp: RuntimeValue) => RuntimeValue;
380
+ declare const ARR_SUM: (a: RuntimeValue) => RuntimeValue;
446
381
  /**
447
- * Get the hour from a timestamp (0-23, local timezone)
382
+ * Get the minimum element of an array.
383
+ * Supports numbers, strings, dates, times, and datetimes.
384
+ * Throws on empty arrays.
448
385
  */
449
- declare const GET_HOUR: (timestamp: RuntimeValue) => RuntimeValue;
386
+ declare const ARR_MIN: (a: RuntimeValue) => RuntimeValue;
450
387
  /**
451
- * Get the minute from a timestamp (0-59, local timezone)
388
+ * Get the maximum element of an array.
389
+ * Supports numbers, strings, dates, times, and datetimes.
390
+ * Throws on empty arrays.
452
391
  */
453
- declare const GET_MINUTE: (timestamp: RuntimeValue) => RuntimeValue;
392
+ declare const ARR_MAX: (a: RuntimeValue) => RuntimeValue;
393
+ declare namespace core {
394
+ export { TYPE, STR, NUM };
395
+ }
454
396
  /**
455
- * Get the second from a timestamp (0-59, local timezone)
397
+ * Convert a value to string representation
398
+ * Supports numbers, booleans, and dates. Arrays throw TypeError.
456
399
  */
457
- declare const GET_SECOND: (timestamp: RuntimeValue) => RuntimeValue;
400
+ declare const STR: (v: RuntimeValue) => RuntimeValue;
458
401
  /**
459
- * Get the millisecond component from a timestamp (0-999, local timezone)
402
+ * Convert a value to number
403
+ * Supports strings (via Number()) and booleans (true→1, false→0).
404
+ * Dates and arrays throw TypeError.
460
405
  */
461
- declare const GET_MILLISECOND: (timestamp: RuntimeValue) => RuntimeValue;
406
+ declare const NUM: (v: RuntimeValue) => RuntimeValue;
462
407
  /**
463
- * Get the day of week from a timestamp (0 = Sunday, 6 = Saturday, local timezone)
408
+ * Returns the type name of a value as a string
464
409
  */
465
- declare const GET_WEEKDAY: (timestamp: RuntimeValue) => RuntimeValue;
410
+ declare const TYPE: (v: RuntimeValue) => RuntimeValue;
411
+ declare namespace datetime {
412
+ export { TODAY, START_OF_YEAR, START_OF_WEEK, START_OF_QUARTER, START_OF_MONTH, IS_WEEKEND, IS_SAME_DAY, IS_LEAP_YEAR, GET_YEAR, GET_WEEKDAY, GET_QUARTER, GET_MONTH, GET_DAY_OF_YEAR, GET_DAY, END_OF_YEAR, END_OF_MONTH, DIFFERENCE_IN_YEARS, DIFFERENCE_IN_WEEKS, DIFFERENCE_IN_MONTHS, DIFFERENCE_IN_DAYS, DATE, ADD_YEARS, ADD_MONTHS, ADD_DAYS };
413
+ }
466
414
  /**
467
- * Get the day of year (1-366) from a timestamp (local timezone)
468
- * January 1st = 1, December 31st = 365 or 366 (leap year)
415
+ * Date utility functions using Temporal.PlainDate and Temporal.PlainDateTime
416
+ * Most functions accept both PlainDate and PlainDateTime, preserving the input type.
417
+ * TODAY() and DATE() remain PlainDate-only constructors.
469
418
  */
470
- declare const GET_DAY_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
471
419
  /**
472
- * Get the quarter (1-4) from a timestamp (local timezone)
420
+ * Get today's date as a Temporal.PlainDate
473
421
  */
474
- declare const GET_QUARTER: (timestamp: RuntimeValue) => RuntimeValue;
422
+ declare const TODAY: () => RuntimeValue;
475
423
  /**
476
- * Get the absolute difference between two timestamps in seconds (whole seconds)
424
+ * Create a date from year, month (1-based), and day
477
425
  */
478
- declare const DIFFERENCE_IN_SECONDS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
426
+ declare const DATE: (year: RuntimeValue, month: RuntimeValue, day: RuntimeValue) => RuntimeValue;
479
427
  /**
480
- * Get the absolute difference between two timestamps in minutes (whole minutes)
428
+ * Get the year from a date or datetime
481
429
  */
482
- declare const DIFFERENCE_IN_MINUTES: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
430
+ declare const GET_YEAR: (date: RuntimeValue) => RuntimeValue;
483
431
  /**
484
- * Get the absolute difference between two timestamps in hours (whole hours)
432
+ * Get the month from a date or datetime (1-based: 1 = January, 12 = December)
485
433
  */
486
- declare const DIFFERENCE_IN_HOURS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
434
+ declare const GET_MONTH: (date: RuntimeValue) => RuntimeValue;
487
435
  /**
488
- * Get the difference in calendar days between two timestamps
489
- * Counts the number of calendar day boundaries crossed, not 24-hour periods
490
- * Example: Nov 7 at 11:59 PM to Nov 8 at 12:01 AM = 1 day (different calendar days)
436
+ * Get the day of month from a date or datetime (1-31)
491
437
  */
492
- declare const DIFFERENCE_IN_DAYS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
438
+ declare const GET_DAY: (date: RuntimeValue) => RuntimeValue;
493
439
  /**
494
- * Get the difference in calendar weeks between two timestamps
495
- * Counts the number of week boundaries crossed (based on calendar days)
440
+ * Get the day of week from a date or datetime (1 = Monday, 7 = Sunday)
496
441
  */
497
- declare const DIFFERENCE_IN_WEEKS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
442
+ declare const GET_WEEKDAY: (date: RuntimeValue) => RuntimeValue;
498
443
  /**
499
- * Get the number of full calendar months between two timestamps (local timezone)
500
- * Counts complete months where the same day-of-month has been reached
501
- *
502
- * Examples:
503
- * Jan 15 → Feb 14 = 0 months (Feb 15 not reached yet)
504
- * Jan 15 → Feb 15 = 1 month
505
- * Jan 31 → Feb 28 = 0 months (Feb 31 doesn't exist)
506
- * Jan 31 → Mar 31 = 2 months
444
+ * Get the day of year (1-366) from a date or datetime
507
445
  */
508
- declare const DIFFERENCE_IN_MONTHS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
446
+ declare const GET_DAY_OF_YEAR: (date: RuntimeValue) => RuntimeValue;
509
447
  /**
510
- * Get the number of full calendar years between two timestamps (local timezone)
511
- * Counts complete years where the same month and day have been reached
512
- *
513
- * Examples:
514
- * Jan 15, 2020 → Jan 14, 2021 = 0 years (Jan 15 not reached)
515
- * Jan 15, 2020 → Jan 15, 2021 = 1 year
516
- * Feb 29, 2020 → Feb 28, 2021 = 0 years (Feb 29 doesn't exist)
517
- * Feb 29, 2020 → Mar 1, 2021 = 1 year
448
+ * Get the quarter (1-4) from a date or datetime
518
449
  */
519
- declare const DIFFERENCE_IN_YEARS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
450
+ declare const GET_QUARTER: (date: RuntimeValue) => RuntimeValue;
520
451
  /**
521
- * Get the start of day (00:00:00.000 local time) for a given timestamp
452
+ * Add days to a date or datetime, returning the same type
522
453
  */
523
- declare const START_OF_DAY: (timestamp: RuntimeValue) => RuntimeValue;
454
+ declare const ADD_DAYS: (date: RuntimeValue, days: RuntimeValue) => RuntimeValue;
524
455
  /**
525
- * Get the end of day (23:59:59.999 local time) for a given timestamp
456
+ * Add months to a date or datetime, returning the same type
526
457
  */
527
- declare const END_OF_DAY: (timestamp: RuntimeValue) => RuntimeValue;
458
+ declare const ADD_MONTHS: (date: RuntimeValue, months: RuntimeValue) => RuntimeValue;
528
459
  /**
529
- * Get the start of week (Sunday at 00:00:00.000 local time) for a given timestamp
460
+ * Add years to a date or datetime, returning the same type
530
461
  */
531
- declare const START_OF_WEEK: (timestamp: RuntimeValue) => RuntimeValue;
462
+ declare const ADD_YEARS: (date: RuntimeValue, years: RuntimeValue) => RuntimeValue;
532
463
  /**
533
- * Get the start of month (1st day at 00:00:00.000 local time) for a given timestamp
464
+ * Get the difference in days between two dates or datetimes (same type required)
534
465
  */
535
- declare const START_OF_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
466
+ declare const DIFFERENCE_IN_DAYS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
536
467
  /**
537
- * Get the end of month (last day at 23:59:59.999 local time) for a given timestamp
468
+ * Get the difference in weeks between two dates or datetimes (same type, whole weeks)
538
469
  */
539
- declare const END_OF_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
470
+ declare const DIFFERENCE_IN_WEEKS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
540
471
  /**
541
- * Get the start of year (Jan 1st at 00:00:00.000 local time) for a given timestamp
472
+ * Get the difference in months between two dates or datetimes (same type, whole months)
542
473
  */
543
- declare const START_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
474
+ declare const DIFFERENCE_IN_MONTHS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
544
475
  /**
545
- * Get the end of year (Dec 31st at 23:59:59.999 local time) for a given timestamp
476
+ * Get the difference in years between two dates or datetimes (same type, whole years)
546
477
  */
547
- declare const END_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
478
+ declare const DIFFERENCE_IN_YEARS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
548
479
  /**
549
- * Add days to a timestamp (local timezone)
480
+ * Get the first day of the month for a given date or datetime
550
481
  */
551
- declare const ADD_DAYS: (timestamp: RuntimeValue, days: RuntimeValue) => RuntimeValue;
482
+ declare const START_OF_MONTH: (date: RuntimeValue) => RuntimeValue;
552
483
  /**
553
- * Add months to a timestamp (handles variable month lengths correctly, local timezone)
484
+ * Get the last day of the month for a given date or datetime
554
485
  */
555
- declare const ADD_MONTHS: (timestamp: RuntimeValue, months: RuntimeValue) => RuntimeValue;
486
+ declare const END_OF_MONTH: (date: RuntimeValue) => RuntimeValue;
556
487
  /**
557
- * Add years to a timestamp (local timezone)
488
+ * Get the first day of the year for a given date or datetime
558
489
  */
559
- declare const ADD_YEARS: (timestamp: RuntimeValue, years: RuntimeValue) => RuntimeValue;
490
+ declare const START_OF_YEAR: (date: RuntimeValue) => RuntimeValue;
560
491
  /**
561
- * Check if two timestamps are on the same calendar day (local timezone)
562
- * Returns 1 if true, 0 if false
492
+ * Get the last day of the year for a given date or datetime
563
493
  */
564
- declare const IS_SAME_DAY: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
494
+ declare const END_OF_YEAR: (date: RuntimeValue) => RuntimeValue;
565
495
  /**
566
- * Check if timestamp falls on a weekend (Saturday or Sunday, local timezone)
567
- * Returns 1 if true, 0 if false
496
+ * Get the first day of the week (Monday) for a given date or datetime
568
497
  */
569
- declare const IS_WEEKEND: (timestamp: RuntimeValue) => RuntimeValue;
498
+ declare const START_OF_WEEK: (date: RuntimeValue) => RuntimeValue;
570
499
  /**
571
- * Check if timestamp is in a leap year (local timezone)
572
- * Returns 1 if true, 0 if false
500
+ * Get the first day of the quarter for a given date or datetime
573
501
  */
574
- declare const IS_LEAP_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
502
+ declare const START_OF_QUARTER: (date: RuntimeValue) => RuntimeValue;
575
503
  /**
576
- * Get the start of quarter for a given timestamp (local timezone)
504
+ * Check if two dates/datetimes fall on the same calendar day.
505
+ * For PlainDateTime values, only the date portion is compared.
506
+ * Mixed date+datetime is allowed (datetime is converted to date for comparison).
577
507
  */
578
- declare const START_OF_QUARTER: (timestamp: RuntimeValue) => RuntimeValue;
579
- declare namespace exports_math {
580
- export { TAN, SQRT, SIN, ROUND, MIN, MAX, LOG10, LOG, FLOOR, EXP, COS, CLAMP, CEIL, ABS };
508
+ declare const IS_SAME_DAY: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
509
+ /**
510
+ * Check if a date or datetime falls on a weekend (Saturday or Sunday)
511
+ */
512
+ declare const IS_WEEKEND: (date: RuntimeValue) => RuntimeValue;
513
+ /**
514
+ * Check if a date or datetime is in a leap year
515
+ */
516
+ declare const IS_LEAP_YEAR: (date: RuntimeValue) => RuntimeValue;
517
+ declare namespace datetimefull {
518
+ export { TO_TIME, TO_DATE, START_OF_DAY, NOW, END_OF_DAY, DATETIME, COMBINE };
581
519
  }
582
520
  /**
583
- * Math utility functions
584
- * All functions work with numbers only
521
+ * DateTime construction and conversion functions using Temporal.PlainDateTime
585
522
  */
586
523
  /**
587
- * Constrain a value between a minimum and maximum
588
- * @example CLAMP(value, 0, 100) - Clamps value between 0 and 100
524
+ * Create a PlainDateTime from year, month, day, hour, minute, second
525
+ */
526
+ declare const DATETIME: (year: RuntimeValue, month: RuntimeValue, day: RuntimeValue, hour: RuntimeValue, minute: RuntimeValue, second: RuntimeValue) => RuntimeValue;
527
+ /**
528
+ * Get the current date and time as a PlainDateTime
529
+ */
530
+ declare const NOW: () => RuntimeValue;
531
+ /**
532
+ * Extract the PlainDate from a PlainDateTime
533
+ */
534
+ declare const TO_DATE: (dt: RuntimeValue) => RuntimeValue;
535
+ /**
536
+ * Extract the PlainTime from a PlainDateTime
537
+ */
538
+ declare const TO_TIME: (dt: RuntimeValue) => RuntimeValue;
539
+ /**
540
+ * Combine a PlainDate and PlainTime into a PlainDateTime
541
+ */
542
+ declare const COMBINE: (date: RuntimeValue, time: RuntimeValue) => RuntimeValue;
543
+ /**
544
+ * Get midnight (00:00:00) of a PlainDateTime's day
545
+ */
546
+ declare const START_OF_DAY: (dt: RuntimeValue) => RuntimeValue;
547
+ /**
548
+ * Get the last representable instant (23:59:59.999999999) of a PlainDateTime's day
549
+ */
550
+ declare const END_OF_DAY: (dt: RuntimeValue) => RuntimeValue;
551
+ declare namespace math {
552
+ export { TAN, SQRT, SIN, ROUND, MIN, MAX, LOG10, LOG, FLOOR, EXP, COS, CLAMP, CEIL, ABS };
553
+ }
554
+ /**
555
+ * Math utility functions
556
+ * All functions assert number inputs and return numbers
589
557
  */
590
- declare const CLAMP: (value: RuntimeValue, min: RuntimeValue, max: RuntimeValue) => RuntimeValue;
591
558
  declare const ABS: (x: RuntimeValue) => RuntimeValue;
592
559
  declare const CEIL: (x: RuntimeValue) => RuntimeValue;
593
560
  declare const FLOOR: (x: RuntimeValue) => RuntimeValue;
@@ -602,37 +569,174 @@ declare const LOG: (x: RuntimeValue) => RuntimeValue;
602
569
  declare const LOG10: (x: RuntimeValue) => RuntimeValue;
603
570
  declare const EXP: (x: RuntimeValue) => RuntimeValue;
604
571
  /**
572
+ * Constrain a value between a minimum and maximum
573
+ */
574
+ declare const CLAMP: (value: RuntimeValue, min: RuntimeValue, max: RuntimeValue) => RuntimeValue;
575
+ declare namespace string {
576
+ export { STR_UPPER, STR_TRIM, STR_STARTS_WITH, STR_SPLIT, STR_SLICE, STR_REPLACE, STR_REPEAT, STR_LOWER, STR_LEN, STR_INDEX_OF, STR_ENDS_WITH, STR_CONTAINS };
577
+ }
578
+ /**
579
+ * Get the length of a string
580
+ */
581
+ declare const STR_LEN: (s: RuntimeValue) => RuntimeValue;
582
+ /**
583
+ * Convert string to uppercase
584
+ */
585
+ declare const STR_UPPER: (s: RuntimeValue) => RuntimeValue;
586
+ /**
587
+ * Convert string to lowercase
588
+ */
589
+ declare const STR_LOWER: (s: RuntimeValue) => RuntimeValue;
590
+ /**
591
+ * Trim whitespace from both ends of a string
592
+ */
593
+ declare const STR_TRIM: (s: RuntimeValue) => RuntimeValue;
594
+ /**
595
+ * Extract a section of a string (0-based indices)
596
+ */
597
+ declare const STR_SLICE: (s: RuntimeValue, start: RuntimeValue, end?: RuntimeValue) => RuntimeValue;
598
+ /**
599
+ * Check if a string contains another string
600
+ * Returns boolean
601
+ */
602
+ declare const STR_CONTAINS: (s: RuntimeValue, search: RuntimeValue) => RuntimeValue;
603
+ /**
604
+ * Find the first index of a substring (-1 if not found)
605
+ */
606
+ declare const STR_INDEX_OF: (s: RuntimeValue, search: RuntimeValue) => RuntimeValue;
607
+ /**
608
+ * Split a string by a separator into a string array
609
+ */
610
+ declare const STR_SPLIT: (s: RuntimeValue, sep: RuntimeValue) => RuntimeValue;
611
+ /**
612
+ * Replace the first occurrence of a search string with a replacement
613
+ */
614
+ declare const STR_REPLACE: (s: RuntimeValue, search: RuntimeValue, replacement: RuntimeValue) => RuntimeValue;
615
+ /**
616
+ * Check if a string starts with a given prefix
617
+ */
618
+ declare const STR_STARTS_WITH: (s: RuntimeValue, prefix: RuntimeValue) => RuntimeValue;
619
+ /**
620
+ * Check if a string ends with a given suffix
621
+ */
622
+ declare const STR_ENDS_WITH: (s: RuntimeValue, suffix: RuntimeValue) => RuntimeValue;
623
+ /**
624
+ * Repeat a string n times. Count must be a non-negative integer.
625
+ */
626
+ declare const STR_REPEAT: (s: RuntimeValue, count: RuntimeValue) => RuntimeValue;
627
+ declare namespace time {
628
+ export { TIME, NOW_TIME, IS_SAME_TIME, GET_SECOND, GET_MINUTE, GET_MILLISECOND, GET_HOUR, DIFFERENCE_IN_SECONDS, DIFFERENCE_IN_MINUTES, DIFFERENCE_IN_HOURS, ADD_SECONDS, ADD_MINUTES, ADD_HOURS };
629
+ }
630
+ /**
631
+ * Time utility functions using Temporal.PlainTime and Temporal.PlainDateTime
632
+ * Extractor and arithmetic functions accept both PlainTime and PlainDateTime.
633
+ * Difference functions require both arguments to be the same type.
634
+ */
635
+ /**
636
+ * Create a PlainTime from hour, minute, and second
637
+ */
638
+ declare const TIME: (hour: RuntimeValue, minute: RuntimeValue, second: RuntimeValue) => RuntimeValue;
639
+ /**
640
+ * Get the current wall-clock time as a PlainTime
641
+ */
642
+ declare const NOW_TIME: () => RuntimeValue;
643
+ /**
644
+ * Get the hour (0-23) from a time or datetime
645
+ */
646
+ declare const GET_HOUR: (t: RuntimeValue) => RuntimeValue;
647
+ /**
648
+ * Get the minute (0-59) from a time or datetime
649
+ */
650
+ declare const GET_MINUTE: (t: RuntimeValue) => RuntimeValue;
651
+ /**
652
+ * Get the second (0-59) from a time or datetime
653
+ */
654
+ declare const GET_SECOND: (t: RuntimeValue) => RuntimeValue;
655
+ /**
656
+ * Get the millisecond (0-999) from a time or datetime
657
+ */
658
+ declare const GET_MILLISECOND: (t: RuntimeValue) => RuntimeValue;
659
+ /**
660
+ * Add hours to a time or datetime.
661
+ * PlainTime wraps around at midnight boundaries.
662
+ */
663
+ declare const ADD_HOURS: (t: RuntimeValue, hours: RuntimeValue) => RuntimeValue;
664
+ /**
665
+ * Add minutes to a time or datetime.
666
+ * PlainTime wraps around at midnight boundaries.
667
+ */
668
+ declare const ADD_MINUTES: (t: RuntimeValue, minutes: RuntimeValue) => RuntimeValue;
669
+ /**
670
+ * Add seconds to a time or datetime.
671
+ * PlainTime wraps around at midnight boundaries.
672
+ */
673
+ declare const ADD_SECONDS: (t: RuntimeValue, seconds: RuntimeValue) => RuntimeValue;
674
+ /**
675
+ * Get the absolute difference in hours between two times or datetimes (same type required)
676
+ */
677
+ declare const DIFFERENCE_IN_HOURS: (t1: RuntimeValue, t2: RuntimeValue) => RuntimeValue;
678
+ /**
679
+ * Get the absolute difference in minutes between two times or datetimes (same type required)
680
+ */
681
+ declare const DIFFERENCE_IN_MINUTES: (t1: RuntimeValue, t2: RuntimeValue) => RuntimeValue;
682
+ /**
683
+ * Get the absolute difference in seconds between two times or datetimes (same type required)
684
+ */
685
+ declare const DIFFERENCE_IN_SECONDS: (t1: RuntimeValue, t2: RuntimeValue) => RuntimeValue;
686
+ /**
687
+ * Check if two times/datetimes have the same time-of-day.
688
+ * For PlainDateTime values, only the time portion is compared.
689
+ * Mixed time+datetime is allowed (datetime is converted to time for comparison).
690
+ */
691
+ declare const IS_SAME_TIME: (t1: RuntimeValue, t2: RuntimeValue) => RuntimeValue;
692
+ /**
605
693
  * Default execution context with standard library functions
606
- * Users can use this as-is or spread it into their own context
607
- *
608
- * All functions use UPPERCASE naming convention to avoid collisions with user variables.
609
- * All date-related functions work with timestamps (milliseconds since Unix epoch)
610
- * to maintain the language's numbers-only type system.
611
- *
612
- * @example
613
- * // Use as-is
614
- * execute('ABS(-5)', defaultContext)
615
- *
616
- * @example
617
- * // Spread into custom context
618
- * execute('NOW() + FROM_MINUTES(5)', {
619
- * ...defaultContext,
620
- * variables: { customVar: 42 }
621
- * })
622
- *
623
- * @example
624
- * // Work with timestamps
625
- * const result = execute('NOW() + FROM_DAYS(7)', defaultContext)
626
- * const futureDate = new Date(result) // Convert back to Date if needed
627
- *
628
- * @example
629
- * // Calculate time differences
630
- * const ts1 = Date.now()
631
- * const ts2 = ts1 + 1000 * 60 * 60 * 3 // 3 hours later
632
- * execute('DIFFERENCE_IN_HOURS(ts1, ts2)', { ...defaultContext, variables: { ts1, ts2 } })
694
+ * Includes math, string, array, datetime, time, datetimefull, and type conversion functions
633
695
  */
634
696
  declare const defaultContext: ExecutionContext;
635
697
  /**
698
+ * Return the type name of a runtime value
699
+ * Note: PlainDateTime check must precede PlainDate because PlainDateTime is not an
700
+ * instance of PlainDate in the Temporal API, but ordering is kept explicit for clarity.
701
+ */
702
+ declare function typeOf(value: RuntimeValue): string;
703
+ /**
704
+ * Assert a value is a number, throwing a TypeError if not
705
+ */
706
+ declare function assertNumber(v: RuntimeValue, context: string, side?: string): asserts v is number;
707
+ /**
708
+ * Assert a value is a boolean, throwing a TypeError if not
709
+ */
710
+ declare function assertBoolean(v: RuntimeValue, context: string, side?: string): asserts v is boolean;
711
+ /**
712
+ * Assert a value is a string, throwing a TypeError if not
713
+ */
714
+ declare function assertString(v: RuntimeValue, context: string): asserts v is string;
715
+ /**
716
+ * Assert a value is a Temporal.PlainDate, throwing a TypeError if not
717
+ */
718
+ declare function assertDate(v: RuntimeValue, context: string): asserts v is Temporal.PlainDate;
719
+ /**
720
+ * Assert a value is a Temporal.PlainTime, throwing a TypeError if not
721
+ */
722
+ declare function assertTime(v: RuntimeValue, context: string): asserts v is Temporal.PlainTime;
723
+ /**
724
+ * Assert a value is a Temporal.PlainDateTime, throwing a TypeError if not
725
+ */
726
+ declare function assertDateTime(v: RuntimeValue, context: string): asserts v is Temporal.PlainDateTime;
727
+ /**
728
+ * Assert a value is a Temporal.PlainDate or Temporal.PlainDateTime
729
+ */
730
+ declare function assertDateOrDateTime(v: RuntimeValue, context: string): asserts v is Temporal.PlainDate | Temporal.PlainDateTime;
731
+ /**
732
+ * Assert a value is a Temporal.PlainTime or Temporal.PlainDateTime
733
+ */
734
+ declare function assertTimeOrDateTime(v: RuntimeValue, context: string): asserts v is Temporal.PlainTime | Temporal.PlainDateTime;
735
+ /**
736
+ * Assert a value is an array, throwing a TypeError if not
737
+ */
738
+ declare function assertArray(v: RuntimeValue, context: string): asserts v is readonly RuntimeValue[];
739
+ /**
636
740
  * Type-safe visitor pattern for AST traversal.
637
741
  *
638
742
  * A visitor is an object with handler functions for each AST node type.
@@ -640,133 +744,32 @@ declare const defaultContext: ExecutionContext;
640
744
  * - The node (correctly typed based on node.type)
641
745
  * - A recurse function to visit child nodes with the same visitor
642
746
  *
643
- * The visitor pattern centralizes AST traversal logic and ensures
644
- * exhaustive handling of all node types at compile time.
645
- *
646
- * Time complexity: O(n) where n is the number of nodes in the AST
647
- * Space complexity: O(d) where d is the maximum depth (recursion stack)
648
- *
649
747
  * @template T The return type of visitor handlers
650
- *
651
- * @example
652
- * // Count all nodes in an AST
653
- * const nodeCount = visit(ast, {
654
- * Program: (n, recurse) => 1 + n.statements.reduce((sum, stmt) => sum + recurse(stmt), 0),
655
- * NumberLiteral: () => 1,
656
- * Identifier: () => 1,
657
- * BinaryOp: (n, recurse) => 1 + recurse(n.left) + recurse(n.right),
658
- * UnaryOp: (n, recurse) => 1 + recurse(n.argument),
659
- * FunctionCall: (n, recurse) => 1 + n.arguments.reduce((sum, arg) => sum + recurse(arg), 0),
660
- * Assignment: (n, recurse) => 1 + recurse(n.value),
661
- * ConditionalExpression: (n, recurse) => 1 + recurse(n.condition) + recurse(n.consequent) + recurse(n.alternate),
662
- * })
663
- *
664
- * @example
665
- * // Transform AST: constant folding
666
- * const optimized = visit(ast, {
667
- * NumberLiteral: (n) => n,
668
- * Identifier: (n) => n,
669
- * BinaryOp: (n, recurse) => {
670
- * const left = recurse(n.left)
671
- * const right = recurse(n.right)
672
- * if (isNumberLiteral(left) && isNumberLiteral(right)) {
673
- * return ast.number(left.value + right.value)
674
- * }
675
- * return ast.binaryOp(left, n.operator, right)
676
- * },
677
- * // ... other handlers
678
- * })
679
748
  */
680
749
  type Visitor<T> = {
681
- /**
682
- * Handle a Program node (multiple statements)
683
- */
684
750
  Program: (node: Program, recurse: (n: ASTNode) => T) => T;
685
- /**
686
- * Handle a NumberLiteral node
687
- */
688
751
  NumberLiteral: (node: NumberLiteral, recurse: (n: ASTNode) => T) => T;
689
- /**
690
- * Handle an Identifier node (variable reference)
691
- */
692
- Identifier: (node: Identifier, recurse: (n: ASTNode) => T) => T;
693
- /**
694
- * Handle a BinaryOp node (binary operation)
695
- */
752
+ StringLiteral: (node: StringLiteral, recurse: (n: ASTNode) => T) => T;
753
+ BooleanLiteral: (node: BooleanLiteral, recurse: (n: ASTNode) => T) => T;
754
+ ArrayLiteral: (node: ArrayLiteral, recurse: (n: ASTNode) => T) => T;
755
+ Identifier2: (node: Identifier2, recurse: (n: ASTNode) => T) => T;
696
756
  BinaryOp: (node: BinaryOp, recurse: (n: ASTNode) => T) => T;
697
- /**
698
- * Handle a UnaryOp node (unary operation)
699
- */
700
757
  UnaryOp: (node: UnaryOp, recurse: (n: ASTNode) => T) => T;
701
- /**
702
- * Handle a FunctionCall node
703
- */
704
758
  FunctionCall: (node: FunctionCall, recurse: (n: ASTNode) => T) => T;
705
- /**
706
- * Handle an Assignment node (variable assignment)
707
- */
708
759
  Assignment: (node: Assignment, recurse: (n: ASTNode) => T) => T;
709
- /**
710
- * Handle a ConditionalExpression node (ternary operator)
711
- */
712
- ConditionalExpression: (node: ConditionalExpression, recurse: (n: ASTNode) => T) => T;
760
+ IfExpression: (node: IfExpression, recurse: (n: ASTNode) => T) => T;
761
+ ForExpression: (node: ForExpression, recurse: (n: ASTNode) => T) => T;
762
+ IndexAccess: (node: IndexAccess, recurse: (n: ASTNode) => T) => T;
763
+ RangeExpression: (node: RangeExpression, recurse: (n: ASTNode) => T) => T;
713
764
  };
714
765
  /**
715
766
  * Visit an AST node using a visitor object with type-specific handlers.
716
- *
717
- * This function implements the visitor pattern for AST traversal.
718
767
  * All node types must have handlers (exhaustive by design).
719
- * TypeScript enforces exhaustiveness at compile time via the switch statement.
720
- *
721
- * The visitor pattern provides several benefits:
722
- * - DRY: Centralizes traversal logic across all modules
723
- * - Type safety: Handlers receive correctly-typed nodes
724
- * - Exhaustiveness: Compile-time guarantee that all node types are handled
725
- * - Flexibility: Supports transform, fold, and walk patterns
726
768
  *
727
769
  * @template T The return type of visitor handlers
728
770
  * @param node The AST node to visit
729
771
  * @param visitor Object with handlers for each node type
730
772
  * @returns The result of visiting the node
731
- *
732
- * @example
733
- * // Evaluate an AST (fold pattern)
734
- * const result = visit(ast, {
735
- * Program: (n, recurse) => {
736
- * let result = 0
737
- * for (const stmt of n.statements) {
738
- * result = recurse(stmt)
739
- * }
740
- * return result
741
- * },
742
- * NumberLiteral: (n) => n.value,
743
- * BinaryOp: (n, recurse) => {
744
- * const left = recurse(n.left)
745
- * const right = recurse(n.right)
746
- * return left + right // simplified
747
- * },
748
- * // ... other handlers
749
- * })
750
- *
751
- * @example
752
- * // Transform an AST (transform pattern)
753
- * const transformed = visit(ast, {
754
- * NumberLiteral: (n) => ast.number(n.value * 2), // Double all numbers
755
- * BinaryOp: (n, recurse) => ast.binaryOp(
756
- * recurse(n.left),
757
- * n.operator,
758
- * recurse(n.right)
759
- * ),
760
- * // ... other handlers
761
- * })
762
- *
763
- * @example
764
- * // Walk an AST (walk pattern - side effects)
765
- * visit(ast, {
766
- * NumberLiteral: (n) => { console.log('Number:', n.value) },
767
- * Identifier: (n) => { console.log('Variable:', n.name) },
768
- * // ... other handlers
769
- * })
770
773
  */
771
774
  declare function visit<T>(node: ASTNode, visitor: Visitor<T>): T;
772
775
  /**
@@ -776,52 +779,11 @@ declare function visit<T>(node: ASTNode, visitor: Visitor<T>): T;
776
779
  * you to handle only specific node types. Unhandled nodes are processed by
777
780
  * the default handler.
778
781
  *
779
- * This is useful for:
780
- * - Analysis passes that only care about certain node types
781
- * - Transformations that only modify specific nodes
782
- * - Walking the tree to collect information
783
- *
784
782
  * @template T The return type of visitor handlers
785
783
  * @param node The AST node to visit
786
784
  * @param visitor Object with optional handlers for node types
787
785
  * @param defaultHandler Handler for unhandled node types
788
786
  * @returns The result of visiting the node
789
- *
790
- * @example
791
- * // Collect all variable names (only care about Identifier nodes)
792
- * const variables: string[] = []
793
- * visitPartial(
794
- * ast,
795
- * {
796
- * Identifier: (n) => {
797
- * variables.push(n.name)
798
- * return undefined
799
- * }
800
- * },
801
- * (node, recurse) => {
802
- * // Default: recurse into children for all other node types
803
- * if (node.type === 'BinaryOp') {
804
- * recurse(node.left)
805
- * recurse(node.right)
806
- * }
807
- * // ... handle other node types' children
808
- * return undefined
809
- * }
810
- * )
811
- *
812
- * @example
813
- * // Transform only BinaryOp nodes, keep everything else as-is
814
- * const transformed = visitPartial(
815
- * ast,
816
- * {
817
- * BinaryOp: (n, recurse) => ast.binaryOp(
818
- * recurse(n.left),
819
- * '+', // Force all operators to addition
820
- * recurse(n.right)
821
- * )
822
- * },
823
- * (node, recurse) => node // Default: identity (no transformation)
824
- * )
825
787
  */
826
788
  declare function visitPartial<T>(node: ASTNode, visitor: Partial<Visitor<T>>, defaultHandler: (node: ASTNode, recurse: (n: ASTNode) => T) => T): T;
827
- export { visitPartial, visit, parse, optimize, exports_math as math, isUnaryOp, isProgram, isNumberLiteral, isIdentifier, isFunctionCall, isConditionalExpression, isBinaryOp, isAssignment, humanize, generate, extractInputVariables, evaluate, defaultContext, exports_datetime as datetime, compile, exports_ast as ast, Visitor, UnaryOp, RuntimeValue, Program, Operator, NumberLiteral, NodeKind, Identifier, HumanizeOptions, FunctionCall, ExecutionContext, ConditionalExpression, CompiledExpression, BinaryOp, Assignment, ASTNode };
789
+ export { visitPartial, visit, typeOf, time, string, parse, optimize, math, isUnaryOp, isStringLiteral, isRangeExpression, isProgram, isNumberLiteral, isIndexAccess, isIfExpression, isIdentifier, isFunctionCall, isForExpression, isBooleanLiteral, isBinaryOp, isAssignment, isArrayLiteral, generate, extractInputVariables, extractAssignedVariables, evaluateScope, evaluate, defaultContext, datetimefull, datetime, core, exports_ast as ast, assertTimeOrDateTime, assertTime, assertString, assertNumber, assertDateTime, assertDateOrDateTime, assertDate, assertBoolean, assertArray, array, Visitor, UnaryOp, StringLiteral, RuntimeValue, RangeExpression, Program, Operator, NumberLiteral, NodeKind, IndexAccess, IfExpression, Identifier2 as Identifier, FunctionCall, ForExpression, ExecutionContext, BooleanLiteral, BinaryOp, Assignment, ArrayLiteral, ASTNodeBase, ASTNode };