littlewing 1.3.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 +476 -548
  2. package/dist/index.js +1996 -826
  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
+ }
110
+ /**
111
+ * If expression (if condition then consequent else alternate)
112
+ * Returns consequent if condition is true, otherwise returns alternate
113
+ */
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
+ }
57
144
  /**
58
- * Conditional expression (ternary operator: condition ? consequent : alternate)
59
- * Returns consequent if condition !== 0, otherwise returns alternate
60
- * Tuple: [kind, condition, consequent, alternate]
145
+ * Range expression (1..5, 1..=5)
61
146
  */
62
- type ConditionalExpression = readonly [kind: NodeKind.ConditionalExpression, condition: ASTNode, consequent: ASTNode, alternate: ASTNode];
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
  /**
@@ -227,76 +296,13 @@ declare function extractAssignedVariables(ast: ASTNode): string[];
227
296
  */
228
297
  declare function generate(node: ASTNode): string;
229
298
  /**
230
- * Options for customizing the humanization output
231
- */
232
- interface HumanizeOptions {
233
- /**
234
- * Enable HTML output with wrapper tags
235
- * @default false
236
- */
237
- html?: boolean;
238
- /**
239
- * CSS classes to apply to different node types when html is true
240
- */
241
- htmlClasses?: {
242
- number?: string;
243
- identifier?: string;
244
- operator?: string;
245
- function?: string;
246
- };
247
- /**
248
- * Custom phrases for function names
249
- * Maps function name to human-readable phrase
250
- * Example: { 'MAX': 'the maximum of', 'CUSTOM': 'my custom function with' }
251
- */
252
- functionPhrases?: Record<string, string>;
253
- /**
254
- * Custom phrases for operators
255
- * Overrides default operator text
256
- */
257
- operatorPhrases?: Partial<Record<Operator, string>>;
258
- /**
259
- * Use more verbose, descriptive phrasing
260
- * @default false
261
- */
262
- verbose?: boolean;
263
- }
264
- /**
265
- * Humanize an AST node into human-readable English text
266
- *
267
- * @param node - The AST node to humanize
268
- * @param options - Optional configuration for the output
269
- * @returns Human-readable English text
270
- *
271
- * @example
272
- * ```typescript
273
- * const ast = parse('price * quantity > 100 ? (price * quantity - discount) * (1 + tax_rate) : MAX(price * quantity, 50)')
274
- * const text = humanize(ast)
275
- * // "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"
276
- * ```
277
- *
278
- * @example
279
- * ```typescript
280
- * // With HTML formatting
281
- * const text = humanize(ast, {
282
- * html: true,
283
- * htmlClasses: {
284
- * identifier: 'variable',
285
- * operator: 'op',
286
- * number: 'num'
287
- * }
288
- * })
289
- * ```
290
- */
291
- declare function humanize(node: ASTNode, options?: HumanizeOptions): string;
292
- /**
293
- * Runtime value type - only numbers
299
+ * Runtime value type - numbers, strings, booleans, dates, times, datetimes, and homogeneous arrays
294
300
  */
295
- type RuntimeValue = number;
301
+ type RuntimeValue = number | string | boolean | Temporal.PlainDate | Temporal.PlainTime | Temporal.PlainDateTime | readonly RuntimeValue[];
296
302
  /**
297
303
  * Execution context providing global functions and variables
298
- * Functions must accept zero or more number arguments and return a number
299
- * Variables must be numbers
304
+ * Functions accept zero or more RuntimeValue arguments and return a RuntimeValue
305
+ * Variables can be any RuntimeValue
300
306
  */
301
307
  interface ExecutionContext {
302
308
  functions?: Record<string, (...args: RuntimeValue[]) => RuntimeValue>;
@@ -304,324 +310,251 @@ interface ExecutionContext {
304
310
  }
305
311
  /**
306
312
  * Evaluate source code or AST with given context
307
- * @param input - Either a source code string or an AST node
308
- * @param context - Optional execution context with variables and functions
309
- * @returns The evaluated result
310
313
  */
311
314
  declare function evaluate(input: string | ASTNode, context?: ExecutionContext): RuntimeValue;
312
315
  /**
313
316
  * Evaluate source code or AST and return the full variable scope.
314
- *
315
- * Runs the same interpreter as `evaluate()` but instead of returning
316
- * the last expression value, returns a record of all variables that
317
- * exist in scope after execution (both script-assigned and context-provided).
318
- *
319
- * @param input - Either a source code string or an AST node
320
- * @param context - Optional execution context with variables and functions
321
- * @returns Record of all variable names to their values after execution
322
- *
323
- * @example
324
- * ```typescript
325
- * const scope = evaluateScope('x = 10; y = x * 2')
326
- * // scope === { x: 10, y: 20 }
327
- * ```
328
- */
329
- declare function evaluateScope(input: string | ASTNode, context?: ExecutionContext): Record<string, number>;
330
- /**
331
- * Compiled expression that can be executed multiple times
332
- * Provides faster repeated execution compared to tree-walk interpreter
333
- */
334
- interface CompiledExpression {
335
- /**
336
- * Execute the compiled expression with optional context
337
- * @param context - Execution context with variables and functions
338
- * @returns The evaluated result
339
- */
340
- execute: (context?: ExecutionContext) => RuntimeValue;
341
- /**
342
- * Generated JavaScript source code (for debugging and inspection)
343
- */
344
- source: string;
345
- }
346
- /**
347
- * Compile source code or AST to a JavaScript function for faster repeated execution
348
- *
349
- * JIT compilation trades compilation time for execution speed:
350
- * - First call: Parse + Optimize + Compile (~10-50µs depending on size)
351
- * - Subsequent calls: Direct JavaScript execution (~1-5µs, 5-10x faster)
352
- *
353
- * The compiler automatically optimizes the AST before code generation:
354
- * - Constant folding: `2 + 3` → `5` (safe constants only)
355
- * - Dead code elimination: removes unused variable assignments
356
- * - Expression simplification: `1 ? x : y` → `x`
357
- *
358
- * Optimization is safe because:
359
- * - Constant folding errors (e.g., division by zero) propagate to compile-time
360
- * - Variables that could be external are preserved (no unsafe DCE)
361
- * - The optimizer respects ExecutionContext override semantics
362
- *
363
- * The compiler generates optimized JavaScript code:
364
- * - Uses comma operator instead of IIFEs for better performance
365
- * - Only initializes variables that are actually used
366
- * - Pre-declares temporary variables for reuse
367
- *
368
- * Best for expressions that are evaluated many times with different contexts.
369
- *
370
- * Security: Uses `new Function()` to generate executable code. Safe for trusted
371
- * input only. For untrusted input, use the tree-walk interpreter instead.
372
- *
373
- * @param input - Either a source code string or an AST node
374
- * @returns Compiled expression that can be executed multiple times
375
- * @throws {Error} If compilation fails or AST contains invalid operations (e.g., constant division by zero)
376
- *
377
- * @example
378
- * ```typescript
379
- * const expr = compile('x * 2 + y')
380
- * expr.execute({ variables: { x: 10, y: 5 } }) // 25
381
- * expr.execute({ variables: { x: 20, y: 3 } }) // 43
382
- * ```
383
- *
384
- * @example Automatic optimization
385
- * ```typescript
386
- * const expr = compile('2 + 3 * 4') // Automatically optimized to 14
387
- * expr.execute() // Fast execution of pre-folded constant
388
- * ```
389
317
  */
390
- declare function compile(input: string | ASTNode): CompiledExpression;
318
+ declare function evaluateScope(input: string | ASTNode, context?: ExecutionContext): Record<string, RuntimeValue>;
391
319
  /**
392
- * Optimize an AST using constant folding, expression simplification, and dead code elimination.
393
- *
394
- * This optimizer performs SAFE optimizations that preserve program semantics:
395
- * - Constant folding: Evaluates arithmetic with literal operands at compile-time
396
- * - Function argument pre-evaluation: Simplifies expressions passed to functions
397
- * - Conditional folding: Evaluates ternary with constant condition
398
- * - Dead code elimination: Removes unused variable assignments
399
- *
400
- * Optimizations that are NOT performed (because they're unsafe with context variables):
401
- * - Variable propagation: Variables can be overridden by ExecutionContext
402
- * - Cross-statement analysis: Each statement may affect external state
403
- *
404
- * Time complexity: O(n) where n is the number of AST nodes
405
- * Space complexity: O(d) where d is the max depth (recursion stack)
406
- *
407
- * Algorithm properties:
408
- * - Sound: Preserves program semantics exactly
409
- * - Safe: No assumptions about variable values
410
- * - Local: Only optimizes within individual expressions
320
+ * Optimize an AST using constant folding, constant propagation, and dead code elimination.
411
321
  *
412
- * @param node - The AST node to optimize
413
- * @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).
414
325
  */
415
- declare function optimize(node: ASTNode): ASTNode;
326
+ declare function optimize(node: ASTNode, externalVariables?: ReadonlySet<string>): ASTNode;
416
327
  /**
417
328
  * Parse source code string into AST
418
- * Implements Pratt parsing (top-down operator precedence)
419
- * Uses lazy lexing - calls lexer on-demand instead of receiving all tokens upfront
420
- *
421
- * @param source - The source code to parse
422
- * @returns Parsed AST
423
329
  */
424
330
  declare function parse(source: string): ASTNode;
425
- declare namespace exports_datetime {
426
- 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 };
427
333
  }
428
334
  /**
429
- * Date utility functions for working with timestamps
430
- * All functions work with milliseconds since Unix epoch (numbers only)
431
- *
432
- * IMPORTANT: All functions use local timezone to match the user's context.
433
- * In a browser, this reflects the user's timezone. On a server, this reflects
434
- * the server's configured timezone. This ensures date calculations align with
435
- * the user's calendar expectations.
335
+ * Get the length of an array
436
336
  */
337
+ declare const ARR_LEN: (a: RuntimeValue) => RuntimeValue;
437
338
  /**
438
- * Get current timestamp (milliseconds since Unix epoch)
339
+ * Append a value to an array, returning a new array
340
+ * Validates homogeneity
439
341
  */
440
- declare const NOW: () => RuntimeValue;
342
+ declare const ARR_PUSH: (a: RuntimeValue, value: RuntimeValue) => RuntimeValue;
441
343
  /**
442
- * Create timestamp from date components (local timezone)
443
- * Year is required, all other parameters default to minimum values
444
- * Month is 1-based (1 = January, 12 = December)
445
- * All parameters are interpreted in local timezone
344
+ * Extract a section of an array (0-based indices)
446
345
  */
447
- 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;
448
347
  /**
449
- * Convert days to milliseconds
348
+ * Check if an array contains a value (using deep equality)
349
+ * Returns boolean
450
350
  */
451
- declare const FROM_DAYS: (d: RuntimeValue) => RuntimeValue;
351
+ declare const ARR_CONTAINS: (a: RuntimeValue, value: RuntimeValue) => RuntimeValue;
452
352
  /**
453
- * Convert weeks to milliseconds
353
+ * Reverse an array, returning a new array
454
354
  */
455
- declare const FROM_WEEKS: (w: RuntimeValue) => RuntimeValue;
355
+ declare const ARR_REVERSE: (a: RuntimeValue) => RuntimeValue;
456
356
  /**
457
- * Convert months to milliseconds (approximate: 30 days per month)
458
- * WARNING: This is an approximation. Not all months have 30 days.
459
- * 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.
460
361
  */
461
- declare const FROM_MONTHS: (months: RuntimeValue) => RuntimeValue;
362
+ declare const ARR_SORT: (a: RuntimeValue) => RuntimeValue;
462
363
  /**
463
- * Convert years to milliseconds (approximate: 365 days per year)
464
- * WARNING: This is an approximation. Leap years have 366 days.
465
- * For accurate year arithmetic, use ADD_YEARS() instead.
364
+ * Remove duplicate elements using deep equality, preserving first occurrence order.
466
365
  */
467
- declare const FROM_YEARS: (years: RuntimeValue) => RuntimeValue;
366
+ declare const ARR_UNIQUE: (a: RuntimeValue) => RuntimeValue;
468
367
  /**
469
- * 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.
470
370
  */
471
- declare const GET_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
371
+ declare const ARR_FLAT: (a: RuntimeValue) => RuntimeValue;
472
372
  /**
473
- * 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.
474
375
  */
475
- declare const GET_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
376
+ declare const ARR_JOIN: (a: RuntimeValue, sep: RuntimeValue) => RuntimeValue;
476
377
  /**
477
- * Get the day of month from a timestamp (1-31, local timezone)
378
+ * Sum all elements of a numeric array. Empty array returns 0.
478
379
  */
479
- declare const GET_DAY: (timestamp: RuntimeValue) => RuntimeValue;
380
+ declare const ARR_SUM: (a: RuntimeValue) => RuntimeValue;
480
381
  /**
481
- * 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.
482
385
  */
483
- declare const GET_HOUR: (timestamp: RuntimeValue) => RuntimeValue;
386
+ declare const ARR_MIN: (a: RuntimeValue) => RuntimeValue;
484
387
  /**
485
- * 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.
486
391
  */
487
- 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
+ }
488
396
  /**
489
- * 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.
490
399
  */
491
- declare const GET_SECOND: (timestamp: RuntimeValue) => RuntimeValue;
400
+ declare const STR: (v: RuntimeValue) => RuntimeValue;
492
401
  /**
493
- * 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.
494
405
  */
495
- declare const GET_MILLISECOND: (timestamp: RuntimeValue) => RuntimeValue;
406
+ declare const NUM: (v: RuntimeValue) => RuntimeValue;
496
407
  /**
497
- * 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
498
409
  */
499
- 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
+ }
500
414
  /**
501
- * Get the day of year (1-366) from a timestamp (local timezone)
502
- * 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.
503
418
  */
504
- declare const GET_DAY_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
505
419
  /**
506
- * Get the quarter (1-4) from a timestamp (local timezone)
420
+ * Get today's date as a Temporal.PlainDate
507
421
  */
508
- declare const GET_QUARTER: (timestamp: RuntimeValue) => RuntimeValue;
422
+ declare const TODAY: () => RuntimeValue;
509
423
  /**
510
- * Get the absolute difference between two timestamps in seconds (whole seconds)
424
+ * Create a date from year, month (1-based), and day
511
425
  */
512
- declare const DIFFERENCE_IN_SECONDS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
426
+ declare const DATE: (year: RuntimeValue, month: RuntimeValue, day: RuntimeValue) => RuntimeValue;
513
427
  /**
514
- * Get the absolute difference between two timestamps in minutes (whole minutes)
428
+ * Get the year from a date or datetime
515
429
  */
516
- declare const DIFFERENCE_IN_MINUTES: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
430
+ declare const GET_YEAR: (date: RuntimeValue) => RuntimeValue;
517
431
  /**
518
- * 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)
519
433
  */
520
- declare const DIFFERENCE_IN_HOURS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
434
+ declare const GET_MONTH: (date: RuntimeValue) => RuntimeValue;
521
435
  /**
522
- * Get the difference in calendar days between two timestamps
523
- * Counts the number of calendar day boundaries crossed, not 24-hour periods
524
- * 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)
525
437
  */
526
- declare const DIFFERENCE_IN_DAYS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
438
+ declare const GET_DAY: (date: RuntimeValue) => RuntimeValue;
527
439
  /**
528
- * Get the difference in calendar weeks between two timestamps
529
- * 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)
530
441
  */
531
- declare const DIFFERENCE_IN_WEEKS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
442
+ declare const GET_WEEKDAY: (date: RuntimeValue) => RuntimeValue;
532
443
  /**
533
- * Get the number of full calendar months between two timestamps (local timezone)
534
- * Counts complete months where the same day-of-month has been reached
535
- *
536
- * Examples:
537
- * Jan 15 → Feb 14 = 0 months (Feb 15 not reached yet)
538
- * Jan 15 → Feb 15 = 1 month
539
- * Jan 31 → Feb 28 = 0 months (Feb 31 doesn't exist)
540
- * Jan 31 → Mar 31 = 2 months
444
+ * Get the day of year (1-366) from a date or datetime
541
445
  */
542
- declare const DIFFERENCE_IN_MONTHS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
446
+ declare const GET_DAY_OF_YEAR: (date: RuntimeValue) => RuntimeValue;
543
447
  /**
544
- * Get the number of full calendar years between two timestamps (local timezone)
545
- * Counts complete years where the same month and day have been reached
546
- *
547
- * Examples:
548
- * Jan 15, 2020 → Jan 14, 2021 = 0 years (Jan 15 not reached)
549
- * Jan 15, 2020 → Jan 15, 2021 = 1 year
550
- * Feb 29, 2020 → Feb 28, 2021 = 0 years (Feb 29 doesn't exist)
551
- * Feb 29, 2020 → Mar 1, 2021 = 1 year
448
+ * Get the quarter (1-4) from a date or datetime
552
449
  */
553
- declare const DIFFERENCE_IN_YEARS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
450
+ declare const GET_QUARTER: (date: RuntimeValue) => RuntimeValue;
554
451
  /**
555
- * 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
556
453
  */
557
- declare const START_OF_DAY: (timestamp: RuntimeValue) => RuntimeValue;
454
+ declare const ADD_DAYS: (date: RuntimeValue, days: RuntimeValue) => RuntimeValue;
558
455
  /**
559
- * 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
560
457
  */
561
- declare const END_OF_DAY: (timestamp: RuntimeValue) => RuntimeValue;
458
+ declare const ADD_MONTHS: (date: RuntimeValue, months: RuntimeValue) => RuntimeValue;
562
459
  /**
563
- * 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
564
461
  */
565
- declare const START_OF_WEEK: (timestamp: RuntimeValue) => RuntimeValue;
462
+ declare const ADD_YEARS: (date: RuntimeValue, years: RuntimeValue) => RuntimeValue;
566
463
  /**
567
- * 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)
568
465
  */
569
- declare const START_OF_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
466
+ declare const DIFFERENCE_IN_DAYS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
570
467
  /**
571
- * 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)
572
469
  */
573
- declare const END_OF_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
470
+ declare const DIFFERENCE_IN_WEEKS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
574
471
  /**
575
- * 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)
576
473
  */
577
- declare const START_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
474
+ declare const DIFFERENCE_IN_MONTHS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
578
475
  /**
579
- * 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)
580
477
  */
581
- declare const END_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
478
+ declare const DIFFERENCE_IN_YEARS: (d1: RuntimeValue, d2: RuntimeValue) => RuntimeValue;
582
479
  /**
583
- * Add days to a timestamp (local timezone)
480
+ * Get the first day of the month for a given date or datetime
584
481
  */
585
- declare const ADD_DAYS: (timestamp: RuntimeValue, days: RuntimeValue) => RuntimeValue;
482
+ declare const START_OF_MONTH: (date: RuntimeValue) => RuntimeValue;
586
483
  /**
587
- * 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
588
485
  */
589
- declare const ADD_MONTHS: (timestamp: RuntimeValue, months: RuntimeValue) => RuntimeValue;
486
+ declare const END_OF_MONTH: (date: RuntimeValue) => RuntimeValue;
590
487
  /**
591
- * Add years to a timestamp (local timezone)
488
+ * Get the first day of the year for a given date or datetime
592
489
  */
593
- declare const ADD_YEARS: (timestamp: RuntimeValue, years: RuntimeValue) => RuntimeValue;
490
+ declare const START_OF_YEAR: (date: RuntimeValue) => RuntimeValue;
594
491
  /**
595
- * Check if two timestamps are on the same calendar day (local timezone)
596
- * Returns 1 if true, 0 if false
492
+ * Get the last day of the year for a given date or datetime
597
493
  */
598
- declare const IS_SAME_DAY: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
494
+ declare const END_OF_YEAR: (date: RuntimeValue) => RuntimeValue;
599
495
  /**
600
- * Check if timestamp falls on a weekend (Saturday or Sunday, local timezone)
601
- * Returns 1 if true, 0 if false
496
+ * Get the first day of the week (Monday) for a given date or datetime
602
497
  */
603
- declare const IS_WEEKEND: (timestamp: RuntimeValue) => RuntimeValue;
498
+ declare const START_OF_WEEK: (date: RuntimeValue) => RuntimeValue;
604
499
  /**
605
- * Check if timestamp is in a leap year (local timezone)
606
- * Returns 1 if true, 0 if false
500
+ * Get the first day of the quarter for a given date or datetime
607
501
  */
608
- declare const IS_LEAP_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
502
+ declare const START_OF_QUARTER: (date: RuntimeValue) => RuntimeValue;
609
503
  /**
610
- * 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).
611
507
  */
612
- declare const START_OF_QUARTER: (timestamp: RuntimeValue) => RuntimeValue;
613
- declare namespace exports_math {
614
- 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 };
615
519
  }
616
520
  /**
617
- * Math utility functions
618
- * All functions work with numbers only
521
+ * DateTime construction and conversion functions using Temporal.PlainDateTime
619
522
  */
620
523
  /**
621
- * Constrain a value between a minimum and maximum
622
- * @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
623
557
  */
624
- declare const CLAMP: (value: RuntimeValue, min: RuntimeValue, max: RuntimeValue) => RuntimeValue;
625
558
  declare const ABS: (x: RuntimeValue) => RuntimeValue;
626
559
  declare const CEIL: (x: RuntimeValue) => RuntimeValue;
627
560
  declare const FLOOR: (x: RuntimeValue) => RuntimeValue;
@@ -636,37 +569,174 @@ declare const LOG: (x: RuntimeValue) => RuntimeValue;
636
569
  declare const LOG10: (x: RuntimeValue) => RuntimeValue;
637
570
  declare const EXP: (x: RuntimeValue) => RuntimeValue;
638
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
+ /**
639
693
  * Default execution context with standard library functions
640
- * Users can use this as-is or spread it into their own context
641
- *
642
- * All functions use UPPERCASE naming convention to avoid collisions with user variables.
643
- * All date-related functions work with timestamps (milliseconds since Unix epoch)
644
- * to maintain the language's numbers-only type system.
645
- *
646
- * @example
647
- * // Use as-is
648
- * execute('ABS(-5)', defaultContext)
649
- *
650
- * @example
651
- * // Spread into custom context
652
- * execute('NOW() + FROM_MINUTES(5)', {
653
- * ...defaultContext,
654
- * variables: { customVar: 42 }
655
- * })
656
- *
657
- * @example
658
- * // Work with timestamps
659
- * const result = execute('NOW() + FROM_DAYS(7)', defaultContext)
660
- * const futureDate = new Date(result) // Convert back to Date if needed
661
- *
662
- * @example
663
- * // Calculate time differences
664
- * const ts1 = Date.now()
665
- * const ts2 = ts1 + 1000 * 60 * 60 * 3 // 3 hours later
666
- * execute('DIFFERENCE_IN_HOURS(ts1, ts2)', { ...defaultContext, variables: { ts1, ts2 } })
694
+ * Includes math, string, array, datetime, time, datetimefull, and type conversion functions
667
695
  */
668
696
  declare const defaultContext: ExecutionContext;
669
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
+ /**
670
740
  * Type-safe visitor pattern for AST traversal.
671
741
  *
672
742
  * A visitor is an object with handler functions for each AST node type.
@@ -674,133 +744,32 @@ declare const defaultContext: ExecutionContext;
674
744
  * - The node (correctly typed based on node.type)
675
745
  * - A recurse function to visit child nodes with the same visitor
676
746
  *
677
- * The visitor pattern centralizes AST traversal logic and ensures
678
- * exhaustive handling of all node types at compile time.
679
- *
680
- * Time complexity: O(n) where n is the number of nodes in the AST
681
- * Space complexity: O(d) where d is the maximum depth (recursion stack)
682
- *
683
747
  * @template T The return type of visitor handlers
684
- *
685
- * @example
686
- * // Count all nodes in an AST
687
- * const nodeCount = visit(ast, {
688
- * Program: (n, recurse) => 1 + n.statements.reduce((sum, stmt) => sum + recurse(stmt), 0),
689
- * NumberLiteral: () => 1,
690
- * Identifier: () => 1,
691
- * BinaryOp: (n, recurse) => 1 + recurse(n.left) + recurse(n.right),
692
- * UnaryOp: (n, recurse) => 1 + recurse(n.argument),
693
- * FunctionCall: (n, recurse) => 1 + n.arguments.reduce((sum, arg) => sum + recurse(arg), 0),
694
- * Assignment: (n, recurse) => 1 + recurse(n.value),
695
- * ConditionalExpression: (n, recurse) => 1 + recurse(n.condition) + recurse(n.consequent) + recurse(n.alternate),
696
- * })
697
- *
698
- * @example
699
- * // Transform AST: constant folding
700
- * const optimized = visit(ast, {
701
- * NumberLiteral: (n) => n,
702
- * Identifier: (n) => n,
703
- * BinaryOp: (n, recurse) => {
704
- * const left = recurse(n.left)
705
- * const right = recurse(n.right)
706
- * if (isNumberLiteral(left) && isNumberLiteral(right)) {
707
- * return ast.number(left.value + right.value)
708
- * }
709
- * return ast.binaryOp(left, n.operator, right)
710
- * },
711
- * // ... other handlers
712
- * })
713
748
  */
714
749
  type Visitor<T> = {
715
- /**
716
- * Handle a Program node (multiple statements)
717
- */
718
750
  Program: (node: Program, recurse: (n: ASTNode) => T) => T;
719
- /**
720
- * Handle a NumberLiteral node
721
- */
722
751
  NumberLiteral: (node: NumberLiteral, recurse: (n: ASTNode) => T) => T;
723
- /**
724
- * Handle an Identifier node (variable reference)
725
- */
726
- Identifier: (node: Identifier, recurse: (n: ASTNode) => T) => T;
727
- /**
728
- * Handle a BinaryOp node (binary operation)
729
- */
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;
730
756
  BinaryOp: (node: BinaryOp, recurse: (n: ASTNode) => T) => T;
731
- /**
732
- * Handle a UnaryOp node (unary operation)
733
- */
734
757
  UnaryOp: (node: UnaryOp, recurse: (n: ASTNode) => T) => T;
735
- /**
736
- * Handle a FunctionCall node
737
- */
738
758
  FunctionCall: (node: FunctionCall, recurse: (n: ASTNode) => T) => T;
739
- /**
740
- * Handle an Assignment node (variable assignment)
741
- */
742
759
  Assignment: (node: Assignment, recurse: (n: ASTNode) => T) => T;
743
- /**
744
- * Handle a ConditionalExpression node (ternary operator)
745
- */
746
- 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;
747
764
  };
748
765
  /**
749
766
  * Visit an AST node using a visitor object with type-specific handlers.
750
- *
751
- * This function implements the visitor pattern for AST traversal.
752
767
  * All node types must have handlers (exhaustive by design).
753
- * TypeScript enforces exhaustiveness at compile time via the switch statement.
754
- *
755
- * The visitor pattern provides several benefits:
756
- * - DRY: Centralizes traversal logic across all modules
757
- * - Type safety: Handlers receive correctly-typed nodes
758
- * - Exhaustiveness: Compile-time guarantee that all node types are handled
759
- * - Flexibility: Supports transform, fold, and walk patterns
760
768
  *
761
769
  * @template T The return type of visitor handlers
762
770
  * @param node The AST node to visit
763
771
  * @param visitor Object with handlers for each node type
764
772
  * @returns The result of visiting the node
765
- *
766
- * @example
767
- * // Evaluate an AST (fold pattern)
768
- * const result = visit(ast, {
769
- * Program: (n, recurse) => {
770
- * let result = 0
771
- * for (const stmt of n.statements) {
772
- * result = recurse(stmt)
773
- * }
774
- * return result
775
- * },
776
- * NumberLiteral: (n) => n.value,
777
- * BinaryOp: (n, recurse) => {
778
- * const left = recurse(n.left)
779
- * const right = recurse(n.right)
780
- * return left + right // simplified
781
- * },
782
- * // ... other handlers
783
- * })
784
- *
785
- * @example
786
- * // Transform an AST (transform pattern)
787
- * const transformed = visit(ast, {
788
- * NumberLiteral: (n) => ast.number(n.value * 2), // Double all numbers
789
- * BinaryOp: (n, recurse) => ast.binaryOp(
790
- * recurse(n.left),
791
- * n.operator,
792
- * recurse(n.right)
793
- * ),
794
- * // ... other handlers
795
- * })
796
- *
797
- * @example
798
- * // Walk an AST (walk pattern - side effects)
799
- * visit(ast, {
800
- * NumberLiteral: (n) => { console.log('Number:', n.value) },
801
- * Identifier: (n) => { console.log('Variable:', n.name) },
802
- * // ... other handlers
803
- * })
804
773
  */
805
774
  declare function visit<T>(node: ASTNode, visitor: Visitor<T>): T;
806
775
  /**
@@ -810,52 +779,11 @@ declare function visit<T>(node: ASTNode, visitor: Visitor<T>): T;
810
779
  * you to handle only specific node types. Unhandled nodes are processed by
811
780
  * the default handler.
812
781
  *
813
- * This is useful for:
814
- * - Analysis passes that only care about certain node types
815
- * - Transformations that only modify specific nodes
816
- * - Walking the tree to collect information
817
- *
818
782
  * @template T The return type of visitor handlers
819
783
  * @param node The AST node to visit
820
784
  * @param visitor Object with optional handlers for node types
821
785
  * @param defaultHandler Handler for unhandled node types
822
786
  * @returns The result of visiting the node
823
- *
824
- * @example
825
- * // Collect all variable names (only care about Identifier nodes)
826
- * const variables: string[] = []
827
- * visitPartial(
828
- * ast,
829
- * {
830
- * Identifier: (n) => {
831
- * variables.push(n.name)
832
- * return undefined
833
- * }
834
- * },
835
- * (node, recurse) => {
836
- * // Default: recurse into children for all other node types
837
- * if (node.type === 'BinaryOp') {
838
- * recurse(node.left)
839
- * recurse(node.right)
840
- * }
841
- * // ... handle other node types' children
842
- * return undefined
843
- * }
844
- * )
845
- *
846
- * @example
847
- * // Transform only BinaryOp nodes, keep everything else as-is
848
- * const transformed = visitPartial(
849
- * ast,
850
- * {
851
- * BinaryOp: (n, recurse) => ast.binaryOp(
852
- * recurse(n.left),
853
- * '+', // Force all operators to addition
854
- * recurse(n.right)
855
- * )
856
- * },
857
- * (node, recurse) => node // Default: identity (no transformation)
858
- * )
859
787
  */
860
788
  declare function visitPartial<T>(node: ASTNode, visitor: Partial<Visitor<T>>, defaultHandler: (node: ASTNode, recurse: (n: ASTNode) => T) => T): T;
861
- export { visitPartial, visit, parse, optimize, exports_math as math, isUnaryOp, isProgram, isNumberLiteral, isIdentifier, isFunctionCall, isConditionalExpression, isBinaryOp, isAssignment, humanize, generate, extractInputVariables, extractAssignedVariables, evaluateScope, 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 };