@enspirit/elo 0.9.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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +322 -0
  3. package/bin/elo +2 -0
  4. package/bin/eloc +2 -0
  5. package/dist/src/ast.d.ts +309 -0
  6. package/dist/src/ast.d.ts.map +1 -0
  7. package/dist/src/ast.js +173 -0
  8. package/dist/src/ast.js.map +1 -0
  9. package/dist/src/bindings/javascript.d.ts +17 -0
  10. package/dist/src/bindings/javascript.d.ts.map +1 -0
  11. package/dist/src/bindings/javascript.js +350 -0
  12. package/dist/src/bindings/javascript.js.map +1 -0
  13. package/dist/src/bindings/ruby.d.ts +20 -0
  14. package/dist/src/bindings/ruby.d.ts.map +1 -0
  15. package/dist/src/bindings/ruby.js +365 -0
  16. package/dist/src/bindings/ruby.js.map +1 -0
  17. package/dist/src/bindings/sql.d.ts +20 -0
  18. package/dist/src/bindings/sql.d.ts.map +1 -0
  19. package/dist/src/bindings/sql.js +319 -0
  20. package/dist/src/bindings/sql.js.map +1 -0
  21. package/dist/src/cli.d.ts +3 -0
  22. package/dist/src/cli.d.ts.map +1 -0
  23. package/dist/src/cli.js +225 -0
  24. package/dist/src/cli.js.map +1 -0
  25. package/dist/src/compile.d.ts +47 -0
  26. package/dist/src/compile.d.ts.map +1 -0
  27. package/dist/src/compile.js +55 -0
  28. package/dist/src/compile.js.map +1 -0
  29. package/dist/src/compilers/javascript.d.ts +41 -0
  30. package/dist/src/compilers/javascript.d.ts.map +1 -0
  31. package/dist/src/compilers/javascript.js +323 -0
  32. package/dist/src/compilers/javascript.js.map +1 -0
  33. package/dist/src/compilers/ruby.d.ts +40 -0
  34. package/dist/src/compilers/ruby.d.ts.map +1 -0
  35. package/dist/src/compilers/ruby.js +326 -0
  36. package/dist/src/compilers/ruby.js.map +1 -0
  37. package/dist/src/compilers/sql.d.ts +37 -0
  38. package/dist/src/compilers/sql.d.ts.map +1 -0
  39. package/dist/src/compilers/sql.js +164 -0
  40. package/dist/src/compilers/sql.js.map +1 -0
  41. package/dist/src/elo.d.ts +3 -0
  42. package/dist/src/elo.d.ts.map +1 -0
  43. package/dist/src/elo.js +187 -0
  44. package/dist/src/elo.js.map +1 -0
  45. package/dist/src/eloc.d.ts +3 -0
  46. package/dist/src/eloc.d.ts.map +1 -0
  47. package/dist/src/eloc.js +232 -0
  48. package/dist/src/eloc.js.map +1 -0
  49. package/dist/src/eval.d.ts +3 -0
  50. package/dist/src/eval.d.ts.map +1 -0
  51. package/dist/src/eval.js +196 -0
  52. package/dist/src/eval.js.map +1 -0
  53. package/dist/src/index.d.ts +17 -0
  54. package/dist/src/index.d.ts.map +1 -0
  55. package/dist/src/index.js +36 -0
  56. package/dist/src/index.js.map +1 -0
  57. package/dist/src/ir.d.ts +295 -0
  58. package/dist/src/ir.d.ts.map +1 -0
  59. package/dist/src/ir.js +224 -0
  60. package/dist/src/ir.js.map +1 -0
  61. package/dist/src/parser.d.ts +137 -0
  62. package/dist/src/parser.d.ts.map +1 -0
  63. package/dist/src/parser.js +1266 -0
  64. package/dist/src/parser.js.map +1 -0
  65. package/dist/src/preludes/index.d.ts +14 -0
  66. package/dist/src/preludes/index.d.ts.map +1 -0
  67. package/dist/src/preludes/index.js +27 -0
  68. package/dist/src/preludes/index.js.map +1 -0
  69. package/dist/src/runtime.d.ts +23 -0
  70. package/dist/src/runtime.d.ts.map +1 -0
  71. package/dist/src/runtime.js +326 -0
  72. package/dist/src/runtime.js.map +1 -0
  73. package/dist/src/stdlib.d.ts +121 -0
  74. package/dist/src/stdlib.d.ts.map +1 -0
  75. package/dist/src/stdlib.js +237 -0
  76. package/dist/src/stdlib.js.map +1 -0
  77. package/dist/src/transform.d.ts +38 -0
  78. package/dist/src/transform.d.ts.map +1 -0
  79. package/dist/src/transform.js +322 -0
  80. package/dist/src/transform.js.map +1 -0
  81. package/dist/src/typedefs.d.ts +50 -0
  82. package/dist/src/typedefs.d.ts.map +1 -0
  83. package/dist/src/typedefs.js +294 -0
  84. package/dist/src/typedefs.js.map +1 -0
  85. package/dist/src/types.d.ts +54 -0
  86. package/dist/src/types.d.ts.map +1 -0
  87. package/dist/src/types.js +62 -0
  88. package/dist/src/types.js.map +1 -0
  89. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Bernard Lambeau
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,322 @@
1
+ # What is Elo ?
2
+
3
+ [![CI](https://github.com/enspirit/elo/actions/workflows/ci.yml/badge.svg)](https://github.com/enspirit/elo/actions/workflows/ci.yml)
4
+
5
+ A simple, well-designed, portable and safe data expression language that
6
+ compiles to Ruby, Javascript and PostgreSQL.
7
+
8
+ **[Try Elo online](https://elo-lang.org/)** - Interactive playground and documentation
9
+
10
+ ## Why ?
11
+
12
+ No-Code tools like Klaro Cards generally require an expression language for user
13
+ to manipulate data easily. This language must be :
14
+
15
+ - simple, because No-Code tools are used by non-tech people
16
+ - portable, because they are implemented in various frontend/backend/db technologies
17
+ - safe, because end-users writing code yield serious security issues
18
+ - well-designed, because there are too many ill-designed programming languages already
19
+
20
+ See also the Related work section below.
21
+
22
+ ## Current Features
23
+
24
+ - **Arithmetic expressions** with scalars and variables
25
+ - **Boolean expressions** with comparison and logical operators
26
+ - **Temporal types** with dates, datetimes, and ISO8601 durations
27
+ - **Infix notation** (standard mathematical notation)
28
+ - **Arithmetic operators**: `+`, `-`, `*`, `/`, `%`, `^` (power, plus string repeat and array concat)
29
+ - **Comparison operators**: `<`, `>`, `<=`, `>=`, `==`, `!=`
30
+ - **Logical operators**: `&&`, `||`, `!`
31
+ - **Unary operators**: `-`, `+`, `!`
32
+ - **Pipe operator**: `|>` for function chaining (Elixir-style), parentheses optional
33
+ - **Alternative operator**: `|` for fallback chains (returns first defined value)
34
+ - **Type selectors**: `Int()`, `Float()`, `Bool()`, `Date()`, `Datetime()`, `Duration()`, `Data()` for parsing strings to typed values
35
+ - **Type definitions**: Finitio-like schema validation with `let Person = { name: String, age: Int } in data |> Person`
36
+ - **Lambdas**: `fn(x ~> x * 2)` or `x ~> x * 2` (sugar) for anonymous functions
37
+ - **Input variable**: `_` for accessing external data passed to expressions
38
+ - **Array iteration**: `map`, `filter`, `reduce`, `any`, `all` (JS/Ruby only)
39
+ - **List functions**: `reverse`, `join(list, separator)`, `split(string, separator)`
40
+ - **Literals**:
41
+ - Numbers: `42`, `3.14`
42
+ - Booleans: `true`, `false`
43
+ - Strings: `'hello'`
44
+ - Null: `null`
45
+ - Dates: `D2024-01-15`
46
+ - DateTimes: `D2024-01-15T10:30:00Z`
47
+ - Durations: `P1D`, `PT1H30M`, `P1Y2M3D` (ISO8601)
48
+ - Objects: `{name: 'Alice', age: 30}`
49
+ - Arrays: `[1, 2, 3]`, `['a', 'b']`, `[1, 'mixed', true, null]`
50
+ - DataPaths: `.x.y.z`, `.items.0.name` (for navigating data structures)
51
+ - **Data functions**: `fetch(data, .path)` for safe access with null handling, `patch(data, .path, value)` for immutable updates, `merge(a, b)` and `deepMerge(a, b)` for merging objects
52
+ - **Parentheses** for grouping
53
+ - **Multi-target compilation**:
54
+ - Ruby (using `**` for power, `&&`/`||`/`!` for boolean logic, `Date.parse()`, `DateTime.parse()`, `ActiveSupport::Duration.parse()`)
55
+ - JavaScript (using `Math.pow()` for power, `&&`/`||`/`!` for boolean logic, `new Date()`, `Duration.parse()`)
56
+ - PostgreSQL (using `POWER()` for power, `AND`/`OR`/`NOT` for boolean logic, `DATE`, `TIMESTAMP`, `INTERVAL` for temporals)
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ npm install
62
+ npm run build
63
+ ```
64
+
65
+ ## Testing
66
+
67
+ Elo uses a comprehensive test suite that verifies:
68
+ - **Unit tests**: Parser, AST, and compiler components
69
+ - **Integration tests**: End-to-end compilation output
70
+ - **Acceptance tests**: Compiled code execution in real runtimes (Ruby, Node.js, PostgreSQL)
71
+
72
+ ```bash
73
+ npm run test:unit
74
+ npm run test:integration
75
+ npm run test:acceptance
76
+ ```
77
+
78
+ ## Command Line Interface
79
+
80
+ Elo provides two CLI tools:
81
+ - `eloc` - The compiler (for developers integrating Elo into their products)
82
+ - `elo` - The evaluator (for quickly running Elo expressions)
83
+
84
+ ### Compiler (eloc)
85
+
86
+ The compiler translates Elo expressions to Ruby, JavaScript, or SQL:
87
+
88
+ ```bash
89
+ # Compile expression to JavaScript (default)
90
+ ./bin/eloc -e "2 + 3 * 4"
91
+
92
+ # Compile expression to Ruby
93
+ ./bin/eloc -e "2 + 3 * 4" -t ruby
94
+
95
+ # Compile expression to SQL
96
+ ./bin/eloc -e "2 + 3 * 4" -t sql
97
+
98
+ # Compile with prelude (includes required runtime libraries)
99
+ ./bin/eloc -e "NOW + PT2H" -t ruby -p
100
+
101
+ # Output only the prelude (useful for bundling)
102
+ ./bin/eloc --prelude-only -t js
103
+
104
+ # Compile from file (each line is compiled separately)
105
+ ./bin/eloc input.elo -t ruby
106
+
107
+ # Compile to file
108
+ ./bin/eloc -e "2 + 3" -t ruby -f output.rb
109
+
110
+ # Compile from stdin
111
+ echo "2 + 3 * 4" | ./bin/eloc -
112
+ cat input.elo | ./bin/eloc - -t ruby
113
+ ```
114
+
115
+ Options:
116
+ - `-e, --expression <expr>` - Expression to compile
117
+ - `-t, --target <lang>` - Target language: `ruby`, `js` (default), `sql`
118
+ - `-p, --prelude` - Include necessary library imports/requires
119
+ - `--prelude-only` - Output only the prelude (no expression needed)
120
+ - `-f, --file <path>` - Output to file instead of stdout
121
+ - `-h, --help` - Show help message
122
+
123
+ ### Evaluator (elo)
124
+
125
+ The evaluator compiles to JavaScript and immediately evaluates the expression:
126
+
127
+ ```bash
128
+ # Evaluate a simple expression
129
+ ./bin/elo -e "2 + 3 * 4"
130
+ # Outputs: 14
131
+
132
+ # Evaluate with input data
133
+ ./bin/elo -e "_.x + _.y" -d '{"x": 1, "y": 2}'
134
+ # Outputs: 3
135
+
136
+ # Evaluate with data from file
137
+ ./bin/elo -e "_.name" -d @data.json
138
+
139
+ # Evaluate from .elo file
140
+ ./bin/elo expressions.elo
141
+
142
+ # Pipe data through stdin
143
+ echo '{"x": 10}' | ./bin/elo -e "_.x * 2" --stdin
144
+ # Outputs: 20
145
+ ```
146
+
147
+ Options:
148
+ - `-e, --expression <expr>` - Expression to evaluate
149
+ - `-d, --data <json>` - JSON input data for `_` variable (or `@file` to read from file)
150
+ - `--stdin` - Read input data as JSON from stdin
151
+ - `-h, --help` - Show help message
152
+
153
+ ## Using Elo in JavaScript/TypeScript
154
+
155
+ The simplest way to use Elo is with the `compile()` function, which creates a callable JavaScript function from an Elo lambda expression:
156
+
157
+ ```typescript
158
+ import { compile } from '@enspirit/elo';
159
+ import { DateTime, Duration } from 'luxon';
160
+
161
+ // Compile a lambda to a callable function
162
+ const double = compile<(x: number) => number>(
163
+ 'fn(x ~> x * 2)',
164
+ { runtime: { DateTime, Duration } }
165
+ );
166
+ double(21); // => 42
167
+
168
+ // Temporal expressions work too
169
+ const inThisWeek = compile<(d: unknown) => boolean>(
170
+ 'fn(d ~> d in SOW ... EOW)',
171
+ { runtime: { DateTime, Duration } }
172
+ );
173
+ inThisWeek(DateTime.now()); // => true or false
174
+ ```
175
+
176
+ The `runtime` option injects dependencies (like `DateTime` and `Duration` from luxon) into the compiled function. This avoids global variables and keeps the compiled code portable.
177
+
178
+ ## Lower-Level API
179
+
180
+ For more control, you can use the lower-level parsing and compilation functions:
181
+
182
+ ```typescript
183
+ import { parse, compileToRuby, compileToJavaScript, compileToSQL } from '@enspirit/elo';
184
+
185
+ // Parse an expression
186
+ const ast = parse(`
187
+ let
188
+ x = TODAY,
189
+ y = 3
190
+ in
191
+ assert(x + y * P1D == TODAY + P3D)
192
+ `);
193
+
194
+ // Compile to different targets
195
+ console.log(compileToRuby(ast));
196
+ console.log(compileToJavaScript(ast));
197
+ console.log(compileToSQL(ast));
198
+ ```
199
+
200
+ ## Programmatic AST Construction
201
+
202
+ ```typescript
203
+ import { binary, variable, literal } from './src';
204
+
205
+ // Build: (price * quantity) - discount
206
+ const ast = binary(
207
+ '-',
208
+ binary('*', variable('price'), variable('quantity')),
209
+ variable('discount')
210
+ );
211
+ ```
212
+
213
+ ## Examples
214
+
215
+ Run the examples:
216
+
217
+ ```bash
218
+ npm run build
219
+ node dist/examples/basic.js # Arithmetic expressions
220
+ node dist/examples/boolean.js # Boolean expressions
221
+ node dist/examples/temporal.js # Temporal expressions (dates, durations)
222
+ node dist/examples/demo.js # Quick demo
223
+ ```
224
+
225
+ ## Project Structure
226
+
227
+ ```
228
+ elo/
229
+ ├── src/ # Compiler source code
230
+ │ ├── parser.ts # Lexer and parser
231
+ │ ├── ast.ts # AST definitions
232
+ │ ├── types.ts # Type system
233
+ │ ├── ir.ts # Intermediate representation
234
+ │ ├── transform.ts # AST → IR transformation with type inference
235
+ │ ├── stdlib.ts # Standard library abstraction
236
+ │ ├── compilers/ # Code generators (Ruby, JavaScript, SQL)
237
+ │ └── preludes/ # Runtime support libraries
238
+ ├── test/ # Test suite
239
+ │ ├── fixtures/ # Test cases
240
+ │ ├── unit/ # Component tests
241
+ │ ├── integration/ # Compilation tests
242
+ │ └── acceptance/ # Runtime execution tests
243
+ ├── examples/ # Usage examples
244
+ ├── bin/eloc # Compiler CLI
245
+ ├── bin/elo # Evaluator CLI
246
+ └── CLAUDE.md # Developer guide
247
+ ```
248
+
249
+ For detailed architecture documentation, see [CLAUDE.md](CLAUDE.md).
250
+
251
+ ## Related work
252
+
253
+ Enspirit's previous research work includes a lot of places where such expressions
254
+ are used, calling for a shared solution for the future.
255
+
256
+ In many cases, observe that we require compiling expressions that amount to a
257
+ single function evaluating on a context object, sometimes a scalar (Finitio),
258
+ sometimes a current Tuple (Bmg), sometimes json data received from an API
259
+ (Webspicy), or a current Card (Klaro Cards, similar to Bmg's Tuple).
260
+
261
+ See https://elo-lang.org for more documentation.
262
+
263
+ ### Finitio
264
+
265
+ The Finitio data validation language supports subtypes by constraints such as:
266
+
267
+ ```finitio
268
+ PositiveInt = Int( i | i > 0 )
269
+ ```
270
+
271
+ Currently, the constraint expression is written in the host language (js or ruby)
272
+ and would require a portable expression language to go further.
273
+
274
+ See https://finitio.io, https://github.com/enspirit/finitio-rb, https://github.com/enspirit/finitio.js
275
+
276
+ ### Bmg
277
+
278
+ The Bmg relational algebra requires expressions for the `restrict` and `extend`
279
+ operators inspired by **Tutorial D**. We currently rely on ruby code in some cases,
280
+ but that prevents compiling relational expressions to SQL :
281
+
282
+ ```ruby
283
+ r.restrict(->(t){ t[:budget] >= 120 })
284
+ r.extend(:upcased => ->(t) { t[:name].upcase })
285
+ ```
286
+
287
+ See https://www.relational-algebra.dev/, https://github.com/enspirit/bmg
288
+
289
+ ### Webspicy
290
+
291
+ The Webspicy test framework requires a better expression language for data assertions.
292
+ We currently rely on an hardcoded expression language that is very limited:
293
+
294
+ ```
295
+ assert:
296
+ - isEmpty
297
+ - size(10)
298
+ ```
299
+
300
+ See https://github.com/enspirit/webspicy
301
+
302
+ ### Klaro Cards
303
+
304
+ The Klaro Cards No-Code tool uses various data expressions here and there :
305
+
306
+ - Date ranges for Date/time dimensions : `SOW ... SOW+P1W`
307
+ - Computed dimensions : `_.budget * 1.21`
308
+ - Summary functions : `min(_.budget)`
309
+
310
+ See https://klaro.cards
311
+
312
+ ## Contributing
313
+
314
+ Elo follows a strict test-driven development methodology to ensure semantic equivalence across all three target languages (Ruby, JavaScript, SQL).
315
+
316
+ **For developers and AI assistants**: See [CLAUDE.md](CLAUDE.md) for:
317
+ - Test-driven development workflow
318
+ - Three-stage test methodology (unit → integration → acceptance)
319
+ - How to add new features and operators
320
+ - Architecture documentation
321
+ - Troubleshooting guide
322
+
package/bin/elo ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/src/elo.js');
package/bin/eloc ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/src/eloc.js');
@@ -0,0 +1,309 @@
1
+ /**
2
+ * AST node types for Elo expressions
3
+ */
4
+ export type Expr = Literal | NullLiteral | StringLiteral | Variable | BinaryOp | UnaryOp | DateLiteral | DateTimeLiteral | DurationLiteral | TemporalKeyword | FunctionCall | MemberAccess | LetExpr | IfExpr | Lambda | ObjectLiteral | ArrayLiteral | Alternative | Apply | DataPath | TypeDef;
5
+ /**
6
+ * Literal value (number or boolean)
7
+ */
8
+ export interface Literal {
9
+ type: 'literal';
10
+ value: number | boolean;
11
+ }
12
+ /**
13
+ * Null literal
14
+ */
15
+ export interface NullLiteral {
16
+ type: 'null';
17
+ }
18
+ /**
19
+ * String literal (single-quoted)
20
+ */
21
+ export interface StringLiteral {
22
+ type: 'string';
23
+ value: string;
24
+ }
25
+ /**
26
+ * Date literal (ISO8601 date string)
27
+ */
28
+ export interface DateLiteral {
29
+ type: 'date';
30
+ value: string;
31
+ }
32
+ /**
33
+ * DateTime literal (ISO8601 datetime string)
34
+ */
35
+ export interface DateTimeLiteral {
36
+ type: 'datetime';
37
+ value: string;
38
+ }
39
+ /**
40
+ * Duration literal (ISO8601 duration)
41
+ */
42
+ export interface DurationLiteral {
43
+ type: 'duration';
44
+ value: string;
45
+ }
46
+ /**
47
+ * Temporal keyword (NOW, TODAY, TOMORROW, YESTERDAY, and period boundaries)
48
+ */
49
+ export interface TemporalKeyword {
50
+ type: 'temporal_keyword';
51
+ keyword: 'NOW' | 'TODAY' | 'TOMORROW' | 'YESTERDAY' | 'SOD' | 'EOD' | 'SOW' | 'EOW' | 'SOM' | 'EOM' | 'SOQ' | 'EOQ' | 'SOY' | 'EOY' | 'BOT' | 'EOT';
52
+ }
53
+ /**
54
+ * Variable reference
55
+ */
56
+ export interface Variable {
57
+ type: 'variable';
58
+ name: string;
59
+ }
60
+ /**
61
+ * Binary operation
62
+ */
63
+ export interface BinaryOp {
64
+ type: 'binary';
65
+ operator: '+' | '-' | '*' | '/' | '%' | '^' | '<' | '>' | '<=' | '>=' | '==' | '!=' | '&&' | '||';
66
+ left: Expr;
67
+ right: Expr;
68
+ }
69
+ /**
70
+ * Unary operation
71
+ */
72
+ export interface UnaryOp {
73
+ type: 'unary';
74
+ operator: '-' | '+' | '!';
75
+ operand: Expr;
76
+ }
77
+ /**
78
+ * Function call
79
+ */
80
+ export interface FunctionCall {
81
+ type: 'function_call';
82
+ name: string;
83
+ args: Expr[];
84
+ }
85
+ /**
86
+ * Function application (calling an expression that evaluates to a function)
87
+ */
88
+ export interface Apply {
89
+ type: 'apply';
90
+ fn: Expr;
91
+ args: Expr[];
92
+ }
93
+ /**
94
+ * Member access (dot notation)
95
+ */
96
+ export interface MemberAccess {
97
+ type: 'member_access';
98
+ object: Expr;
99
+ property: string;
100
+ }
101
+ /**
102
+ * Variable binding in a let expression
103
+ */
104
+ export interface LetBinding {
105
+ name: string;
106
+ value: Expr;
107
+ }
108
+ /**
109
+ * Let expression: let x = 1, y = 2 in body
110
+ */
111
+ export interface LetExpr {
112
+ type: 'let';
113
+ bindings: LetBinding[];
114
+ body: Expr;
115
+ }
116
+ /**
117
+ * If expression: if condition then consequent else alternative
118
+ */
119
+ export interface IfExpr {
120
+ type: 'if';
121
+ condition: Expr;
122
+ then: Expr;
123
+ else: Expr;
124
+ }
125
+ /**
126
+ * Lambda expression: fn( params ~> body )
127
+ */
128
+ export interface Lambda {
129
+ type: 'lambda';
130
+ params: string[];
131
+ body: Expr;
132
+ }
133
+ /**
134
+ * Helper functions to create AST nodes
135
+ */
136
+ export declare function literal(value: number | boolean): Literal;
137
+ export declare function nullLiteral(): NullLiteral;
138
+ export declare function stringLiteral(value: string): StringLiteral;
139
+ export declare function dateLiteral(value: string): DateLiteral;
140
+ export declare function dateTimeLiteral(value: string): DateTimeLiteral;
141
+ export declare function durationLiteral(value: string): DurationLiteral;
142
+ export declare function variable(name: string): Variable;
143
+ export declare function binary(operator: BinaryOp['operator'], left: Expr, right: Expr): BinaryOp;
144
+ export declare function unary(operator: UnaryOp['operator'], operand: Expr): UnaryOp;
145
+ export declare function temporalKeyword(keyword: TemporalKeyword['keyword']): TemporalKeyword;
146
+ export declare function functionCall(name: string, args: Expr[]): FunctionCall;
147
+ export declare function apply(fn: Expr, args: Expr[]): Apply;
148
+ export declare function memberAccess(object: Expr, property: string): MemberAccess;
149
+ /**
150
+ * Creates a let expression, desugaring multiple bindings into nested let expressions.
151
+ * `let a = 1, b = 2 in body` becomes `let a = 1 in let b = 2 in body`
152
+ * This ensures that later bindings can reference earlier ones.
153
+ */
154
+ export declare function letExpr(bindings: LetBinding[], body: Expr): LetExpr;
155
+ /**
156
+ * Creates an if expression: if condition then consequent else alternative
157
+ */
158
+ export declare function ifExpr(condition: Expr, thenBranch: Expr, elseBranch: Expr): IfExpr;
159
+ /**
160
+ * Creates a lambda expression: fn( params ~> body )
161
+ */
162
+ export declare function lambda(params: string[], body: Expr): Lambda;
163
+ /**
164
+ * Object property (key-value pair)
165
+ */
166
+ export interface ObjectProperty {
167
+ key: string;
168
+ value: Expr;
169
+ }
170
+ /**
171
+ * Object literal: {key: value, ...}
172
+ */
173
+ export interface ObjectLiteral {
174
+ type: 'object';
175
+ properties: ObjectProperty[];
176
+ }
177
+ /**
178
+ * Creates an object literal: {key: value, ...}
179
+ */
180
+ export declare function objectLiteral(properties: ObjectProperty[]): ObjectLiteral;
181
+ /**
182
+ * Array literal: [expr, expr, ...]
183
+ */
184
+ export interface ArrayLiteral {
185
+ type: 'array';
186
+ elements: Expr[];
187
+ }
188
+ /**
189
+ * Creates an array literal: [expr, expr, ...]
190
+ */
191
+ export declare function arrayLiteral(elements: Expr[]): ArrayLiteral;
192
+ /**
193
+ * Alternative expression: a | b | c
194
+ * Evaluates alternatives left-to-right, returns first non-null value.
195
+ */
196
+ export interface Alternative {
197
+ type: 'alternative';
198
+ alternatives: Expr[];
199
+ }
200
+ /**
201
+ * Creates an alternative expression: a | b | c
202
+ */
203
+ export declare function alternative(alternatives: Expr[]): Alternative;
204
+ /**
205
+ * DataPath literal: .x.y.z or .items.0.name
206
+ * A path for navigating data structures, inspired by JSONPath.
207
+ * Segments can be property names (strings) or array indices (numbers).
208
+ */
209
+ export interface DataPath {
210
+ type: 'datapath';
211
+ segments: (string | number)[];
212
+ }
213
+ /**
214
+ * Creates a datapath literal: .x.y.z
215
+ */
216
+ export declare function dataPath(segments: (string | number)[]): DataPath;
217
+ /**
218
+ * Type expression for type definitions
219
+ * Used in `let Person = { name: String, age: Int }` style declarations
220
+ */
221
+ export type TypeExpr = TypeRef | TypeSchema | SubtypeConstraint | ArrayType | UnionType;
222
+ /**
223
+ * Reference to a base type: String, Int, Bool, Datetime, Any
224
+ */
225
+ export interface TypeRef {
226
+ kind: 'type_ref';
227
+ name: string;
228
+ }
229
+ /**
230
+ * Object type schema: { name: String, age: Int }
231
+ * extras controls handling of extra attributes:
232
+ * - undefined/'closed': extra attributes are not allowed (default)
233
+ * - 'ignored': extra attributes are allowed but not included in output
234
+ * - TypeExpr: extra attributes are allowed and must match this type
235
+ */
236
+ export interface TypeSchema {
237
+ kind: 'type_schema';
238
+ properties: TypeSchemaProperty[];
239
+ extras?: 'closed' | 'ignored' | TypeExpr;
240
+ }
241
+ /**
242
+ * Subtype constraint: Int(i | i > 0)
243
+ * A base type with a predicate constraint
244
+ */
245
+ export interface SubtypeConstraint {
246
+ kind: 'subtype_constraint';
247
+ baseType: TypeExpr;
248
+ variable: string;
249
+ constraint: Expr;
250
+ }
251
+ /**
252
+ * Array type: [Int], [String], [{ name: String }]
253
+ */
254
+ export interface ArrayType {
255
+ kind: 'array_type';
256
+ elementType: TypeExpr;
257
+ }
258
+ /**
259
+ * Union type: Int|String, String|Int|Bool
260
+ * Tries each type in order, returns first successful parse
261
+ */
262
+ export interface UnionType {
263
+ kind: 'union_type';
264
+ types: TypeExpr[];
265
+ }
266
+ /**
267
+ * Property in a type schema
268
+ */
269
+ export interface TypeSchemaProperty {
270
+ key: string;
271
+ typeExpr: TypeExpr;
272
+ optional?: boolean;
273
+ }
274
+ /**
275
+ * Type definition: let Person = { name: String, age: Int }
276
+ * Binds a type name (uppercase) to a type expression.
277
+ * The body can use the type via pipe: data |> Person
278
+ */
279
+ export interface TypeDef {
280
+ type: 'typedef';
281
+ name: string;
282
+ typeExpr: TypeExpr;
283
+ body: Expr;
284
+ }
285
+ /**
286
+ * Creates a type reference: String, Int, etc.
287
+ */
288
+ export declare function typeRef(name: string): TypeRef;
289
+ /**
290
+ * Creates a type schema: { name: String, age: Int }
291
+ */
292
+ export declare function typeSchema(properties: TypeSchemaProperty[], extras?: 'closed' | 'ignored' | TypeExpr): TypeSchema;
293
+ /**
294
+ * Creates a type definition expression
295
+ */
296
+ export declare function typeDef(name: string, typeExpr: TypeExpr, body: Expr): TypeDef;
297
+ /**
298
+ * Creates a subtype constraint: Int(i | i > 0)
299
+ */
300
+ export declare function subtypeConstraint(baseType: TypeExpr, variable: string, constraint: Expr): SubtypeConstraint;
301
+ /**
302
+ * Creates an array type: [Int]
303
+ */
304
+ export declare function arrayType(elementType: TypeExpr): ArrayType;
305
+ /**
306
+ * Creates a union type: Int|String
307
+ */
308
+ export declare function unionType(types: TypeExpr[]): UnionType;
309
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"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"}