littlewing 1.0.0 → 1.1.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.
- package/README.md +49 -26
- package/dist/index.d.ts +320 -150
- package/dist/index.js +985 -954
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -260,17 +260,27 @@ const ast = parse("x = 5; x + 10");
|
|
|
260
260
|
|
|
261
261
|
// Count all identifiers in an AST
|
|
262
262
|
const count = visit(ast, {
|
|
263
|
-
|
|
264
|
-
|
|
263
|
+
// Tuple: [kind, statements]
|
|
264
|
+
Program: (n, recurse) => {
|
|
265
|
+
const statements = n[1];
|
|
266
|
+
return statements.reduce((sum, stmt) => sum + recurse(stmt), 0);
|
|
267
|
+
},
|
|
265
268
|
NumberLiteral: () => 0,
|
|
266
269
|
Identifier: () => 1,
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
// Tuple: [kind, left, operator, right]
|
|
271
|
+
BinaryOp: (n, recurse) => recurse(n[1]) + recurse(n[3]),
|
|
272
|
+
// Tuple: [kind, operator, argument]
|
|
273
|
+
UnaryOp: (n, recurse) => recurse(n[2]),
|
|
274
|
+
// Tuple: [kind, name, value]
|
|
275
|
+
Assignment: (n, recurse) => 1 + recurse(n[2]),
|
|
276
|
+
// Tuple: [kind, name, arguments]
|
|
277
|
+
FunctionCall: (n, recurse) => {
|
|
278
|
+
const args = n[2];
|
|
279
|
+
return 1 + args.reduce((sum, arg) => sum + recurse(arg), 0);
|
|
280
|
+
},
|
|
281
|
+
// Tuple: [kind, condition, consequent, alternate]
|
|
272
282
|
ConditionalExpression: (n, recurse) =>
|
|
273
|
-
recurse(n
|
|
283
|
+
recurse(n[1]) + recurse(n[2]) + recurse(n[3]),
|
|
274
284
|
}); // → 3 (x appears 3 times)
|
|
275
285
|
```
|
|
276
286
|
|
|
@@ -287,18 +297,24 @@ const ast = parse("x = 5; y = x + 10; y * 2");
|
|
|
287
297
|
const result = visitPartial(
|
|
288
298
|
ast,
|
|
289
299
|
{
|
|
300
|
+
// Tuple: [kind, statements]
|
|
290
301
|
Program: (n, recurse) => {
|
|
291
|
-
|
|
302
|
+
const statements = n[1];
|
|
303
|
+
for (const stmt of statements) {
|
|
292
304
|
const found = recurse(stmt);
|
|
293
305
|
if (found !== undefined) return found;
|
|
294
306
|
}
|
|
295
307
|
return undefined;
|
|
296
308
|
},
|
|
309
|
+
// Tuple: [kind, name, value]
|
|
297
310
|
Assignment: (n, recurse) => {
|
|
298
|
-
|
|
299
|
-
|
|
311
|
+
const name = n[1];
|
|
312
|
+
const value = n[2];
|
|
313
|
+
if (name === "y") return n; // Found it!
|
|
314
|
+
return recurse(value); // Keep searching
|
|
300
315
|
},
|
|
301
|
-
|
|
316
|
+
// Tuple: [kind, left, operator, right]
|
|
317
|
+
BinaryOp: (n, recurse) => recurse(n[1]) ?? recurse(n[3]),
|
|
302
318
|
},
|
|
303
319
|
() => undefined,
|
|
304
320
|
); // → Assignment node for "y = x + 10"
|
|
@@ -313,22 +329,29 @@ import { visit, parse, ast } from "littlewing";
|
|
|
313
329
|
|
|
314
330
|
// Double all numeric literals
|
|
315
331
|
const transformed = visit<ASTNode>(parse("2 + 3 * 4"), {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
332
|
+
// Tuple: [kind, statements]
|
|
333
|
+
Program: (n, recurse) => {
|
|
334
|
+
const statements = n[1];
|
|
335
|
+
return ast.program(statements.map((stmt) => recurse(stmt)));
|
|
336
|
+
},
|
|
337
|
+
// Tuple: [kind, value]
|
|
338
|
+
NumberLiteral: (n) => ast.number(n[1] * 2),
|
|
319
339
|
Identifier: (n) => n,
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
340
|
+
// Tuple: [kind, left, operator, right]
|
|
341
|
+
BinaryOp: (n, recurse) => ast.binaryOp(recurse(n[1]), n[2], recurse(n[3])),
|
|
342
|
+
// Tuple: [kind, operator, argument]
|
|
343
|
+
UnaryOp: (n, recurse) => ast.unaryOp(n[1], recurse(n[2])),
|
|
344
|
+
// Tuple: [kind, name, value]
|
|
345
|
+
Assignment: (n, recurse) => ast.assign(n[1], recurse(n[2])),
|
|
346
|
+
// Tuple: [kind, name, arguments]
|
|
347
|
+
FunctionCall: (n, recurse) => {
|
|
348
|
+
const name = n[1];
|
|
349
|
+
const args = n[2];
|
|
350
|
+
return ast.functionCall(name, args.map(recurse));
|
|
351
|
+
},
|
|
352
|
+
// Tuple: [kind, condition, consequent, alternate]
|
|
326
353
|
ConditionalExpression: (n, recurse) =>
|
|
327
|
-
ast.conditional(
|
|
328
|
-
recurse(n.condition),
|
|
329
|
-
recurse(n.consequent),
|
|
330
|
-
recurse(n.alternate),
|
|
331
|
-
),
|
|
354
|
+
ast.conditional(recurse(n[1]), recurse(n[2]), recurse(n[3])),
|
|
332
355
|
});
|
|
333
356
|
|
|
334
357
|
generate(transformed); // → "4 + 6 * 8"
|
package/dist/index.d.ts
CHANGED
|
@@ -1,168 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type RuntimeValue = number;
|
|
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 };
|
|
3
|
+
}
|
|
5
4
|
/**
|
|
6
5
|
* Binary operator types
|
|
7
6
|
*/
|
|
8
7
|
type Operator = "+" | "-" | "*" | "/" | "%" | "^" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "&&" | "||";
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
declare enum TokenType {
|
|
22
|
-
NUMBER = "NUMBER",
|
|
23
|
-
IDENTIFIER = "IDENTIFIER",
|
|
24
|
-
PLUS = "PLUS",
|
|
25
|
-
MINUS = "MINUS",
|
|
26
|
-
STAR = "STAR",
|
|
27
|
-
SLASH = "SLASH",
|
|
28
|
-
PERCENT = "PERCENT",
|
|
29
|
-
CARET = "CARET",
|
|
30
|
-
EXCLAMATION = "EXCLAMATION",
|
|
31
|
-
DOUBLE_EQUALS = "DOUBLE_EQUALS",
|
|
32
|
-
NOT_EQUALS = "NOT_EQUALS",
|
|
33
|
-
LESS_THAN = "LESS_THAN",
|
|
34
|
-
GREATER_THAN = "GREATER_THAN",
|
|
35
|
-
LESS_EQUAL = "LESS_EQUAL",
|
|
36
|
-
GREATER_EQUAL = "GREATER_EQUAL",
|
|
37
|
-
LOGICAL_AND = "LOGICAL_AND",
|
|
38
|
-
LOGICAL_OR = "LOGICAL_OR",
|
|
39
|
-
LPAREN = "LPAREN",
|
|
40
|
-
RPAREN = "RPAREN",
|
|
41
|
-
EQUALS = "EQUALS",
|
|
42
|
-
COMMA = "COMMA",
|
|
43
|
-
QUESTION = "QUESTION",
|
|
44
|
-
COLON = "COLON",
|
|
45
|
-
EOF = "EOF"
|
|
9
|
+
* AST Node kind discriminator (const enum for zero-cost abstraction)
|
|
10
|
+
*/
|
|
11
|
+
declare const enum NodeKind {
|
|
12
|
+
Program = 0,
|
|
13
|
+
NumberLiteral = 1,
|
|
14
|
+
Identifier = 2,
|
|
15
|
+
BinaryOp = 3,
|
|
16
|
+
UnaryOp = 4,
|
|
17
|
+
FunctionCall = 5,
|
|
18
|
+
Assignment = 6,
|
|
19
|
+
ConditionalExpression = 7
|
|
46
20
|
}
|
|
47
21
|
/**
|
|
48
|
-
* Token produced by lexer
|
|
49
|
-
*/
|
|
50
|
-
interface Token {
|
|
51
|
-
type: TokenType;
|
|
52
|
-
value: string | number;
|
|
53
|
-
position: number;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* AST Node - base type
|
|
57
|
-
*/
|
|
58
|
-
type ASTNode = Program | NumberLiteral | Identifier | BinaryOp | UnaryOp | FunctionCall | Assignment | ConditionalExpression;
|
|
59
|
-
/**
|
|
60
22
|
* Program node (multiple statements)
|
|
23
|
+
* Tuple: [kind, statements]
|
|
61
24
|
*/
|
|
62
|
-
|
|
63
|
-
type: "Program";
|
|
64
|
-
statements: ASTNode[];
|
|
65
|
-
}
|
|
25
|
+
type Program = readonly [kind: NodeKind.Program, statements: readonly ASTNode[]];
|
|
66
26
|
/**
|
|
67
27
|
* Number literal (123, 45.67)
|
|
28
|
+
* Tuple: [kind, value]
|
|
68
29
|
*/
|
|
69
|
-
|
|
70
|
-
type: "NumberLiteral";
|
|
71
|
-
value: number;
|
|
72
|
-
}
|
|
30
|
+
type NumberLiteral = readonly [kind: NodeKind.NumberLiteral, value: number];
|
|
73
31
|
/**
|
|
74
32
|
* Identifier (variable or function name)
|
|
33
|
+
* Tuple: [kind, name]
|
|
75
34
|
*/
|
|
76
|
-
|
|
77
|
-
type: "Identifier";
|
|
78
|
-
name: string;
|
|
79
|
-
}
|
|
35
|
+
type Identifier = readonly [kind: NodeKind.Identifier, name: string];
|
|
80
36
|
/**
|
|
81
37
|
* Binary operation (a + b, x * y, etc.)
|
|
38
|
+
* Tuple: [kind, left, operator, right]
|
|
39
|
+
* Note: left-to-right reading order
|
|
82
40
|
*/
|
|
83
|
-
|
|
84
|
-
type: "BinaryOp";
|
|
85
|
-
left: ASTNode;
|
|
86
|
-
operator: Operator;
|
|
87
|
-
right: ASTNode;
|
|
88
|
-
}
|
|
41
|
+
type BinaryOp = readonly [kind: NodeKind.BinaryOp, left: ASTNode, operator: Operator, right: ASTNode];
|
|
89
42
|
/**
|
|
90
43
|
* Unary operation (-x, !x, etc.)
|
|
44
|
+
* Tuple: [kind, operator, argument]
|
|
91
45
|
*/
|
|
92
|
-
|
|
93
|
-
type: "UnaryOp";
|
|
94
|
-
operator: "-" | "!";
|
|
95
|
-
argument: ASTNode;
|
|
96
|
-
}
|
|
46
|
+
type UnaryOp = readonly [kind: NodeKind.UnaryOp, operator: "-" | "!", argument: ASTNode];
|
|
97
47
|
/**
|
|
98
|
-
* Function call (
|
|
48
|
+
* Function call (NOW(), MAX(a, b), etc.)
|
|
49
|
+
* Tuple: [kind, name, arguments]
|
|
99
50
|
*/
|
|
100
|
-
|
|
101
|
-
type: "FunctionCall";
|
|
102
|
-
name: string;
|
|
103
|
-
arguments: ASTNode[];
|
|
104
|
-
}
|
|
51
|
+
type FunctionCall = readonly [kind: NodeKind.FunctionCall, name: string, arguments: readonly ASTNode[]];
|
|
105
52
|
/**
|
|
106
53
|
* Variable assignment (x = 5)
|
|
54
|
+
* Tuple: [kind, name, value]
|
|
107
55
|
*/
|
|
108
|
-
|
|
109
|
-
type: "Assignment";
|
|
110
|
-
name: string;
|
|
111
|
-
value: ASTNode;
|
|
112
|
-
}
|
|
56
|
+
type Assignment = readonly [kind: NodeKind.Assignment, name: string, value: ASTNode];
|
|
113
57
|
/**
|
|
114
58
|
* Conditional expression (ternary operator: condition ? consequent : alternate)
|
|
115
59
|
* Returns consequent if condition !== 0, otherwise returns alternate
|
|
60
|
+
* Tuple: [kind, condition, consequent, alternate]
|
|
116
61
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
62
|
+
type ConditionalExpression = readonly [kind: NodeKind.ConditionalExpression, condition: ASTNode, consequent: ASTNode, alternate: ASTNode];
|
|
63
|
+
/**
|
|
64
|
+
* AST Node - discriminated union of all node types
|
|
65
|
+
*/
|
|
66
|
+
type ASTNode = Program | NumberLiteral | Identifier | BinaryOp | UnaryOp | FunctionCall | Assignment | ConditionalExpression;
|
|
123
67
|
/**
|
|
124
68
|
* Type guard functions for discriminated union narrowing
|
|
125
69
|
*/
|
|
70
|
+
declare function isProgram(node: ASTNode): node is Program;
|
|
126
71
|
declare function isNumberLiteral(node: ASTNode): node is NumberLiteral;
|
|
127
72
|
declare function isIdentifier(node: ASTNode): node is Identifier;
|
|
128
73
|
declare function isBinaryOp(node: ASTNode): node is BinaryOp;
|
|
129
74
|
declare function isUnaryOp(node: ASTNode): node is UnaryOp;
|
|
130
75
|
declare function isFunctionCall(node: ASTNode): node is FunctionCall;
|
|
131
76
|
declare function isAssignment(node: ASTNode): node is Assignment;
|
|
132
|
-
declare function isProgram(node: ASTNode): node is Program;
|
|
133
77
|
declare function isConditionalExpression(node: ASTNode): node is ConditionalExpression;
|
|
134
78
|
/**
|
|
135
|
-
* Extracts input variables from an AST.
|
|
136
|
-
*
|
|
137
|
-
* Input variables are those whose values can be determined without knowing
|
|
138
|
-
* the values of other variables in the script. This includes:
|
|
139
|
-
* - Literals (10, -5, 3.14)
|
|
140
|
-
* - Unary minus of literals (-10)
|
|
141
|
-
* - Constant expressions (2 + 3, -5 * 2)
|
|
142
|
-
* - Function calls with constant arguments (MAX(10, 20), NOW())
|
|
143
|
-
*
|
|
144
|
-
* Computed variables (those that reference other variables) are excluded.
|
|
145
|
-
*
|
|
146
|
-
* @param ast - The AST to analyze (can be a single statement or Program node)
|
|
147
|
-
* @returns Array of input variable names
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* ```typescript
|
|
151
|
-
* const ast = parse('price = 100; tax = price * 0.08')
|
|
152
|
-
* extractInputVariables(ast) // ['price']
|
|
153
|
-
* ```
|
|
154
|
-
*/
|
|
155
|
-
declare function extractInputVariables(ast: ASTNode): string[];
|
|
156
|
-
declare namespace exports_ast {
|
|
157
|
-
export { unaryOp, subtract, program, number, notEquals, negate, multiply, modulo, logicalOr, logicalNot, logicalAnd, lessThan, lessEqual, identifier, greaterThan, greaterEqual, functionCall, exponentiate, equals, divide, conditional, binaryOp, assign, add };
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
79
|
* Builder functions for creating AST nodes manually
|
|
161
80
|
*/
|
|
162
81
|
/**
|
|
163
82
|
* Create a program node
|
|
164
83
|
*/
|
|
165
|
-
declare function program(statements: ASTNode[]): Program;
|
|
84
|
+
declare function program(statements: readonly ASTNode[]): Program;
|
|
166
85
|
/**
|
|
167
86
|
* Create a number literal node
|
|
168
87
|
*/
|
|
@@ -182,7 +101,7 @@ declare function unaryOp(operator: "-" | "!", argument: ASTNode): UnaryOp;
|
|
|
182
101
|
/**
|
|
183
102
|
* Create a function call node
|
|
184
103
|
*/
|
|
185
|
-
declare function functionCall(name: string, args?: ASTNode[]): FunctionCall;
|
|
104
|
+
declare function functionCall(name: string, args?: readonly ASTNode[]): FunctionCall;
|
|
186
105
|
/**
|
|
187
106
|
* Create a variable assignment node
|
|
188
107
|
*/
|
|
@@ -264,41 +183,33 @@ declare function logicalAnd(left: ASTNode, right: ASTNode): BinaryOp;
|
|
|
264
183
|
* Create a logical OR operation (||)
|
|
265
184
|
*/
|
|
266
185
|
declare function logicalOr(left: ASTNode, right: ASTNode): BinaryOp;
|
|
186
|
+
declare function getNodeName(node: ASTNode): string;
|
|
267
187
|
/**
|
|
268
|
-
*
|
|
269
|
-
*/
|
|
270
|
-
declare function generate(node: ASTNode): string;
|
|
271
|
-
/**
|
|
272
|
-
* Default execution context with common Math functions and date/time utilities
|
|
273
|
-
* Users can use this as-is or spread it into their own context
|
|
274
|
-
*
|
|
275
|
-
* All functions use UPPERCASE naming convention to avoid collisions with user variables.
|
|
276
|
-
* All date-related functions work with timestamps (milliseconds since Unix epoch)
|
|
277
|
-
* to maintain the language's numbers-only type system.
|
|
188
|
+
* Extracts input variables from an AST.
|
|
278
189
|
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
190
|
+
* Input variables are those whose values can be determined without knowing
|
|
191
|
+
* the values of other variables in the script. This includes:
|
|
192
|
+
* - Literals (10, -5, 3.14)
|
|
193
|
+
* - Unary minus of literals (-10)
|
|
194
|
+
* - Constant expressions (2 + 3, -5 * 2)
|
|
195
|
+
* - Function calls with constant arguments (MAX(10, 20), NOW())
|
|
282
196
|
*
|
|
283
|
-
*
|
|
284
|
-
* // Spread into custom context
|
|
285
|
-
* execute('NOW() + FROM_MINUTES(5)', {
|
|
286
|
-
* ...defaultContext,
|
|
287
|
-
* variables: { customVar: 42 }
|
|
288
|
-
* })
|
|
197
|
+
* Computed variables (those that reference other variables) are excluded.
|
|
289
198
|
*
|
|
290
|
-
* @
|
|
291
|
-
*
|
|
292
|
-
* const result = execute('NOW() + FROM_DAYS(7)', defaultContext)
|
|
293
|
-
* const futureDate = new Date(result) // Convert back to Date if needed
|
|
199
|
+
* @param ast - The AST to analyze (can be a single statement or Program node)
|
|
200
|
+
* @returns Array of input variable names
|
|
294
201
|
*
|
|
295
202
|
* @example
|
|
296
|
-
*
|
|
297
|
-
* const
|
|
298
|
-
*
|
|
299
|
-
*
|
|
203
|
+
* ```typescript
|
|
204
|
+
* const ast = parse('price = 100; tax = price * 0.08')
|
|
205
|
+
* extractInputVariables(ast) // ['price']
|
|
206
|
+
* ```
|
|
300
207
|
*/
|
|
301
|
-
declare
|
|
208
|
+
declare function extractInputVariables(ast: ASTNode): string[];
|
|
209
|
+
/**
|
|
210
|
+
* Generate source code from an AST node
|
|
211
|
+
*/
|
|
212
|
+
declare function generate(node: ASTNode): string;
|
|
302
213
|
/**
|
|
303
214
|
* Options for customizing the humanization output
|
|
304
215
|
*/
|
|
@@ -363,9 +274,23 @@ interface HumanizeOptions {
|
|
|
363
274
|
*/
|
|
364
275
|
declare function humanize(node: ASTNode, options?: HumanizeOptions): string;
|
|
365
276
|
/**
|
|
277
|
+
* Runtime value type - only numbers
|
|
278
|
+
*/
|
|
279
|
+
type RuntimeValue = number;
|
|
280
|
+
/**
|
|
281
|
+
* 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
|
|
284
|
+
*/
|
|
285
|
+
interface ExecutionContext {
|
|
286
|
+
functions?: Record<string, (...args: RuntimeValue[]) => RuntimeValue>;
|
|
287
|
+
variables?: Record<string, RuntimeValue>;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
366
290
|
* Evaluate source code or AST with given context
|
|
367
291
|
* @param input - Either a source code string or an AST node
|
|
368
292
|
* @param context - Optional execution context with variables and functions
|
|
293
|
+
* @returns The evaluated result
|
|
369
294
|
*/
|
|
370
295
|
declare function evaluate(input: string | ASTNode, context?: ExecutionContext): RuntimeValue;
|
|
371
296
|
/**
|
|
@@ -395,12 +320,257 @@ declare function evaluate(input: string | ASTNode, context?: ExecutionContext):
|
|
|
395
320
|
declare function optimize(node: ASTNode): ASTNode;
|
|
396
321
|
/**
|
|
397
322
|
* Parse source code string into AST
|
|
398
|
-
*
|
|
323
|
+
* Implements Pratt parsing (top-down operator precedence)
|
|
324
|
+
* Uses lazy lexing - calls lexer on-demand instead of receiving all tokens upfront
|
|
399
325
|
*
|
|
400
326
|
* @param source - The source code to parse
|
|
401
327
|
* @returns Parsed AST
|
|
402
328
|
*/
|
|
403
329
|
declare function parse(source: string): ASTNode;
|
|
330
|
+
declare namespace exports_datetime {
|
|
331
|
+
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 };
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Date utility functions for working with timestamps
|
|
335
|
+
* All functions work with milliseconds since Unix epoch (numbers only)
|
|
336
|
+
*
|
|
337
|
+
* IMPORTANT: All functions use local timezone to match the user's context.
|
|
338
|
+
* In a browser, this reflects the user's timezone. On a server, this reflects
|
|
339
|
+
* the server's configured timezone. This ensures date calculations align with
|
|
340
|
+
* the user's calendar expectations.
|
|
341
|
+
*/
|
|
342
|
+
/**
|
|
343
|
+
* Get current timestamp (milliseconds since Unix epoch)
|
|
344
|
+
*/
|
|
345
|
+
declare const NOW: () => RuntimeValue;
|
|
346
|
+
/**
|
|
347
|
+
* Create timestamp from date components (local timezone)
|
|
348
|
+
* Year is required, all other parameters default to minimum values
|
|
349
|
+
* Month is 1-based (1 = January, 12 = December)
|
|
350
|
+
* All parameters are interpreted in local timezone
|
|
351
|
+
*/
|
|
352
|
+
declare const DATE: (year: RuntimeValue, month?: number, day?: number, hour?: number, minute?: number, second?: number) => RuntimeValue;
|
|
353
|
+
/**
|
|
354
|
+
* Convert days to milliseconds
|
|
355
|
+
*/
|
|
356
|
+
declare const FROM_DAYS: (d: RuntimeValue) => RuntimeValue;
|
|
357
|
+
/**
|
|
358
|
+
* Convert weeks to milliseconds
|
|
359
|
+
*/
|
|
360
|
+
declare const FROM_WEEKS: (w: RuntimeValue) => RuntimeValue;
|
|
361
|
+
/**
|
|
362
|
+
* Convert months to milliseconds (approximate: 30 days per month)
|
|
363
|
+
* WARNING: This is an approximation. Not all months have 30 days.
|
|
364
|
+
* For accurate month arithmetic, use ADD_MONTHS() instead.
|
|
365
|
+
*/
|
|
366
|
+
declare const FROM_MONTHS: (months: RuntimeValue) => RuntimeValue;
|
|
367
|
+
/**
|
|
368
|
+
* Convert years to milliseconds (approximate: 365 days per year)
|
|
369
|
+
* WARNING: This is an approximation. Leap years have 366 days.
|
|
370
|
+
* For accurate year arithmetic, use ADD_YEARS() instead.
|
|
371
|
+
*/
|
|
372
|
+
declare const FROM_YEARS: (years: RuntimeValue) => RuntimeValue;
|
|
373
|
+
/**
|
|
374
|
+
* Get the year from a timestamp (local timezone)
|
|
375
|
+
*/
|
|
376
|
+
declare const GET_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
|
|
377
|
+
/**
|
|
378
|
+
* Get the month from a timestamp (1-based: 1 = January, 12 = December, local timezone)
|
|
379
|
+
*/
|
|
380
|
+
declare const GET_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
|
|
381
|
+
/**
|
|
382
|
+
* Get the day of month from a timestamp (1-31, local timezone)
|
|
383
|
+
*/
|
|
384
|
+
declare const GET_DAY: (timestamp: RuntimeValue) => RuntimeValue;
|
|
385
|
+
/**
|
|
386
|
+
* Get the hour from a timestamp (0-23, local timezone)
|
|
387
|
+
*/
|
|
388
|
+
declare const GET_HOUR: (timestamp: RuntimeValue) => RuntimeValue;
|
|
389
|
+
/**
|
|
390
|
+
* Get the minute from a timestamp (0-59, local timezone)
|
|
391
|
+
*/
|
|
392
|
+
declare const GET_MINUTE: (timestamp: RuntimeValue) => RuntimeValue;
|
|
393
|
+
/**
|
|
394
|
+
* Get the second from a timestamp (0-59, local timezone)
|
|
395
|
+
*/
|
|
396
|
+
declare const GET_SECOND: (timestamp: RuntimeValue) => RuntimeValue;
|
|
397
|
+
/**
|
|
398
|
+
* Get the millisecond component from a timestamp (0-999, local timezone)
|
|
399
|
+
*/
|
|
400
|
+
declare const GET_MILLISECOND: (timestamp: RuntimeValue) => RuntimeValue;
|
|
401
|
+
/**
|
|
402
|
+
* Get the day of week from a timestamp (0 = Sunday, 6 = Saturday, local timezone)
|
|
403
|
+
*/
|
|
404
|
+
declare const GET_WEEKDAY: (timestamp: RuntimeValue) => RuntimeValue;
|
|
405
|
+
/**
|
|
406
|
+
* Get the day of year (1-366) from a timestamp (local timezone)
|
|
407
|
+
* January 1st = 1, December 31st = 365 or 366 (leap year)
|
|
408
|
+
*/
|
|
409
|
+
declare const GET_DAY_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
|
|
410
|
+
/**
|
|
411
|
+
* Get the quarter (1-4) from a timestamp (local timezone)
|
|
412
|
+
*/
|
|
413
|
+
declare const GET_QUARTER: (timestamp: RuntimeValue) => RuntimeValue;
|
|
414
|
+
/**
|
|
415
|
+
* Get the absolute difference between two timestamps in seconds (whole seconds)
|
|
416
|
+
*/
|
|
417
|
+
declare const DIFFERENCE_IN_SECONDS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
418
|
+
/**
|
|
419
|
+
* Get the absolute difference between two timestamps in minutes (whole minutes)
|
|
420
|
+
*/
|
|
421
|
+
declare const DIFFERENCE_IN_MINUTES: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
422
|
+
/**
|
|
423
|
+
* Get the absolute difference between two timestamps in hours (whole hours)
|
|
424
|
+
*/
|
|
425
|
+
declare const DIFFERENCE_IN_HOURS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
426
|
+
/**
|
|
427
|
+
* Get the difference in calendar days between two timestamps
|
|
428
|
+
* Counts the number of calendar day boundaries crossed, not 24-hour periods
|
|
429
|
+
* Example: Nov 7 at 11:59 PM to Nov 8 at 12:01 AM = 1 day (different calendar days)
|
|
430
|
+
*/
|
|
431
|
+
declare const DIFFERENCE_IN_DAYS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
432
|
+
/**
|
|
433
|
+
* Get the difference in calendar weeks between two timestamps
|
|
434
|
+
* Counts the number of week boundaries crossed (based on calendar days)
|
|
435
|
+
*/
|
|
436
|
+
declare const DIFFERENCE_IN_WEEKS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
437
|
+
/**
|
|
438
|
+
* Get the number of full calendar months between two timestamps (local timezone)
|
|
439
|
+
* Counts complete months where the same day-of-month has been reached
|
|
440
|
+
*
|
|
441
|
+
* Examples:
|
|
442
|
+
* Jan 15 → Feb 14 = 0 months (Feb 15 not reached yet)
|
|
443
|
+
* Jan 15 → Feb 15 = 1 month
|
|
444
|
+
* Jan 31 → Feb 28 = 0 months (Feb 31 doesn't exist)
|
|
445
|
+
* Jan 31 → Mar 31 = 2 months
|
|
446
|
+
*/
|
|
447
|
+
declare const DIFFERENCE_IN_MONTHS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
448
|
+
/**
|
|
449
|
+
* Get the number of full calendar years between two timestamps (local timezone)
|
|
450
|
+
* Counts complete years where the same month and day have been reached
|
|
451
|
+
*
|
|
452
|
+
* Examples:
|
|
453
|
+
* Jan 15, 2020 → Jan 14, 2021 = 0 years (Jan 15 not reached)
|
|
454
|
+
* Jan 15, 2020 → Jan 15, 2021 = 1 year
|
|
455
|
+
* Feb 29, 2020 → Feb 28, 2021 = 0 years (Feb 29 doesn't exist)
|
|
456
|
+
* Feb 29, 2020 → Mar 1, 2021 = 1 year
|
|
457
|
+
*/
|
|
458
|
+
declare const DIFFERENCE_IN_YEARS: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
459
|
+
/**
|
|
460
|
+
* Get the start of day (00:00:00.000 local time) for a given timestamp
|
|
461
|
+
*/
|
|
462
|
+
declare const START_OF_DAY: (timestamp: RuntimeValue) => RuntimeValue;
|
|
463
|
+
/**
|
|
464
|
+
* Get the end of day (23:59:59.999 local time) for a given timestamp
|
|
465
|
+
*/
|
|
466
|
+
declare const END_OF_DAY: (timestamp: RuntimeValue) => RuntimeValue;
|
|
467
|
+
/**
|
|
468
|
+
* Get the start of week (Sunday at 00:00:00.000 local time) for a given timestamp
|
|
469
|
+
*/
|
|
470
|
+
declare const START_OF_WEEK: (timestamp: RuntimeValue) => RuntimeValue;
|
|
471
|
+
/**
|
|
472
|
+
* Get the start of month (1st day at 00:00:00.000 local time) for a given timestamp
|
|
473
|
+
*/
|
|
474
|
+
declare const START_OF_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
|
|
475
|
+
/**
|
|
476
|
+
* Get the end of month (last day at 23:59:59.999 local time) for a given timestamp
|
|
477
|
+
*/
|
|
478
|
+
declare const END_OF_MONTH: (timestamp: RuntimeValue) => RuntimeValue;
|
|
479
|
+
/**
|
|
480
|
+
* Get the start of year (Jan 1st at 00:00:00.000 local time) for a given timestamp
|
|
481
|
+
*/
|
|
482
|
+
declare const START_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
|
|
483
|
+
/**
|
|
484
|
+
* Get the end of year (Dec 31st at 23:59:59.999 local time) for a given timestamp
|
|
485
|
+
*/
|
|
486
|
+
declare const END_OF_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
|
|
487
|
+
/**
|
|
488
|
+
* Add days to a timestamp (local timezone)
|
|
489
|
+
*/
|
|
490
|
+
declare const ADD_DAYS: (timestamp: RuntimeValue, days: RuntimeValue) => RuntimeValue;
|
|
491
|
+
/**
|
|
492
|
+
* Add months to a timestamp (handles variable month lengths correctly, local timezone)
|
|
493
|
+
*/
|
|
494
|
+
declare const ADD_MONTHS: (timestamp: RuntimeValue, months: RuntimeValue) => RuntimeValue;
|
|
495
|
+
/**
|
|
496
|
+
* Add years to a timestamp (local timezone)
|
|
497
|
+
*/
|
|
498
|
+
declare const ADD_YEARS: (timestamp: RuntimeValue, years: RuntimeValue) => RuntimeValue;
|
|
499
|
+
/**
|
|
500
|
+
* Check if two timestamps are on the same calendar day (local timezone)
|
|
501
|
+
* Returns 1 if true, 0 if false
|
|
502
|
+
*/
|
|
503
|
+
declare const IS_SAME_DAY: (ts1: RuntimeValue, ts2: RuntimeValue) => RuntimeValue;
|
|
504
|
+
/**
|
|
505
|
+
* Check if timestamp falls on a weekend (Saturday or Sunday, local timezone)
|
|
506
|
+
* Returns 1 if true, 0 if false
|
|
507
|
+
*/
|
|
508
|
+
declare const IS_WEEKEND: (timestamp: RuntimeValue) => RuntimeValue;
|
|
509
|
+
/**
|
|
510
|
+
* Check if timestamp is in a leap year (local timezone)
|
|
511
|
+
* Returns 1 if true, 0 if false
|
|
512
|
+
*/
|
|
513
|
+
declare const IS_LEAP_YEAR: (timestamp: RuntimeValue) => RuntimeValue;
|
|
514
|
+
/**
|
|
515
|
+
* Get the start of quarter for a given timestamp (local timezone)
|
|
516
|
+
*/
|
|
517
|
+
declare const START_OF_QUARTER: (timestamp: RuntimeValue) => RuntimeValue;
|
|
518
|
+
declare namespace exports_math {
|
|
519
|
+
export { TAN, SQRT, SIN, ROUND, MIN, MAX, LOG10, LOG, FLOOR, EXP, COS, CLAMP, CEIL, ABS };
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Math utility functions
|
|
523
|
+
* All functions work with numbers only
|
|
524
|
+
*/
|
|
525
|
+
/**
|
|
526
|
+
* Constrain a value between a minimum and maximum
|
|
527
|
+
* @example CLAMP(value, 0, 100) - Clamps value between 0 and 100
|
|
528
|
+
*/
|
|
529
|
+
declare const CLAMP: (value: RuntimeValue, min: RuntimeValue, max: RuntimeValue) => RuntimeValue;
|
|
530
|
+
declare const ABS: (x: RuntimeValue) => RuntimeValue;
|
|
531
|
+
declare const CEIL: (x: RuntimeValue) => RuntimeValue;
|
|
532
|
+
declare const FLOOR: (x: RuntimeValue) => RuntimeValue;
|
|
533
|
+
declare const ROUND: (x: RuntimeValue) => RuntimeValue;
|
|
534
|
+
declare const SQRT: (x: RuntimeValue) => RuntimeValue;
|
|
535
|
+
declare const MIN: (...values: RuntimeValue[]) => RuntimeValue;
|
|
536
|
+
declare const MAX: (...values: RuntimeValue[]) => RuntimeValue;
|
|
537
|
+
declare const SIN: (x: RuntimeValue) => RuntimeValue;
|
|
538
|
+
declare const COS: (x: RuntimeValue) => RuntimeValue;
|
|
539
|
+
declare const TAN: (x: RuntimeValue) => RuntimeValue;
|
|
540
|
+
declare const LOG: (x: RuntimeValue) => RuntimeValue;
|
|
541
|
+
declare const LOG10: (x: RuntimeValue) => RuntimeValue;
|
|
542
|
+
declare const EXP: (x: RuntimeValue) => RuntimeValue;
|
|
543
|
+
/**
|
|
544
|
+
* Default execution context with standard library functions
|
|
545
|
+
* Users can use this as-is or spread it into their own context
|
|
546
|
+
*
|
|
547
|
+
* All functions use UPPERCASE naming convention to avoid collisions with user variables.
|
|
548
|
+
* All date-related functions work with timestamps (milliseconds since Unix epoch)
|
|
549
|
+
* to maintain the language's numbers-only type system.
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* // Use as-is
|
|
553
|
+
* execute('ABS(-5)', defaultContext)
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* // Spread into custom context
|
|
557
|
+
* execute('NOW() + FROM_MINUTES(5)', {
|
|
558
|
+
* ...defaultContext,
|
|
559
|
+
* variables: { customVar: 42 }
|
|
560
|
+
* })
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* // Work with timestamps
|
|
564
|
+
* const result = execute('NOW() + FROM_DAYS(7)', defaultContext)
|
|
565
|
+
* const futureDate = new Date(result) // Convert back to Date if needed
|
|
566
|
+
*
|
|
567
|
+
* @example
|
|
568
|
+
* // Calculate time differences
|
|
569
|
+
* const ts1 = Date.now()
|
|
570
|
+
* const ts2 = ts1 + 1000 * 60 * 60 * 3 // 3 hours later
|
|
571
|
+
* execute('DIFFERENCE_IN_HOURS(ts1, ts2)', { ...defaultContext, variables: { ts1, ts2 } })
|
|
572
|
+
*/
|
|
573
|
+
declare const defaultContext: ExecutionContext;
|
|
404
574
|
/**
|
|
405
575
|
* Type-safe visitor pattern for AST traversal.
|
|
406
576
|
*
|
|
@@ -593,4 +763,4 @@ declare function visit<T>(node: ASTNode, visitor: Visitor<T>): T;
|
|
|
593
763
|
* )
|
|
594
764
|
*/
|
|
595
765
|
declare function visitPartial<T>(node: ASTNode, visitor: Partial<Visitor<T>>, defaultHandler: (node: ASTNode, recurse: (n: ASTNode) => T) => T): T;
|
|
596
|
-
export { visitPartial, visit, parse, optimize, isUnaryOp, isProgram, isNumberLiteral, isIdentifier, isFunctionCall, isConditionalExpression, isBinaryOp, isAssignment, humanize, generate, extractInputVariables, evaluate, defaultContext, exports_ast as ast, Visitor, UnaryOp,
|
|
766
|
+
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, exports_ast as ast, Visitor, UnaryOp, RuntimeValue, Program, Operator, NumberLiteral, NodeKind, Identifier, HumanizeOptions, FunctionCall, ExecutionContext, ConditionalExpression, BinaryOp, Assignment, ASTNode };
|