@telorun/cel 0.0.0-stage → 0.107.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 +17 -0
- package/README.md +281 -2
- package/dist/activation.d.ts +27 -0
- package/dist/activation.d.ts.map +1 -0
- package/dist/activation.js +24 -0
- package/dist/backend-runtime.d.ts +146 -0
- package/dist/backend-runtime.d.ts.map +1 -0
- package/dist/backend-runtime.js +322 -0
- package/dist/bounded-cache.d.ts +21 -0
- package/dist/bounded-cache.d.ts.map +1 -0
- package/dist/bounded-cache.js +42 -0
- package/dist/catalog-runtime.d.ts +59 -0
- package/dist/catalog-runtime.d.ts.map +1 -0
- package/dist/catalog-runtime.js +785 -0
- package/dist/cel-expression.d.ts +32 -0
- package/dist/cel-expression.d.ts.map +1 -0
- package/dist/cel-expression.js +29 -0
- package/dist/cel-map-value.d.ts +34 -0
- package/dist/cel-map-value.d.ts.map +1 -0
- package/dist/cel-map-value.js +74 -0
- package/dist/cel-program.d.ts +44 -0
- package/dist/cel-program.d.ts.map +1 -0
- package/dist/cel-program.js +72 -0
- package/dist/cel-type.d.ts +131 -0
- package/dist/cel-type.d.ts.map +1 -0
- package/dist/cel-type.js +293 -0
- package/dist/cel-value.d.ts +159 -0
- package/dist/cel-value.d.ts.map +1 -0
- package/dist/cel-value.js +225 -0
- package/dist/check-diagnostic.d.ts +53 -0
- package/dist/check-diagnostic.d.ts.map +1 -0
- package/dist/check-diagnostic.js +66 -0
- package/dist/checker.d.ts +77 -0
- package/dist/checker.d.ts.map +1 -0
- package/dist/checker.js +721 -0
- package/dist/closure-backend.d.ts +21 -0
- package/dist/closure-backend.d.ts.map +1 -0
- package/dist/closure-backend.js +436 -0
- package/dist/comprehension-bindings.d.ts +33 -0
- package/dist/comprehension-bindings.d.ts.map +1 -0
- package/dist/comprehension-bindings.js +50 -0
- package/dist/comprehension-runtime.d.ts +44 -0
- package/dist/comprehension-runtime.d.ts.map +1 -0
- package/dist/comprehension-runtime.js +137 -0
- package/dist/declared-chain.d.ts +35 -0
- package/dist/declared-chain.d.ts.map +1 -0
- package/dist/declared-chain.js +36 -0
- package/dist/duration-value.d.ts +59 -0
- package/dist/duration-value.d.ts.map +1 -0
- package/dist/duration-value.js +135 -0
- package/dist/emitted-module.d.ts +207 -0
- package/dist/emitted-module.d.ts.map +1 -0
- package/dist/emitted-module.js +359 -0
- package/dist/engine-version.d.ts +3 -0
- package/dist/engine-version.d.ts.map +1 -0
- package/dist/engine-version.js +8 -0
- package/dist/environment-digest.d.ts +44 -0
- package/dist/environment-digest.d.ts.map +1 -0
- package/dist/environment-digest.js +98 -0
- package/dist/environment.d.ts +283 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +459 -0
- package/dist/function-catalog.d.ts +66 -0
- package/dist/function-catalog.d.ts.map +1 -0
- package/dist/function-catalog.js +77 -0
- package/dist/function-registry.d.ts +78 -0
- package/dist/function-registry.d.ts.map +1 -0
- package/dist/function-registry.js +189 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/integer-arithmetic.d.ts +27 -0
- package/dist/integer-arithmetic.d.ts.map +1 -0
- package/dist/integer-arithmetic.js +58 -0
- package/dist/js-emitter.d.ts +132 -0
- package/dist/js-emitter.d.ts.map +1 -0
- package/dist/js-emitter.js +562 -0
- package/dist/json-schema-type.d.ts +182 -0
- package/dist/json-schema-type.d.ts.map +1 -0
- package/dist/json-schema-type.js +487 -0
- package/dist/json-text-scan.d.ts +28 -0
- package/dist/json-text-scan.d.ts.map +1 -0
- package/dist/json-text-scan.js +159 -0
- package/dist/lexer.d.ts +103 -0
- package/dist/lexer.d.ts.map +1 -0
- package/dist/lexer.js +458 -0
- package/dist/macro-check.d.ts +33 -0
- package/dist/macro-check.d.ts.map +1 -0
- package/dist/macro-check.js +162 -0
- package/dist/macro-shape.d.ts +24 -0
- package/dist/macro-shape.d.ts.map +1 -0
- package/dist/macro-shape.js +55 -0
- package/dist/member-read.d.ts +52 -0
- package/dist/member-read.d.ts.map +1 -0
- package/dist/member-read.js +125 -0
- package/dist/namespace-resolution.d.ts +35 -0
- package/dist/namespace-resolution.d.ts.map +1 -0
- package/dist/namespace-resolution.js +160 -0
- package/dist/nominal-type.d.ts +63 -0
- package/dist/nominal-type.d.ts.map +1 -0
- package/dist/nominal-type.js +98 -0
- package/dist/nullable-access.d.ts +38 -0
- package/dist/nullable-access.d.ts.map +1 -0
- package/dist/nullable-access.js +93 -0
- package/dist/parse-limits.d.ts +26 -0
- package/dist/parse-limits.d.ts.map +1 -0
- package/dist/parse-limits.js +21 -0
- package/dist/parser.d.ts +48 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +503 -0
- package/dist/qualified-calls.d.ts +22 -0
- package/dist/qualified-calls.d.ts.map +1 -0
- package/dist/qualified-calls.js +27 -0
- package/dist/regular-expression.d.ts +48 -0
- package/dist/regular-expression.d.ts.map +1 -0
- package/dist/regular-expression.js +77 -0
- package/dist/reserved-words.d.ts +52 -0
- package/dist/reserved-words.d.ts.map +1 -0
- package/dist/reserved-words.js +77 -0
- package/dist/resolved-call.d.ts +33 -0
- package/dist/resolved-call.d.ts.map +1 -0
- package/dist/resolved-call.js +15 -0
- package/dist/root-references.d.ts +23 -0
- package/dist/root-references.d.ts.map +1 -0
- package/dist/root-references.js +120 -0
- package/dist/runtime-library.d.ts +56 -0
- package/dist/runtime-library.d.ts.map +1 -0
- package/dist/runtime-library.js +545 -0
- package/dist/serializer.d.ts +24 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +240 -0
- package/dist/sha256.d.ts +20 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +103 -0
- package/dist/signature.d.ts +72 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +61 -0
- package/dist/signatures/function-catalog.json +788 -0
- package/dist/signatures/standard-library.json +229 -0
- package/dist/standard-library.d.ts +41 -0
- package/dist/standard-library.d.ts.map +1 -0
- package/dist/standard-library.js +85 -0
- package/dist/syntax-diagnostic.d.ts +61 -0
- package/dist/syntax-diagnostic.d.ts.map +1 -0
- package/dist/syntax-diagnostic.js +28 -0
- package/dist/syntax-tree.d.ts +160 -0
- package/dist/syntax-tree.d.ts.map +1 -0
- package/dist/syntax-tree.js +58 -0
- package/dist/timestamp-value.d.ts +53 -0
- package/dist/timestamp-value.d.ts.map +1 -0
- package/dist/timestamp-value.js +223 -0
- package/dist/tree-equality.d.ts +15 -0
- package/dist/tree-equality.d.ts.map +1 -0
- package/dist/tree-equality.js +105 -0
- package/dist/type-expression.d.ts +26 -0
- package/dist/type-expression.d.ts.map +1 -0
- package/dist/type-expression.js +134 -0
- package/dist/value-equality.d.ts +38 -0
- package/dist/value-equality.d.ts.map +1 -0
- package/dist/value-equality.js +196 -0
- package/dist/value-text.d.ts +25 -0
- package/dist/value-text.d.ts.map +1 -0
- package/dist/value-text.js +44 -0
- package/dist/zoned-calendar.d.ts +61 -0
- package/dist/zoned-calendar.d.ts.map +1 -0
- package/dist/zoned-calendar.js +143 -0
- package/package.json +56 -3
- package/src/activation.ts +32 -0
- package/src/backend-runtime.ts +454 -0
- package/src/bounded-cache.ts +45 -0
- package/src/catalog-runtime.ts +921 -0
- package/src/cel-expression.ts +53 -0
- package/src/cel-map-value.ts +86 -0
- package/src/cel-program.ts +103 -0
- package/src/cel-type.ts +359 -0
- package/src/cel-value.ts +353 -0
- package/src/check-diagnostic.ts +102 -0
- package/src/checker.ts +932 -0
- package/src/closure-backend.ts +502 -0
- package/src/comprehension-bindings.ts +66 -0
- package/src/comprehension-runtime.ts +157 -0
- package/src/declared-chain.ts +45 -0
- package/src/duration-value.ts +145 -0
- package/src/emitted-module.ts +494 -0
- package/src/engine-version.ts +9 -0
- package/src/environment-digest.ts +111 -0
- package/src/environment.ts +740 -0
- package/src/function-catalog.ts +140 -0
- package/src/function-registry.ts +229 -0
- package/src/index.ts +386 -0
- package/src/integer-arithmetic.ts +64 -0
- package/src/js-emitter.ts +713 -0
- package/src/json-schema-type.ts +664 -0
- package/src/json-text-scan.ts +163 -0
- package/src/lexer.ts +562 -0
- package/src/macro-check.ts +191 -0
- package/src/macro-shape.ts +66 -0
- package/src/member-read.ts +126 -0
- package/src/namespace-resolution.ts +167 -0
- package/src/nominal-type.ts +149 -0
- package/src/nullable-access.ts +95 -0
- package/src/parse-limits.ts +36 -0
- package/src/parser.ts +554 -0
- package/src/qualified-calls.ts +39 -0
- package/src/regular-expression.ts +101 -0
- package/src/reserved-words.ts +94 -0
- package/src/resolved-call.ts +34 -0
- package/src/root-references.ts +126 -0
- package/src/runtime-library.ts +615 -0
- package/src/serializer.ts +246 -0
- package/src/sha256.ts +112 -0
- package/src/signature.ts +127 -0
- package/src/signatures/function-catalog.json +788 -0
- package/src/signatures/standard-library.json +235 -0
- package/src/standard-library.ts +149 -0
- package/src/syntax-diagnostic.ts +72 -0
- package/src/syntax-tree.ts +229 -0
- package/src/timestamp-value.ts +294 -0
- package/src/tree-equality.ts +130 -0
- package/src/type-expression.ts +160 -0
- package/src/value-equality.ts +201 -0
- package/src/value-text.ts +45 -0
- package/src/zoned-calendar.ts +178 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# SUSTAINABLE USE LICENSE (Fair-code)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CodeNet Sp. z o.o.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, and distribute the Software for any purpose—including commercial purposes—subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
1. ANTI-COMPETITION RESTRICTION: The Software may not be provided to third parties as a managed service, commercial SaaS (Software-as-a-Service), PaaS (Platform-as-a-Service), BaaS (Backend-as-a-Service), or similar offering where the primary value provided to the user is the functionality of the Software itself, without a separate commercial license from the copyright holder.
|
|
8
|
+
|
|
9
|
+
2. PERMITTED COMMERCIAL USE: You are free to use the Software to build, host, and monetize your own commercial applications, products, and services, provided such use does not violate Clause 1.
|
|
10
|
+
|
|
11
|
+
3. ATTRIBUTION: This copyright notice and license must be included in all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
4. CONTRIBUTIONS: Contributions to the Software are welcome and encouraged. By contributing, you agree that your contributions may be incorporated into the Software and distributed under this license.
|
|
14
|
+
|
|
15
|
+
5. DISCLAIMER: The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
|
|
16
|
+
|
|
17
|
+
For commercial licensing, managed hosting exemptions, or enterprise inquiries, please contact <contact@codenet.pl>.
|
package/README.md
CHANGED
|
@@ -1,3 +1,282 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @telorun/cel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Common Expression Language, as a library: read an expression, hold it as a tree, check it, run it,
|
|
4
|
+
compile it to JavaScript, write it back.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import { parseExpression, qualifiedCalls, rootReferences, serializeTree } from "@telorun/cel";
|
|
8
|
+
|
|
9
|
+
const expression = parseExpression("Billing.total(cart.items)", { namespaces: ["Billing"] });
|
|
10
|
+
|
|
11
|
+
expression.diagnostics; // [] — nothing it could not read
|
|
12
|
+
rootReferences(expression.root); // ["cart"] — what it reads from its environment
|
|
13
|
+
qualifiedCalls(expression.root); // one call: Billing.total, arity 1, with its range
|
|
14
|
+
serializeTree(expression.root); // "Billing.total(cart.items)"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## What it answers
|
|
18
|
+
|
|
19
|
+
- **The whole expression grammar**, into a tree whose every node carries the `[start, end]` span of
|
|
20
|
+
source it covers: int64, `u`-suffixed uint64 and double literals; single-, double- and
|
|
21
|
+
triple-quoted strings, raw strings, `b"…"` and `br"…"` bytes, with every escape CEL defines; `true`,
|
|
22
|
+
`false`, `null`; list and map literals; the operator precedence table; member access and index access
|
|
23
|
+
in both their plain and optional forms (`.`, `.?`, `[]`, `[?]`), a member name between backticks, and
|
|
24
|
+
a name a dot opens (`.y`); global calls and receiver calls.
|
|
25
|
+
- **Qualified calls.** `Alias.fn(x)` and `obj.method(x)` are the same syntax, so the only thing that
|
|
26
|
+
can tell them apart is a set of names that denote namespaces. Pass that set as `namespaces` and
|
|
27
|
+
every call on one of those names becomes a `qcall` node. An expression records the set it was
|
|
28
|
+
resolved under, so a consumer can tell whether it is looking at a tree resolved for its own site.
|
|
29
|
+
- **Error recovery.** Reading never throws. A malformed or half-typed expression gives back a tree
|
|
30
|
+
for the longest prefix that read, plus one diagnostic with the range of what stopped it — a member
|
|
31
|
+
with no name yet (`request.`) is a select with an empty field, which is what completion after a dot
|
|
32
|
+
needs.
|
|
33
|
+
- **Round-trip.** `serializeTree` writes any tree back as source that reads as an equal expression
|
|
34
|
+
(`treesEqual`), parentheses placed from precedence rather than remembered from the text.
|
|
35
|
+
- **Two questions about a tree**: `rootReferences` — the first name of every access chain, excluding
|
|
36
|
+
what a comprehension or `cel.bind` binds and excluding a namespace; and `qualifiedCalls` — every
|
|
37
|
+
call on a namespace, in source order.
|
|
38
|
+
- **Input limits.** 100000 nodes, 250 levels of nesting, 1000 list elements, 1000 map entries and 32
|
|
39
|
+
call arguments, each reported as an ordinary diagnostic rather than an exception, so hostile input
|
|
40
|
+
behaves like any other unreadable input. `DEFAULT_PARSE_LIMITS` are those numbers; pass `limits` to
|
|
41
|
+
change them.
|
|
42
|
+
|
|
43
|
+
## Checking
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { CelEnvironment } from "@telorun/cel";
|
|
47
|
+
|
|
48
|
+
const environment = new CelEnvironment({ enableOptionalTypes: true })
|
|
49
|
+
.registerVariable("request", { schema: requestSchema }) // typed to full depth
|
|
50
|
+
.registerFunction("sha256(string): string", { hostBacked: true, throws: ["ERR_DIGEST_FAILED"] })
|
|
51
|
+
.registerNamespace("Billing", ["total(int, int): int"]);
|
|
52
|
+
|
|
53
|
+
const result = environment.check("request.query.limti");
|
|
54
|
+
result.valid; // false
|
|
55
|
+
result.diagnostics; // [{ code: "CEL_UNKNOWN_FIELD", message: "…(declared: limit, tags)", range: [14, 19] }]
|
|
56
|
+
result.calls; // which signature each call resolved to, with its metadata
|
|
57
|
+
environment.check("request.query.limit").typeName; // "int"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- **Registration is not privileged.** CEL's own library registers through the same `registerFunction`,
|
|
61
|
+
and the dispatch key is a call's name, form and parameter types — not its return type. So
|
|
62
|
+
`registerFunction("duration(string): Money")` **replaces** the library's `duration(string)`, and
|
|
63
|
+
`removeFunctionsNamed("duration")` makes a call to it `CEL_UNKNOWN_FUNCTION`. `clone()` inherits
|
|
64
|
+
everything and then diverges.
|
|
65
|
+
- **JSON Schema is the native input, to full depth** — nested objects, element types, unions kept as
|
|
66
|
+
unions, `allOf` intersected, and a reference followed. A flat field map (`{ fields: { columns: "map" } }`)
|
|
67
|
+
is still accepted, for a host that must type exactly as shallowly as something it is replacing.
|
|
68
|
+
- **Nothing a schema says falls through to `dyn` in silence.** A `#/$defs/…` reference is resolved against
|
|
69
|
+
the document the node belongs to; one that leaves the document is answered by the host's own resolver,
|
|
70
|
+
which returns a registered type name **or the document to read in place of that node**. A node the
|
|
71
|
+
engine has no rule for is **reported** by JSON Pointer rather than typed `dyn` quietly —
|
|
72
|
+
`environment.schemaReports()`, so the consumer that knows where the schema was written can anchor a
|
|
73
|
+
diagnostic at that line. A reference re-entered on the descent is a recursive schema: the one deliberate
|
|
74
|
+
`dyn`, declared as such.
|
|
75
|
+
- **A named type is not its base.** `registerType({ name: "Money", base: "int" })` gives a type its own
|
|
76
|
+
operators, comparisons, conversions, members and invariant type parameters; a plain `int` is refused at
|
|
77
|
+
a `Money` slot, and `Holder<string>` where `Holder<int>` is wanted is `CEL_TYPE_ARGUMENT_MISMATCH`.
|
|
78
|
+
- **Every verdict carries a range and is decided by the checker** — `CEL_SYNTAX_ERROR`,
|
|
79
|
+
`CEL_TYPE_ERROR`, `CEL_UNKNOWN_IDENTIFIER`, `CEL_UNKNOWN_FIELD`, `CEL_UNKNOWN_FUNCTION`,
|
|
80
|
+
`CEL_WRONG_CALL_FORM`, `CEL_TYPE_ARGUMENT_MISMATCH`, `CEL_NULLABLE_ACCESS`, `CEL_INVALID_ARGUMENT`, and
|
|
81
|
+
`FUNCTION_UNRESOLVED` / `FUNCTION_ARITY_MISMATCH` / `FUNCTION_ARGUMENT_MISMATCH` for a namespaced call.
|
|
82
|
+
A fix, where one is offered, is the whole corrected source.
|
|
83
|
+
- **A namespaced call is judged only against what you declared.** `registerNamespace("Billing", […],
|
|
84
|
+
{ open: true })` makes a name you did not declare type `dyn` and report nothing — it is still **listed**
|
|
85
|
+
in `result.calls`, so you resolve it against your own vocabulary and word that verdict yourself. And a
|
|
86
|
+
declaration written `{ name: "total", returns: "double" }` instead of `{ signature }` withholds the
|
|
87
|
+
parameter list: the result is typed, the arity and argument types are yours to judge. Both are for a host
|
|
88
|
+
whose resolution or whose signature grammar is richer than CEL's; neither can be half-declared, since
|
|
89
|
+
there is no way to supply parameters and ask for them to be ignored.
|
|
90
|
+
- **Three guards clear a read of something that may be null** and no others: `?:`, `&&`, `||`.
|
|
91
|
+
- **The optional library enters whole** where `enableOptionalTypes` is on: `.?`, `[?]`, `[?x]`,
|
|
92
|
+
`{?k: v}`, `optional.of`, `none`, `ofNonZeroValue`, `hasValue`, `value`, `or`, `orValue`, `optMap`,
|
|
93
|
+
`optFlatMap`, equality over optionals, `type()` of one, and the type name `optional_type`.
|
|
94
|
+
- **A member whose name is not an identifier is read between backticks** —
|
|
95
|
+
`request.headers.`` `content-type` ``, typed against the schema's `properties` exactly as a plain
|
|
96
|
+
member is, so a typo in a dashed or dotted key is still `CEL_UNKNOWN_FIELD`. Only where a member is
|
|
97
|
+
read: anywhere else a backtick is a syntax error.
|
|
98
|
+
- **A dotted declaration is one name.** Declare `a.b.c`, or `a.b`, or both: `a.b.c` reads the variable of
|
|
99
|
+
that name where it is declared and the map's entry where only `a.b` is — the longest prefix wins.
|
|
100
|
+
- **`.y` resolves against the environment**, never against a name the expression bound: it is the only
|
|
101
|
+
spelling for an outer name where a comprehension variable shares it.
|
|
102
|
+
- `convertsToString(type)` answers whether a value of that type can be rendered as text by the
|
|
103
|
+
environment's own `string()`.
|
|
104
|
+
|
|
105
|
+
The standard library is data — `src/signatures/standard-library.json`, described in
|
|
106
|
+
[docs/signature-data.md](docs/signature-data.md). It is **CEL's** library: a declaration CEL itself does
|
|
107
|
+
not define carries `"spec": false` and a reason saying why it is here, where the equivalent lives and how
|
|
108
|
+
this member differs from it — and nineteen do.
|
|
109
|
+
|
|
110
|
+
## The function catalog
|
|
111
|
+
|
|
112
|
+
Beside CEL's own library there is a second one — Telo's dialect, 67 functions over 86 signatures, also
|
|
113
|
+
data (`src/signatures/function-catalog.json`):
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { CelEnvironment, functionCatalog, registerFunctionCatalog } from "@telorun/cel";
|
|
117
|
+
|
|
118
|
+
const environment = new CelEnvironment({ enableOptionalTypes: true });
|
|
119
|
+
registerFunctionCatalog(environment, {
|
|
120
|
+
handlers: { sha256: hashHex, json: writeJson, joinPath: (base, rest) => join(base, rest) },
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
environment.evaluate("formatDuration(510, 480)"); // "1d 30m"
|
|
124
|
+
functionCatalog(); // the one listing surface: name, signature, category, summary, flags
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- **It registers through the public surface** — `registerFunction`, once per signature — so it can be
|
|
128
|
+
left out, replaced function by function, or removed by name. A default environment has none of it.
|
|
129
|
+
- **Nine functions are the host's**: `sha256`, `md5`, `sha1`, `sha512`, `hmac`, `base64Encode`,
|
|
130
|
+
`base64Decode`, `json` and `joinPath`, each needing a facility this package may not reach. One left
|
|
131
|
+
out still registers, so a consumer that only checks still type-checks the call; evaluating it answers
|
|
132
|
+
`unbound_function` naming the function.
|
|
133
|
+
- **A refusal is the catalog's own words**, `<function>: <what is wrong>` — never a library's wording.
|
|
134
|
+
An invalid pattern ends with one of RE2's own parse-error kinds and nothing after it, and `parseJson`
|
|
135
|
+
words its own offset (`parseJson: invalid JSON at offset 3`).
|
|
136
|
+
- **A literal argument is refused at CHECK**, not only when the expression runs: `fixed(1.0, 11)` is
|
|
137
|
+
`CEL_INVALID_ARGUMENT` naming the call, because a signature constrains types and a decimal count out
|
|
138
|
+
of range is a value. Twelve functions carry such a guard, and each runs the very code the evaluation
|
|
139
|
+
runs.
|
|
140
|
+
- **Two families reach a host facility by declaration** — the clock (`now`, `nowIso`, `today`,
|
|
141
|
+
`nowMillis`, `nowSeconds`) and the random source behind the UUID functions, which is what
|
|
142
|
+
`deterministic: false` means. Both exist in a browser as in Node.
|
|
143
|
+
|
|
144
|
+
## Evaluating
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const program = environment.compile("request.query.limit != null ? int(request.query.limit) : 25");
|
|
148
|
+
|
|
149
|
+
program.evaluate({ request: { query: { limit: "50" } } }); // 50n
|
|
150
|
+
program.evaluate({ request: { query: {} } }); // 25n
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- **Every operator and function behaves as cel-spec requires.** `int` is a `bigint` and an overflow is
|
|
154
|
+
an error rather than a wrap; `uint` and `double` are distinct types; division and modulus by zero are
|
|
155
|
+
two different errors; bytes and strings are distinct and both are ordered; a timestamp is
|
|
156
|
+
nanosecond-precise and its getters take a zone (an IANA name or a fixed `HH:MM` offset); `matches` is
|
|
157
|
+
RE2, so a pattern the host's own engine would accept and RE2 would not is refused.
|
|
158
|
+
- **A duration is the signed 64-bit range of its total nanoseconds** —
|
|
159
|
+
`-9223372036.854775808s … 9223372036.854775807s`, roughly ±292 years, which is cel-spec's own limit.
|
|
160
|
+
It is checked wherever a duration is built: the conversion, duration `+` and `-`, `timestamp -
|
|
161
|
+
timestamp`, and the duration operand of `timestamp ± duration`. A host's own duration format may be
|
|
162
|
+
wider — `google.protobuf.Duration` is ±10,000 years — and CEL's is a subrange of it, so a duration a
|
|
163
|
+
transport can carry is not always one CEL can construct.
|
|
164
|
+
- **Eight string members are not CEL's**, and each says so in its own declaration (`"spec": false` with a
|
|
165
|
+
reason): `indexOf`, `lastIndexOf` and `substring` index by **UTF-16 code unit** rather than by code
|
|
166
|
+
point, `lowerAscii` and `upperAscii` apply the host language's casing rather than touching the ASCII
|
|
167
|
+
letters alone, and `trim`, `split` and `join` differ from the strings extension's equivalents in the
|
|
168
|
+
ways their reasons name. `size`, `startsWith`, `endsWith`, `contains`, `matches` and concatenation are
|
|
169
|
+
CEL's own.
|
|
170
|
+
- **An error is a VALUE that participates in short-circuit.** `false && <missing key>` is `false` and
|
|
171
|
+
`true || <missing key>` is `true`, from either side; an error that survives to the top of an
|
|
172
|
+
evaluation becomes a thrown `CelEvaluationError` carrying one of the codes in `CEL_EVALUATION_CODES`
|
|
173
|
+
(`no_such_key`, `numeric_overflow`, `division_by_zero`, `modulo_by_zero`, `index_out_of_range`,
|
|
174
|
+
`invalid_regular_expression`, `invalid_conversion`, `optional_value_missing`,
|
|
175
|
+
`async_value_unsupported`, …) and the range of the text it is about.
|
|
176
|
+
- **Evaluation is synchronous**, and a value that must be awaited is refused at **every door it comes
|
|
177
|
+
through**: an activation read, a registered implementation's result, a member read in any form, an
|
|
178
|
+
element entering a comprehension body, the value `cel.bind` binds, an optional's held value, and list
|
|
179
|
+
membership. Each answers `async_value_unsupported`, never a value passed along and never an answer
|
|
180
|
+
decided about a value nothing touched: the element is refused where it is **bound**, and that refusal is
|
|
181
|
+
terminal — `xs.all(e, false)` and `xs.exists(e, true)` over a list holding a promise refuse rather than
|
|
182
|
+
answering off the one element that is readable, while an ordinary `no_such_key` still short-circuits as
|
|
183
|
+
before. A container is deliberately not walked, so `size(xs)` and `xs + [3]` carry it along and every
|
|
184
|
+
way of reading the element out is refused.
|
|
185
|
+
- **A value says what it is by a string type key** under `Symbol.for("telo.cel.value")`, never by its
|
|
186
|
+
constructor, so two copies of the engine agree about a value either of them built. `null`, a boolean,
|
|
187
|
+
a string, a `number` (double), a `bigint` (int), a `Uint8Array` (bytes), an array (list) and a plain
|
|
188
|
+
object (a string-keyed map) carry no key; a uint, a timestamp, a duration, a type value, an optional,
|
|
189
|
+
a map with typed keys and an error do. A plain object carrying a string-keyed look-alike brand is
|
|
190
|
+
data, as it must be.
|
|
191
|
+
- **Every member read goes through one lookup** over the value's own entries — `a.b`, `a['b']`,
|
|
192
|
+
`a[expr]`, `.?`, `[?]` and a macro's field read alike — so no key, however it was computed, reaches a
|
|
193
|
+
prototype, a method or a function property. A CEL map is built prototype-free, so `__proto__`,
|
|
194
|
+
`constructor` and `prototype` round-trip as data.
|
|
195
|
+
- **No `eval`, no `new Function`, no disk.** `compile` builds a tree of closures over the runtime
|
|
196
|
+
library, which is where every operator lives exactly once. In-process caches — compiled expressions
|
|
197
|
+
per environment, compiled patterns, a call site's resolved overloads — are bounded, each with a
|
|
198
|
+
declared capacity.
|
|
199
|
+
- `evaluateToValue` answers the error value instead of throwing, for a caller that carries errors
|
|
200
|
+
itself. A namespaced call is dispatched through `namespaceFunction`, supplied per evaluation; one
|
|
201
|
+
nothing binds is `unbound_function`.
|
|
202
|
+
|
|
203
|
+
## Emitting JavaScript
|
|
204
|
+
|
|
205
|
+
The same expressions compile to **JavaScript source**, as one module for a set of them:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const module = environment.emit(["a + b * 2", "xs.map(e, e * 2)"]);
|
|
209
|
+
|
|
210
|
+
module.key; // 64 hexadecimal characters: what a host names its stored copy by
|
|
211
|
+
module.text; // the module's source, which imports nothing
|
|
212
|
+
module.header; // { format, engine, environment, key, body } — the header line's own fields
|
|
213
|
+
|
|
214
|
+
// A host loads it however it loads a module, then:
|
|
215
|
+
const programs = programsFromEmittedModule(loaded, module, environment.emitterRuntime());
|
|
216
|
+
programs[0].evaluate({ a: 3n, b: 4n }); // 11n
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- **Both backends answer identically, case for case** — the same value, or the same error code and the
|
|
220
|
+
same range. That is a property of the wiring rather than of the tests: every operator, comprehension,
|
|
221
|
+
member read, name read, bool operand and call-site dispatch is one function both backends call, so the
|
|
222
|
+
only thing the two compile differently is how control gets from one call to the next.
|
|
223
|
+
- **The runtime is the factory's argument, never an import.** The module's default export takes the
|
|
224
|
+
runtime support library and answers one synchronous function per expression, and the text names no
|
|
225
|
+
specifier — so it loads from a `data:` URL, from a cache directory mounted anywhere, and under a host
|
|
226
|
+
whose resolver is not Node's. A module importing a package would also accept a runtime of another
|
|
227
|
+
version silently, which the key could not see.
|
|
228
|
+
- **The key covers the environment, not just the source.** It hashes the emitter's format generation, the
|
|
229
|
+
engine version, the environment's digest and the ordered list of expression sources. The digest is over
|
|
230
|
+
the environment's **resolved listing** — every surviving function signature, every named type, every
|
|
231
|
+
variable, every namespace, every option — so two environments built by different registration orders
|
|
232
|
+
are one key, and a host that replaced or removed a standard function is a different one.
|
|
233
|
+
- **The header is verified before anything runs, and it is five fields rather than three.** `format`,
|
|
234
|
+
`engine` and `environment` are provenance, and they are byte-identical for every module one engine
|
|
235
|
+
writes against one environment — so `key` (the module's own identity) and `body` (the digest of
|
|
236
|
+
everything after the header line) are what catch a store that answered the wrong lookup, a text
|
|
237
|
+
truncated after its header, and a text edited after it was written. `body` covers the `integrity`
|
|
238
|
+
export and so cannot live in it: the header line carries all five, the export carries the four a loaded
|
|
239
|
+
object can be held to. Every mismatch a stored **text** shows is a recompile naming itself under
|
|
240
|
+
`refused`; a loaded **module** that declares nothing, declares another key or answers the wrong number
|
|
241
|
+
of functions is refused with `CelEngineError` (`emitted_module_rejected`).
|
|
242
|
+
- **One store seam, and no loader.** `environment.emittedModule(sources, store)` reads and writes module
|
|
243
|
+
text by key through an interface the host supplies; the engine touches no filesystem, and a hit parses
|
|
244
|
+
nothing. A store's write should be **atomic** — written elsewhere, then renamed — because several hosts
|
|
245
|
+
share one cache root; that is how a half-written entry is avoided, and the `body` digest is how one is
|
|
246
|
+
detected if it is not.
|
|
247
|
+
- **Emission is deterministic**: the same expressions in the same order against the same environment are
|
|
248
|
+
the same bytes.
|
|
249
|
+
- It is **faster, not differently behaved** — and by exactly one thing: what the closure calls cost.
|
|
250
|
+
Both backends pay the same shared runtime underneath, so an expression whose cost is a dotted-chain
|
|
251
|
+
search and a conversion is a wash, while one that calls many small operations gains.
|
|
252
|
+
|
|
253
|
+
## What it deliberately does not do
|
|
254
|
+
|
|
255
|
+
- **Nothing is expanded at read time.** `has(x)`, `xs.map(i, i)` and `cel.bind(x, 1, x)` are ordinary
|
|
256
|
+
call nodes in the tree; the checker lowers them, so the source stays writable from the tree.
|
|
257
|
+
- **It knows no host's vocabulary.** No type name, no annotation, no manifest word: a host registers
|
|
258
|
+
its own through `registerType` and one schema resolver. The function catalog above is a set of
|
|
259
|
+
functions over CEL's own types — no signature in it names a host type — which is what a dialect is.
|
|
260
|
+
- **It never type-checks on its way to evaluating.** The checker decides every verdict and a consumer
|
|
261
|
+
asks for them; compiling refuses only what cannot be compiled at all — a source that did not read
|
|
262
|
+
whole.
|
|
263
|
+
- **The LANGUAGE reaches no host facility.** No filesystem, no clock, no network, no Node built-in — it
|
|
264
|
+
runs unchanged in a browser, and so does the catalog: its clock and UUID functions read facilities
|
|
265
|
+
every host has, and its nine host-backed functions reach nothing at all by themselves.
|
|
266
|
+
|
|
267
|
+
## Reserved words
|
|
268
|
+
|
|
269
|
+
CEL reserves 21 words, and none of them can be read as a name: `as break const continue else false for
|
|
270
|
+
function if import in let loop namespace null package return true var void while`. Seventeen are refused
|
|
271
|
+
outright; `true`, `false` and `null` are literals where they stand, and `in` is the membership operator,
|
|
272
|
+
which is why a name position can never reach them.
|
|
273
|
+
|
|
274
|
+
A reserved word is still a legal **member** name — `{'let': 1}.let`, `a.while()`, `a.in`, `a.true` — which
|
|
275
|
+
is CEL's own rule: a member names an entry of a value, not a name in the expression's scope.
|
|
276
|
+
|
|
277
|
+
Nothing is reserved on a host's behalf: `__proto__`, `prototype` and `constructor` are ordinary names.
|
|
278
|
+
Keeping a host's own properties out of a CEL value is the member read's job, not a word list's — a
|
|
279
|
+
member key can be computed (`a[request.query.k]`), which no list of names would judge.
|
|
280
|
+
|
|
281
|
+
`cel` and `optional` are ordinary identifiers, but can never be registered as a namespace: the
|
|
282
|
+
standard macros are written on them.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The activation: the values an expression reads names from.
|
|
3
|
+
*
|
|
4
|
+
* Two rules, both of which the checker already applies to types, so the evaluator must
|
|
5
|
+
* apply them to values or `telo check` and the runtime disagree:
|
|
6
|
+
*
|
|
7
|
+
* - **A dotted declaration is one name, and the longest one wins.** A host may hold
|
|
8
|
+
* `a.b.c`, or `a.b` holding a map, or both; `a.b.c` reads the entry of that name where
|
|
9
|
+
* it is held and the map's entry where only `a.b` is. So resolution tries the longest
|
|
10
|
+
* prefix first, exactly as `qualifiedVariableType` does at check.
|
|
11
|
+
* - **A read is an OWN entry**, never an inherited one, so an activation whose prototype
|
|
12
|
+
* is `Object.prototype` cannot answer `constructor` or `toString`.
|
|
13
|
+
*
|
|
14
|
+
* A name nothing holds is `no_such_variable` — the error value, so it short-circuits like
|
|
15
|
+
* any other. A value read from here is a HOST's, so it is admitted through the backend's
|
|
16
|
+
* one entry point for a host value, which is where a thenable is refused.
|
|
17
|
+
*/
|
|
18
|
+
/** What a host binds names to. A value is read through the guard below, never trusted. */
|
|
19
|
+
export interface CelActivation {
|
|
20
|
+
readonly [name: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether the activation holds a name itself. The backend asks this for each prefix of a
|
|
24
|
+
* dotted chain, longest first, having built the prefixes once at compile time.
|
|
25
|
+
*/
|
|
26
|
+
export declare function activationHolds(activation: CelActivation, name: string): boolean;
|
|
27
|
+
//# sourceMappingURL=activation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../src/activation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The activation: the values an expression reads names from.
|
|
3
|
+
*
|
|
4
|
+
* Two rules, both of which the checker already applies to types, so the evaluator must
|
|
5
|
+
* apply them to values or `telo check` and the runtime disagree:
|
|
6
|
+
*
|
|
7
|
+
* - **A dotted declaration is one name, and the longest one wins.** A host may hold
|
|
8
|
+
* `a.b.c`, or `a.b` holding a map, or both; `a.b.c` reads the entry of that name where
|
|
9
|
+
* it is held and the map's entry where only `a.b` is. So resolution tries the longest
|
|
10
|
+
* prefix first, exactly as `qualifiedVariableType` does at check.
|
|
11
|
+
* - **A read is an OWN entry**, never an inherited one, so an activation whose prototype
|
|
12
|
+
* is `Object.prototype` cannot answer `constructor` or `toString`.
|
|
13
|
+
*
|
|
14
|
+
* A name nothing holds is `no_such_variable` — the error value, so it short-circuits like
|
|
15
|
+
* any other. A value read from here is a HOST's, so it is admitted through the backend's
|
|
16
|
+
* one entry point for a host value, which is where a thenable is refused.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Whether the activation holds a name itself. The backend asks this for each prefix of a
|
|
20
|
+
* dotted chain, longest first, having built the prefixes once at compile time.
|
|
21
|
+
*/
|
|
22
|
+
export function activationHolds(activation, name) {
|
|
23
|
+
return Object.prototype.hasOwnProperty.call(activation, name);
|
|
24
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a backend does at each kind of site — once, for both of them.
|
|
3
|
+
*
|
|
4
|
+
* `runtime-library.ts` holds what every operator and standard function **does**. This
|
|
5
|
+
* holds everything *around* a call: admitting a host value, reading a member in every
|
|
6
|
+
* form, taking a bool operand, reading a name or a dotted chain, and the per-call-site
|
|
7
|
+
* overload dispatch with its bounded cache. None of it is a tree walk and none of it is an
|
|
8
|
+
* operator, which is exactly why it cannot live in a backend: the closure backend compiles
|
|
9
|
+
* a tree to closures and the emitter compiles the same tree to JavaScript source, and both
|
|
10
|
+
* call *these* functions. A second copy of the dispatch rule or the member-read rule is a
|
|
11
|
+
* second set of answers, and the whole point of two backends over one runtime is that
|
|
12
|
+
* there is one answer per operation.
|
|
13
|
+
*
|
|
14
|
+
* So the emitter emits a call to `readThrough` and never a bare `obj.name`; it emits a
|
|
15
|
+
* `CallSite` per call and never its own overload search; and a thenable is refused at the
|
|
16
|
+
* same doors on both backends because the doors are here.
|
|
17
|
+
*/
|
|
18
|
+
import type { CelActivation } from "./activation.js";
|
|
19
|
+
import type { CelType } from "./cel-type.js";
|
|
20
|
+
import type { CelError, CelOptional, CelValue } from "./cel-value.js";
|
|
21
|
+
import type { FunctionRegistry } from "./function-registry.js";
|
|
22
|
+
import type { CelImplementation } from "./runtime-library.js";
|
|
23
|
+
import type { CallForm } from "./signature.js";
|
|
24
|
+
import type { CelSelectNode, SourceRange } from "./syntax-tree.js";
|
|
25
|
+
/** A compile-time refusal: a tree neither backend can compile at all. */
|
|
26
|
+
export declare class CelCompileError extends Error {
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
/** How many distinct argument-type combinations one call site remembers. */
|
|
30
|
+
export declare const CALL_SITE_CACHE_CAPACITY = 16;
|
|
31
|
+
/** What a namespaced call is dispatched through, when something bound it. */
|
|
32
|
+
export type NamespaceDispatch = (namespace: string, name: string) => CelImplementation | undefined;
|
|
33
|
+
export interface EvaluationFrame {
|
|
34
|
+
readonly activation: CelActivation;
|
|
35
|
+
readonly slots: CelValue[];
|
|
36
|
+
/** Absent rather than optional: one frame shape, however the evaluation was started. */
|
|
37
|
+
readonly namespaceFunction: NamespaceDispatch | undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* One evaluation of one expression. The closure backend builds these by composition and
|
|
41
|
+
* the emitter's module returns them already built, so a program is indifferent to which
|
|
42
|
+
* backend produced it.
|
|
43
|
+
*/
|
|
44
|
+
export type CelStep = (frame: EvaluationFrame) => CelValue;
|
|
45
|
+
/** What a backend needs of the environment it compiles against. */
|
|
46
|
+
export interface CompileTarget {
|
|
47
|
+
readonly registry: FunctionRegistry;
|
|
48
|
+
/** The library's own names — the type values and `google`. */
|
|
49
|
+
readonly constants: ReadonlyMap<string, CelValue>;
|
|
50
|
+
/** How many type arguments a host's named type takes, for dispatch on one of its values. */
|
|
51
|
+
readonly nominalArity: (name: string) => number | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Whether a host DECLARED this name — including a dotted one. It decides where a chain
|
|
54
|
+
* splits, at compile time, through the same function the checker uses.
|
|
55
|
+
*/
|
|
56
|
+
readonly declares: (name: string) => boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A host value entering the engine — from an activation, from an implementation the host
|
|
60
|
+
* registered, or out of a host value a read reached into. A thenable is refused here rather
|
|
61
|
+
* than carried: an awaiting expression is an invocation in disguise, invisible to a journal
|
|
62
|
+
* and absent from a trace. The refusal itself lives in `cel-value.ts`, so every door answers
|
|
63
|
+
* with the same code and the same wording.
|
|
64
|
+
*/
|
|
65
|
+
export declare function readHostValue(value: unknown, range: SourceRange): CelValue;
|
|
66
|
+
/** A bare name: the activation's own entry, then the library's constants. */
|
|
67
|
+
export declare function readName(activation: CelActivation, constants: ReadonlyMap<string, CelValue>, name: string, range: SourceRange): CelValue;
|
|
68
|
+
/**
|
|
69
|
+
* One name read from the activation (or the library's constants), then its members. This
|
|
70
|
+
* is a chain whose split is already decided — at compile time, over the names the host
|
|
71
|
+
* declared (`declared-chain.ts`) — so evaluating it is one lookup plus member reads.
|
|
72
|
+
*/
|
|
73
|
+
export declare function readNameChain(activation: CelActivation, constants: ReadonlyMap<string, CelValue>, name: string, rest: readonly string[], range: SourceRange): CelValue;
|
|
74
|
+
/** One prefix of a dotted chain, and the segments left to read off its value. */
|
|
75
|
+
export interface ChainCandidate {
|
|
76
|
+
readonly name: string;
|
|
77
|
+
readonly rest: readonly string[];
|
|
78
|
+
}
|
|
79
|
+
/** Every prefix of a dotted chain, longest first, with the segments left to read. */
|
|
80
|
+
export declare function prefixCandidates(segments: readonly string[]): readonly ChainCandidate[];
|
|
81
|
+
/**
|
|
82
|
+
* A chain **no** prefix of which the host declared: the activation is searched, longest
|
|
83
|
+
* prefix first. Every conformance row that binds a dotted key reads this way, and the
|
|
84
|
+
* checker has no opinion about such a chain either.
|
|
85
|
+
*/
|
|
86
|
+
export declare function searchNameChain(activation: CelActivation, constants: ReadonlyMap<string, CelValue>, candidates: readonly ChainCandidate[], written: string, range: SourceRange): CelValue;
|
|
87
|
+
/**
|
|
88
|
+
* The dotted chain a select spells, when every step is a plain named member of a **free**
|
|
89
|
+
* name. A name a macro bound is a value, so a chain rooted at one is an ordinary member
|
|
90
|
+
* read — the same rule the checker applies, and the same answer both backends compile.
|
|
91
|
+
*/
|
|
92
|
+
export declare function plainMemberChain(node: CelSelectNode, bound: (name: string) => boolean): readonly string[] | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* A member read in every form. Reading **through an optional** answers an optional
|
|
95
|
+
* whichever form the read is written in, which is what lets a chain over a value that
|
|
96
|
+
* may be absent stay one expression: an absent one propagates as absent, a key the held
|
|
97
|
+
* value does not have is absent too, and a held value that holds no members at all is
|
|
98
|
+
* still the mistake it would be outside an optional.
|
|
99
|
+
*/
|
|
100
|
+
export declare function readThrough(container: CelValue, key: CelValue, optionalForm: boolean, range: SourceRange): CelValue;
|
|
101
|
+
/**
|
|
102
|
+
* `has(a.b)` — presence, which a missing key answers `false` for rather than erroring.
|
|
103
|
+
* An absent optional has no members, and a present one is asked about what it holds.
|
|
104
|
+
*/
|
|
105
|
+
export declare function hasMember(container: CelValue, field: CelValue, range: SourceRange): CelValue;
|
|
106
|
+
/** A bool operand, or the error it is — a non-bool is a mistake of its own. */
|
|
107
|
+
export declare function boolOperand(value: CelValue, range: SourceRange): boolean | CelError;
|
|
108
|
+
/** What an optional entry of an aggregate contributes, or the error it is not one. */
|
|
109
|
+
export declare function optionalEntry(value: CelValue, range: SourceRange): CelOptional | CelError;
|
|
110
|
+
/**
|
|
111
|
+
* One call site, and the overloads it has resolved.
|
|
112
|
+
*
|
|
113
|
+
* **Overloads are resolved on the values' own types**, per site: `dyn(1.0) == 1` checks and
|
|
114
|
+
* must then answer across the numeric types, so the statically resolved signature is not
|
|
115
|
+
* enough. A site is almost always monomorphic, so the last resolution is held beside a
|
|
116
|
+
* bounded cache and reached by comparing the type names themselves — building a cache key
|
|
117
|
+
* per call is the allocation that costs most on the hottest path there is. A container's
|
|
118
|
+
* element type is read as `dyn` rather than walked, so dispatch does not get more expensive
|
|
119
|
+
* as the data gets larger.
|
|
120
|
+
*
|
|
121
|
+
* The arguments arrive **already evaluated and already free of errors**: carrying an
|
|
122
|
+
* error-valued operand out is the caller's, because only the caller knows how far it got.
|
|
123
|
+
*/
|
|
124
|
+
export declare class CallSite {
|
|
125
|
+
private readonly name;
|
|
126
|
+
private readonly form;
|
|
127
|
+
private readonly range;
|
|
128
|
+
private readonly registry;
|
|
129
|
+
private readonly nominalArity;
|
|
130
|
+
private readonly resolved;
|
|
131
|
+
private readonly context;
|
|
132
|
+
private lastNames;
|
|
133
|
+
private lastDispatch;
|
|
134
|
+
constructor(name: string, form: CallForm, range: SourceRange, registry: FunctionRegistry, nominalArity: (name: string) => number | undefined);
|
|
135
|
+
call(values: readonly CelValue[]): CelValue;
|
|
136
|
+
private answer;
|
|
137
|
+
}
|
|
138
|
+
/** A call site over an environment, which both backends build one of per call. */
|
|
139
|
+
export declare function callSiteOf(target: CompileTarget, name: string, form: CallForm, range: SourceRange): CallSite;
|
|
140
|
+
/**
|
|
141
|
+
* The type of a value, for dispatch. A container's element type is `dyn`: reading it
|
|
142
|
+
* exactly would mean walking the data on every call, and the registry's loose pass
|
|
143
|
+
* resolves a parameterized overload against `dyn` anyway.
|
|
144
|
+
*/
|
|
145
|
+
export declare function runtimeType(value: CelValue, nominalArity: (name: string) => number | undefined): CelType;
|
|
146
|
+
//# sourceMappingURL=backend-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-runtime.d.ts","sourceRoot":"","sources":["../src/backend-runtime.ts"],"names":[],"mappings":"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"}
|