@telorun/cel 0.0.0-stage → 0.108.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 +184 -0
- package/dist/backend-runtime.d.ts.map +1 -0
- package/dist/backend-runtime.js +425 -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 +786 -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 +47 -0
- package/dist/cel-map-value.d.ts.map +1 -0
- package/dist/cel-map-value.js +85 -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 +166 -0
- package/dist/cel-value.d.ts.map +1 -0
- package/dist/cel-value.js +225 -0
- package/dist/check-diagnostic.d.ts +54 -0
- package/dist/check-diagnostic.d.ts.map +1 -0
- package/dist/check-diagnostic.js +66 -0
- package/dist/checker.d.ts +86 -0
- package/dist/checker.d.ts.map +1 -0
- package/dist/checker.js +806 -0
- package/dist/closure-backend.d.ts +21 -0
- package/dist/closure-backend.d.ts.map +1 -0
- package/dist/closure-backend.js +487 -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 +70 -0
- package/dist/duration-value.d.ts.map +1 -0
- package/dist/duration-value.js +149 -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 +291 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +474 -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 +118 -0
- package/dist/function-registry.d.ts.map +1 -0
- package/dist/function-registry.js +292 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -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 +133 -0
- package/dist/js-emitter.d.ts.map +1 -0
- package/dist/js-emitter.js +568 -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 +41 -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 +89 -0
- package/dist/member-read.d.ts.map +1 -0
- package/dist/member-read.js +166 -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 +46 -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 +67 -0
- package/dist/runtime-library.d.ts.map +1 -0
- package/dist/runtime-library.js +554 -0
- package/dist/serializer.d.ts +24 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +256 -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 +62 -0
- package/dist/timestamp-value.d.ts.map +1 -0
- package/dist/timestamp-value.js +238 -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 +42 -0
- package/dist/type-expression.d.ts.map +1 -0
- package/dist/type-expression.js +154 -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 +604 -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 +97 -0
- package/src/cel-program.ts +103 -0
- package/src/cel-type.ts +359 -0
- package/src/cel-value.ts +361 -0
- package/src/check-diagnostic.ts +104 -0
- package/src/checker.ts +1045 -0
- package/src/closure-backend.ts +547 -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 +160 -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 +761 -0
- package/src/function-catalog.ts +140 -0
- package/src/function-registry.ts +341 -0
- package/src/index.ts +407 -0
- package/src/integer-arithmetic.ts +64 -0
- package/src/js-emitter.ts +721 -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 +197 -0
- package/src/macro-shape.ts +66 -0
- package/src/member-read.ts +167 -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 +47 -0
- package/src/root-references.ts +126 -0
- package/src/runtime-library.ts +639 -0
- package/src/serializer.ts +262 -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 +310 -0
- package/src/tree-equality.ts +130 -0
- package/src/type-expression.ts +182 -0
- package/src/value-equality.ts +201 -0
- package/src/value-text.ts +45 -0
- package/src/zoned-calendar.ts +178 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named types a host registers — the one mechanism, with none of the vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* A nominal type is a name over a base type, with its own operators, comparisons,
|
|
5
|
+
* conversions and member functions, and with named **invariant** type parameters. It
|
|
6
|
+
* is not its base: a value of the base does not stand where the named type is wanted,
|
|
7
|
+
* and only what the definition declares applies to it. That is what makes a named type
|
|
8
|
+
* worth having — a slot that wants one refuses a plain value of the base, which is
|
|
9
|
+
* exactly what an engine typing by wrapper class cannot express.
|
|
10
|
+
*
|
|
11
|
+
* Invariance is deliberate: `Holder<string>` and `Holder<int>` are unrelated, so a
|
|
12
|
+
* type argument that differs is a mistake with its own diagnostic rather than a silent
|
|
13
|
+
* widening to the base.
|
|
14
|
+
*
|
|
15
|
+
* `Self` inside a definition names the type being defined, with its own parameters
|
|
16
|
+
* applied, so a member can answer its own type without repeating it.
|
|
17
|
+
*/
|
|
18
|
+
import { parameterOf } from "./cel-type.js";
|
|
19
|
+
import { parseTypeExpression } from "./type-expression.js";
|
|
20
|
+
const NAME = /^[A-Za-z_][A-Za-z0-9_.]*$/;
|
|
21
|
+
const PARAMETER = /^[A-Z]$/;
|
|
22
|
+
const LANGUAGE_NAMES = new Set([
|
|
23
|
+
"dyn",
|
|
24
|
+
"int",
|
|
25
|
+
"uint",
|
|
26
|
+
"double",
|
|
27
|
+
"bool",
|
|
28
|
+
"string",
|
|
29
|
+
"bytes",
|
|
30
|
+
"null",
|
|
31
|
+
"null_type",
|
|
32
|
+
"type",
|
|
33
|
+
"list",
|
|
34
|
+
"map",
|
|
35
|
+
"optional",
|
|
36
|
+
"timestamp",
|
|
37
|
+
"duration",
|
|
38
|
+
]);
|
|
39
|
+
export class CelTypeRegistrationError extends Error {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = "CelTypeRegistrationError";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function validateTypeName(name) {
|
|
46
|
+
if (!NAME.test(name)) {
|
|
47
|
+
throw new CelTypeRegistrationError(`${JSON.stringify(name)} is not spelled as a type name`);
|
|
48
|
+
}
|
|
49
|
+
if (LANGUAGE_NAMES.has(name)) {
|
|
50
|
+
throw new CelTypeRegistrationError(`${JSON.stringify(name)} is a type of the language and cannot be redefined`);
|
|
51
|
+
}
|
|
52
|
+
if (PARAMETER.test(name)) {
|
|
53
|
+
throw new CelTypeRegistrationError(`${JSON.stringify(name)} is a single capital letter, which a signature reads as a type parameter`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Builds the registered form of a definition. `resolveNominal` resolves names the
|
|
58
|
+
* definition's own base or members mention, including itself through `Self`.
|
|
59
|
+
*/
|
|
60
|
+
export function buildRegisteredType(definition, resolveNominal) {
|
|
61
|
+
validateTypeName(definition.name);
|
|
62
|
+
const parameters = definition.parameters ?? [];
|
|
63
|
+
for (const parameter of parameters) {
|
|
64
|
+
if (!PARAMETER.test(parameter)) {
|
|
65
|
+
throw new CelTypeRegistrationError(`type parameter ${JSON.stringify(parameter)} of ${definition.name} must be a single capital letter`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const self = {
|
|
69
|
+
kind: "nominal",
|
|
70
|
+
name: definition.name,
|
|
71
|
+
base: { kind: "dyn" },
|
|
72
|
+
args: parameters.map(parameterOf),
|
|
73
|
+
};
|
|
74
|
+
const withSelf = (name, args) => name === "Self" || name === definition.name
|
|
75
|
+
? { ...self, args: args.length > 0 ? args : self.args }
|
|
76
|
+
: resolveNominal(name, args);
|
|
77
|
+
let base;
|
|
78
|
+
try {
|
|
79
|
+
base = parseTypeExpression(definition.base, withSelf);
|
|
80
|
+
}
|
|
81
|
+
catch (cause) {
|
|
82
|
+
throw new CelTypeRegistrationError(`the base of ${definition.name} does not read as a type: ${cause.message}`);
|
|
83
|
+
}
|
|
84
|
+
return { definition, base, parameters, self: { ...self, base } };
|
|
85
|
+
}
|
|
86
|
+
/** The signatures a definition declares, as text, in registration order. */
|
|
87
|
+
export function nominalSignatures(definition) {
|
|
88
|
+
return [...(definition.conversions ?? []), ...(definition.members ?? [])];
|
|
89
|
+
}
|
|
90
|
+
/** The operator declarations a definition implies, its comparisons expanded. */
|
|
91
|
+
export function nominalOperators(definition) {
|
|
92
|
+
const comparisons = (definition.comparisons ?? []).map((operator) => ({
|
|
93
|
+
operator,
|
|
94
|
+
parameters: ["Self", "Self"],
|
|
95
|
+
returns: "bool",
|
|
96
|
+
}));
|
|
97
|
+
return [...(definition.operators ?? []), ...comparisons];
|
|
98
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which dereferences a guard has proven safe.
|
|
3
|
+
*
|
|
4
|
+
* A value whose declared type admits null is only safely dereferenced where something
|
|
5
|
+
* has proven it is not null, and **what counts as proof is exactly three constructs**:
|
|
6
|
+
* a ternary, `&&` and `||`. Not more, not less. That bound is not a simplification — a
|
|
7
|
+
* consumer switching engines must not newly accept an expression (which recognising
|
|
8
|
+
* another construct would do) nor newly reject one (which recognising fewer would do),
|
|
9
|
+
* and a guard written as a function call is deliberately not proof.
|
|
10
|
+
*
|
|
11
|
+
* The rules, over a condition `c`:
|
|
12
|
+
*
|
|
13
|
+
* - `chain != null` proves `chain` where `c` holds; `chain == null` proves it where `c`
|
|
14
|
+
* fails. `null` may stand on either side of the comparison.
|
|
15
|
+
* - `!c` swaps the two.
|
|
16
|
+
* - `a && b` proves, where it holds, everything `a` and `b` prove; where it fails,
|
|
17
|
+
* nothing, since either arm may be the one that failed.
|
|
18
|
+
* - `a || b` is the mirror: where it fails, both arms failed, so both their negative
|
|
19
|
+
* proofs hold.
|
|
20
|
+
*
|
|
21
|
+
* A chain is a plain path of named members (`error.code`), which is what a proof can
|
|
22
|
+
* name: nothing proves anything about `xs[i].code`, because the index is not part of a
|
|
23
|
+
* name.
|
|
24
|
+
*/
|
|
25
|
+
import type { CelNode } from "./syntax-tree.js";
|
|
26
|
+
/** The dotted path a node spells, if it is a plain chain of named members. */
|
|
27
|
+
export declare function chainText(node: CelNode): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* The name a chain is rooted at, or nothing when it is not a chain of plain members over a
|
|
30
|
+
* name. It is what says whether the chain's subject is a name the EXPRESSION bound — a
|
|
31
|
+
* comprehension variable, a `cel.bind` name — rather than one the host declared.
|
|
32
|
+
*/
|
|
33
|
+
export declare function chainRoot(node: CelNode): string | undefined;
|
|
34
|
+
/** The chains proven non-null where the condition holds. */
|
|
35
|
+
export declare function provenWhereTrue(condition: CelNode): readonly string[];
|
|
36
|
+
/** The chains proven non-null where the condition fails. */
|
|
37
|
+
export declare function provenWhereFalse(condition: CelNode): readonly string[];
|
|
38
|
+
//# sourceMappingURL=nullable-access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nullable-access.d.ts","sourceRoot":"","sources":["../src/nullable-access.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAK3D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI3D;AAED,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAarE;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAatE"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which dereferences a guard has proven safe.
|
|
3
|
+
*
|
|
4
|
+
* A value whose declared type admits null is only safely dereferenced where something
|
|
5
|
+
* has proven it is not null, and **what counts as proof is exactly three constructs**:
|
|
6
|
+
* a ternary, `&&` and `||`. Not more, not less. That bound is not a simplification — a
|
|
7
|
+
* consumer switching engines must not newly accept an expression (which recognising
|
|
8
|
+
* another construct would do) nor newly reject one (which recognising fewer would do),
|
|
9
|
+
* and a guard written as a function call is deliberately not proof.
|
|
10
|
+
*
|
|
11
|
+
* The rules, over a condition `c`:
|
|
12
|
+
*
|
|
13
|
+
* - `chain != null` proves `chain` where `c` holds; `chain == null` proves it where `c`
|
|
14
|
+
* fails. `null` may stand on either side of the comparison.
|
|
15
|
+
* - `!c` swaps the two.
|
|
16
|
+
* - `a && b` proves, where it holds, everything `a` and `b` prove; where it fails,
|
|
17
|
+
* nothing, since either arm may be the one that failed.
|
|
18
|
+
* - `a || b` is the mirror: where it fails, both arms failed, so both their negative
|
|
19
|
+
* proofs hold.
|
|
20
|
+
*
|
|
21
|
+
* A chain is a plain path of named members (`error.code`), which is what a proof can
|
|
22
|
+
* name: nothing proves anything about `xs[i].code`, because the index is not part of a
|
|
23
|
+
* name.
|
|
24
|
+
*/
|
|
25
|
+
/** The dotted path a node spells, if it is a plain chain of named members. */
|
|
26
|
+
export function chainText(node) {
|
|
27
|
+
if (node.kind === "ident")
|
|
28
|
+
return node.name;
|
|
29
|
+
if (node.kind !== "select" || node.optional || node.field === "")
|
|
30
|
+
return undefined;
|
|
31
|
+
const operand = chainText(node.operand);
|
|
32
|
+
return operand === undefined ? undefined : `${operand}.${node.field}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The name a chain is rooted at, or nothing when it is not a chain of plain members over a
|
|
36
|
+
* name. It is what says whether the chain's subject is a name the EXPRESSION bound — a
|
|
37
|
+
* comprehension variable, a `cel.bind` name — rather than one the host declared.
|
|
38
|
+
*/
|
|
39
|
+
export function chainRoot(node) {
|
|
40
|
+
if (node.kind === "ident")
|
|
41
|
+
return node.name;
|
|
42
|
+
if (node.kind !== "select" || node.optional || node.field === "")
|
|
43
|
+
return undefined;
|
|
44
|
+
return chainRoot(node.operand);
|
|
45
|
+
}
|
|
46
|
+
/** The chains proven non-null where the condition holds. */
|
|
47
|
+
export function provenWhereTrue(condition) {
|
|
48
|
+
switch (condition.kind) {
|
|
49
|
+
case "binary":
|
|
50
|
+
if (condition.operator === "!=")
|
|
51
|
+
return nullTest(condition);
|
|
52
|
+
if (condition.operator === "&&") {
|
|
53
|
+
return [...provenWhereTrue(condition.left), ...provenWhereTrue(condition.right)];
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
case "unary":
|
|
57
|
+
return condition.operator === "!" ? provenWhereFalse(condition.operand) : [];
|
|
58
|
+
default:
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** The chains proven non-null where the condition fails. */
|
|
63
|
+
export function provenWhereFalse(condition) {
|
|
64
|
+
switch (condition.kind) {
|
|
65
|
+
case "binary":
|
|
66
|
+
if (condition.operator === "==")
|
|
67
|
+
return nullTest(condition);
|
|
68
|
+
if (condition.operator === "||") {
|
|
69
|
+
return [...provenWhereFalse(condition.left), ...provenWhereFalse(condition.right)];
|
|
70
|
+
}
|
|
71
|
+
return [];
|
|
72
|
+
case "unary":
|
|
73
|
+
return condition.operator === "!" ? provenWhereTrue(condition.operand) : [];
|
|
74
|
+
default:
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** The chain a comparison against `null` is about, either way round. */
|
|
79
|
+
function nullTest(comparison) {
|
|
80
|
+
const { left, right } = comparison;
|
|
81
|
+
if (isNullLiteral(right)) {
|
|
82
|
+
const chain = chainText(left);
|
|
83
|
+
return chain === undefined ? [] : [chain];
|
|
84
|
+
}
|
|
85
|
+
if (isNullLiteral(left)) {
|
|
86
|
+
const chain = chainText(right);
|
|
87
|
+
return chain === undefined ? [] : [chain];
|
|
88
|
+
}
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
function isNullLiteral(node) {
|
|
92
|
+
return node.kind === "literal" && node.literal.type === "null";
|
|
93
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the front end refuses to read because it is too big.
|
|
3
|
+
*
|
|
4
|
+
* An expression arrives from a manifest, from an editor buffer or over a wire, so
|
|
5
|
+
* the parser is a hostile-input boundary: without a bound, nesting alone exhausts
|
|
6
|
+
* the call stack of a recursive-descent parser, and a generated list exhausts
|
|
7
|
+
* memory. Each limit is reported as an ordinary ranged diagnostic — never a
|
|
8
|
+
* thrown error — so an editor keeps the prefix it could read.
|
|
9
|
+
*
|
|
10
|
+
* The defaults are the ones every already-written manifest was accepted under.
|
|
11
|
+
*/
|
|
12
|
+
export interface CelParseLimits {
|
|
13
|
+
/** Nodes in the tree. */
|
|
14
|
+
readonly maxNodes: number;
|
|
15
|
+
/** Nesting depth of the expression grammar. */
|
|
16
|
+
readonly maxDepth: number;
|
|
17
|
+
/** Elements in one list literal. */
|
|
18
|
+
readonly maxListElements: number;
|
|
19
|
+
/** Entries in one map literal. */
|
|
20
|
+
readonly maxMapEntries: number;
|
|
21
|
+
/** Arguments at one call. */
|
|
22
|
+
readonly maxCallArguments: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const DEFAULT_PARSE_LIMITS: CelParseLimits;
|
|
25
|
+
export declare function resolveParseLimits(limits?: Partial<CelParseLimits>): CelParseLimits;
|
|
26
|
+
//# sourceMappingURL=parse-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-limits.d.ts","sourceRoot":"","sources":["../src/parse-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,kCAAkC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,6BAA6B;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,eAAO,MAAM,oBAAoB,EAAE,cAMlC,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAEnF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the front end refuses to read because it is too big.
|
|
3
|
+
*
|
|
4
|
+
* An expression arrives from a manifest, from an editor buffer or over a wire, so
|
|
5
|
+
* the parser is a hostile-input boundary: without a bound, nesting alone exhausts
|
|
6
|
+
* the call stack of a recursive-descent parser, and a generated list exhausts
|
|
7
|
+
* memory. Each limit is reported as an ordinary ranged diagnostic — never a
|
|
8
|
+
* thrown error — so an editor keeps the prefix it could read.
|
|
9
|
+
*
|
|
10
|
+
* The defaults are the ones every already-written manifest was accepted under.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_PARSE_LIMITS = {
|
|
13
|
+
maxNodes: 100000,
|
|
14
|
+
maxDepth: 250,
|
|
15
|
+
maxListElements: 1000,
|
|
16
|
+
maxMapEntries: 1000,
|
|
17
|
+
maxCallArguments: 32,
|
|
18
|
+
};
|
|
19
|
+
export function resolveParseLimits(limits) {
|
|
20
|
+
return limits ? { ...DEFAULT_PARSE_LIMITS, ...limits } : DEFAULT_PARSE_LIMITS;
|
|
21
|
+
}
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CEL's grammar, read by recursive descent into the canonical tree.
|
|
3
|
+
*
|
|
4
|
+
* **Error recovery is the point.** Parsing never throws and never discards what it
|
|
5
|
+
* read: the first thing it cannot read becomes one ranged diagnostic, the reader
|
|
6
|
+
* stops there, and the tree holds the longest prefix it understood with an
|
|
7
|
+
* `unparsed` node where the rest would have been. That is what lets completion and
|
|
8
|
+
* hover work on an expression mid-token, and nothing downstream has to re-parse a
|
|
9
|
+
* shortened prefix to get an answer. A member left unnamed (`request.`) is a select
|
|
10
|
+
* with an **empty field name**, which is the shape completion after a dot reads; an
|
|
11
|
+
* aggregate or a call left open keeps the elements it read. Neither can be
|
|
12
|
+
* serialized, and the diagnostic is what says the tree is incomplete.
|
|
13
|
+
*
|
|
14
|
+
* **Nothing is expanded.** A macro call (`has(x)`, `xs.map(i, i)`, `cel.bind(…)`) is
|
|
15
|
+
* an ordinary call node: expanding it here would make the serializer unable to
|
|
16
|
+
* write the source back, and lowering it to a comprehension is the checker's and a
|
|
17
|
+
* backend's business. A qualified call is not produced here either — see
|
|
18
|
+
* `namespace-resolution.ts`.
|
|
19
|
+
*
|
|
20
|
+
* **A unary minus directly on a numeric literal folds into the literal.** That is
|
|
21
|
+
* how the int64 minimum is written at all, and it keeps `-0.0` a value rather than
|
|
22
|
+
* a negation of zero. A minus on a parenthesized literal does not fold, so the
|
|
23
|
+
* serializer can write a hand-built negation back without changing its shape.
|
|
24
|
+
*/
|
|
25
|
+
import { type CelParseLimits } from "./parse-limits.js";
|
|
26
|
+
import type { CelSyntaxDiagnostic } from "./syntax-diagnostic.js";
|
|
27
|
+
import type { CelNode } from "./syntax-tree.js";
|
|
28
|
+
export interface ParseOptions {
|
|
29
|
+
readonly limits?: Partial<CelParseLimits>;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the optional library's own syntax is read: `[?x]` and `{?k: v}`, whose entry
|
|
32
|
+
* holds an optional and contributes its value type. It follows the environment's
|
|
33
|
+
* `enableOptionalTypes`, because a syntax for a type that does not exist would parse to
|
|
34
|
+
* a tree nothing can check.
|
|
35
|
+
*/
|
|
36
|
+
readonly optionalSyntax?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface ParseResult {
|
|
39
|
+
readonly source: string;
|
|
40
|
+
readonly root: CelNode;
|
|
41
|
+
readonly diagnostics: readonly CelSyntaxDiagnostic[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Reads one CEL expression. Always answers a tree; `diagnostics` holds at most one
|
|
45
|
+
* entry, and holds one exactly when the whole source could not be read.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseSyntax(source: string, options?: ParseOptions): ParseResult;
|
|
48
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,KAAK,cAAc,EAAsB,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,KAAK,EAIV,OAAO,EAGR,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACtD;AA2eD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAK/E"}
|