@astrale-os/kernel-dsl 0.2.0-beta.9 → 1.0.0-beta.1
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/dist/v1/addressing/class-key.js +5 -4
- package/dist/v1/addressing/method-key.js +3 -2
- package/dist/v1/addressing/patterns.d.ts +0 -5
- package/dist/v1/addressing/patterns.js +5 -5
- package/dist/v1/builder/callable/authoring.d.ts +87 -41
- package/dist/v1/builder/callable/authoring.js +29 -14
- package/dist/v1/builder/class/authoring.d.ts +311 -36
- package/dist/v1/builder/class/authoring.js +3 -4
- package/dist/v1/builder/class/property.d.ts +16 -8
- package/dist/v1/builder/class/property.js +21 -5
- package/dist/v1/builder/core/authoring.d.ts +28 -13
- package/dist/v1/builder/core/authoring.js +22 -2
- package/dist/v1/builder/index.d.ts +9 -8
- package/dist/v1/builder/index.js +2 -2
- package/dist/v1/builder/lowering/callable.d.ts +3 -1
- package/dist/v1/builder/lowering/callable.js +43 -51
- package/dist/v1/builder/lowering/class.d.ts +7 -0
- package/dist/v1/builder/lowering/class.js +79 -29
- package/dist/v1/builder/lowering/core.d.ts +3 -2
- package/dist/v1/builder/lowering/core.js +9 -6
- package/dist/v1/builder/lowering/policy.d.ts +8 -1
- package/dist/v1/builder/lowering/policy.js +35 -0
- package/dist/v1/builder/lowering/schema/capture.js +9 -4
- package/dist/v1/builder/lowering/schema/compile.d.ts +2 -2
- package/dist/v1/builder/lowering/schema/compile.js +15 -2
- package/dist/v1/builder/lowering/schema/context.d.ts +11 -8
- package/dist/v1/builder/lowering/schema/context.js +59 -29
- package/dist/v1/builder/lowering/schema/ownership.d.ts +3 -3
- package/dist/v1/builder/lowering/schema/ownership.js +2 -1
- package/dist/v1/builder/lowering/value/compile.js +14 -4
- package/dist/v1/builder/lowering/value/zod.d.ts +7 -6
- package/dist/v1/builder/lowering/value/zod.js +16 -7
- package/dist/v1/builder/lowering/view.d.ts +4 -3
- package/dist/v1/builder/lowering/view.js +2 -14
- package/dist/v1/builder/policy/authoring.d.ts +23 -6
- package/dist/v1/builder/policy/authoring.js +35 -8
- package/dist/v1/builder/schema/define.d.ts +8 -5
- package/dist/v1/builder/schema/diagnostic.d.ts +1 -1
- package/dist/v1/builder/schema/handle.d.ts +2 -1
- package/dist/v1/builder/schema/input.d.ts +9 -1
- package/dist/v1/builder/schema/projection/callable.d.ts +51 -0
- package/dist/v1/builder/schema/projection/callable.js +1 -0
- package/dist/v1/builder/schema/projection/class.d.ts +89 -0
- package/dist/v1/builder/schema/projection/class.js +1 -0
- package/dist/v1/builder/schema/projection/core-input.d.ts +32 -0
- package/dist/v1/builder/schema/projection/core-input.js +1 -0
- package/dist/v1/builder/schema/projection/domain.d.ts +59 -0
- package/dist/v1/builder/schema/projection/domain.js +1 -0
- package/dist/v1/builder/schema/projection/identity.d.ts +39 -0
- package/dist/v1/builder/schema/projection/identity.js +1 -0
- package/dist/v1/builder/schema/projection/model.d.ts +59 -0
- package/dist/v1/builder/schema/projection/model.js +1 -0
- package/dist/v1/builder/schema/projection/property.d.ts +32 -0
- package/dist/v1/builder/schema/projection/property.js +1 -0
- package/dist/v1/builder/schema/projection/resolved-class.d.ts +76 -0
- package/dist/v1/builder/schema/projection/resolved-class.js +1 -0
- package/dist/v1/builder/schema/projection.d.ts +4 -258
- package/dist/v1/builder/value/full-match.js +6 -3
- package/dist/v1/builder/value/path.d.ts +2 -2
- package/dist/v1/builder/value/path.js +2 -2
- package/dist/v1/builder/view/authoring.d.ts +6 -14
- package/dist/v1/builder/view/authoring.js +13 -5
- package/dist/v1/bundle/structure.d.ts +2 -1
- package/dist/v1/compiled/admission/accept.d.ts +1 -1
- package/dist/v1/compiled/admission/accept.js +11 -814
- package/dist/v1/compiled/admission/closure.d.ts +3 -0
- package/dist/v1/compiled/admission/closure.js +173 -0
- package/dist/v1/compiled/admission/diagnostic.d.ts +7 -0
- package/dist/v1/compiled/admission/diagnostic.js +13 -0
- package/dist/v1/compiled/admission/revision.js +9 -1
- package/dist/v1/compiled/admission/semantics/cardinality.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/cardinality.js +113 -0
- package/dist/v1/compiled/admission/semantics/class.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/class.js +125 -0
- package/dist/v1/compiled/admission/semantics/context.d.ts +60 -0
- package/dist/v1/compiled/admission/semantics/context.js +81 -0
- package/dist/v1/compiled/admission/semantics/core.d.ts +35 -0
- package/dist/v1/compiled/admission/semantics/core.js +123 -0
- package/dist/v1/compiled/admission/semantics/edge.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/edge.js +89 -0
- package/dist/v1/compiled/admission/semantics/policy/admit.d.ts +4 -0
- package/dist/v1/compiled/admission/semantics/policy/admit.js +63 -0
- package/dist/v1/compiled/admission/semantics/policy/callable.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/policy/callable.js +72 -0
- package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +24 -0
- package/dist/v1/compiled/admission/semantics/policy/contracts.js +45 -0
- package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/policy/equality.js +27 -0
- package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +9 -0
- package/dist/v1/compiled/admission/semantics/policy/measure.js +81 -0
- package/dist/v1/compiled/admission/semantics/policy/parity.d.ts +4 -0
- package/dist/v1/compiled/admission/semantics/policy/parity.js +138 -0
- package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/policy/pattern.js +78 -0
- package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +28 -0
- package/dist/v1/compiled/admission/semantics/policy/typing.js +206 -0
- package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +10 -0
- package/dist/v1/compiled/admission/semantics/policy/variants.js +65 -0
- package/dist/v1/compiled/admission/semantics.d.ts +1 -1
- package/dist/v1/compiled/admission/semantics.js +8 -1078
- package/dist/v1/compiled/admission/wire/callable.d.ts +6 -0
- package/dist/v1/compiled/admission/wire/callable.js +90 -0
- package/dist/v1/compiled/admission/wire/class.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/class.js +133 -0
- package/dist/v1/compiled/admission/wire/core.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/core.js +32 -0
- package/dist/v1/compiled/admission/wire/dependency.d.ts +14 -0
- package/dist/v1/compiled/admission/wire/dependency.js +43 -0
- package/dist/v1/compiled/admission/wire/entry.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/entry.js +100 -0
- package/dist/v1/compiled/admission/wire/pattern.d.ts +12 -0
- package/dist/v1/compiled/admission/wire/pattern.js +111 -0
- package/dist/v1/compiled/admission/wire/policy.d.ts +10 -0
- package/dist/v1/compiled/admission/wire/policy.js +189 -0
- package/dist/v1/compiled/admission/wire/program.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/program.js +52 -0
- package/dist/v1/compiled/admission/wire/property.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/property.js +74 -0
- package/dist/v1/compiled/admission/wire/reference.d.ts +8 -0
- package/dist/v1/compiled/admission/wire/reference.js +33 -0
- package/dist/v1/compiled/admission/wire/value.d.ts +29 -0
- package/dist/v1/compiled/admission/wire/value.js +98 -0
- package/dist/v1/compiled/admission/wire/view.d.ts +3 -0
- package/dist/v1/compiled/admission/wire/view.js +17 -0
- package/dist/v1/compiled/compiler/compile.js +43 -11
- package/dist/v1/compiled/generated.d.ts +10 -0
- package/dist/v1/compiled/generated.js +15 -0
- package/dist/v1/compiled/loader/load.d.ts +5 -0
- package/dist/v1/compiled/loader/load.js +18 -4
- package/dist/v1/compiled/model/schema.d.ts +16 -7
- package/dist/v1/domain/create.js +18 -28
- package/dist/v1/domain/model/domain.d.ts +0 -1
- package/dist/v1/domain/model/input.d.ts +3 -0
- package/dist/v1/domain/projection/classes.js +13 -41
- package/dist/v1/domain/validation/create.d.ts +2 -0
- package/dist/v1/domain/validation/create.js +12 -0
- package/dist/v1/index.d.ts +5 -2
- package/dist/v1/index.js +3 -1
- package/dist/v1/language/callable/composition.d.ts +27 -0
- package/dist/v1/language/callable/composition.js +52 -0
- package/dist/v1/language/callable/executable.d.ts +6 -0
- package/dist/v1/language/callable/executable.js +4 -0
- package/dist/v1/language/callable/model/callable.d.ts +34 -9
- package/dist/v1/language/callable/model/callable.js +3 -1
- package/dist/v1/language/callable/resolved.d.ts +23 -8
- package/dist/v1/language/class/facets.d.ts +5 -2
- package/dist/v1/language/class/inheritance.d.ts +12 -0
- package/dist/v1/language/class/inheritance.js +25 -0
- package/dist/v1/language/class/lifetime.d.ts +17 -0
- package/dist/v1/language/class/lifetime.js +26 -0
- package/dist/v1/language/class/model/class.d.ts +8 -4
- package/dist/v1/language/class/model/property.d.ts +4 -2
- package/dist/v1/language/class/property-values.js +5 -2
- package/dist/v1/language/class/resolved.d.ts +25 -15
- package/dist/v1/language/core/model/core.d.ts +7 -1
- package/dist/v1/language/core/resolved.d.ts +6 -2
- package/dist/v1/language/definition/metadata.d.ts +8 -0
- package/dist/v1/language/definition/metadata.js +12 -0
- package/dist/v1/language/index.d.ts +9 -0
- package/dist/v1/language/index.js +6 -0
- package/dist/v1/language/policy/analysis/branches.d.ts +4 -3
- package/dist/v1/language/policy/analysis/branches.js +54 -12
- package/dist/v1/language/policy/analysis/budgets.js +1 -1
- package/dist/v1/language/policy/analysis/checks.d.ts +28 -0
- package/dist/v1/language/policy/analysis/checks.js +80 -0
- package/dist/v1/language/policy/index.d.ts +1 -0
- package/dist/v1/language/policy/index.js +1 -0
- package/dist/v1/language/policy/model/policy.d.ts +71 -5
- package/dist/v1/language/policy/model/policy.js +52 -1
- package/dist/v1/language/policy/normalization/normalize.d.ts +12 -1
- package/dist/v1/language/policy/normalization/normalize.js +178 -44
- package/dist/v1/language/state/index.d.ts +3 -0
- package/dist/v1/language/state/index.js +1 -0
- package/dist/v1/language/state/machine.d.ts +28 -0
- package/dist/v1/language/state/machine.js +40 -0
- package/dist/v1/language/state/topology.d.ts +14 -0
- package/dist/v1/language/state/topology.js +69 -0
- package/dist/v1/language/value/compile/fields.d.ts +1 -1
- package/dist/v1/language/value/compile/load.d.ts +4 -2
- package/dist/v1/language/value/compile/load.js +22 -1
- package/dist/v1/language/value/compile/model.d.ts +16 -1
- package/dist/v1/language/value/evaluate/assertions.d.ts +2 -0
- package/dist/v1/language/value/evaluate/assertions.js +13 -0
- package/dist/v1/language/value/evaluate/evaluator.js +111 -28
- package/dist/v1/language/value/evaluate/preparation.d.ts +10 -1
- package/dist/v1/language/value/evaluate/preparation.js +17 -26
- package/dist/v1/language/value/evaluate/program.js +1 -1
- package/dist/v1/language/value/evaluate/validate.d.ts +6 -2
- package/dist/v1/language/value/evaluate/validate.js +18 -11
- package/dist/v1/language/value/inclusion/includes.d.ts +9 -0
- package/dist/v1/language/value/inclusion/includes.js +777 -0
- package/dist/v1/language/value/model/blob.d.ts +31 -0
- package/dist/v1/language/value/model/blob.js +90 -0
- package/dist/v1/language/value/model/instant.d.ts +0 -2
- package/dist/v1/language/value/model/instant.js +1 -1
- package/dist/v1/language/value/model/schema.d.ts +2 -1
- package/dist/v1/language/value/model/schema.js +1 -5
- package/dist/v1/language/value/ordering.d.ts +2 -0
- package/dist/v1/language/value/ordering.js +4 -8
- package/dist/v1/language/value/profile/json.validate.js +1 -1
- package/dist/v1/language/value/profile/rules.js +48 -12
- package/dist/v1/language/value/reference/registry.d.ts +2 -1
- package/dist/v1/language/value/regexp/ast.js +3 -64
- package/dist/v1/language/value/regexp/compile.d.ts +32 -3
- package/dist/v1/language/value/regexp/compile.js +117 -21
- package/dist/v1/language/value/regexp/matcher.d.ts +6 -3
- package/dist/v1/language/value/regexp/matcher.js +185 -28
- package/dist/v1/language/value/regexp/syntax.d.ts +12 -1
- package/dist/v1/language/value/regexp/syntax.js +14 -2
- package/dist/v1/language/value/regexp/unicode.d.ts +32 -0
- package/dist/v1/language/value/regexp/unicode.js +139 -0
- package/dist/v1/language/value/syntax/full-match.js +8 -5
- package/dist/v1/language/value/syntax/node-path/validate.js +4 -6
- package/dist/v1/language/view/model/view.d.ts +2 -4
- package/dist/v1/language/view/resolved.d.ts +2 -2
- package/dist/v1/schema/analysis/class.d.ts +36 -6
- package/dist/v1/schema/analysis/class.js +31 -66
- package/dist/v1/schema/canonical/revision.d.ts +2 -1
- package/dist/v1/schema/canonical/revision.js +4 -1
- package/dist/v1/schema/compatibility/api.d.ts +3 -0
- package/dist/v1/schema/compatibility/api.js +2 -0
- package/dist/v1/schema/compatibility/comparators/callables.d.ts +39 -0
- package/dist/v1/schema/compatibility/comparators/callables.js +101 -0
- package/dist/v1/schema/compatibility/comparators/classes.d.ts +47 -0
- package/dist/v1/schema/compatibility/comparators/classes.js +160 -0
- package/dist/v1/schema/compatibility/comparators/index.d.ts +12 -0
- package/dist/v1/schema/compatibility/comparators/index.js +53 -0
- package/dist/v1/schema/compatibility/comparators/members.d.ts +4 -0
- package/dist/v1/schema/compatibility/comparators/members.js +49 -0
- package/dist/v1/schema/compatibility/comparators/values.d.ts +5 -0
- package/dist/v1/schema/compatibility/comparators/values.js +37 -0
- package/dist/v1/schema/compatibility/compare.d.ts +5 -0
- package/dist/v1/schema/compatibility/compare.js +23 -0
- package/dist/v1/schema/compatibility/context.d.ts +19 -0
- package/dist/v1/schema/compatibility/context.js +49 -0
- package/dist/v1/schema/compatibility/coordinate.d.ts +40 -0
- package/dist/v1/schema/compatibility/coordinate.js +38 -0
- package/dist/v1/schema/compatibility/diff.d.ts +12 -0
- package/dist/v1/schema/compatibility/diff.js +39 -0
- package/dist/v1/schema/compatibility/evidence.d.ts +16 -0
- package/dist/v1/schema/compatibility/evidence.js +62 -0
- package/dist/v1/schema/compatibility/fields.d.ts +194 -0
- package/dist/v1/schema/compatibility/fields.js +94 -0
- package/dist/v1/schema/compatibility/index.d.ts +6 -0
- package/dist/v1/schema/compatibility/index.js +3 -0
- package/dist/v1/schema/compatibility/meaning/footprint.d.ts +7 -0
- package/dist/v1/schema/compatibility/meaning/footprint.js +59 -0
- package/dist/v1/schema/compatibility/meaning/index.d.ts +3 -0
- package/dist/v1/schema/compatibility/meaning/index.js +16 -0
- package/dist/v1/schema/compatibility/model.d.ts +131 -0
- package/dist/v1/schema/compatibility/model.js +1 -0
- package/dist/v1/schema/compatibility/references.d.ts +38 -0
- package/dist/v1/schema/compatibility/references.js +149 -0
- package/dist/v1/schema/compatibility/report.d.ts +27 -0
- package/dist/v1/schema/compatibility/report.js +100 -0
- package/dist/v1/schema/compatibility/scope.d.ts +36 -0
- package/dist/v1/schema/compatibility/scope.js +110 -0
- package/dist/v1/schema/compatibility/structure/index.d.ts +3 -0
- package/dist/v1/schema/compatibility/structure/index.js +40 -0
- package/dist/v1/schema/compatibility/structure/inheritance.d.ts +7 -0
- package/dist/v1/schema/compatibility/structure/inheritance.js +68 -0
- package/dist/v1/schema/compatibility/structure/requirements.d.ts +7 -0
- package/dist/v1/schema/compatibility/structure/requirements.js +97 -0
- package/dist/v1/schema/compatibility/subjects.d.ts +39 -0
- package/dist/v1/schema/compatibility/subjects.js +143 -0
- package/dist/v1/schema/compatibility/versioning/index.d.ts +8 -0
- package/dist/v1/schema/compatibility/versioning/index.js +50 -0
- package/dist/v1/schema/compatibility/versioning/members.d.ts +12 -0
- package/dist/v1/schema/compatibility/versioning/members.js +47 -0
- package/dist/v1/schema/compatibility/versioning/surface.d.ts +11 -0
- package/dist/v1/schema/compatibility/versioning/surface.js +61 -0
- package/dist/v1/schema/diagnostic.d.ts +1 -1
- package/dist/v1/schema/fingerprint.d.ts +2 -0
- package/dist/v1/schema/fingerprint.js +1 -0
- package/dist/v1/schema/index.d.ts +4 -3
- package/dist/v1/schema/index.js +2 -1
- package/dist/v1/schema/model/schema.d.ts +8 -11
- package/dist/v1/schema/normalization/domain.js +57 -13
- package/dist/v1/schema/resolution/definition.index.d.ts +1 -2
- package/dist/v1/schema/resolution/definition.index.js +0 -3
- package/dist/v1/schema/resolution/domain.d.ts +4 -1
- package/dist/v1/schema/resolution/domain.js +26 -18
- package/dist/v1/schema/resolution/origins.d.ts +28 -5
- package/dist/v1/schema/resolution/origins.js +68 -31
- package/dist/v1/schema/validation/callable.d.ts +4 -0
- package/dist/v1/schema/validation/callable.js +39 -0
- package/dist/v1/schema/validation/class.d.ts +10 -0
- package/dist/v1/schema/validation/class.js +79 -60
- package/dist/v1/schema/validation/core.js +83 -55
- package/dist/v1/schema/validation/domain.d.ts +2 -1
- package/dist/v1/schema/validation/domain.js +2 -0
- package/dist/v1/schema/validation/domain.structure.d.ts +0 -2
- package/dist/v1/schema/validation/domain.structure.js +214 -171
- package/dist/v1/schema/validation/policy/budgets.js +36 -6
- package/dist/v1/schema/validation/policy/context.js +5 -16
- package/dist/v1/schema/validation/policy/objects.d.ts +4 -0
- package/dist/v1/schema/validation/policy/objects.js +71 -0
- package/dist/v1/schema/validation/policy/references.js +16 -4
- package/dist/v1/schema/validation/policy/typing.d.ts +2 -0
- package/dist/v1/schema/validation/policy/typing.js +55 -7
- package/dist/v1/schema/validation/policy/uses.js +73 -99
- package/dist/v1/schema/validation/value-api.d.ts +2 -0
- package/dist/v1/schema/validation/value-api.js +1 -0
- package/dist/v1/schema/validation/value.js +7 -1
- package/dist/v1/schema/validation/view.js +14 -9
- package/dist/value/accept.d.ts +9 -0
- package/dist/value/accept.js +106 -7
- package/dist/value/canonical.d.ts +3 -0
- package/dist/value/canonical.js +22 -6
- package/dist/value/immutable.optimization.d.ts +15 -0
- package/dist/value/immutable.optimization.js +34 -0
- package/dist/value/index.d.ts +1 -1
- package/dist/value/index.js +1 -1
- package/dist/value/json.d.ts +1 -1
- package/dist/value/json.js +1 -1
- package/dist/value/limits.d.ts +1 -1
- package/dist/value/unicode.d.ts +4 -1
- package/dist/value/unicode.js +28 -0
- package/package.json +19 -3
- package/dist/v1/schema/compatibility/meaning.d.ts +0 -29
- package/dist/v1/schema/compatibility/meaning.js +0 -605
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import {} from '@astrale-os/kernel-dsl/value';
|
|
2
|
+
import { dependencyLimits } from '../../addressing/domain-dependency.js';
|
|
3
|
+
import { Key, isDefinitionRef } from '../../addressing/index.js';
|
|
4
|
+
import {} from '../../language/class/model/edge.js';
|
|
5
|
+
import {} from '../model/schema.js';
|
|
6
|
+
import { invalid, pointer } from './diagnostic.js';
|
|
7
|
+
/** Require closed direct references, acyclic inheritance and concrete Core Classes. */
|
|
8
|
+
export function validateClosure(candidate) {
|
|
9
|
+
validateDependencyCycles(candidate);
|
|
10
|
+
const definitions = new Map();
|
|
11
|
+
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
12
|
+
const collections = [
|
|
13
|
+
['classes', entry.definitions.classes],
|
|
14
|
+
['functions', entry.definitions.functions],
|
|
15
|
+
['policies', entry.definitions.policies],
|
|
16
|
+
['views', entry.definitions.views],
|
|
17
|
+
['core', entry.definitions.core],
|
|
18
|
+
];
|
|
19
|
+
for (const [collection, values] of collections) {
|
|
20
|
+
for (const [definitionIndex, definition] of values.entries()) {
|
|
21
|
+
const path = `/closure/${entryIndex}/definitions/${collection}/${definitionIndex}`;
|
|
22
|
+
const key = Key.of(definition.ref);
|
|
23
|
+
if (definitions.has(key))
|
|
24
|
+
invalid('duplicate Definition', undefined, `${path}/ref`);
|
|
25
|
+
definitions.set(key, { value: definition, path });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const requireDefinition = (ref, label, path) => {
|
|
30
|
+
const result = definitions.get(Key.of(ref));
|
|
31
|
+
if (result === undefined)
|
|
32
|
+
invalid(label, 'COMPILED_SOURCE_INVALID', path);
|
|
33
|
+
return result.value;
|
|
34
|
+
};
|
|
35
|
+
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
36
|
+
const visibleOrigins = new Set([
|
|
37
|
+
entry.origin,
|
|
38
|
+
...Object.values(entry.dependencies).map(({ origin }) => origin),
|
|
39
|
+
]);
|
|
40
|
+
const collections = [
|
|
41
|
+
['definitions/classes', entry.definitions.classes],
|
|
42
|
+
['definitions/functions', entry.definitions.functions],
|
|
43
|
+
['definitions/policies', entry.definitions.policies],
|
|
44
|
+
['definitions/views', entry.definitions.views],
|
|
45
|
+
['definitions/core', entry.definitions.core],
|
|
46
|
+
['facts/core', entry.facts.core],
|
|
47
|
+
];
|
|
48
|
+
for (const [collection, values] of collections) {
|
|
49
|
+
for (const [definitionIndex, definition] of values.entries()) {
|
|
50
|
+
walk(definition, `/closure/${entryIndex}/${collection}/${definitionIndex}`, (ref, path) => {
|
|
51
|
+
const resolved = requireDefinition(ref, 'unresolved Definition ref', path);
|
|
52
|
+
if (!visibleOrigins.has(ref.origin))
|
|
53
|
+
invalid('non-direct dependency ref', 'COMPILED_SOURCE_INVALID', path);
|
|
54
|
+
if (resolved.ref === undefined)
|
|
55
|
+
invalid('resolved Definition', 'COMPILED_SOURCE_INVALID', path);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const classes = new Map();
|
|
61
|
+
for (const [entryIndex, entry] of candidate.closure.entries())
|
|
62
|
+
for (const [classIndex, definition] of entry.definitions.classes.entries())
|
|
63
|
+
classes.set(Key.of(definition.ref), {
|
|
64
|
+
value: definition,
|
|
65
|
+
path: `/closure/${entryIndex}/definitions/classes/${classIndex}`,
|
|
66
|
+
});
|
|
67
|
+
const visiting = new Set();
|
|
68
|
+
const visited = new Set();
|
|
69
|
+
const visitClass = (key) => {
|
|
70
|
+
if (visited.has(key))
|
|
71
|
+
return;
|
|
72
|
+
if (visiting.has(key))
|
|
73
|
+
invalid('Class inheritance cycle', 'COMPILED_SOURCE_INVALID', `${classes.get(key)?.path ?? ''}/extends`);
|
|
74
|
+
const definition = classes.get(key);
|
|
75
|
+
if (definition === undefined)
|
|
76
|
+
invalid('Class inheritance ref', 'COMPILED_SOURCE_INVALID', '/closure');
|
|
77
|
+
visiting.add(key);
|
|
78
|
+
for (const [parentIndex, parentRef] of definition.value.extends.entries()) {
|
|
79
|
+
const parent = classes.get(Key.of(parentRef));
|
|
80
|
+
if (parent === undefined || parent.value.kind !== definition.value.kind) {
|
|
81
|
+
invalid('Class inheritance kind', 'COMPILED_SOURCE_INVALID', `${definition.path}/extends/${parentIndex}`);
|
|
82
|
+
}
|
|
83
|
+
visitClass(Key.of(parentRef));
|
|
84
|
+
}
|
|
85
|
+
visiting.delete(key);
|
|
86
|
+
visited.add(key);
|
|
87
|
+
};
|
|
88
|
+
for (const key of classes.keys())
|
|
89
|
+
visitClass(key);
|
|
90
|
+
for (const definition of classes.values()) {
|
|
91
|
+
if (definition.value.kind !== 'edge')
|
|
92
|
+
continue;
|
|
93
|
+
const endpoints = definition.value.orientation === 'directed'
|
|
94
|
+
? [
|
|
95
|
+
definition.value.endpoints.source,
|
|
96
|
+
definition.value.endpoints.target,
|
|
97
|
+
]
|
|
98
|
+
: definition.value.endpoints;
|
|
99
|
+
for (const [endpointIndex, endpoint] of endpoints.entries()) {
|
|
100
|
+
const endpointPath = definition.value.orientation === 'directed'
|
|
101
|
+
? `${definition.path}/endpoints/${endpointIndex === 0 ? 'source' : 'target'}`
|
|
102
|
+
: `${definition.path}/endpoints/${endpointIndex}`;
|
|
103
|
+
for (const [acceptedIndex, accepted] of endpoint.accepts.entries()) {
|
|
104
|
+
if (classes.get(Key.of(accepted))?.value.kind !== 'node') {
|
|
105
|
+
invalid('Edge endpoint Class', 'COMPILED_SOURCE_INVALID', `${endpointPath}/accepts/${acceptedIndex}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
111
|
+
for (const [definitionIndex, definition] of entry.definitions.core.entries()) {
|
|
112
|
+
const owner = classes.get(Key.of(definition.class));
|
|
113
|
+
if (owner?.value.kind !== 'node' || owner.value.abstract) {
|
|
114
|
+
invalid('Core exact Class', 'COMPILED_SOURCE_INVALID', `/closure/${entryIndex}/definitions/core/${definitionIndex}/class`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const [edgeIndex, edge] of entry.facts.core.entries()) {
|
|
118
|
+
const owner = classes.get(Key.of(edge.class));
|
|
119
|
+
if (owner?.value.kind !== 'edge' || owner.value.abstract) {
|
|
120
|
+
invalid('Core Edge exact Class', 'COMPILED_SOURCE_INVALID', `/closure/${entryIndex}/facts/core/${edgeIndex}/class`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function validateDependencyCycles(candidate) {
|
|
126
|
+
const byOrigin = new Map(candidate.closure.map((entry, index) => [entry.origin, { entry, index }]));
|
|
127
|
+
const active = new Set();
|
|
128
|
+
const visited = new Set();
|
|
129
|
+
const frames = [];
|
|
130
|
+
const push = (origin, depth) => {
|
|
131
|
+
if (depth > dependencyLimits.depth) {
|
|
132
|
+
invalid('dependency depth limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${byOrigin.get(origin)?.index ?? 0}/dependencies`);
|
|
133
|
+
}
|
|
134
|
+
active.add(origin);
|
|
135
|
+
frames.push({
|
|
136
|
+
origin,
|
|
137
|
+
depth,
|
|
138
|
+
dependencies: Object.values(byOrigin.get(origin)?.entry.dependencies ?? {}),
|
|
139
|
+
index: 0,
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
push(candidate.root.origin, 0);
|
|
143
|
+
while (frames.length > 0) {
|
|
144
|
+
const frame = frames.at(-1);
|
|
145
|
+
const dependency = frame.dependencies[frame.index++];
|
|
146
|
+
if (dependency === undefined) {
|
|
147
|
+
frames.pop();
|
|
148
|
+
active.delete(frame.origin);
|
|
149
|
+
visited.add(frame.origin);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (active.has(dependency.origin)) {
|
|
153
|
+
invalid('dependency cycle', 'COMPILED_DEPENDENCY_CYCLE', `/closure/${byOrigin.get(dependency.origin)?.index ?? 0}/dependencies`);
|
|
154
|
+
}
|
|
155
|
+
if (!visited.has(dependency.origin))
|
|
156
|
+
push(dependency.origin, frame.depth + 1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function walk(input, path, visit) {
|
|
160
|
+
if (isDefinitionRef(input)) {
|
|
161
|
+
visit(input, path);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (input === null || typeof input !== 'object')
|
|
165
|
+
return;
|
|
166
|
+
if (Array.isArray(input)) {
|
|
167
|
+
for (const [index, value] of input.entries())
|
|
168
|
+
walk(value, `${path}/${index}`, visit);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
for (const [key, value] of Object.entries(input))
|
|
172
|
+
walk(value, pointer(path, key), visit);
|
|
173
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type CompiledDiagnosticCode } from '../diagnostic.js';
|
|
2
|
+
/** Append one escaped JSON Pointer segment. */
|
|
3
|
+
export declare function pointer(parent: string, member: string | number): string;
|
|
4
|
+
/** Report a structural compiled-input violation with its stable diagnostic code. */
|
|
5
|
+
export declare function invalid(label: string, code?: CompiledDiagnosticCode, path?: string): never;
|
|
6
|
+
/** Report a contextual compiled-language violation at its original source pointer. */
|
|
7
|
+
export declare function fail(pointer: string, message: string): never;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { invalidCompiled } from '../diagnostic.js';
|
|
2
|
+
/** Append one escaped JSON Pointer segment. */
|
|
3
|
+
export function pointer(parent, member) {
|
|
4
|
+
return `${parent}/${String(member).replaceAll('~', '~0').replaceAll('/', '~1')}`;
|
|
5
|
+
}
|
|
6
|
+
/** Report a structural compiled-input violation with its stable diagnostic code. */
|
|
7
|
+
export function invalid(label, code = 'COMPILED_STRUCTURE_INVALID', path = '') {
|
|
8
|
+
return invalidCompiled(code, `Invalid compiled Schema ${label}.`, path);
|
|
9
|
+
}
|
|
10
|
+
/** Report a contextual compiled-language violation at its original source pointer. */
|
|
11
|
+
export function fail(pointer, message) {
|
|
12
|
+
return invalidCompiled('COMPILED_SOURCE_INVALID', message, pointer);
|
|
13
|
+
}
|
|
@@ -9,6 +9,8 @@ function revisionPreimage(entry) {
|
|
|
9
9
|
format: 'astrale.dsl',
|
|
10
10
|
version: 'v1',
|
|
11
11
|
origin: entry.origin,
|
|
12
|
+
name: entry.name,
|
|
13
|
+
...(entry.entrypoint === undefined ? {} : { entrypoint: entry.entrypoint }),
|
|
12
14
|
dependencies: entry.dependencies,
|
|
13
15
|
classes: Object.fromEntries(entry.definitions.classes.map((definition) => [
|
|
14
16
|
definition.ref.name,
|
|
@@ -54,7 +56,13 @@ function sourceFunction(entry, definition) {
|
|
|
54
56
|
const { input, fields: _, output, ...rest } = definition;
|
|
55
57
|
return {
|
|
56
58
|
...rest,
|
|
57
|
-
input:
|
|
59
|
+
input: typeof input === 'number'
|
|
60
|
+
? schemaOf(entry, input)
|
|
61
|
+
: {
|
|
62
|
+
mode: 'binary',
|
|
63
|
+
metadata: schemaOf(entry, input.metadata),
|
|
64
|
+
maximumBytes: input.maximumBytes,
|
|
65
|
+
},
|
|
58
66
|
output: sourceOutput(entry, output),
|
|
59
67
|
};
|
|
60
68
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type CompiledSchemaEntry } from '../../model/schema.js';
|
|
2
|
+
import { type SemanticIndex } from './context.js';
|
|
3
|
+
import { type CoreNode, type CoreEdgeValue } from './core.js';
|
|
4
|
+
/** Check normalized Edge uniqueness, noSelf, cycles and complete Core degrees. */
|
|
5
|
+
export declare function validateCoreEdgeSet(context: SemanticIndex, entry: CompiledSchemaEntry, entryIndex: number, nodes: ReadonlyMap<string, CoreNode>, edges: readonly CoreEdgeValue[]): void;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Key } from '../../../addressing/index.js';
|
|
2
|
+
import { compareUnicode } from '../../../addressing/ordering.js';
|
|
3
|
+
import {} from '../../../language/class/model/edge.js';
|
|
4
|
+
import {} from '../../model/schema.js';
|
|
5
|
+
import { fail } from '../diagnostic.js';
|
|
6
|
+
import { isCompiledEdge, classSatisfiesAny, } from './context.js';
|
|
7
|
+
import {} from './core.js';
|
|
8
|
+
import { sameIncidentEndpoint, countBounds } from './edge.js';
|
|
9
|
+
/** Check normalized Edge uniqueness, noSelf, cycles and complete Core degrees. */
|
|
10
|
+
export function validateCoreEdgeSet(context, entry, entryIndex, nodes, edges) {
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
const slices = new Map();
|
|
13
|
+
for (const edge of edges) {
|
|
14
|
+
const classKey = Key.of(edge.value.class);
|
|
15
|
+
const [source, target] = edge.class.value.orientation === 'undirected' &&
|
|
16
|
+
compareUnicode(edge.source.key, edge.target.key) > 0
|
|
17
|
+
? [edge.target.key, edge.source.key]
|
|
18
|
+
: [edge.source.key, edge.target.key];
|
|
19
|
+
const key = `${classKey}\u0000${source}\u0000${target}`;
|
|
20
|
+
if (seen.has(key))
|
|
21
|
+
fail(edge.pointer, 'Core Edge duplicates an exact normalized Edge identity.');
|
|
22
|
+
seen.add(key);
|
|
23
|
+
const values = slices.get(classKey) ?? [];
|
|
24
|
+
values.push(edge);
|
|
25
|
+
slices.set(classKey, values);
|
|
26
|
+
if (edge.class.value.constraints.noSelf === true && edge.source.key === edge.target.key)
|
|
27
|
+
fail(edge.pointer, 'Core Edge violates noSelf.');
|
|
28
|
+
}
|
|
29
|
+
for (const edgeClass of entry.definitions.classes) {
|
|
30
|
+
if (!isCompiledEdge(edgeClass))
|
|
31
|
+
continue;
|
|
32
|
+
const classEdges = slices.get(Key.of(edgeClass.ref)) ?? [];
|
|
33
|
+
if (edgeClass.constraints.acyclic === true && hasCycle(classEdges))
|
|
34
|
+
fail(`/closure/${entryIndex}/facts/core`, 'Core Edge set violates exact-Class acyclicity.');
|
|
35
|
+
validateCardinality(context, edgeClass, classEdges, nodes);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function validateCardinality(context, declaration, edges, nodes) {
|
|
39
|
+
for (const subject of cardinalitySubjects(edges, nodes)) {
|
|
40
|
+
if (declaration.orientation === 'directed') {
|
|
41
|
+
if (classSatisfiesAny(context, subject.class, declaration.endpoints.source.accepts))
|
|
42
|
+
checkCount(declaration.endpoints.source.outgoing, edges.filter(({ source }) => source.key === subject.key).length, subject.pointer, subject.minimum);
|
|
43
|
+
if (classSatisfiesAny(context, subject.class, declaration.endpoints.target.accepts))
|
|
44
|
+
checkCount(declaration.endpoints.target.incoming, edges.filter(({ target }) => target.key === subject.key).length, subject.pointer, subject.minimum);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const degree = edges.filter(({ source, target }) => source.key === subject.key || target.key === subject.key).length;
|
|
48
|
+
const [first, second] = declaration.endpoints;
|
|
49
|
+
if (classSatisfiesAny(context, subject.class, first.accepts))
|
|
50
|
+
checkCount(first.incident, degree, subject.pointer, subject.minimum);
|
|
51
|
+
if (!sameIncidentEndpoint(first, second) &&
|
|
52
|
+
classSatisfiesAny(context, subject.class, second.accepts))
|
|
53
|
+
checkCount(second.incident, degree, subject.pointer, subject.minimum);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Every declared Core Node proves its own complete degree, so both bounds hold. A Definition
|
|
59
|
+
* endpoint is only named by the Edges that reach it: the Domain may also create ordinary Edges of
|
|
60
|
+
* the same Class against it, so a minimum is unprovable here and only the maximum is enforced.
|
|
61
|
+
*/
|
|
62
|
+
function cardinalitySubjects(edges, nodes) {
|
|
63
|
+
const subjects = new Map();
|
|
64
|
+
for (const node of nodes.values()) {
|
|
65
|
+
subjects.set(node.key, {
|
|
66
|
+
key: node.key,
|
|
67
|
+
class: node.value.class,
|
|
68
|
+
pointer: node.pointer,
|
|
69
|
+
minimum: true,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
for (const edge of edges) {
|
|
73
|
+
for (const endpoint of [edge.source, edge.target]) {
|
|
74
|
+
if ('value' in endpoint || !('class' in endpoint) || subjects.has(endpoint.key))
|
|
75
|
+
continue;
|
|
76
|
+
subjects.set(endpoint.key, {
|
|
77
|
+
key: endpoint.key,
|
|
78
|
+
class: endpoint.class,
|
|
79
|
+
pointer: endpoint.pointer,
|
|
80
|
+
minimum: false,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return Object.freeze([...subjects.values()]);
|
|
85
|
+
}
|
|
86
|
+
function checkCount(count, degree, path, enforceMinimum) {
|
|
87
|
+
const [minimum, maximum] = countBounds(count);
|
|
88
|
+
if (degree > maximum || (degree < minimum && enforceMinimum))
|
|
89
|
+
fail(path, `Core degree ${degree} violates Edge count ${count}.`);
|
|
90
|
+
}
|
|
91
|
+
function hasCycle(edges) {
|
|
92
|
+
const outgoing = new Map();
|
|
93
|
+
for (const edge of edges) {
|
|
94
|
+
const values = outgoing.get(edge.source.key) ?? [];
|
|
95
|
+
values.push(edge.target.key);
|
|
96
|
+
outgoing.set(edge.source.key, values);
|
|
97
|
+
}
|
|
98
|
+
const visiting = new Set();
|
|
99
|
+
const visited = new Set();
|
|
100
|
+
const visit = (key) => {
|
|
101
|
+
if (visiting.has(key))
|
|
102
|
+
return true;
|
|
103
|
+
if (visited.has(key))
|
|
104
|
+
return false;
|
|
105
|
+
visiting.add(key);
|
|
106
|
+
if ((outgoing.get(key) ?? []).some(visit))
|
|
107
|
+
return true;
|
|
108
|
+
visiting.delete(key);
|
|
109
|
+
visited.add(key);
|
|
110
|
+
return false;
|
|
111
|
+
};
|
|
112
|
+
return [...outgoing.keys()].some(visit);
|
|
113
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Located, type CompiledClass, type ClassAnalysis, type SemanticIndex } from './context.js';
|
|
2
|
+
/** Compose inherited Properties, Methods and Data ownership once per Class. */
|
|
3
|
+
export declare function analyzeClasses(classes: ReadonlyMap<string, Located<CompiledClass>>): ReadonlyMap<string, ClassAnalysis>;
|
|
4
|
+
/** Check automatic Properties, immutability and abstract Class obligations. */
|
|
5
|
+
export declare function validateClassFacets(context: SemanticIndex): void;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { json } from '@astrale-os/kernel-dsl/value';
|
|
2
|
+
import { Key, PropertyKey as PropertyKeyValue, } from '../../../addressing/index.js';
|
|
3
|
+
import { composeMethods } from '../../../language/callable/composition.js';
|
|
4
|
+
import { isMethodExecutable } from '../../../language/callable/executable.js';
|
|
5
|
+
import { bindValueProgram } from '../../../language/value/compile/load.js';
|
|
6
|
+
import {} from '../../model/schema.js';
|
|
7
|
+
import { fail } from '../diagnostic.js';
|
|
8
|
+
import {} from './context.js';
|
|
9
|
+
/** Compose inherited Properties, Methods and Data ownership once per Class. */
|
|
10
|
+
export function analyzeClasses(classes) {
|
|
11
|
+
const analyses = new Map();
|
|
12
|
+
const visiting = new Set();
|
|
13
|
+
const analyze = (located) => {
|
|
14
|
+
const classKey = Key.of(located.value.ref);
|
|
15
|
+
const cached = analyses.get(classKey);
|
|
16
|
+
if (cached !== undefined)
|
|
17
|
+
return cached;
|
|
18
|
+
if (visiting.has(classKey))
|
|
19
|
+
fail(`${located.pointer}/extends`, 'Class inheritance is cyclic.');
|
|
20
|
+
visiting.add(classKey);
|
|
21
|
+
const parents = located.value.extends.map((ref, index) => {
|
|
22
|
+
const parent = classes.get(Key.of(ref));
|
|
23
|
+
if (parent === undefined)
|
|
24
|
+
fail(`${located.pointer}/extends/${index}`, 'Parent Class is absent.');
|
|
25
|
+
return analyze(parent);
|
|
26
|
+
});
|
|
27
|
+
const properties = new Map();
|
|
28
|
+
for (const parent of parents)
|
|
29
|
+
for (const [key, value] of parent.properties)
|
|
30
|
+
properties.set(key, value);
|
|
31
|
+
for (const property of located.value.properties) {
|
|
32
|
+
const key = PropertyKeyValue.of(located.value.ref, property.name);
|
|
33
|
+
properties.set(key, {
|
|
34
|
+
key,
|
|
35
|
+
owner: located.value.ref,
|
|
36
|
+
declaration: property,
|
|
37
|
+
entry: located.entry,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
let dataOwner;
|
|
41
|
+
for (const parent of parents) {
|
|
42
|
+
if (parent.dataOwner === undefined)
|
|
43
|
+
continue;
|
|
44
|
+
if (dataOwner !== undefined && Key.of(dataOwner) !== Key.of(parent.dataOwner)) {
|
|
45
|
+
fail(located.pointer, 'Data has distinct inherited declaring owners.');
|
|
46
|
+
}
|
|
47
|
+
dataOwner = parent.dataOwner;
|
|
48
|
+
}
|
|
49
|
+
if (located.value.kind === 'node' && located.value.data !== undefined) {
|
|
50
|
+
if (dataOwner !== undefined)
|
|
51
|
+
fail(`${located.pointer}/data`, 'Data cannot redeclare an inherited contract.');
|
|
52
|
+
dataOwner = located.value.ref;
|
|
53
|
+
}
|
|
54
|
+
const own = new Map((located.value.kind === 'node' ? located.value.methods : []).map((method) => [
|
|
55
|
+
method.name,
|
|
56
|
+
{
|
|
57
|
+
key: `${classKey}.method.${method.name}`,
|
|
58
|
+
name: method.name,
|
|
59
|
+
owner: located.value.ref,
|
|
60
|
+
declaration: method,
|
|
61
|
+
entry: located.entry,
|
|
62
|
+
},
|
|
63
|
+
]));
|
|
64
|
+
const composition = composeMethods(parents, own, located.value.abstract, (left, right) => sameMethodSignature(left.entry, left.declaration, right.entry, right.declaration), (message) => fail(`${located.pointer}/methods`, message));
|
|
65
|
+
const analysis = {
|
|
66
|
+
properties,
|
|
67
|
+
...composition,
|
|
68
|
+
...(dataOwner === undefined ? {} : { dataOwner }),
|
|
69
|
+
};
|
|
70
|
+
analyses.set(classKey, analysis);
|
|
71
|
+
visiting.delete(classKey);
|
|
72
|
+
return analysis;
|
|
73
|
+
};
|
|
74
|
+
for (const value of classes.values())
|
|
75
|
+
analyze(value);
|
|
76
|
+
return analyses;
|
|
77
|
+
}
|
|
78
|
+
function sameMethodSignature(leftEntry, left, rightEntry, right) {
|
|
79
|
+
return (programKey(leftEntry, left.input) === programKey(rightEntry, right.input) &&
|
|
80
|
+
outputKey(leftEntry, left.output) === outputKey(rightEntry, right.output) &&
|
|
81
|
+
left.auth === right.auth &&
|
|
82
|
+
left.static === right.static &&
|
|
83
|
+
left.execution?.durable === right.execution?.durable);
|
|
84
|
+
}
|
|
85
|
+
function outputKey(entry, output) {
|
|
86
|
+
return output.mode === 'binary' ? 'binary' : `${output.mode}:${programKey(entry, output.value)}`;
|
|
87
|
+
}
|
|
88
|
+
function programKey(entry, value) {
|
|
89
|
+
return json.serialize(bindValueProgram(entry.values[value], entry.patterns));
|
|
90
|
+
}
|
|
91
|
+
/** Check automatic Properties, immutability and abstract Class obligations. */
|
|
92
|
+
export function validateClassFacets(context) {
|
|
93
|
+
for (const located of context.classes.values()) {
|
|
94
|
+
if (located.value.abstract &&
|
|
95
|
+
(located.value.policies.read !== undefined || located.value.policies.traverse !== undefined)) {
|
|
96
|
+
fail(`${located.pointer}/policies`, 'Abstract Classes cannot declare observation Policies.');
|
|
97
|
+
}
|
|
98
|
+
for (const [index, property] of located.value.properties.entries()) {
|
|
99
|
+
const path = `${located.pointer}/properties/${index}`;
|
|
100
|
+
if (property.auto !== undefined) {
|
|
101
|
+
if (property.required && !property.auto.on.includes('create')) {
|
|
102
|
+
fail(`${path}/auto/on`, 'A required auto Property must run on create.');
|
|
103
|
+
}
|
|
104
|
+
if (property.auto.set === 'instant' && property.ordering !== 'instant') {
|
|
105
|
+
fail(`${path}/auto/set`, 'The instant setter requires an Instant value program.');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (property.immutable !== undefined) {
|
|
109
|
+
if (property.auto !== undefined || property.state !== undefined) {
|
|
110
|
+
fail(`${path}/immutable`, 'An immutable Property is neither automatic nor a State Property.');
|
|
111
|
+
}
|
|
112
|
+
if (property.immutable === 'once' && property.required) {
|
|
113
|
+
fail(`${path}/immutable`, 'A required immutable Property is declared create, not once.');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (located.value.kind === 'node') {
|
|
118
|
+
for (const [index, method] of located.value.methods.entries()) {
|
|
119
|
+
if (!isMethodExecutable(located.value, method) && method.policy !== undefined) {
|
|
120
|
+
fail(`${located.pointer}/methods/${index}/policy`, 'An abstract Method cannot have a Policy.');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type PropertyKey, type ClassRef, type DefinitionRef } from '../../../addressing/index.js';
|
|
2
|
+
import { type MethodComposition } from '../../../language/callable/composition.js';
|
|
3
|
+
import { type EdgeClassDefinition } from '../../../language/class/model/class.js';
|
|
4
|
+
import { type CompiledSchemaEntry, type CompiledProperty, type CompiledMethod, type CompiledSchema } from '../../model/schema.js';
|
|
5
|
+
/** One decoded Class declaration in a compiled entry. */
|
|
6
|
+
export type CompiledClass = CompiledSchemaEntry['definitions']['classes'][number];
|
|
7
|
+
/** The Edge variant of a decoded Class declaration. */
|
|
8
|
+
export type CompiledEdge = EdgeClassDefinition extends infer Definition ? Definition extends EdgeClassDefinition ? Omit<Definition, 'properties'> & {
|
|
9
|
+
readonly properties: readonly CompiledProperty[];
|
|
10
|
+
} : never : never;
|
|
11
|
+
/** One decoded named Policy declaration. */
|
|
12
|
+
export type CompiledPolicy = CompiledSchemaEntry['definitions']['policies'][number];
|
|
13
|
+
/** A declaration together with its owner and exact diagnostic coordinates. */
|
|
14
|
+
export interface Located<Value> {
|
|
15
|
+
readonly value: Value;
|
|
16
|
+
readonly entry: CompiledSchemaEntry;
|
|
17
|
+
readonly entryIndex: number;
|
|
18
|
+
readonly index: number;
|
|
19
|
+
readonly pointer: string;
|
|
20
|
+
}
|
|
21
|
+
/** An inherited Property together with its declaring owner and value program. */
|
|
22
|
+
export interface EffectiveProperty {
|
|
23
|
+
readonly key: PropertyKey;
|
|
24
|
+
readonly owner: ClassRef;
|
|
25
|
+
readonly declaration: CompiledProperty;
|
|
26
|
+
readonly entry: CompiledSchemaEntry;
|
|
27
|
+
}
|
|
28
|
+
/** An inherited Method together with its declaring owner and value program. */
|
|
29
|
+
export interface EffectiveMethod {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly key: string;
|
|
32
|
+
readonly owner: ClassRef;
|
|
33
|
+
readonly declaration: CompiledMethod;
|
|
34
|
+
readonly entry: CompiledSchemaEntry;
|
|
35
|
+
}
|
|
36
|
+
/** The effective Properties, Methods and Data owner of one Class. */
|
|
37
|
+
export interface ClassAnalysis extends MethodComposition<EffectiveMethod> {
|
|
38
|
+
readonly properties: ReadonlyMap<PropertyKey, EffectiveProperty>;
|
|
39
|
+
readonly dataOwner?: ClassRef;
|
|
40
|
+
}
|
|
41
|
+
/** Closure-wide declaration indexes and composed Class contracts. */
|
|
42
|
+
export interface SemanticIndex {
|
|
43
|
+
readonly definitions: ReadonlyMap<string, Located<DefinitionRef>>;
|
|
44
|
+
readonly classes: ReadonlyMap<string, Located<CompiledClass>>;
|
|
45
|
+
readonly policies: ReadonlyMap<string, Located<CompiledPolicy>>;
|
|
46
|
+
readonly core: ReadonlyMap<string, Located<CompiledSchemaEntry['definitions']['core'][number]>>;
|
|
47
|
+
readonly analyses: ReadonlyMap<string, ClassAnalysis>;
|
|
48
|
+
}
|
|
49
|
+
/** Index declarations by exact coordinates while retaining their source pointers. */
|
|
50
|
+
export declare function index(candidate: CompiledSchema): Omit<SemanticIndex, 'analyses'>;
|
|
51
|
+
/**
|
|
52
|
+
* The origins each closure entry was admitted against: itself and its transitive dependencies.
|
|
53
|
+
* Source admission types Policies within that closure alone, so a
|
|
54
|
+
* dependent's Class extending a dependency's Classes never reaches the dependency's own decisions.
|
|
55
|
+
*/
|
|
56
|
+
export declare function admittedOrigins(candidate: CompiledSchema): ReadonlyMap<string, ReadonlySet<string>>;
|
|
57
|
+
/** Decide whether a Class satisfies any accepted ancestor contract. */
|
|
58
|
+
export declare function classSatisfiesAny(context: SemanticIndex, candidate: ClassRef, accepted: readonly ClassRef[]): boolean;
|
|
59
|
+
/** Narrow a compiled Class to its Edge contract. */
|
|
60
|
+
export declare function isCompiledEdge(value: CompiledClass): value is CompiledEdge;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Key, } from '../../../addressing/index.js';
|
|
2
|
+
import {} from '../../../language/callable/composition.js';
|
|
3
|
+
import { classSatisfies } from '../../../language/class/inheritance.js';
|
|
4
|
+
import {} from '../../../language/class/model/class.js';
|
|
5
|
+
import {} from '../../model/schema.js';
|
|
6
|
+
/** Index declarations by exact coordinates while retaining their source pointers. */
|
|
7
|
+
export function index(candidate) {
|
|
8
|
+
const definitions = new Map();
|
|
9
|
+
const classes = new Map();
|
|
10
|
+
const policies = new Map();
|
|
11
|
+
const core = new Map();
|
|
12
|
+
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
13
|
+
const collections = [
|
|
14
|
+
['classes', entry.definitions.classes],
|
|
15
|
+
['functions', entry.definitions.functions],
|
|
16
|
+
['policies', entry.definitions.policies],
|
|
17
|
+
['views', entry.definitions.views],
|
|
18
|
+
['core', entry.definitions.core],
|
|
19
|
+
];
|
|
20
|
+
for (const [collection, values] of collections) {
|
|
21
|
+
for (const [valueIndex, value] of values.entries()) {
|
|
22
|
+
const located = {
|
|
23
|
+
value,
|
|
24
|
+
entry,
|
|
25
|
+
entryIndex,
|
|
26
|
+
index: valueIndex,
|
|
27
|
+
pointer: `/closure/${entryIndex}/definitions/${collection}/${valueIndex}`,
|
|
28
|
+
};
|
|
29
|
+
definitions.set(Key.of(value.ref), {
|
|
30
|
+
...located,
|
|
31
|
+
value: value.ref,
|
|
32
|
+
});
|
|
33
|
+
if (value.ref.kind === 'class')
|
|
34
|
+
classes.set(Key.of(value.ref), located);
|
|
35
|
+
if (value.ref.kind === 'policy')
|
|
36
|
+
policies.set(Key.of(value.ref), located);
|
|
37
|
+
if (value.ref.kind === 'core')
|
|
38
|
+
core.set(Key.of(value.ref), located);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { definitions, classes, policies, core };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The origins each closure entry was admitted against: itself and its transitive dependencies.
|
|
46
|
+
* Source admission types Policies within that closure alone, so a
|
|
47
|
+
* dependent's Class extending a dependency's Classes never reaches the dependency's own decisions.
|
|
48
|
+
*/
|
|
49
|
+
export function admittedOrigins(candidate) {
|
|
50
|
+
const entries = new Map(candidate.closure.map((entry) => [entry.origin, entry]));
|
|
51
|
+
const scopes = new Map();
|
|
52
|
+
const scope = (origin) => {
|
|
53
|
+
const known = scopes.get(origin);
|
|
54
|
+
if (known !== undefined)
|
|
55
|
+
return known;
|
|
56
|
+
const origins = new Set([origin]);
|
|
57
|
+
for (const dependency of Object.values(entries.get(origin)?.dependencies ?? {}))
|
|
58
|
+
for (const reached of scope(dependency.origin))
|
|
59
|
+
origins.add(reached);
|
|
60
|
+
scopes.set(origin, origins);
|
|
61
|
+
return origins;
|
|
62
|
+
};
|
|
63
|
+
for (const entry of candidate.closure)
|
|
64
|
+
scope(entry.origin);
|
|
65
|
+
return scopes;
|
|
66
|
+
}
|
|
67
|
+
/** Decide whether a Class satisfies any accepted ancestor contract. */
|
|
68
|
+
export function classSatisfiesAny(context, candidate, accepted) {
|
|
69
|
+
const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
|
|
70
|
+
const actual = resolve(candidate);
|
|
71
|
+
if (actual === undefined)
|
|
72
|
+
return false;
|
|
73
|
+
return accepted.some((ref) => {
|
|
74
|
+
const required = resolve(ref);
|
|
75
|
+
return required !== undefined && classSatisfies(actual, required, resolve);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** Narrow a compiled Class to its Edge contract. */
|
|
79
|
+
export function isCompiledEdge(value) {
|
|
80
|
+
return value.kind === 'edge';
|
|
81
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ClassRef } from '../../../addressing/index.js';
|
|
2
|
+
import { type CoreEdge } from '../../../language/core/model/core.js';
|
|
3
|
+
import { type CompiledSchemaEntry, type CompiledSchema } from '../../model/schema.js';
|
|
4
|
+
import { type Located, type CompiledClass, type ClassAnalysis, type CompiledEdge, type SemanticIndex } from './context.js';
|
|
5
|
+
/** A local Core Node paired with its admitted Class analysis. */
|
|
6
|
+
export interface CoreNode {
|
|
7
|
+
readonly key: string;
|
|
8
|
+
readonly value: CompiledSchemaEntry['definitions']['core'][number];
|
|
9
|
+
readonly class: Located<CompiledClass>;
|
|
10
|
+
readonly analysis: ClassAnalysis;
|
|
11
|
+
readonly pointer: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A local Definition other than a Core Node, or a Class-owned Method. The Domain projects it as a
|
|
15
|
+
* Kernel declaration Node, so `class` names that Kernel Class rather than an authored one.
|
|
16
|
+
*/
|
|
17
|
+
interface CoreMemberEndpoint {
|
|
18
|
+
readonly key: string;
|
|
19
|
+
readonly class: ClassRef;
|
|
20
|
+
readonly pointer: string;
|
|
21
|
+
}
|
|
22
|
+
type CoreEndpoint = CoreNode | CoreMemberEndpoint | {
|
|
23
|
+
readonly key: 'domain';
|
|
24
|
+
};
|
|
25
|
+
/** A Core Edge paired with resolved endpoints and its exact Class. */
|
|
26
|
+
export interface CoreEdgeValue {
|
|
27
|
+
readonly source: CoreEndpoint;
|
|
28
|
+
readonly target: CoreEndpoint;
|
|
29
|
+
readonly value: CoreEdge;
|
|
30
|
+
readonly class: Located<CompiledEdge>;
|
|
31
|
+
readonly pointer: string;
|
|
32
|
+
}
|
|
33
|
+
/** Admit local Core Nodes, Properties and Edge endpoint contracts. */
|
|
34
|
+
export declare function validateCore(candidate: CompiledSchema, context: SemanticIndex): void;
|
|
35
|
+
export {};
|