@libdbm/libcel-ts 1.0.2-rc.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/LICENSE +20 -0
- package/README.md +288 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +740 -0
- package/dist/index.mjs +1414 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, gtnicol
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
11
|
+
|
|
12
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
13
|
+
|
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
15
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
17
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
18
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
19
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
20
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# libcel-ts - Common Expression Language for TypeScript
|
|
2
|
+
|
|
3
|
+
A complete TypeScript implementation of Google's [Common Expression Language (CEL)](https://github.com/google/cel-spec) specification, ported from the Java implementation.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
CEL is a non-Turing complete expression language designed for simplicity, speed, and safety. It's commonly used for evaluating user-provided expressions in a secure sandbox environment.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Complete CEL Implementation**: All CEL operators, functions, and macros
|
|
12
|
+
- **Type Safe**: Leverages TypeScript's type system with strict typing
|
|
13
|
+
- **High Performance**: Hand-written recursive descent parser with AST compilation
|
|
14
|
+
- **Extensible**: Easy to add custom functions
|
|
15
|
+
- **Well Tested**: 100+ comprehensive tests ensuring functional equivalence
|
|
16
|
+
- **Zero External Dependencies**: Pure TypeScript implementation (except dev dependencies)
|
|
17
|
+
- **Vite-Powered**: Modern tooling with fast builds and excellent DX
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @libdbm/libcel-ts
|
|
23
|
+
# or
|
|
24
|
+
pnpm add @libdbm/libcel-ts
|
|
25
|
+
# or
|
|
26
|
+
yarn add @libdbm/libcel-ts
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### Basic Usage
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { CEL } from '@libdbm/libcel-ts';
|
|
35
|
+
|
|
36
|
+
const cel = new CEL();
|
|
37
|
+
|
|
38
|
+
// Simple expression evaluation
|
|
39
|
+
console.log(cel.eval('2 + 3 * 4', {})); // 14
|
|
40
|
+
|
|
41
|
+
// Using variables
|
|
42
|
+
const vars = { name: 'Alice', age: 30 };
|
|
43
|
+
console.log(cel.eval('name + " is " + string(age) + " years old"', vars));
|
|
44
|
+
// Output: Alice is 30 years old
|
|
45
|
+
|
|
46
|
+
// Boolean logic
|
|
47
|
+
console.log(cel.eval('age >= 18 && age < 65', vars)); // true
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Compiling and Reusing Programs
|
|
51
|
+
|
|
52
|
+
For better performance when evaluating the same expression multiple times:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const cel = new CEL();
|
|
56
|
+
const program = cel.compile('price * quantity * (1 - discount)');
|
|
57
|
+
|
|
58
|
+
// Reuse with different variables
|
|
59
|
+
const result1 = program.evaluate({ price: 10, quantity: 5, discount: 0.1 });
|
|
60
|
+
const result2 = program.evaluate({ price: 20, quantity: 3, discount: 0.2 });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Working with Complex Data
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const cel = new CEL();
|
|
67
|
+
const data = {
|
|
68
|
+
user: {
|
|
69
|
+
name: 'Alice',
|
|
70
|
+
roles: ['admin', 'user'],
|
|
71
|
+
metadata: { active: true },
|
|
72
|
+
},
|
|
73
|
+
permissions: ['read', 'write', 'delete'],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Check complex conditions
|
|
77
|
+
const canDelete = cel.eval('"admin" in user.roles && "delete" in permissions', data);
|
|
78
|
+
// true
|
|
79
|
+
|
|
80
|
+
// Use macro functions
|
|
81
|
+
const users = [
|
|
82
|
+
{ name: 'Alice', active: true },
|
|
83
|
+
{ name: 'Bob', active: false },
|
|
84
|
+
{ name: 'Charlie', active: true },
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const activeNames = cel.eval('users.filter(u, u.active).map(u, u.name)', { users });
|
|
88
|
+
// ['Alice', 'Charlie']
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Custom Functions
|
|
92
|
+
|
|
93
|
+
Extend the standard library with custom functions:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { CEL, StandardFunctions } from '@libdbm/libcel-ts';
|
|
97
|
+
|
|
98
|
+
class CustomFunctions extends StandardFunctions {
|
|
99
|
+
callFunction(name: string, args: any[]): any {
|
|
100
|
+
if (name === 'reverse') {
|
|
101
|
+
return (args[0] as string).split('').reverse().join('');
|
|
102
|
+
}
|
|
103
|
+
return super.callFunction(name, args);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const cel = new CEL(new CustomFunctions());
|
|
108
|
+
console.log(cel.eval("reverse('hello')", {})); // "olleh"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Supported Features
|
|
112
|
+
|
|
113
|
+
### Literals
|
|
114
|
+
|
|
115
|
+
- Null: `null`
|
|
116
|
+
- Booleans: `true`, `false`
|
|
117
|
+
- Integers: `42`, `-7`, `0xFF` (hexadecimal)
|
|
118
|
+
- Unsigned: `42u`, `0xFFu`
|
|
119
|
+
- Doubles: `3.14`, `6.022e23`
|
|
120
|
+
- Strings: `"hello"`, `'world'`, `r"raw\nstring"`, `"""multi-line"""`
|
|
121
|
+
- Bytes: `b"data"`
|
|
122
|
+
- Lists: `[1, 2, 3]`
|
|
123
|
+
- Maps: `{"key": "value"}`
|
|
124
|
+
|
|
125
|
+
### Operators
|
|
126
|
+
|
|
127
|
+
- **Arithmetic**: `+`, `-`, `*`, `/`, `%`
|
|
128
|
+
- **Comparison**: `<`, `<=`, `>`, `>=`, `==`, `!=`
|
|
129
|
+
- **Logical**: `&&`, `||`, `!`
|
|
130
|
+
- **Conditional**: `condition ? trueValue : falseValue`
|
|
131
|
+
- **Membership**: `in` (for lists, maps, strings)
|
|
132
|
+
|
|
133
|
+
### Functions
|
|
134
|
+
|
|
135
|
+
- **Type conversions**: `int()`, `double()`, `string()`, `bool()`
|
|
136
|
+
- **Type checking**: `type()`
|
|
137
|
+
- **Collections**: `size()`, `has()`
|
|
138
|
+
- **String methods**: `contains()`, `startsWith()`, `endsWith()`, `toLowerCase()`, `toUpperCase()`, `trim()`, `replace()`, `split()`
|
|
139
|
+
- **Regex**: `matches()`
|
|
140
|
+
- **Math**: `max()`, `min()`
|
|
141
|
+
|
|
142
|
+
### Macro Functions
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// map - Transform each element
|
|
146
|
+
cel.eval('[1, 2, 3].map(x, x * 2)', {}); // [2, 4, 6]
|
|
147
|
+
|
|
148
|
+
// filter - Keep elements matching condition
|
|
149
|
+
cel.eval('[1, 2, 3, 4].filter(x, x % 2 == 0)', {}); // [2, 4]
|
|
150
|
+
|
|
151
|
+
// exists - Check if any element matches
|
|
152
|
+
cel.eval('[1, 2, 3].exists(x, x > 2)', {}); // true
|
|
153
|
+
|
|
154
|
+
// all - Check if all elements match
|
|
155
|
+
cel.eval('[1, 2, 3].all(x, x > 0)', {}); // true
|
|
156
|
+
|
|
157
|
+
// existsOne - Check if exactly one element matches
|
|
158
|
+
cel.eval('[1, 2, 3].existsOne(x, x == 2)', {}); // true
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Building
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Install dependencies
|
|
165
|
+
npm install
|
|
166
|
+
|
|
167
|
+
# Run tests
|
|
168
|
+
npm test
|
|
169
|
+
|
|
170
|
+
# Run tests with coverage
|
|
171
|
+
npm run test:coverage
|
|
172
|
+
|
|
173
|
+
# Build the library
|
|
174
|
+
npm run build
|
|
175
|
+
|
|
176
|
+
# Type check
|
|
177
|
+
npm run typecheck
|
|
178
|
+
|
|
179
|
+
# Lint and format
|
|
180
|
+
npm run lint
|
|
181
|
+
npm run format
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Testing
|
|
185
|
+
|
|
186
|
+
The project includes comprehensive test coverage:
|
|
187
|
+
|
|
188
|
+
- 32 parser tests
|
|
189
|
+
- 21 interpreter tests
|
|
190
|
+
- 50 integration tests
|
|
191
|
+
- All tests from the Java implementation ported and passing
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Run all tests
|
|
195
|
+
npm test
|
|
196
|
+
|
|
197
|
+
# Run tests in watch mode
|
|
198
|
+
npm run test:watch
|
|
199
|
+
|
|
200
|
+
# Generate coverage report
|
|
201
|
+
npm run test:coverage
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Architecture
|
|
205
|
+
|
|
206
|
+
- **expression.ts**: Abstract Syntax Tree (AST) with visitor pattern
|
|
207
|
+
- **parser.ts**: Hand-written recursive descent parser with integrated lexer
|
|
208
|
+
- **interpreter.ts**: AST evaluator using Visitor pattern
|
|
209
|
+
- **functions.ts**: Extensible function library
|
|
210
|
+
- **cel.ts**: Main API entry point
|
|
211
|
+
- **program.ts**: Compiled, reusable programs
|
|
212
|
+
|
|
213
|
+
## Functional Equivalence
|
|
214
|
+
|
|
215
|
+
This TypeScript implementation is functionally equivalent to the [Java libcel](https://github.com/libdbm/libcel-java) implementation:
|
|
216
|
+
|
|
217
|
+
- Same AST structure and expression types
|
|
218
|
+
- Identical parsing rules and operator precedence
|
|
219
|
+
- Same evaluation semantics
|
|
220
|
+
- Equivalent macro function behavior
|
|
221
|
+
- Compatible error handling
|
|
222
|
+
|
|
223
|
+
All tests from the Java version have been ported to ensure equivalence.
|
|
224
|
+
|
|
225
|
+
## Requirements
|
|
226
|
+
|
|
227
|
+
- Node.js 18+ or modern browser
|
|
228
|
+
- TypeScript 5.0+ (for development)
|
|
229
|
+
|
|
230
|
+
## API Documentation
|
|
231
|
+
|
|
232
|
+
### CEL Class
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
class CEL {
|
|
236
|
+
constructor(functions?: Functions | null);
|
|
237
|
+
compile(expression: string): Program;
|
|
238
|
+
eval(expression: string, variables?: Record<string, any>): any;
|
|
239
|
+
|
|
240
|
+
static compile(expression: string, functions: Functions): Program;
|
|
241
|
+
static eval(expression: string, functions: Functions, variables: Record<string, any>): any;
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Program Class
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
class Program {
|
|
249
|
+
evaluate(variables?: Record<string, any>): any;
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Functions Interface
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
interface Functions {
|
|
257
|
+
callFunction(name: string, args: any[]): any;
|
|
258
|
+
callMethod(target: any, method: string, args: any[]): any;
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Examples
|
|
263
|
+
|
|
264
|
+
See the [examples](./examples) directory for more detailed examples:
|
|
265
|
+
|
|
266
|
+
- [quickstart.ts](./examples/quickstart.ts) - Comprehensive usage examples
|
|
267
|
+
- [parser-example.ts](./examples/parser-example.ts) - Parser API demonstration
|
|
268
|
+
- [interpreter-example.ts](./examples/interpreter-example.ts) - Interpreter API demonstration
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
BSD 3-Clause License - see [LICENSE](./LICENSE) file for details.
|
|
273
|
+
|
|
274
|
+
## Acknowledgments
|
|
275
|
+
|
|
276
|
+
- Based on the [Common Expression Language](https://github.com/google/cel-spec) specification by Google
|
|
277
|
+
- Ported from the [Java libcel](https://github.com/libdbm/libcel-java) implementation
|
|
278
|
+
- Original [Dart libcel](https://pub.dev/packages/libcel) implementation
|
|
279
|
+
|
|
280
|
+
## Contributing
|
|
281
|
+
|
|
282
|
+
Contributions are welcome! Please feel free to submit issues or pull requests.
|
|
283
|
+
|
|
284
|
+
## Links
|
|
285
|
+
|
|
286
|
+
- [CEL Specification](https://github.com/google/cel-spec)
|
|
287
|
+
- [Java Implementation](https://github.com/libdbm/libcel-java)
|
|
288
|
+
- [Dart Implementation](https://pub.dev/packages/libcel)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class p extends Error{constructor(t,e,i){super(`${t} at ${e}:${i}`),this.line=e,this.column=i,this.name="ParseError"}}var s=(r=>(r.NULL="NULL",r.TRUE="TRUE",r.FALSE="FALSE",r.INT="INT",r.UINT="UINT",r.DOUBLE="DOUBLE",r.STRING="STRING",r.BYTES="BYTES",r.IDENTIFIER="IDENTIFIER",r.PLUS="PLUS",r.MINUS="MINUS",r.STAR="STAR",r.SLASH="SLASH",r.PERCENT="PERCENT",r.EQ="EQ",r.NE="NE",r.LT="LT",r.LE="LE",r.GT="GT",r.GE="GE",r.LOGICAL_AND="LOGICAL_AND",r.LOGICAL_OR="LOGICAL_OR",r.BANG="BANG",r.IN="IN",r.LPAREN="LPAREN",r.RPAREN="RPAREN",r.LBRACKET="LBRACKET",r.RBRACKET="RBRACKET",r.LBRACE="LBRACE",r.RBRACE="RBRACE",r.DOT="DOT",r.COMMA="COMMA",r.COLON="COLON",r.QUESTION="QUESTION",r.EOF="EOF",r))(s||{});class h{constructor(t,e,i,n){this.type=t,this.value=e,this.line=i,this.column=n}toString(){return`${this.type}(${this.value})`}}class H{constructor(t){this.input=t,this.position=0,this.line=1,this.column=1,this.lookahead=[]}next(){return this.lookahead.length>0?this.lookahead.shift():this.token()}peek(t){for(;this.lookahead.length<t;)this.lookahead.push(this.token());return this.lookahead[t-1]}step(){if(this.position>=this.input.length)return;const t=this.input[this.position];this.position++,t==="\r"?(this.position<this.input.length&&this.input[this.position]===`
|
|
2
|
+
`&&this.position++,this.line++,this.column=1):t===`
|
|
3
|
+
`?(this.line++,this.column=1):this.column++}forward(t){for(let e=0;e<t;e++)this.step()}token(){if(this.whitespace(),this.position>=this.input.length)return new h("EOF","",this.line,this.column);const t=this.position,e=this.line,i=this.column,n=this.input[this.position];switch(n){case"(":return this.step(),new h("LPAREN","(",e,i);case")":return this.step(),new h("RPAREN",")",e,i);case"[":return this.step(),new h("LBRACKET","[",e,i);case"]":return this.step(),new h("RBRACKET","]",e,i);case"{":return this.step(),new h("LBRACE","{",e,i);case"}":return this.step(),new h("RBRACE","}",e,i);case",":return this.step(),new h("COMMA",",",e,i);case".":return this.step(),new h("DOT",".",e,i);case":":return this.step(),new h("COLON",":",e,i);case"?":return this.step(),new h("QUESTION","?",e,i);case"+":return this.step(),new h("PLUS","+",e,i);case"*":return this.step(),new h("STAR","*",e,i);case"/":return this.step(),new h("SLASH","/",e,i);case"%":return this.step(),new h("PERCENT","%",e,i)}if(n==="&"&&this.peekChar()==="&")return this.forward(2),new h("LOGICAL_AND","&&",e,i);if(n==="|"&&this.peekChar()==="|")return this.forward(2),new h("LOGICAL_OR","||",e,i);if(n==="="&&this.peekChar()==="=")return this.forward(2),new h("EQ","==",e,i);if(n==="!"&&this.peekChar()==="=")return this.forward(2),new h("NE","!=",e,i);if(n==="<"&&this.peekChar()==="=")return this.forward(2),new h("LE","<=",e,i);if(n===">"&&this.peekChar()==="=")return this.forward(2),new h("GE",">=",e,i);if(n==="<")return this.step(),new h("LT","<",e,i);if(n===">")return this.step(),new h("GT",">",e,i);if(n==="!")return this.step(),new h("BANG","!",e,i);if(n==="-")return this.step(),new h("MINUS","-",e,i);if(n==='"'||n==="'")return this.string(e,i,t);if((n==="r"||n==="R")&&this.position+1<this.input.length){const o=this.input[this.position+1];if(o==='"'||o==="'")return this.string(e,i,t)}if((n==="b"||n==="B")&&this.position+1<this.input.length){const o=this.input[this.position+1];if(o==='"'||o==="'")return this.bytes(e,i,t)}if(this.isDigit(n))return this.number(e,i,t);if(this.isLetter(n)||n==="_")return this.identifier(e,i,t);throw new p(`Unexpected character: ${n}`,e,i)}string(t,e,i){let n=!1;if((this.input[this.position]==="r"||this.input[this.position]==="R")&&(n=!0,this.step()),this.position+2<this.input.length){const l=this.input.substring(this.position,this.position+3);if(l==='"""'||l==="'''"){const c=this.input[this.position];for(this.forward(3);this.position+2<this.input.length;){if(this.input[this.position]===c&&this.input[this.position+1]===c&&this.input[this.position+2]===c)return this.forward(3),new h("STRING",this.input.substring(i,this.position),t,e);this.step()}throw new p("Unterminated triple-quoted string",t,e)}}const o=this.input[this.position];for(this.step();this.position<this.input.length;){const l=this.input[this.position];if(l===o)return this.step(),new h("STRING",this.input.substring(i,this.position),t,e);l==="\\"&&!n&&this.position+1<this.input.length?this.forward(2):this.step()}throw new p("Unterminated string",t,e)}bytes(t,e,i){this.step();const n=this.input[this.position];for(this.step();this.position<this.input.length;){const o=this.input[this.position];if(o===n)return this.step(),new h("BYTES",this.input.substring(i,this.position),t,e);o==="\\"&&this.position+1<this.input.length?this.forward(2):this.step()}throw new p("Unterminated bytes literal",t,e)}number(t,e,i){if(this.input[this.position]==="0"&&this.position+1<this.input.length){const l=this.input[this.position+1];if(l==="x"||l==="X"){for(this.forward(2);this.position<this.input.length&&this.isHexDigit(this.input[this.position]);)this.step();if(this.position<this.input.length){const c=this.input[this.position];if(c==="u"||c==="U")return this.step(),new h("UINT",this.input.substring(i,this.position),t,e)}return new h("INT",this.input.substring(i,this.position),t,e)}}for(;this.position<this.input.length&&this.isDigit(this.input[this.position]);)this.step();let n=!1;if(this.position<this.input.length&&this.input[this.position]===".")for(n=!0,this.step();this.position<this.input.length&&this.isDigit(this.input[this.position]);)this.step();if(this.position<this.input.length){const l=this.input[this.position];if(l==="e"||l==="E"){if(n=!0,this.step(),this.position<this.input.length){const c=this.input[this.position];(c==="+"||c==="-")&&this.step()}for(;this.position<this.input.length&&this.isDigit(this.input[this.position]);)this.step()}}if(!n&&this.position<this.input.length){const l=this.input[this.position];if(l==="u"||l==="U")return this.step(),new h("UINT",this.input.substring(i,this.position),t,e)}const o=n?"DOUBLE":"INT";return new h(o,this.input.substring(i,this.position),t,e)}identifier(t,e,i){for(;this.position<this.input.length;){const l=this.input[this.position];if(!this.isLetterOrDigit(l)&&l!=="_")break;this.step()}const n=this.input.substring(i,this.position),o=this.typeOf(n);return new h(o,n,t,e)}typeOf(t){switch(t){case"null":return"NULL";case"true":return"TRUE";case"false":return"FALSE";case"in":return"IN";default:return"IDENTIFIER"}}whitespace(){for(;this.position<this.input.length;){const t=this.input[this.position];if(t!==" "&&t!==" "&&t!==`
|
|
4
|
+
`&&t!=="\r")break;this.step()}}peekChar(){const t=this.position+1;return t>=this.input.length?"\0":this.input[t]}isHexDigit(t){return t>="0"&&t<="9"||t>="a"&&t<="f"||t>="A"&&t<="F"}isDigit(t){return t>="0"&&t<="9"}isLetter(t){return t>="a"&&t<="z"||t>="A"&&t<="Z"}isLetterOrDigit(t){return this.isLetter(t)||this.isDigit(t)}}var u=(r=>(r.ADD="ADD",r.SUBTRACT="SUBTRACT",r.MULTIPLY="MULTIPLY",r.DIVIDE="DIVIDE",r.MODULO="MODULO",r.EQUAL="EQUAL",r.NOT_EQUAL="NOT_EQUAL",r.LESS="LESS",r.LESS_EQUAL="LESS_EQUAL",r.GREATER="GREATER",r.GREATER_EQUAL="GREATER_EQUAL",r.IN="IN",r.LOGICAL_AND="LOGICAL_AND",r.LOGICAL_OR="LOGICAL_OR",r))(u||{}),A=(r=>(r.NOT="NOT",r.NEGATE="NEGATE",r))(A||{}),w=(r=>(r.NULL_VALUE="NULL_VALUE",r.BOOL="BOOL",r.INT="INT",r.UINT="UINT",r.DOUBLE="DOUBLE",r.STRING="STRING",r.BYTES="BYTES",r))(w||{});class d{constructor(t,e){this.value=t,this.literalType=e}accept(t){return t.visitLiteral(this)}}class S{constructor(t){this.name=t}accept(t){return t.visitIdentifier(this)}}class R{constructor(t,e,i=!1){this.operand=t,this.field=e,this.isTest=i}accept(t){return t.visitSelect(this)}}class D{constructor(t,e){this.operand=t,this.index=e}accept(t){return t.visitIndex(this)}}class y{constructor(t,e,i,n=!1){this.target=t,this.functionName=e,this.args=i,this.isMacro=n}accept(t){return t.visitCall(this)}}class T{constructor(t){this.elements=t}accept(t){return t.visitList(this)}}class B{constructor(t,e){this.key=t,this.value=e}}class b{constructor(t){this.entries=t}accept(t){return t.visitMap(this)}}class x{constructor(t,e){this.field=t,this.value=e}}class m{constructor(t,e){this.typeName=t,this.fields=e}accept(t){return t.visitStruct(this)}}class V{constructor(t,e,i,n,o,l,c){this.variable=t,this.range=e,this.accumulator=i,this.initializer=n,this.condition=o,this.step=l,this.result=c}accept(t){return t.visitComprehension(this)}}class N{constructor(t,e){this.op=t,this.operand=e}accept(t){return t.visitUnary(this)}}class L{constructor(t,e,i){this.op=t,this.left=e,this.right=i}accept(t){return t.visitBinary(this)}}class G{constructor(t,e,i){this.condition=t,this.thenExpr=e,this.otherwiseExpr=i}accept(t){return t.visitConditional(this)}}const X=new Set(["map","filter","all","exists","existsOne"]);class ${constructor(t){this.lexer=new H(t),this.current=this.lexer.next()}parse(){const t=this.parseExpr();if(this.current.type!==s.EOF)throw new p(`Unexpected token after expression: ${this.current.value}`,this.current.line,this.current.column);return t}parseExpr(){const t=this.parseConditionalOr();if(this.match(s.QUESTION)){const e=this.parseConditionalOr();this.expect(s.COLON);const i=this.parseExpr();return new G(t,e,i)}return t}parseConditionalOr(){let t=this.parseConditionalAnd();for(;this.match(s.LOGICAL_OR);){const e=this.parseConditionalAnd();t=new L(u.LOGICAL_OR,t,e)}return t}parseConditionalAnd(){let t=this.parseRelation();for(;this.match(s.LOGICAL_AND);){const e=this.parseRelation();t=new L(u.LOGICAL_AND,t,e)}return t}parseRelation(){let t=this.parseAddition();for(;this.isRelationalOp(this.current.type);){const e=this.current.type;this.advance();const i=this.parseAddition();t=new L(this.toBinaryOp(e),t,i)}return t}parseAddition(){let t=this.parseMultiplication();for(;this.current.type===s.PLUS||this.current.type===s.MINUS;){const e=this.current.type;this.advance();const i=this.parseMultiplication();t=new L(e===s.PLUS?u.ADD:u.SUBTRACT,t,i)}return t}parseMultiplication(){let t=this.parseUnary();for(;this.current.type===s.STAR||this.current.type===s.SLASH||this.current.type===s.PERCENT;){const e=this.current.type;this.advance();const i=this.parseUnary(),n=e===s.STAR?u.MULTIPLY:e===s.SLASH?u.DIVIDE:u.MODULO;t=new L(n,t,i)}return t}parseUnary(){return this.current.type===s.BANG?(this.advance(),new N(A.NOT,this.parseUnary())):this.current.type===s.MINUS?(this.advance(),new N(A.NEGATE,this.parseUnary())):this.parseMember()}parseMember(){let t=this.parsePrimary();for(;;)if(this.current.type===s.DOT){this.advance();const e=this.expectIdentifier();if(this.current.type===s.LPAREN){this.advance();const i=this.parseExprList();this.expect(s.RPAREN);const n=X.has(e);t=new y(t,e,i,n)}else t=new R(t,e)}else if(this.current.type===s.LBRACKET){this.advance();const e=this.parseExpr();this.expect(s.RBRACKET),t=new D(t,e)}else break;return t}parsePrimary(){if(this.isLiteralToken(this.current.type))return this.parseLiteral();if(this.current.type===s.LBRACKET)return this.parseListLiteral();if(this.current.type===s.LBRACE)return this.parseMapOrStructLiteral(null);if(this.current.type===s.LPAREN){this.advance();const t=this.parseExpr();return this.expect(s.RPAREN),t}if(this.current.type===s.DOT){this.advance();const t=this.expectIdentifier();if(this.current.type===s.LPAREN){this.advance();const e=this.parseExprList();return this.expect(s.RPAREN),new y(null,t,e)}return new R(null,t)}if(this.current.type===s.IDENTIFIER){const t=this.current.value;if(this.advance(),this.current.type===s.LPAREN){this.advance();const e=this.parseExprList();return this.expect(s.RPAREN),new y(null,t,e)}if(this.current.type===s.DOT&&this.isQualifiedStructLiteral()){const e=this.parseQualifiedIdent(t);return this.parseMapOrStructLiteral(e)}return this.current.type===s.LBRACE?this.parseMapOrStructLiteral(t):new S(t)}throw new p(`Unexpected token: ${this.current.value}`,this.current.line,this.current.column)}parseListLiteral(){this.expect(s.LBRACKET);const t=[];return this.current.type!==s.RBRACKET&&(t.push(...this.parseExprList()),this.current.type===s.COMMA&&this.advance()),this.expect(s.RBRACKET),new T(t)}parseMapOrStructLiteral(t){if(this.expect(s.LBRACE),this.current.type===s.RBRACE)return this.advance(),t!==null?new m(t,[]):new b([]);if(this.current.type===s.IDENTIFIER&&this.peekAhead(1).type===s.COLON||t!==null){const i=this.parseFieldInits();return this.current.type===s.COMMA&&this.advance(),this.expect(s.RBRACE),new m(t,i)}else{const i=this.parseMapInits();return this.current.type===s.COMMA&&this.advance(),this.expect(s.RBRACE),new b(i)}}parseExprList(){const t=[],e=this.current.type;if(e===s.RPAREN||e===s.RBRACKET)return t;for(t.push(this.parseExpr());this.current.type===s.COMMA&&(this.advance(),!(this.current.type===s.RPAREN||this.current.type===s.RBRACKET));)t.push(this.parseExpr());return t}parseMapInits(){const t=[];for(t.push(this.parseMapInit());this.current.type===s.COMMA&&(this.advance(),this.current.type!==s.RBRACE);)t.push(this.parseMapInit());return t}parseMapInit(){const t=this.parseExpr();this.expect(s.COLON);const e=this.parseExpr();return new B(t,e)}parseFieldInits(){const t=[];for(t.push(this.parseFieldInit());this.current.type===s.COMMA&&(this.advance(),this.current.type!==s.RBRACE);)t.push(this.parseFieldInit());return t}parseFieldInit(){const t=this.expectIdentifier();this.expect(s.COLON);const e=this.parseExpr();return new x(t,e)}parseQualifiedIdent(t){let e=t;for(;this.current.type===s.DOT;)this.advance(),e+=".",e+=this.expectIdentifier();return e}parseLiteral(){const t=this.current;switch(this.advance(),t.type){case s.NULL:return new d(null,w.NULL_VALUE);case s.TRUE:return new d(!0,w.BOOL);case s.FALSE:return new d(!1,w.BOOL);case s.INT:return new d(this.parseIntLiteral(t.value),w.INT);case s.UINT:return new d(this.parseUintLiteral(t.value),w.UINT);case s.DOUBLE:return new d(parseFloat(t.value),w.DOUBLE);case s.STRING:return new d(this.parseStringLiteral(t.value),w.STRING);case s.BYTES:return new d(this.parseBytesLiteral(t.value),w.BYTES);default:throw new p(`Not a literal: ${t.value}`,t.line,t.column)}}parseIntLiteral(t){return t.startsWith("-0x")||t.startsWith("-0X")?-parseInt(t.substring(3),16):t.startsWith("0x")||t.startsWith("0X")?parseInt(t.substring(2),16):parseInt(t,10)}parseUintLiteral(t){const e=t.substring(0,t.length-1);return e.startsWith("0x")||e.startsWith("0X")?parseInt(e.substring(2),16):parseInt(e,10)}parseStringLiteral(t){const e=t.startsWith("r")||t.startsWith("R");let i;return e&&(t.substring(1).startsWith('"""')||t.substring(1).startsWith("'''"))?i=t.substring(4,t.length-3):t.startsWith('"""')||t.startsWith("'''")?(i=t.substring(3,t.length-3),i=this.unescapeString(i)):e?i=t.substring(2,t.length-1):(i=t.substring(1,t.length-1),i=this.unescapeString(i)),i}parseBytesLiteral(t){const e=t.substring(2,t.length-1);return this.unescapeString(e)}unescapeString(t){let e="",i=0;for(;i<t.length;)if(t[i]==="\\"&&i+1<t.length){const n=t[i+1];switch(n){case"\\":e+="\\",i+=2;break;case'"':e+='"',i+=2;break;case"'":e+="'",i+=2;break;case"`":e+="`",i+=2;break;case"?":e+="?",i+=2;break;case"a":e+="\x07",i+=2;break;case"b":e+="\b",i+=2;break;case"f":e+="\f",i+=2;break;case"n":e+=`
|
|
5
|
+
`,i+=2;break;case"r":e+="\r",i+=2;break;case"t":e+=" ",i+=2;break;case"v":e+="\v",i+=2;break;case"x":if(i+3<t.length){const o=t.substring(i+2,i+4);e+=String.fromCharCode(parseInt(o,16)),i+=4}else e+=t[i],i++;break;case"u":if(i+5<t.length){const o=t.substring(i+2,i+6);e+=String.fromCharCode(parseInt(o,16)),i+=6}else e+=t[i],i++;break;case"U":if(i+9<t.length){const o=t.substring(i+2,i+10),l=parseInt(o,16);e+=String.fromCodePoint(l),i+=10}else e+=t[i],i++;break;default:if(i+3<t.length&&n>="0"&&n<="3"&&t[i+2]>="0"&&t[i+2]<="7"&&t[i+3]>="0"&&t[i+3]<="7"){const o=t.substring(i+1,i+4);e+=String.fromCharCode(parseInt(o,8)),i+=4}else e+=t[i],i++}}else e+=t[i],i++;return e}isLiteralToken(t){return t===s.NULL||t===s.TRUE||t===s.FALSE||t===s.INT||t===s.UINT||t===s.DOUBLE||t===s.STRING||t===s.BYTES}isRelationalOp(t){return t===s.LT||t===s.LE||t===s.GT||t===s.GE||t===s.EQ||t===s.NE||t===s.IN}toBinaryOp(t){switch(t){case s.LT:return u.LESS;case s.LE:return u.LESS_EQUAL;case s.GT:return u.GREATER;case s.GE:return u.GREATER_EQUAL;case s.EQ:return u.EQUAL;case s.NE:return u.NOT_EQUAL;case s.IN:return u.IN;default:throw new p(`Unknown relational operator: ${t}`,this.current.line,this.current.column)}}match(t){return this.current.type===t?(this.advance(),!0):!1}expect(t){if(this.current.type!==t)throw new p(`Expected ${t} but found ${this.current.type}`,this.current.line,this.current.column);this.advance()}expectIdentifier(){if(this.current.type!==s.IDENTIFIER)throw new p(`Expected identifier but found ${this.current.value}`,this.current.line,this.current.column);const t=this.current.value;return this.advance(),t}advance(){this.current=this.lexer.next()}peekAhead(t){return this.lexer.peek(t)}isQualifiedStructLiteral(){let t=1,e=this.peekAhead(t);if(e.type!==s.IDENTIFIER)return!1;for(t++,e=this.peekAhead(t);e.type===s.DOT;){if(t++,e=this.peekAhead(t),e.type!==s.IDENTIFIER)return!1;t++,e=this.peekAhead(t)}return e.type===s.LBRACE}}class a extends Error{constructor(t){super(t),this.name="EvaluationError"}}function C(r){if(r==null)return 0;if(typeof r=="string"||Array.isArray(r))return r.length;if(typeof r=="object"&&r!==null)return Object.keys(r).length;throw new Error(`size() not supported for type: ${typeof r}`)}function O(r){if(typeof r=="number")return Math.trunc(r);if(typeof r=="string"){const t=parseInt(r,10);if(isNaN(t))throw new Error(`Cannot convert to int: ${r}`);return t}if(typeof r=="boolean")return r?1:0;throw new Error(`Cannot convert to int: ${r}`)}function P(r){const t=O(r);if(t<0)throw new Error(`Cannot convert negative value to uint: ${r}`);return t}function _(r){if(typeof r=="number")return r;if(typeof r=="string"){const t=parseFloat(r);if(isNaN(t))throw new Error(`Cannot convert to double: ${r}`);return t}throw new Error(`Cannot convert to double: ${r}`)}function k(r){return r==null?"null":String(r)}function U(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"||Array.isArray(r)?r.length>0:typeof r=="object"&&r!==null?Object.keys(r).length>0:r!=null}function F(r){return r==null?"null":typeof r=="boolean"?"bool":typeof r=="number"?Number.isInteger(r)?"int":"double":typeof r=="string"?"string":Array.isArray(r)?"list":typeof r=="object"?"map":"unknown"}function Q(r,t){return typeof r=="object"&&r!==null&&typeof t=="string"?t in r:!1}function q(r,t){try{return new RegExp(t).test(r)}catch{throw new Error(`Invalid regex pattern: ${t}`)}}function W(r){if(r.length===0)throw new Error("max() requires at least one argument");let t=r[0];for(let e=1;e<r.length;e++)E(r[e],t)>0&&(t=r[e]);return t}function j(r){if(r.length===0)throw new Error("min() requires at least one argument");let t=r[0];for(let e=1;e<r.length;e++)E(r[e],t)<0&&(t=r[e]);return t}function E(r,t){if(r===null&&t===null)return 0;if(r===null)return-1;if(t===null)return 1;if(typeof r=="number"&&typeof t=="number")return r-t;if(typeof r=="string"&&typeof t=="string")return r.localeCompare(t);if(typeof r=="boolean"&&typeof t=="boolean")return r===t?0:r?1:-1;if(Array.isArray(r)&&Array.isArray(t)){const e=Math.min(r.length,t.length);for(let i=0;i<e;i++){const n=E(r[i],t[i]);if(n!==0)return n}return r.length-t.length}throw new Error(`Cannot compare types: ${typeof r} and ${typeof t}`)}function g(r,t){if(r==null||t===null||t===void 0)return r===t;if(Array.isArray(r)&&Array.isArray(t)){if(r.length!==t.length)return!1;for(let e=0;e<r.length;e++)if(!g(r[e],t[e]))return!1;return!0}if(typeof r=="object"&&typeof t=="object"&&!Array.isArray(r)&&!Array.isArray(t)){const e=Object.keys(r),i=Object.keys(t);if(e.length!==i.length)return!1;for(const n of e)if(!(n in t)||!g(r[n],t[n]))return!1;return!0}return r===t}function K(r,t){for(const e of r)if(g(e,t))return!0;return!1}const Z=Object.freeze(Object.defineProperty({__proto__:null,asBool:U,asDouble:_,asInt:O,asString:k,asUInt:P,compare:E,containsInArray:K,deepEquals:g,has:Q,matches:q,max:W,min:j,sizeOf:C,typeOf:F},Symbol.toStringTag,{value:"Module"}));class v{callFunction(t,e){switch(t){case"size":return C(e[0]);case"int":return O(e[0]);case"uint":return P(e[0]);case"double":return _(e[0]);case"string":return k(e[0]);case"bool":return U(e[0]);case"type":return F(e[0]);case"has":if(e.length!==2)throw new Error("has() requires 2 arguments");return Q(e[0],e[1]);case"matches":if(e.length!==2)throw new Error("matches() requires 2 arguments");return q(e[0],e[1]);case"max":return W(e);case"min":return j(e);default:throw new Error(`Unknown function: ${t}`)}}callMethod(t,e,i){if(t==null)throw new Error("Cannot call method on null");switch(e){case"contains":if(typeof t=="string"&&i.length===1&&typeof i[0]=="string")return t.includes(i[0]);if(Array.isArray(t)&&i.length===1)return t.includes(i[0]);throw new Error("Invalid arguments for contains()");case"startsWith":if(typeof t=="string"&&i.length===1&&typeof i[0]=="string")return t.startsWith(i[0]);throw new Error("startsWith() requires string target and argument");case"endsWith":if(typeof t=="string"&&i.length===1&&typeof i[0]=="string")return t.endsWith(i[0]);throw new Error("endsWith() requires string target and argument");case"toLowerCase":if(typeof t=="string"&&i.length===0)return t.toLowerCase();throw new Error("toLowerCase() requires string target");case"toUpperCase":if(typeof t=="string"&&i.length===0)return t.toUpperCase();throw new Error("toUpperCase() requires string target");case"trim":if(typeof t=="string"&&i.length===0)return t.trim();throw new Error("trim() requires string target");case"replace":if(typeof t=="string"&&i.length===2&&typeof i[0]=="string"&&typeof i[1]=="string")return t.replaceAll(i[0],i[1]);throw new Error("replace() requires string target and 2 string arguments");case"split":if(typeof t=="string"&&i.length===1&&typeof i[0]=="string")return t.split(i[0]);throw new Error("split() requires string target and separator");case"size":return C(t);case"map":case"filter":case"all":case"exists":case"existsOne":throw new a(`Macro function ${e} was not properly handled by the interpreter`);default:return this.callNativeMethod(t,e,i)}}callNativeMethod(t,e,i){if(typeof t[e]=="function")try{return t[e](...i)}catch(n){throw new a(`Invocation of method '${e}' failed: ${n instanceof Error?n.message:String(n)}`)}throw new Error(`No such method '${e}' on type ${typeof t} with ${i.length} argument(s)`)}}class z{constructor(t,e){this.variables=t??{},this.functions=e??new v}evaluate(t){return t.accept(this)}visitLiteral(t){return t.value}visitIdentifier(t){if(!(t.name in this.variables))throw new a(`Undefined variable: ${t.name}`);return this.variables[t.name]}visitSelect(t){const e=t.operand!==null?this.evaluate(t.operand):this.variables;if(e==null){if(t.isTest)return!1;throw new a(`Cannot select field ${t.field} from null`)}if(typeof e=="object"){if(t.isTest)return t.field in e;if(!(t.field in e))throw new a(`Field ${t.field} not found`);return e[t.field]}throw new a("Cannot select field from non-object type")}visitCall(t){if(t.isMacro&&t.target!==null){const i=this.evaluate(t.target);if(t.args.length===0)throw new a(`Macro ${t.functionName} requires arguments`);const n=t.args[0];if(!(n instanceof S))throw new a(`First argument to macro ${t.functionName} must be a variable name`);const o=n.name;if(t.args.length<2)throw new a(`Macro ${t.functionName} requires an expression argument`);const l=t.args[1];return this.evaluateMacro(i,t.functionName,o,l)}const e=[];for(const i of t.args)e.push(this.evaluate(i));if(t.target!==null){const i=this.evaluate(t.target);return this.functions.callMethod(i,t.functionName,e)}else return this.functions.callFunction(t.functionName,e)}evaluateMacro(t,e,i,n){if(!Array.isArray(t))throw new a(`Macro ${e} requires a list target`);const o=this.variables[i],l=i in this.variables;try{switch(e){case"map":{const c=[];for(const f of t)this.variables[i]=f,c.push(this.evaluate(n));return c}case"filter":{const c=[];for(const f of t)this.variables[i]=f,this.evaluate(n)===!0&&c.push(f);return c}case"all":{for(const c of t)if(this.variables[i]=c,this.evaluate(n)!==!0)return!1;return!0}case"exists":{for(const c of t)if(this.variables[i]=c,this.evaluate(n)===!0)return!0;return!1}case"existsOne":{let c=0;for(const f of t)if(this.variables[i]=f,this.evaluate(n)===!0&&(c++,c>1))return!1;return c===1}default:throw new a(`Unknown macro function: ${e}`)}}finally{l?this.variables[i]=o:delete this.variables[i]}}visitList(t){const e=[];for(const i of t.elements)e.push(this.evaluate(i));return e}visitMap(t){const e={};for(const i of t.entries){const n=this.evaluate(i.key),o=this.evaluate(i.value);e[n]=o}return e}visitStruct(t){const e={};for(const i of t.fields)e[i.field]=this.evaluate(i.value);return e}visitComprehension(t){const e=this.evaluate(t.range);if(!Array.isArray(e))throw new a("Comprehension range must be a list");const i=this.variables[t.variable],n=this.variables[t.accumulator],o=t.variable in this.variables,l=t.accumulator in this.variables;try{let c=this.evaluate(t.initializer);this.variables[t.accumulator]=c;for(const f of e)this.variables[t.variable]=f,this.evaluate(t.condition)===!0&&(c=this.evaluate(t.step),this.variables[t.accumulator]=c);return this.evaluate(t.result)}finally{o?this.variables[t.variable]=i:delete this.variables[t.variable],l?this.variables[t.accumulator]=n:delete this.variables[t.accumulator]}}visitUnary(t){const e=this.evaluate(t.operand);switch(t.op){case A.NOT:if(typeof e!="boolean")throw new a("NOT operator requires boolean operand");return!e;case A.NEGATE:if(typeof e!="number")throw new a("Negation requires numeric operand");return-e;default:throw new a(`Unknown unary operator: ${t.op}`)}}visitBinary(t){if(t.op===u.LOGICAL_AND)return this.evaluate(t.left)!==!0?!1:this.evaluate(t.right)===!0;if(t.op===u.LOGICAL_OR)return this.evaluate(t.left)===!0?!0:this.evaluate(t.right)===!0;const e=this.evaluate(t.left),i=this.evaluate(t.right);switch(t.op){case u.ADD:if(typeof e=="string"||typeof i=="string")return String(e)+String(i);if(Array.isArray(e)&&Array.isArray(i))return[...e,...i];if(typeof e=="number"&&typeof i=="number")return e+i;throw new a("Invalid operands for addition");case u.SUBTRACT:if(typeof e=="number"&&typeof i=="number")return e-i;throw new a("Subtraction requires numeric operands");case u.MULTIPLY:if(typeof e=="number"&&typeof i=="number")return e*i;if(typeof e=="string"&&typeof i=="number")return e.repeat(i);if(Array.isArray(e)&&typeof i=="number"){const n=[];for(let o=0;o<i;o++)n.push(...e);return n}throw new a("Invalid operands for multiplication");case u.DIVIDE:if(typeof e=="number"&&typeof i=="number"){if(i===0)throw new a("Division by zero");return e/i}throw new a("Division requires numeric operands");case u.MODULO:if(typeof e=="number"&&typeof i=="number"){if(i===0)throw new a("Modulo by zero");return e%i}throw new a("Modulo requires integer operands");case u.EQUAL:return g(e,i);case u.NOT_EQUAL:return!g(e,i);case u.LESS:return E(e,i)<0;case u.LESS_EQUAL:return E(e,i)<=0;case u.GREATER:return E(e,i)>0;case u.GREATER_EQUAL:return E(e,i)>=0;case u.IN:if(Array.isArray(i))return K(i,e);if(typeof i=="object"&&i!==null)return e in i;if(typeof i=="string"&&typeof e=="string")return i.includes(e);throw new a("IN operator requires list, map, or string on right side");default:throw new a(`Unknown binary operator: ${t.op}`)}}visitConditional(t){return this.evaluate(t.condition)===!0?this.evaluate(t.thenExpr):this.evaluate(t.otherwiseExpr)}visitIndex(t){const e=this.evaluate(t.operand),i=this.evaluate(t.index);if(e==null)throw new a("Cannot index null value");if(Array.isArray(e)){if(typeof i!="number")throw new a("List index must be an integer");const n=Math.trunc(i);if(n<0||n>=e.length)throw new a(`List index out of bounds: ${n}`);return e[n]}else if(typeof e=="object"){if(!(i in e))throw new a(`Map key not found: ${i}`);return e[i]}else if(typeof e=="string"){if(typeof i!="number")throw new a("String index must be an integer");const n=Math.trunc(i);if(n<0||n>=e.length)throw new a(`String index out of bounds: ${n}`);return e[n]}throw new a(`Cannot index type: ${typeof e}`)}}class Y{constructor(t,e){this.ast=t,this.functions=e}evaluate(t={}){return new z({...t},this.functions).evaluate(this.ast)}}class I{constructor(t){this.functions=t??new v}static compile(t,e){const i=new $(t);return new Y(i.parse(),e)}static eval(t,e,i){return this.compile(t,e).evaluate(i)}compile(t){return I.compile(t,this.functions)}eval(t,e={}){return I.eval(t,this.functions,e)}}exports.Binary=L;exports.BinaryOp=u;exports.CEL=I;exports.Call=y;exports.Comprehension=V;exports.Conditional=G;exports.EvaluationError=a;exports.FieldInitializer=x;exports.Identifier=S;exports.Index=D;exports.Interpreter=z;exports.ListExpression=T;exports.Literal=d;exports.LiteralType=w;exports.MapEntry=B;exports.MapExpression=b;exports.ParseError=p;exports.Parser=$;exports.Program=Y;exports.Select=R;exports.StandardFunctions=v;exports.Struct=m;exports.Unary=N;exports.UnaryOp=A;exports.Utilities=Z;exports.asBool=U;
|
|
6
|
+
//# sourceMappingURL=index.cjs.map
|