@intentius/tsad-reference 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CAVEATS.md +95 -0
  2. package/README.md +42 -0
  3. package/dist/adapter.d.ts +5 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +50 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/fnbody.d.ts +11 -0
  8. package/dist/fnbody.d.ts.map +1 -0
  9. package/dist/fnbody.js +68 -0
  10. package/dist/fnbody.js.map +1 -0
  11. package/dist/fold.d.ts +86 -0
  12. package/dist/fold.d.ts.map +1 -0
  13. package/dist/fold.js +558 -0
  14. package/dist/fold.js.map +1 -0
  15. package/dist/foldable-helpers.d.ts +23 -0
  16. package/dist/foldable-helpers.d.ts.map +1 -0
  17. package/dist/foldable-helpers.js +25 -0
  18. package/dist/foldable-helpers.js.map +1 -0
  19. package/dist/host.d.ts +45 -0
  20. package/dist/host.d.ts.map +1 -0
  21. package/dist/host.js +5 -0
  22. package/dist/host.js.map +1 -0
  23. package/dist/index.d.ts +9 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +9 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/module.d.ts +20 -0
  28. package/dist/module.d.ts.map +1 -0
  29. package/dist/module.js +74 -0
  30. package/dist/module.js.map +1 -0
  31. package/dist/project.d.ts +22 -0
  32. package/dist/project.d.ts.map +1 -0
  33. package/dist/project.js +481 -0
  34. package/dist/project.js.map +1 -0
  35. package/dist/revive.d.ts +16 -0
  36. package/dist/revive.d.ts.map +1 -0
  37. package/dist/revive.js +109 -0
  38. package/dist/revive.js.map +1 -0
  39. package/dist/subset.d.ts +42 -0
  40. package/dist/subset.d.ts.map +1 -0
  41. package/dist/subset.js +214 -0
  42. package/dist/subset.js.map +1 -0
  43. package/package.json +37 -0
  44. package/src/adapter.ts +48 -0
  45. package/src/fnbody.ts +61 -0
  46. package/src/fold.ts +581 -0
  47. package/src/foldable-helpers.ts +38 -0
  48. package/src/host.ts +38 -0
  49. package/src/index.ts +8 -0
  50. package/src/module.ts +52 -0
  51. package/src/no-own-execution.test.ts +86 -0
  52. package/src/prebuild.test.ts +68 -0
  53. package/src/project.ts +495 -0
  54. package/src/revive.ts +120 -0
  55. package/src/subset.ts +224 -0
package/CAVEATS.md ADDED
@@ -0,0 +1,95 @@
1
+ # What the reference implementation does not do, and what it found
2
+
3
+ This package is written from `spec/` and nothing else (#50). Where the
4
+ specification is silent, ambiguous, or asks for something the package cannot
5
+ supply, the gap is recorded here rather than papered over in the code.
6
+
7
+ ## Two identity predicates
8
+
9
+ Resolved in the specification by **F-Identity** (J3), which names the entity
10
+ test and the reference test, says the entity test is the normative one, and
11
+ says F-Import over-approximates on purpose. This package follows it: the
12
+ reference test for import and re-export captures, the entity test for call
13
+ leaks. Kept here as a pointer, because the code comments cite F-Identity and
14
+ a reader of an older revision will not find it (#59).
15
+
16
+ ## Revival needs a host, and one envelope has no fate here
17
+
18
+ **F-Val-Fate** is implemented (#61): a declarator's value is revived through
19
+ the folding file's own imports, so a `{__resource}` becomes a real instance of
20
+ the class the host supplies, `{__intrinsic}` and `{__helper}` are invoked, and
21
+ `{__symbol}` resolves as a dotted chain. `{__attrRef}` passes through, and is
22
+ rejected inside a host call's arguments per **F-Val-Position**.
23
+
24
+ Two limits remain.
25
+
26
+ `{__compositeStep}` has no fate here. Its revival is "resolve the composite
27
+ (J2 F-Call), then read `.step` off the real result", and this package has no
28
+ composite factory form, so revival rejects rather than guessing.
29
+
30
+ Revival can only construct what a host supplies. With `EMPTY_HOST` an envelope
31
+ has no class to become and revival rejects, which is correct rather than
32
+ silent: a build that folds a resource and cannot revive it has not folded the
33
+ file. Conformance fixtures name the host they need.
34
+
35
+ ## The composite factory form, measured
36
+
37
+ The corpus cross-check (#25) puts a number on the gap above: 272 of chant's
38
+ 409 corpus files reach a composite factory call, directly or through a file
39
+ that does, and none of them can be compared until this package has the form.
40
+ The count is in `packages/conformance/corpus-report.md`.
41
+
42
+ ## Capture reaches inside an entity
43
+
44
+ **F-Capture** is decided over the produced namespace, and the walk that decides
45
+ it descends through an entity's own data properties, enumerable or not, and
46
+ through a `WeakRef` to what it holds. chant's entity classes keep their props
47
+ on a non-enumerable property and an attribute reference keeps its entity
48
+ behind a `WeakRef`, so a walk over `Object.values` records no capture for the
49
+ two ordinary cases: a shared object passed to a constructor, and an output
50
+ built from another file's attribute. Neither was visible until the corpus ran
51
+ against a real host (#25), because with `EMPTY_HOST` an entity never becomes
52
+ an instance. Accessors are skipped, not invoked; one of chant's throws when
53
+ read too early.
54
+
55
+ ## Same-file constructions are pre-built
56
+
57
+ **F-Prebuild** (#68) is implemented: every top-level `const n = new T(…)` is
58
+ constructed once, in source order, before any declarator is evaluated, and a
59
+ reference to it reads that instance. This package originally rejected such a
60
+ reference, which was the reading F-Eval-Ident step 1 licensed before the rule
61
+ existed; the corpus found twelve chant examples that fold the shape.
62
+
63
+ ## Capture at the import, and over the namespace
64
+
65
+ **F-Import** records a capture at the import for any imported value with
66
+ identity, by F-Identity's reference test; **F-Capture** is decided over the
67
+ produced namespace as well. This package did only the second until the
68
+ corpus at `chant-v0.71.0` showed three files that read a primitive out of an
69
+ imported object, held no object in their namespace, and were tainted by
70
+ chant as F-Import's text says; it now does both (#96). A project-local
71
+ function is excluded at the import, since it is a callable rather than a
72
+ value and F-CallLeak decides its edge at the call.
73
+
74
+ ## No rules, and no provenance
75
+
76
+ `rules.md` (spec `1.4`) specifies the contract a semantic rule runs under. This package runs none: it has no rule hook, and no value provenance, so a finding it produced could name no source line. Both wait on the harness half (#101).
77
+
78
+ ## No filesystem, no module resolution algorithm
79
+
80
+ `foldProject` takes a map of path to source. Specifier resolution joins the
81
+ specifier to the importer's directory, normalises `..` segments, and tries
82
+ the three obvious candidates, `g`, `g.ts`, `g/index.ts`, against that map's
83
+ keys. An earlier version left `../` specifiers unjoined, which dropped an
84
+ import edge and a forward taint with it; the corpus found it (#96). The
85
+ specification does not define a resolution algorithm, and does not need to:
86
+ J3's `→` is "`f` imports `g`, `g ∈ F`" for whatever resolution the host uses.
87
+ A conformance fixture therefore never depends on a resolution subtlety.
88
+
89
+ ## No isolation mode
90
+
91
+ `ι` is always `open`. **F-IsolatedRefusal** distinguishes a mode in which
92
+ resolving a binding would import or invoke project code, and this package
93
+ never imports or invokes anything: every call it admits is J1's project-local
94
+ call, which F-IsolatedRefusal explicitly does not restrict. The mode is
95
+ therefore unobservable here, not unimplemented.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # @intentius/tsad-reference
2
+
3
+ A reference implementation of the specification in `spec/`, written from the
4
+ specification text and nothing else (#50).
5
+
6
+ ## What it implements, and what it does not
7
+
8
+ Implemented: shape classification, expression evaluation (J1), the per-file
9
+ verdict and the identity-taint fixpoint (J2, J3, since #60), revival through
10
+ a host's real constructors (F-Val-Fate, since #64), and the host interface's
11
+ registry, helper allowlist, owned-specifier prefixes and values. It declares
12
+ the specification version it implements (`specVersion` on its adapter), and
13
+ the suite holds that to `spec/VERSION`.
14
+
15
+ Not implemented, with the reason for each: `CAVEATS.md`. The composite factory
16
+ form and isolation mode are the two that cost fixtures.
17
+
18
+ ## As a package
19
+
20
+ `@intentius/tsad-reference` depends on `@intentius/tsad-conformance` for the
21
+ adapter and host types only. Its major and minor are the specification version
22
+ it implements; the patch is its own.
23
+
24
+ ## Provenance
25
+
26
+ From #19 until #50 these files were a *port* of chant's, kept current by a
27
+ sync script and a list of recorded cuts. That guaranteed agreement and made
28
+ agreement uninformative: the cross-check was comparing the same code with
29
+ itself. #50 replaced the ported evaluation layer with one written from the
30
+ specification text.
31
+
32
+ **One honest limit on how independent that is.** The author of the rewrite had
33
+ previously read chant's implementation closely, while writing the
34
+ specification from it. The rewrite was done from `grammar.md` and
35
+ `judgments.md` without consulting the source, but it is not the test a reader
36
+ who had never seen chant would constitute. What it does establish is that the
37
+ specification text is complete enough to implement from, and it found one
38
+ place where it was not: `spec/grammar.md`'s definition of an *unclaimed*
39
+ callee, which four normative sentences used and none defined (#51).
40
+
41
+ The cut list and the sync script are in git history at the commit that removed
42
+ them, as the record of what the host interface was derived from.
@@ -0,0 +1,5 @@
1
+ import type { ConformanceAdapter } from "@intentius/tsad-conformance";
2
+ export declare const referenceAdapter: ConformanceAdapter;
3
+ /** The same implementation judged in the data-host profile: no runtime, and S-ExportDefault admitted. */
4
+ export declare const referenceDataHostAdapter: ConformanceAdapter;
5
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAkC,MAAM,6BAA6B,CAAC;AA6CtG,eAAO,MAAM,gBAAgB,EAAE,kBAAuC,CAAC;AACvE,yGAAyG;AACzG,eAAO,MAAM,wBAAwB,EAAE,kBAA4C,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { EMPTY_HOST } from "./host.js";
2
+ import { shapeOfExport, foldExport } from "./module.js";
3
+ import { foldProject } from "./project.js";
4
+ /** A named conformance host, in this implementation's own terms. */
5
+ function hostOf(h, profile) {
6
+ if (!h)
7
+ return { ...EMPTY_HOST, profile };
8
+ return {
9
+ profile,
10
+ intrinsics: h.intrinsics.map((i) => ({ name: i.name, isTag: i.isTag, foldsAsCall: i.foldsAsCall, foldsEagerly: i.foldsEagerly, outputKey: i.outputKey })),
11
+ helpers: h.helpers,
12
+ ownedSpecifierPrefixes: h.ownedSpecifierPrefixes,
13
+ values: h.values,
14
+ };
15
+ }
16
+ /** The reference reports spec rule identifiers directly: it is written from the spec. One adapter per profile (F-Profile). */
17
+ function adapterFor(profile) {
18
+ return {
19
+ name: profile === "full" ? "reference" : `reference/${profile}`,
20
+ // Bumped by hand when the rule set this package implements moves; the
21
+ // conformance suite fails when it and spec/VERSION disagree (#18).
22
+ specVersion: "1.4",
23
+ shape(source, exportName) {
24
+ const v = shapeOfExport(source, exportName, { ...EMPTY_HOST, profile });
25
+ if (v === "no-such-export")
26
+ return { accepted: false, line: 1, column: 1, message: `no export named ${exportName}` };
27
+ if (!v)
28
+ return { accepted: true };
29
+ const { line, character } = v.node.getSourceFile().getLineAndCharacterOfPosition(v.node.getStart());
30
+ return { accepted: false, rule: v.rule, line: line + 1, column: character + 1, message: v.message };
31
+ },
32
+ foldExport(source, exportName) { return foldExport(source, exportName, { ...EMPTY_HOST, profile }); },
33
+ foldProject(files, host) {
34
+ const r = foldProject(files, hostOf(host, profile));
35
+ const out = { verdicts: {}, tentative: {}, taintedBy: {} };
36
+ for (const [path, v] of r.verdicts) {
37
+ out.verdicts[path] = v.kind === "fold" ? { kind: "fold", exports: Object.fromEntries(v.exports) } : { kind: "run", rule: v.rule, reason: v.reason };
38
+ }
39
+ for (const [path, v] of r.tentative)
40
+ out.tentative[path] = v.kind;
41
+ for (const [path, from] of r.taintSource)
42
+ out.taintedBy[path] = from;
43
+ return out;
44
+ },
45
+ };
46
+ }
47
+ export const referenceAdapter = adapterFor("full");
48
+ /** The same implementation judged in the data-host profile: no runtime, and S-ExportDefault admitted. */
49
+ export const referenceDataHostAdapter = adapterFor("data-host");
50
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * S-FnBody, grammar.md §3: the statement sub-grammar a project-local function
3
+ * must satisfy before J1's F-Eval-CallLocal will evaluate it.
4
+ */
5
+ import * as ts from "typescript";
6
+ export type FnDecl = ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression;
7
+ /** A binding element the sub-grammar admits: `{ a }` or `{ a: b }`, nothing else. */
8
+ export declare function plainBindingKey(el: ts.BindingElement): string | undefined;
9
+ /** A reason the function is outside S-FnBody, or undefined when it is admissible. */
10
+ export declare function findFnBodyViolation(fn: FnDecl): string | undefined;
11
+ //# sourceMappingURL=fnbody.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fnbody.d.ts","sourceRoot":"","sources":["../src/fnbody.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,mBAAmB,GAAG,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,kBAAkB,CAAC;AAEvF,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA4ClE"}
package/dist/fnbody.js ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * S-FnBody, grammar.md §3: the statement sub-grammar a project-local function
3
+ * must satisfy before J1's F-Eval-CallLocal will evaluate it.
4
+ */
5
+ import * as ts from "typescript";
6
+ /** A binding element the sub-grammar admits: `{ a }` or `{ a: b }`, nothing else. */
7
+ export function plainBindingKey(el) {
8
+ if (el.dotDotDotToken || el.initializer || !ts.isIdentifier(el.name))
9
+ return undefined;
10
+ const key = el.propertyName ?? el.name;
11
+ return ts.isIdentifier(key) || ts.isStringLiteral(key) || ts.isNumericLiteral(key) ? key.text : undefined;
12
+ }
13
+ /** A reason the function is outside S-FnBody, or undefined when it is admissible. */
14
+ export function findFnBodyViolation(fn) {
15
+ if (fn.asteriskToken)
16
+ return "a generator function is not foldable";
17
+ if (fn.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword))
18
+ return "an async function is not foldable";
19
+ if (!fn.body)
20
+ return "a function without a body is not foldable";
21
+ for (const p of fn.parameters) {
22
+ if (p.dotDotDotToken)
23
+ return "a rest parameter is not foldable";
24
+ if (ts.isIdentifier(p.name))
25
+ continue;
26
+ if (ts.isObjectBindingPattern(p.name)) {
27
+ for (const el of p.name.elements) {
28
+ if (plainBindingKey(el) === undefined)
29
+ return "a destructured parameter with a rest, default, or nested element is not foldable";
30
+ }
31
+ continue;
32
+ }
33
+ return "an array-destructured parameter is not foldable";
34
+ }
35
+ if (!ts.isBlock(fn.body))
36
+ return undefined; // a concise expression body
37
+ const statements = fn.body.statements;
38
+ for (let i = 0; i < statements.length; i += 1) {
39
+ const st = statements[i];
40
+ const last = i === statements.length - 1;
41
+ if (ts.isReturnStatement(st)) {
42
+ if (!last)
43
+ return "an early `return` is not foldable";
44
+ continue;
45
+ }
46
+ if (!ts.isVariableStatement(st)) {
47
+ return `\`${ts.SyntaxKind[st.kind]}\` in a function body is not foldable, only \`const\` declarations and a final \`return\` are`;
48
+ }
49
+ if ((st.declarationList.flags & ts.NodeFlags.Const) === 0)
50
+ return "`let`/`var` in a function body is not foldable";
51
+ for (const d of st.declarationList.declarations) {
52
+ if (!d.initializer)
53
+ return "an uninitialized `const` in a function body is not foldable";
54
+ if (ts.isIdentifier(d.name))
55
+ continue;
56
+ if (ts.isObjectBindingPattern(d.name)) {
57
+ for (const el of d.name.elements) {
58
+ if (plainBindingKey(el) === undefined)
59
+ return "a destructured `const` with a rest, default, or nested element is not foldable";
60
+ }
61
+ continue;
62
+ }
63
+ return "an array-destructured `const` in a function body is not foldable";
64
+ }
65
+ }
66
+ return undefined;
67
+ }
68
+ //# sourceMappingURL=fnbody.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fnbody.js","sourceRoot":"","sources":["../src/fnbody.ts"],"names":[],"mappings":"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"}
package/dist/fold.d.ts ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Expression evaluation: judgments.md J1, one branch per F-Eval-* rule.
3
+ *
4
+ * Written from the specification text, not derived from any implementation
5
+ * (#50). Executes nothing of the source under fold. Its only executions are
6
+ * F-Eval-CallEager and F-Eval-CallMethod on a real receiver, both of which
7
+ * run code the file imported rather than code it wrote.
8
+ */
9
+ import * as ts from "typescript";
10
+ import { type IntrinsicDef } from "./host.js";
11
+ import { type FnDecl } from "./fnbody.js";
12
+ /** A located rejection, per R9.3: the node and the rule, wording unconstrained. */
13
+ export declare class FoldRejection extends Error {
14
+ readonly rule: string;
15
+ readonly line: number;
16
+ readonly column: number;
17
+ constructor(rule: string, line: number, column: number, message: string);
18
+ }
19
+ /** Γ = (consts, externals, depth), per R6.6. */
20
+ export interface Scope {
21
+ readonly consts: Map<string, ts.Expression>;
22
+ readonly externals: ReadonlyMap<string, unknown>;
23
+ readonly depth: number;
24
+ /**
25
+ * F-Capture's sink for the file being folded, when there is one. A call that
26
+ * leaks the defining module's identity (F-CallLeak) records that module here,
27
+ * which is the same edge an import capture records.
28
+ */
29
+ readonly captures?: Set<string>;
30
+ }
31
+ /** H = (ρ, helpers). The helper allowlist is consulted through foldable-helpers. */
32
+ export interface EvalHost {
33
+ readonly intrinsics: readonly IntrinsicDef[];
34
+ }
35
+ /**
36
+ * F-Val-Callable's marker. J1 may *call* one; it is never a value. Only the
37
+ * module layer populates `externals` with these, so nothing produces one in
38
+ * this implementation yet (#21, #22).
39
+ */
40
+ export declare class FoldableFunction {
41
+ readonly name: string;
42
+ readonly fn: FnDecl;
43
+ /** The defining module's path, for the re-anchored reason of F-Eval-CallLocal step 7. */
44
+ readonly file: string;
45
+ /** The DEFINING module's scope: a body folds there, not in the caller's (R6.6). */
46
+ readonly consts: Map<string, ts.Expression>;
47
+ readonly externals: ReadonlyMap<string, unknown>;
48
+ /** Set when a call returned a live object the body produced (F-CallLeak, J3). */
49
+ leakedIdentity: boolean;
50
+ constructor(name: string, fn: FnDecl,
51
+ /** The defining module's path, for the re-anchored reason of F-Eval-CallLocal step 7. */
52
+ file: string,
53
+ /** The DEFINING module's scope: a body folds there, not in the caller's (R6.6). */
54
+ consts: Map<string, ts.Expression>, externals: ReadonlyMap<string, unknown>);
55
+ }
56
+ export declare const isFoldableFunction: (v: unknown) => v is FoldableFunction;
57
+ /**
58
+ * F-Val-Live: carries a live object when it, or anything reachable through
59
+ * plain objects and arrays, has a prototype other than the plain ones, or is
60
+ * a function. This is F-Identity's entity test, the normative one, and the
61
+ * test F-CallLeak uses. F-Import uses the broader reference test instead, on
62
+ * purpose; F-Identity in J3 says why.
63
+ */
64
+ export declare function carriesLiveObject(v: unknown, seen?: Set<unknown>): boolean;
65
+ /**
66
+ * The non-recursive half of F-Val-Live: this value *is* a live object, rather
67
+ * than a plain structure that may hold one. Revival passes these through
68
+ * unchanged (L6.1); rebuilding one would destroy the identity J3 preserves.
69
+ */
70
+ export declare function isLiveObject(v: unknown): boolean;
71
+ export declare function isEnvelope(v: unknown): boolean;
72
+ /** The depth bound of F-Eval-CallLocal step 2, stated per F-Depth. */
73
+ export declare const MAX_CALL_DEPTH = 32;
74
+ /** Γ, H ⊢ e ⇓ v. */
75
+ export declare function foldExpr(node: ts.Expression, scope: Scope, host: EvalHost): unknown;
76
+ /** F-Bind: a top-level `const` with an identifier name and an initializer. */
77
+ export declare function collectConsts(sf: ts.SourceFile): Map<string, ts.Expression>;
78
+ /**
79
+ * S-LocalFunction, F-Bind: every top-level `function` declaration, exported or
80
+ * not, and every top-level `const` bound to an arrow or function expression,
81
+ * as `FoldableFunction` markers for the file's own scope. A call reaches
82
+ * F-Eval-CallLocal; a use as a value is F-Eval-Ident step 3's rejection. The
83
+ * body is judged by S-FnBody at the call, never here (spec 1.2, #95).
84
+ */
85
+ export declare function collectLocalFunctions(sf: ts.SourceFile, file: string, consts: Map<string, ts.Expression>, externals: ReadonlyMap<string, unknown>): FoldableFunction[];
86
+ //# sourceMappingURL=fold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../src/fold.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAwC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEhF,mFAAmF;AACnF,qBAAa,aAAc,SAAQ,KAAK;IAEpC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAFd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM;CAKlB;AAED,gDAAgD;AAChD,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACjC;AACD,oFAAoF;AACpF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;CAC9C;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAIzB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM;IACnB,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IATlD,iFAAiF;IACjF,cAAc,UAAS;gBAEZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM;IACnB,yFAAyF;IAChF,IAAI,EAAE,MAAM;IACrB,mFAAmF;IAC1E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,EAClC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;CAEnD;AACD,eAAO,MAAM,kBAAkB,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,gBAAiD,CAAC;AASvG;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,eAAqB,GAAG,OAAO,CAMhF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAKhD;AAID,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAG9C;AAqGD,sEAAsE;AACtE,eAAO,MAAM,cAAc,KAAK,CAAC;AAqEjC,oBAAoB;AACpB,wBAAgB,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CA6PnF;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,CAY3E;AAKD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,EAAE,CAAC,UAAU,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,EAClC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC,gBAAgB,EAAE,CAepB"}