@mark1russell7/coeval 0.27.0 → 0.27.2

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/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { strongComponentsCompact } from "@mark1russell7/collections/graph";
1
2
  import { mulberry32 } from "@mark1russell7/rigor-generators";
2
3
  // src/doc.ts
3
4
  /** The keys that an envelope can have. */
@@ -2579,483 +2580,578 @@ function restrictMachine(machine, paths) {
2579
2580
  ...tables.domains === void 0 ? {} : { domains: tables.domains }
2580
2581
  };
2581
2582
  }
2582
- // src/language.ts
2583
- const VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
2584
- function numbers$1(version) {
2585
- const found = VERSION.exec(version);
2586
- if (found === null) throw new TypeError(`A language version has the form MAJOR.MINOR.PATCH. The text ${JSON.stringify(version)} does not.`);
2587
- return [
2588
- Number(found[1]),
2589
- Number(found[2]),
2590
- Number(found[3])
2591
- ];
2592
- }
2593
- /**
2594
- * This function tells if a version satisfies a lowest version, by the rules of a caret range of SemVer. The first
2595
- * number that is not zero stays the same, and the version is not lower.
2596
- */
2597
- function compatible(version, lowest) {
2598
- const have = numbers$1(version);
2599
- const want = numbers$1(lowest);
2600
- const stable = want.findIndex((part) => part !== 0);
2601
- const fixed = stable < 0 ? 3 : stable + 1;
2602
- for (let index = 0; index < 3; index += 1) {
2603
- const [a, b] = [have[index], want[index]];
2604
- if (a !== b) return index >= fixed && a > b;
2583
+ // src/parts.ts
2584
+ var Bad$1 = class {
2585
+ reason;
2586
+ at;
2587
+ constructor(reason, at) {
2588
+ this.reason = reason;
2589
+ this.at = at;
2605
2590
  }
2606
- return true;
2607
- }
2608
- /** This function gives the JSON text of a value with its keys in order. A value that is not JSON is an error. */
2609
- function canonical(value, path) {
2610
- if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
2611
- if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value);
2612
- if (Array.isArray(value)) return `[${value.map((item, index) => canonical(item, [...path, index])).join(",")}]`;
2613
- if (!isRecord(value)) throw new TypeError(`The data half of a language is JSON. The value at ${JSON.stringify(path)} is not.`);
2614
- return `{${Object.keys(value).filter((key) => value[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key], [...path, key])}`).join(",")}}`;
2615
- }
2616
- function frozen(value) {
2617
- if (typeof value !== "object" || value === null) return value;
2618
- for (const item of Object.values(value)) frozen(item);
2619
- return Object.freeze(value);
2620
- }
2621
- /**
2622
- * This function makes one value of a language. The data half is JSON, thus a host can store it and compare it. The
2623
- * code half binds the evaluator names of the world.
2624
- *
2625
- * The language keeps a frozen copy of its data half, thus a later change to the input changes nothing.
2626
- *
2627
- * @param definition - The name, the version, the world, the needed languages and the code.
2628
- * @returns The language.
2629
- * @throws {TypeError} A version in the definition is not `MAJOR.MINOR.PATCH`, the name is empty, or the
2630
- * data half is not JSON.
2631
- */
2632
- function defineLanguage(definition) {
2633
- if (definition.name === "") throw new TypeError("A language has a name.");
2634
- numbers$1(definition.version);
2635
- const requires = definition.requires ?? {};
2636
- for (const name of Object.keys(requires)) numbers$1(requires[name]);
2637
- const data = canonical({
2638
- requires,
2639
- world: definition.world ?? {}
2640
- }, []);
2641
- const copy = frozen(JSON.parse(data));
2642
- const language = {
2643
- name: definition.name,
2644
- version: definition.version,
2645
- world: copy.world,
2646
- requires: copy.requires,
2647
- data
2648
- };
2649
- return Object.freeze(definition.code === void 0 ? language : {
2650
- ...language,
2651
- code: definition.code
2591
+ };
2592
+ /** This function sets an own data property. Only the key `__proto__` needs `defineProperty`. */
2593
+ function setOwn$4(target, key, value) {
2594
+ if (key === "__proto__") Object.defineProperty(target, key, {
2595
+ value,
2596
+ enumerable: true,
2597
+ writable: true,
2598
+ configurable: true
2652
2599
  });
2600
+ else target[key] = value;
2653
2601
  }
2654
- function partOf(language) {
2655
- const { code, world } = language;
2656
- return typeof code === "function" ? (prev) => ({
2657
- ...code(prev),
2658
- world
2659
- }) : {
2660
- ...code,
2661
- world
2662
- };
2602
+ const NO_SLOTS = /* @__PURE__ */ Object.freeze([]);
2603
+ function hasSlots(template) {
2604
+ return template.t !== "data";
2663
2605
  }
2664
- /**
2665
- * This function merges languages into one machine, in the order of the arguments, with `mergeMachines`.
2666
- *
2667
- * - A language comes after each language that it names in `requires`, at a compatible version (LANG.REQUIRES).
2668
- * - One language that comes twice counts once. Thus two languages can share a base.
2669
- * - Two versions of one name, or two data halves under one name and one version, are conflicts (LANG.COMPOSE).
2670
- *
2671
- * @param languages - The languages.
2672
- * @returns The machine.
2673
- * @throws {MergeError} The languages do not fit, or their merge has a conflict. The error lists each conflict.
2674
- */
2675
- function compose(...languages) {
2676
- const conflicts = [];
2677
- const parts = [];
2678
- const seen = /* @__PURE__ */ new Map();
2679
- languages.forEach((language, index) => {
2680
- const earlier = seen.get(language.name);
2681
- const conflict = (name, other, reason) => {
2682
- conflicts.push({
2683
- path: ["languages", name],
2684
- parts: [Math.min(other, index), Math.max(other, index)],
2685
- reason
2686
- });
2687
- };
2688
- if (earlier !== void 0) {
2689
- if (earlier.language.version !== language.version) conflict(language.name, earlier.index, "Two versions of one language.");
2690
- else if (earlier.language.data !== language.data) conflict(language.name, earlier.index, "Two languages with one name and one version differ.");
2691
- else if (earlier.language.code !== language.code) parts.push(partOf(language));
2692
- return;
2693
- }
2694
- for (const name of Object.keys(language.requires)) {
2695
- const needed = language.requires[name];
2696
- const found = seen.get(name);
2697
- if (found === void 0) {
2698
- const later = languages.findIndex((other) => other.name === name);
2699
- if (later < 0) conflict(name, index, `A language requires ${name}, and the composition does not have it.`);
2700
- else conflict(name, later, `A language requires ${name}, and ${name} comes after it.`);
2701
- } else if (!compatible(found.language.version, needed)) conflict(name, found.index, `A language requires ${name} ${needed}, and the composition has ${found.language.version}.`);
2702
- }
2703
- seen.set(language.name, {
2704
- language,
2705
- index
2706
- });
2707
- parts.push(partOf(language));
2708
- });
2709
- if (conflicts.length > 0) throw new MergeError(conflicts);
2710
- return mergeMachines(...parts);
2606
+ /** This function gives the shape of a part with the default type `of` and the value type `expect` of its container. */
2607
+ function termOf$1(of, expect) {
2608
+ return {
2609
+ shape: "term",
2610
+ ...of === void 0 ? {} : { of },
2611
+ ...expect === void 0 ? {} : { expect }
2612
+ };
2711
2613
  }
2712
- // src/ladder.ts
2713
- /** The rungs of the ladder, in the order that a question visits them. */
2714
- const RUNGS = [
2715
- "own",
2716
- "kind",
2717
- "default"
2718
- ];
2719
- function entryOf$1(verbs, verb) {
2720
- return verbs !== void 0 && Object.hasOwn(verbs, verb) ? verbs[verb] : void 0;
2614
+ /** This function tells if a shape holds only data: no value of the shape can hold a part. */
2615
+ function isData(shape) {
2616
+ return shape.shape === "none" || shape.shape === "text" || shape.shape === "number" || shape.shape === "one";
2721
2617
  }
2722
- /**
2723
- * This function finds the kind that a type names, and follows each alias. It gives `undefined` for an unknown
2724
- * type.
2725
- *
2726
- * @param world - The world.
2727
- * @param type - The reference to the type.
2728
- * @returns The kind, or `undefined`.
2729
- */
2730
- function kindOf(world, type) {
2731
- const found = lookupKind(world, type);
2732
- return found.ok ? found.kind : void 0;
2618
+ /** This function gives the reason why a value is not data of a shape, or `undefined` when it is. */
2619
+ function dataFault(spec, item) {
2620
+ if (spec.shape === "text") return typeof item === "string" ? void 0 : "The value must be a text.";
2621
+ if (spec.shape === "one") return spec.values.some((value) => docEquals(value, item)) ? void 0 : `The value must be one of ${JSON.stringify(spec.values)}.`;
2622
+ if (typeof item !== "number") return "The value must be a number.";
2623
+ if (spec.whole === true && !Number.isInteger(item)) return "The value must be a whole number.";
2624
+ if (spec.min !== void 0 && !(item >= spec.min)) return `The value must be ${String(spec.min)} or more.`;
2625
+ if (spec.max !== void 0 && !(item <= spec.max)) return `The value must be ${String(spec.max)} or less.`;
2733
2626
  }
2734
- /**
2735
- * This function finds a kind by a text type. It is the same as `kindOf` for a one-key reference.
2736
- *
2737
- * @param world - The world.
2738
- * @param name - The text of the type.
2739
- * @returns The kind, or `undefined`.
2740
- */
2741
- function kindNamed(world, name) {
2742
- return kindOf(world, name);
2627
+ /** This function stops a split when a part has a type that its position does not permit. */
2628
+ function kindFault(kinds, item, of, path) {
2629
+ const type = isEnvelope(item) ? typePath(item.type) : of === void 0 ? void 0 : [of];
2630
+ if (type !== void 0 && kinds.some((kind) => kind.length <= type.length && kind.every((key, index) => String(key) === String(type[index])))) return;
2631
+ const names = kinds.map((kind) => kind.join(".")).join(", ");
2632
+ throw new Bad$1(`${isEnvelope(item) ? `The kind ${typeName(item.type)} is not permitted here.` : "A value without an envelope is not permitted here."} The permitted kinds are ${names}.`, path);
2743
2633
  }
2744
- /** A test that passes each name. A rung of `answerOf` then answers with each entry that it has. */
2745
- const EACH_NAME = () => true;
2746
2634
  /**
2747
- * This function finds the evaluator of a verb without the record of the rungs. It visits the rungs of `ask` in the
2748
- * same order: the own entry, then the kind, then the default of the world (VERB.LADDER). A plan without a trace,
2749
- * `deref` and the walkers of steps use it, thus each verb has one ladder.
2635
+ * This function splits a value into its parts, by the shape that its kind declares. The evaluator, the view and
2636
+ * the static kit use the same split, thus each one sees the same parts.
2750
2637
  *
2751
- * @param world - The world, for its defaults.
2752
- * @param own - The own entries of the document, when it has some.
2753
- * @param kind - The kind of the document. `undefined` skips the kind rung, as for a value without a type. `null` is
2754
- * a kind that the world does not have: the question stops there, as in `ask`.
2755
- * @param verb - The verb, for example `eval`, `format`, `deref` or `step`.
2756
- * @param has - The test of a name. A rung answers only with a name that passes it. The default passes each name.
2757
- * @returns The evaluator name and its rung, or `undefined` when no rung answers.
2638
+ * @param shape - The shape of the value. The default is data.
2639
+ * @param value - The value of the document.
2640
+ * @returns The parts and a way to fill their places, or the reason why the value does not have the shape.
2758
2641
  */
2759
- function answerOf(world, own, kind, verb, has = EACH_NAME) {
2760
- const ownName = entryOf$1(own, verb);
2761
- if (ownName !== void 0 && has(ownName)) return {
2762
- name: ownName,
2763
- rung: "own"
2642
+ function splitParts(shape, value) {
2643
+ if (shape === void 0 || shape.shape === "none") return {
2644
+ ok: true,
2645
+ parts: NO_SLOTS,
2646
+ data: value,
2647
+ fill: () => value
2764
2648
  };
2765
- if (kind === null) return void 0;
2766
- const kindName = kind === void 0 ? void 0 : entryOf$1(kind.verbs, verb);
2767
- if (kindName !== void 0 && has(kindName)) return {
2768
- name: kindName,
2769
- rung: "kind"
2649
+ const parts = [];
2650
+ const slot = (item, path, of, address = false, expect) => {
2651
+ parts.push({
2652
+ path,
2653
+ key: path.join("."),
2654
+ item,
2655
+ ...of === void 0 ? {} : { of },
2656
+ ...address ? { address: true } : {},
2657
+ ...expect === void 0 ? {} : { expect }
2658
+ });
2659
+ return {
2660
+ t: "slot",
2661
+ index: parts.length - 1
2662
+ };
2770
2663
  };
2771
- const fallback = entryOf$1(world.defaults, verb);
2772
- return fallback !== void 0 && has(fallback) ? {
2773
- name: fallback,
2774
- rung: "default"
2775
- } : void 0;
2776
- }
2777
- /**
2778
- * This function asks a document a question, and gives the evaluator that answers it.
2779
- *
2780
- * The question visits the rungs in order: the own entry of the envelope, then its kind, then the default of the
2781
- * world. The type comes from the envelope, or else from the type that the position declares. The type is a
2782
- * reference into the world. The ladder does not guess a type from the shape of a value. Each verb has this ladder:
2783
- * `eval`, `deref`, `step` and each verb of a language (VERB.LADDER).
2784
- *
2785
- * @param world - The kinds and the defaults.
2786
- * @param doc - The header of the document: an envelope, or `{}` for a bare value.
2787
- * @param verb - The verb of the question, for example `eval` or `view`.
2788
- * @param options - The type that the position declares.
2789
- * @returns The answer, with the record of each rung that the question visited.
2790
- */
2791
- function ask(world, doc, verb, options = {}) {
2792
- const steps = [];
2793
- const own = entryOf$1(doc.own, verb);
2794
- if (own !== void 0) {
2795
- steps.push({
2796
- rung: "own",
2797
- outcome: "answers",
2798
- evaluator: own
2799
- });
2664
+ const deep = (item, path, of, expect) => {
2665
+ if (isEnvelope(item)) return slot(item, path, of, false, expect);
2666
+ if (Array.isArray(item)) {
2667
+ const items = item.map((child, index) => deep(child, [...path, index], of, expect));
2668
+ return items.some(hasSlots) ? {
2669
+ t: "list",
2670
+ items
2671
+ } : {
2672
+ t: "data",
2673
+ value: item
2674
+ };
2675
+ }
2676
+ if (isRecord(item)) {
2677
+ const fields = Object.keys(item).map((key) => [key, deep(item[key], [...path, key], of, expect)]);
2678
+ return fields.some(([, child]) => hasSlots(child)) ? {
2679
+ t: "record",
2680
+ fields
2681
+ } : {
2682
+ t: "data",
2683
+ value: item
2684
+ };
2685
+ }
2800
2686
  return {
2801
- verb,
2802
- evaluator: own,
2803
- rung: "own",
2804
- steps
2687
+ t: "data",
2688
+ value: item
2805
2689
  };
2806
- }
2807
- steps.push({
2808
- rung: "own",
2809
- outcome: "no-entry"
2810
- });
2811
- const type = doc.type ?? options.declaredType;
2812
- if (type === void 0) steps.push({
2813
- rung: "kind",
2814
- outcome: "skipped"
2815
- });
2816
- else {
2817
- const source = doc.type === void 0 ? "container" : "document";
2818
- const name = typeName(type);
2819
- const kind = kindOf(world, type);
2820
- if (kind === void 0) {
2821
- steps.push({
2822
- rung: "kind",
2823
- outcome: "unknown-kind",
2824
- kind: name,
2825
- source
2826
- });
2690
+ };
2691
+ const walk = (spec, item, path) => {
2692
+ if (spec === void 0 || spec.shape === "none") return {
2693
+ t: "data",
2694
+ value: item
2695
+ };
2696
+ if (spec.shape === "text" || spec.shape === "number" || spec.shape === "one") {
2697
+ const reason = dataFault(spec, item);
2698
+ if (reason !== void 0) throw new Bad$1(reason, path);
2827
2699
  return {
2828
- verb,
2829
- error: "unknown-kind",
2830
- steps
2700
+ t: "data",
2701
+ value: item
2831
2702
  };
2832
2703
  }
2833
- const entry = entryOf$1(kind.verbs, verb);
2834
- if (entry !== void 0) {
2835
- steps.push({
2836
- rung: "kind",
2837
- outcome: "answers",
2838
- evaluator: entry,
2839
- kind: name,
2840
- source
2841
- });
2704
+ if (spec.shape === "term") {
2705
+ if (spec.kinds !== void 0) kindFault(spec.kinds, item, spec.of, path);
2706
+ return slot(item, path, spec.of, spec.address === true, spec.expect);
2707
+ }
2708
+ if (spec.shape === "deep") return deep(item, path, spec.of, spec.expect);
2709
+ if (spec.shape === "list") {
2710
+ if (!Array.isArray(item)) throw new Bad$1("The value must be a list.", path);
2711
+ const list = item;
2712
+ if (spec.distinct === true) {
2713
+ const twice = list.findIndex((child, index) => list.slice(0, index).some((before) => docEquals(before, child)));
2714
+ if (twice !== -1) throw new Bad$1("The items of the list must be different.", [...path, twice]);
2715
+ }
2716
+ const each = spec.item ?? termOf$1(spec.of, spec.expect);
2717
+ const items = list.map((child, index) => walk(each, child, [...path, index]));
2718
+ return isData(each) ? {
2719
+ t: "data",
2720
+ value: item
2721
+ } : {
2722
+ t: "list",
2723
+ items
2724
+ };
2725
+ }
2726
+ if (!isRecord(item)) throw new Bad$1("The value must be a record.", path);
2727
+ if (spec.shape === "map") {
2728
+ const each = spec.item ?? termOf$1(spec.of, spec.expect);
2842
2729
  return {
2843
- verb,
2844
- evaluator: entry,
2845
- rung: "kind",
2846
- steps
2730
+ t: "record",
2731
+ fields: Object.keys(item).map((key) => [key, walk(each, item[key], [...path, key])])
2847
2732
  };
2848
2733
  }
2849
- steps.push({
2850
- rung: "kind",
2851
- outcome: "no-entry",
2852
- kind: name,
2853
- source
2854
- });
2855
- }
2856
- const fallback = entryOf$1(world.defaults, verb);
2857
- if (fallback !== void 0) {
2858
- steps.push({
2859
- rung: "default",
2860
- outcome: "answers",
2861
- evaluator: fallback
2862
- });
2734
+ for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad$1(`The field ${name} is missing.`, path);
2735
+ const named = Array.isArray(spec.fields) ? Object.fromEntries(spec.fields.map((name) => [name, termOf$1(spec.of, spec.expect)])) : spec.fields;
2736
+ const fields = [];
2737
+ for (const key of Object.keys(item)) {
2738
+ if (spec.closed === true && !Object.hasOwn(named, key)) throw new Bad$1(`The field ${key} is not a field of this kind.`, [...path, key]);
2739
+ const fieldShape = Object.hasOwn(named, key) ? named[key] : spec.rest;
2740
+ fields.push([key, walk(fieldShape, item[key], [...path, key])]);
2741
+ }
2863
2742
  return {
2864
- verb,
2865
- evaluator: fallback,
2866
- rung: "default",
2867
- steps
2743
+ t: "record",
2744
+ fields
2745
+ };
2746
+ };
2747
+ let template;
2748
+ try {
2749
+ template = walk(shape, value, []);
2750
+ } catch (error) {
2751
+ if (error instanceof Bad$1) return {
2752
+ ok: false,
2753
+ reason: error.reason,
2754
+ at: error.at
2868
2755
  };
2756
+ throw error;
2869
2757
  }
2870
- steps.push({
2871
- rung: "default",
2872
- outcome: "no-entry"
2873
- });
2758
+ const strip = (node) => {
2759
+ if (node.t === "data") return node.value;
2760
+ if (node.t === "slot") return void 0;
2761
+ if (node.t === "list") return node.items.every((child) => child.t === "slot") ? null : node.items.map((child) => strip(child) ?? null);
2762
+ const out = {};
2763
+ for (const [key, child] of node.fields) {
2764
+ const kept = strip(child);
2765
+ if (kept !== void 0) setOwn$4(out, key, kept);
2766
+ }
2767
+ return out;
2768
+ };
2769
+ const fillWith = (node, handles) => {
2770
+ if (node.t === "data") return node.value;
2771
+ if (node.t === "slot") return handles[node.index];
2772
+ if (node.t === "list") return node.items.map((child) => fillWith(child, handles));
2773
+ const out = {};
2774
+ for (const [key, child] of node.fields) setOwn$4(out, key, fillWith(child, handles));
2775
+ return out;
2776
+ };
2874
2777
  return {
2875
- verb,
2876
- error: "no-answer",
2877
- steps
2778
+ ok: true,
2779
+ parts,
2780
+ data: strip(template) ?? null,
2781
+ fill: (handles) => fillWith(template, handles)
2878
2782
  };
2879
2783
  }
2880
- // src/steps.ts
2881
2784
  /**
2882
- * This function makes a ladder of steps, and it checks the declaration (STEPS.LADDER). The list of steps must have one
2883
- * step or more, with no name two times. The step of each construct must be a step of the list.
2785
+ * This function reads one document by the contracts of the world. It finds the kind of the type. A bare value gets
2786
+ * the type that its position declares. Then the function splits the value by the shape of the kind. The plan, the
2787
+ * reference interpreter and the static kit read each document with this function. Thus they see the same parts.
2884
2788
  *
2885
- * @param steps - The names of the steps, from the lowest to the highest.
2886
- * @param constructs - The step that each construct needs.
2887
- * @returns The ladder, frozen.
2888
- * @throws TypeError for a declaration that is not valid, because it is a defect of the language.
2789
+ * @param world - The world of the kinds.
2790
+ * @param value - The document, or a bare value.
2791
+ * @param declaredType - The type that the position of a bare value declares.
2792
+ * @returns The document, its kind and its parts, or the reason why the value is not a document.
2889
2793
  */
2890
- function stepLadder(steps, constructs) {
2891
- if (steps.length === 0) throw new TypeError("a ladder of steps needs one step or more");
2892
- const seen = /* @__PURE__ */ new Set();
2893
- for (const step of steps) {
2894
- if (typeof step !== "string") throw new TypeError(`the step ${String(step)} is not a name`);
2895
- if (seen.has(step)) throw new TypeError(`the step "${step}" is in the ladder two times`);
2896
- seen.add(step);
2897
- }
2898
- for (const [construct, step] of Object.entries(constructs)) if (!seen.has(step)) throw new TypeError(`the construct "${construct}" needs the step "${String(step)}", which is not a step of the ladder`);
2899
- return Object.freeze({
2900
- steps: Object.freeze([...steps]),
2901
- constructs: Object.freeze({ ...constructs })
2902
- });
2794
+ function partsOf(world, value, declaredType) {
2795
+ const envelope = isEnvelope(value) ? value : void 0;
2796
+ if (envelope === void 0 && declaredType === void 0) return {
2797
+ ok: false,
2798
+ code: "#PART?",
2799
+ reason: "The value has no envelope, and its position declares no type."
2800
+ };
2801
+ const doc = envelope ?? {
2802
+ type: declaredType,
2803
+ value
2804
+ };
2805
+ const found = lookupKind(world, doc.type);
2806
+ const kind = found.ok ? found.kind : void 0;
2807
+ const split = splitParts(kind?.parts, doc.value);
2808
+ const typePath = found.ok ? found.path : void 0;
2809
+ if (split.ok) return {
2810
+ ok: true,
2811
+ doc,
2812
+ declared: envelope === void 0,
2813
+ kind,
2814
+ typePath,
2815
+ split
2816
+ };
2817
+ const where = split.at.length === 0 ? "" : ` (at ${split.at.join(".")})`;
2818
+ const reason = `${split.reason}${where} The kind is ${typeName(doc.type)}.`;
2819
+ return {
2820
+ ok: true,
2821
+ doc,
2822
+ declared: envelope === void 0,
2823
+ kind,
2824
+ typePath,
2825
+ split: {
2826
+ ok: false,
2827
+ reason,
2828
+ at: split.at
2829
+ }
2830
+ };
2903
2831
  }
2904
2832
  /**
2905
- * This function tells if a value is a step of a ladder. A host uses it to check its option for the highest step.
2833
+ * This function tells if the path of a part matches a pattern of a scope rule. The key `"*"` of a pattern matches
2834
+ * each key.
2906
2835
  *
2907
- * @param ladder - The ladder.
2908
- * @param value - The value.
2909
- * @returns `true` when the value is the name of a step of the ladder.
2836
+ * @param path - The path of the part.
2837
+ * @param pattern - The pattern.
2838
+ * @returns `true` when the path matches.
2910
2839
  */
2911
- function isStep(ladder, value) {
2912
- return typeof value === "string" && ladder.steps.includes(value);
2840
+ function pathMatches(path, pattern) {
2841
+ if (path.length !== pattern.length) return false;
2842
+ for (let index = 0; index < path.length; index += 1) {
2843
+ const want = pattern[index];
2844
+ if (want !== "*" && String(want) !== String(path[index])) return false;
2845
+ }
2846
+ return true;
2913
2847
  }
2914
2848
  /**
2915
- * This function gives the position of a step in its ladder. The lowest step has the position 0.
2849
+ * This function tells if a list of rules in the form of the lazy rules covers a part (D24, D119). A rule without
2850
+ * `in` covers each part. With `after: n`, a rule covers only the parts after the first `n` parts that it matches.
2916
2851
  *
2917
- * @param ladder - The ladder.
2918
- * @param step - The step.
2919
- * @returns The position.
2920
- * @throws TypeError for a name that is not a step of the ladder.
2852
+ * @param rules - The rules.
2853
+ * @param shape - The shape of the parts of the parent.
2854
+ * @param value - The value of the parent.
2855
+ * @param slot - The path of the part in the value.
2856
+ * @returns `true` when a rule covers the part.
2921
2857
  */
2922
- function stepRank(ladder, step) {
2923
- const rank = ladder.steps.indexOf(step);
2924
- if (rank < 0) throw new TypeError(`"${String(step)}" is not a step of the ladder. The steps are ${ladder.steps.join(", ")}`);
2925
- return rank;
2858
+ function rulesCover(rules, shape, value, slot) {
2859
+ for (const rule of rules) {
2860
+ if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(slot, pattern))) continue;
2861
+ const after = rule.after ?? 0;
2862
+ if (after <= 0) return true;
2863
+ const split = splitParts(shape, value);
2864
+ let count = 0;
2865
+ for (const part of split.ok ? split.parts : []) {
2866
+ if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(part.path, pattern))) continue;
2867
+ if (part.path.length === slot.length && pathMatches(part.path, slot)) {
2868
+ if (count >= after) return true;
2869
+ break;
2870
+ }
2871
+ count += 1;
2872
+ }
2873
+ }
2874
+ return false;
2926
2875
  }
2927
- function pathOf(visit) {
2928
- const path = [];
2929
- for (let v = visit; v?.key !== void 0; v = v.parent) path.push(v.key);
2930
- return path.reverse();
2876
+ function valueAt(value, path) {
2877
+ let here = value;
2878
+ for (const key of path) if (Array.isArray(here)) here = here[Number(key)];
2879
+ else if (isRecord(here) && Object.hasOwn(here, String(key))) here = here[String(key)];
2880
+ else return void 0;
2881
+ return here;
2882
+ }
2883
+ function headerName(item) {
2884
+ return isEnvelope(item) && typeof item.name === "string" ? item.name : void 0;
2885
+ }
2886
+ function namesOf(source, value, covered) {
2887
+ if ("fixed" in source) return source.fixed;
2888
+ if ("keysAt" in source) {
2889
+ const at = valueAt(value, source.keysAt);
2890
+ return isRecord(at) ? Object.keys(at) : [];
2891
+ }
2892
+ if ("listAt" in source) {
2893
+ const at = valueAt(value, source.listAt);
2894
+ return Array.isArray(at) ? at.filter((item) => typeof item === "string") : [];
2895
+ }
2896
+ if ("textAt" in source) {
2897
+ const at = valueAt(value, source.textAt);
2898
+ if (typeof at === "string") return [at];
2899
+ return source.otherwise === void 0 ? [] : [source.otherwise];
2900
+ }
2901
+ return covered.map((slot) => headerName(slot.item)).filter((name) => name !== void 0);
2931
2902
  }
2932
2903
  /**
2933
- * This function gives the lowest step that a document needs, with the reason (STEPS.LOWEST, STEPS.REASON). The step is
2934
- * the highest step of the constructs of its nodes. The reason is the first node in document order with that step. The
2935
- * walk uses its own stack, thus a deep document does not overflow (STEPS.LINEAR). It visits a shared node one time,
2936
- * and it stops at the first node with the highest step of the ladder.
2904
+ * This function gives the names that the scope rules of a kind give each part, and the names that only later parts
2905
+ * see. `check`, `conforms` and the plan read the scope rules with it.
2937
2906
  *
2938
- * @param ladder - The ladder of the language.
2939
- * @param walk - The construct and the child nodes of a node.
2940
- * @param root - The root node of the document.
2941
- * @returns The step, and the reason when the step is not the lowest step.
2907
+ * @param rules - The scope rules of the kind.
2908
+ * @param value - The value of the document.
2909
+ * @param slots - The parts of the value, in order.
2910
+ * @returns The names that each part sees, and the names that only the later parts see, by the index of the part.
2942
2911
  */
2943
- function stepOf(ladder, walk, root) {
2944
- const top = ladder.steps.length - 1;
2945
- let best = 0;
2946
- let reason;
2947
- const seen = /* @__PURE__ */ new Set();
2948
- const todo = [{
2949
- node: root,
2950
- key: void 0,
2951
- parent: void 0
2952
- }];
2953
- for (let visit = todo.pop(); visit !== void 0; visit = todo.pop()) {
2954
- const { node } = visit;
2955
- if (typeof node === "object" && node !== null) {
2956
- if (seen.has(node)) continue;
2957
- seen.add(node);
2958
- }
2959
- const construct = walk.construct(node);
2960
- const step = construct === void 0 || !Object.hasOwn(ladder.constructs, construct) ? void 0 : ladder.constructs[construct];
2961
- const rank = step === void 0 ? 0 : ladder.steps.indexOf(step);
2962
- if (rank > best) {
2963
- best = rank;
2964
- reason = {
2965
- construct,
2966
- step,
2967
- path: pathOf(visit),
2968
- node
2969
- };
2970
- if (best === top) break;
2912
+ function scopesOf(rules, value, slots) {
2913
+ const sees = slots.map(() => []);
2914
+ const later = slots.map(() => []);
2915
+ for (const rule of rules ?? []) {
2916
+ const covered = slots.map((slot, index) => ({
2917
+ slot,
2918
+ index
2919
+ })).filter(({ slot }) => rule.in.some((pattern) => pathMatches(slot.path, pattern)));
2920
+ if (rule.sequential !== true) {
2921
+ const names = namesOf(rule.names, value, covered.map(({ slot }) => slot));
2922
+ for (const { index } of covered) sees[index]?.push(...names);
2923
+ continue;
2971
2924
  }
2972
- const kids = [...walk.children(node)];
2973
- for (let i = kids.length - 1; i >= 0; i--) {
2974
- const [key, child] = kids[i];
2975
- todo.push({
2976
- node: child,
2977
- key,
2978
- parent: visit
2925
+ if ("headers" in rule.names) {
2926
+ covered.forEach(({ index }, position) => {
2927
+ const before = covered.slice(0, position).map(({ slot }) => headerName(slot.item)).filter((name) => name !== void 0);
2928
+ const after = covered.slice(position).map(({ slot }) => headerName(slot.item)).filter((name) => name !== void 0);
2929
+ sees[index]?.push(...before);
2930
+ later[index]?.push(...after);
2979
2931
  });
2932
+ continue;
2980
2933
  }
2934
+ const names = namesOf(rule.names, value, covered.map(({ slot }) => slot));
2935
+ covered.forEach(({ index }, position) => {
2936
+ if (position > 0) sees[index]?.push(...names);
2937
+ else later[index]?.push(...names);
2938
+ });
2981
2939
  }
2982
- const step = ladder.steps[best];
2983
- return reason === void 0 ? { step } : {
2984
- step,
2985
- reason
2940
+ return {
2941
+ sees,
2942
+ later
2986
2943
  };
2987
2944
  }
2945
+ // src/ladder.ts
2946
+ /** The rungs of the ladder, in the order that a question visits them. */
2947
+ const RUNGS = [
2948
+ "own",
2949
+ "kind",
2950
+ "default"
2951
+ ];
2952
+ function entryOf$1(verbs, verb) {
2953
+ return verbs !== void 0 && Object.hasOwn(verbs, verb) ? verbs[verb] : void 0;
2954
+ }
2988
2955
  /**
2989
- * This function compares the step of a document with the highest step that the host accepts (STEPS.MAX). The limit
2990
- * changes only which documents the host accepts. The language evaluates an accepted document as before, thus a limit
2991
- * does not change a value.
2956
+ * This function finds the kind that a type names, and follows each alias. It gives `undefined` for an unknown
2957
+ * type.
2992
2958
  *
2993
- * @param ladder - The ladder of the language.
2994
- * @param need - The step of the document, from `stepOf`.
2995
- * @param maxStep - The highest step that the host accepts.
2996
- * @returns `undefined` when the host accepts the document, or the refusal that names the needed step.
2997
- * @throws TypeError when `maxStep` or the step of `need` is not a step of the ladder.
2959
+ * @param world - The world.
2960
+ * @param type - The reference to the type.
2961
+ * @returns The kind, or `undefined`.
2998
2962
  */
2999
- function checkStep(ladder, need, maxStep) {
3000
- const limit = stepRank(ladder, maxStep);
3001
- if (stepRank(ladder, need.step) <= limit) return void 0;
3002
- const head = `the document needs the step ${need.step}, and the host accepts the steps up to ${maxStep}`;
3003
- const reason = need.reason;
3004
- if (reason === void 0) return {
3005
- needed: need.step,
3006
- maxStep,
3007
- message: head
3008
- };
3009
- const where = reason.path.length === 0 ? "at the root" : `at the path ${JSON.stringify(reason.path)}`;
3010
- return {
3011
- needed: need.step,
3012
- maxStep,
3013
- reason,
3014
- message: `${head}. The construct "${reason.construct}" ${where} needs the step ${reason.step}`
3015
- };
2963
+ function kindOf(world, type) {
2964
+ const found = lookupKind(world, type);
2965
+ return found.ok ? found.kind : void 0;
3016
2966
  }
3017
- // src/deref.ts
3018
- /**
3019
- * The brand of a host thing: an object of the host that answers the steps of a path itself. The brand is a
3020
- * global symbol, thus two copies of the kernel in one program know the things of each other.
3021
- */
3022
- const THING = /* @__PURE__ */ Symbol.for("coeval.thing");
3023
2967
  /**
3024
- * This function tells if a thing is a host thing.
2968
+ * This function finds a kind by a text type. It is the same as `kindOf` for a one-key reference.
3025
2969
  *
3026
- * @param thing - The thing.
3027
- * @returns `true` for a host thing.
2970
+ * @param world - The world.
2971
+ * @param name - The text of the type.
2972
+ * @returns The kind, or `undefined`.
3028
2973
  */
3029
- function isHostThing(thing) {
3030
- return typeof thing === "object" && thing !== null && thing[THING] === true;
3031
- }
3032
- /** The roots of a context. Each path starts with one of them. */
3033
- const ROOTS = [
3034
- "self",
3035
- "names",
3036
- "world",
3037
- "event",
3038
- "caps"
3039
- ];
3040
- /** This function gives the own entries of an envelope, when it has a record of them. */
3041
- function ownEntries(envelope) {
3042
- const own = field(envelope, "own");
3043
- return isRecord(own) ? own : void 0;
2974
+ function kindNamed(world, name) {
2975
+ return kindOf(world, name);
3044
2976
  }
3045
- /** The most kinds in the memo of one world. A larger memo starts again, thus the types of the data cannot fill the memory. */
3046
- const MAX_KINDS = 1e3;
3047
- const kindMemos = /* @__PURE__ */ new WeakMap();
2977
+ /** A test that passes each name. A rung of `answerOf` then answers with each entry that it has. */
2978
+ const EACH_NAME = () => true;
3048
2979
  /**
3049
- * This function gives the kind of a type for the ladder: `null` when the world does not have the kind. The result
3050
- * depends only on the world and on the keys of the type, thus a memo for each world keeps it (PLAN.KIND-MEMO). A
3051
- * world does not change after a plan or a resolution uses it, as for `worldThing`.
2980
+ * This function finds the evaluator of a verb without the record of the rungs. It visits the rungs of `ask` in the
2981
+ * same order: the own entry, then the kind, then the default of the world (VERB.LADDER). A plan without a trace,
2982
+ * `deref` and the walkers of steps use it, thus each verb has one ladder.
2983
+ *
2984
+ * @param world - The world, for its defaults.
2985
+ * @param own - The own entries of the document, when it has some.
2986
+ * @param kind - The kind of the document. `undefined` skips the kind rung, as for a value without a type. `null` is
2987
+ * a kind that the world does not have: the question stops there, as in `ask`.
2988
+ * @param verb - The verb, for example `eval`, `format`, `deref` or `step`.
2989
+ * @param has - The test of a name. A rung answers only with a name that passes it. The default passes each name.
2990
+ * @returns The evaluator name and its rung, or `undefined` when no rung answers.
3052
2991
  */
3053
- function kindFor(world, type) {
3054
- const keys = typeof type === "string" ? void 0 : typePath(type);
3055
- if (typeof type !== "string" && (keys === void 0 || keys.length === 0)) {
3056
- const found = lookupKind(world, type);
3057
- return found.ok ? found.kind : null;
3058
- }
2992
+ function answerOf(world, own, kind, verb, has = EACH_NAME) {
2993
+ const ownName = entryOf$1(own, verb);
2994
+ if (ownName !== void 0 && has(ownName)) return {
2995
+ name: ownName,
2996
+ rung: "own"
2997
+ };
2998
+ if (kind === null) return void 0;
2999
+ const kindName = kind === void 0 ? void 0 : entryOf$1(kind.verbs, verb);
3000
+ if (kindName !== void 0 && has(kindName)) return {
3001
+ name: kindName,
3002
+ rung: "kind"
3003
+ };
3004
+ const fallback = entryOf$1(world.defaults, verb);
3005
+ return fallback !== void 0 && has(fallback) ? {
3006
+ name: fallback,
3007
+ rung: "default"
3008
+ } : void 0;
3009
+ }
3010
+ /**
3011
+ * This function asks a document a question, and gives the evaluator that answers it.
3012
+ *
3013
+ * The question visits the rungs in order: the own entry of the envelope, then its kind, then the default of the
3014
+ * world. The type comes from the envelope, or else from the type that the position declares. The type is a
3015
+ * reference into the world. The ladder does not guess a type from the shape of a value. Each verb has this ladder:
3016
+ * `eval`, `deref`, `step` and each verb of a language (VERB.LADDER).
3017
+ *
3018
+ * @param world - The kinds and the defaults.
3019
+ * @param doc - The header of the document: an envelope, or `{}` for a bare value.
3020
+ * @param verb - The verb of the question, for example `eval` or `view`.
3021
+ * @param options - The type that the position declares.
3022
+ * @returns The answer, with the record of each rung that the question visited.
3023
+ */
3024
+ function ask(world, doc, verb, options = {}) {
3025
+ const steps = [];
3026
+ const own = entryOf$1(doc.own, verb);
3027
+ if (own !== void 0) {
3028
+ steps.push({
3029
+ rung: "own",
3030
+ outcome: "answers",
3031
+ evaluator: own
3032
+ });
3033
+ return {
3034
+ verb,
3035
+ evaluator: own,
3036
+ rung: "own",
3037
+ steps
3038
+ };
3039
+ }
3040
+ steps.push({
3041
+ rung: "own",
3042
+ outcome: "no-entry"
3043
+ });
3044
+ const type = doc.type ?? options.declaredType;
3045
+ if (type === void 0) steps.push({
3046
+ rung: "kind",
3047
+ outcome: "skipped"
3048
+ });
3049
+ else {
3050
+ const source = doc.type === void 0 ? "container" : "document";
3051
+ const name = typeName(type);
3052
+ const kind = kindOf(world, type);
3053
+ if (kind === void 0) {
3054
+ steps.push({
3055
+ rung: "kind",
3056
+ outcome: "unknown-kind",
3057
+ kind: name,
3058
+ source
3059
+ });
3060
+ return {
3061
+ verb,
3062
+ error: "unknown-kind",
3063
+ steps
3064
+ };
3065
+ }
3066
+ const entry = entryOf$1(kind.verbs, verb);
3067
+ if (entry !== void 0) {
3068
+ steps.push({
3069
+ rung: "kind",
3070
+ outcome: "answers",
3071
+ evaluator: entry,
3072
+ kind: name,
3073
+ source
3074
+ });
3075
+ return {
3076
+ verb,
3077
+ evaluator: entry,
3078
+ rung: "kind",
3079
+ steps
3080
+ };
3081
+ }
3082
+ steps.push({
3083
+ rung: "kind",
3084
+ outcome: "no-entry",
3085
+ kind: name,
3086
+ source
3087
+ });
3088
+ }
3089
+ const fallback = entryOf$1(world.defaults, verb);
3090
+ if (fallback !== void 0) {
3091
+ steps.push({
3092
+ rung: "default",
3093
+ outcome: "answers",
3094
+ evaluator: fallback
3095
+ });
3096
+ return {
3097
+ verb,
3098
+ evaluator: fallback,
3099
+ rung: "default",
3100
+ steps
3101
+ };
3102
+ }
3103
+ steps.push({
3104
+ rung: "default",
3105
+ outcome: "no-entry"
3106
+ });
3107
+ return {
3108
+ verb,
3109
+ error: "no-answer",
3110
+ steps
3111
+ };
3112
+ }
3113
+ // src/deref.ts
3114
+ /**
3115
+ * The brand of a host thing: an object of the host that answers the steps of a path itself. The brand is a
3116
+ * global symbol, thus two copies of the kernel in one program know the things of each other.
3117
+ */
3118
+ const THING = /* @__PURE__ */ Symbol.for("coeval.thing");
3119
+ /**
3120
+ * This function tells if a thing is a host thing.
3121
+ *
3122
+ * @param thing - The thing.
3123
+ * @returns `true` for a host thing.
3124
+ */
3125
+ function isHostThing(thing) {
3126
+ return typeof thing === "object" && thing !== null && thing[THING] === true;
3127
+ }
3128
+ /** The roots of a context. Each path starts with one of them. */
3129
+ const ROOTS = [
3130
+ "self",
3131
+ "names",
3132
+ "world",
3133
+ "event",
3134
+ "caps"
3135
+ ];
3136
+ /** This function gives the own entries of an envelope, when it has a record of them. */
3137
+ function ownEntries(envelope) {
3138
+ const own = field(envelope, "own");
3139
+ return isRecord(own) ? own : void 0;
3140
+ }
3141
+ /** The most kinds in the memo of one world. A larger memo starts again, thus the types of the data cannot fill the memory. */
3142
+ const MAX_KINDS = 1e3;
3143
+ const kindMemos = /* @__PURE__ */ new WeakMap();
3144
+ /**
3145
+ * This function gives the kind of a type for the ladder: `null` when the world does not have the kind. The result
3146
+ * depends only on the world and on the keys of the type, thus a memo for each world keeps it (PLAN.KIND-MEMO). A
3147
+ * world does not change after a plan or a resolution uses it, as for `worldThing`.
3148
+ */
3149
+ function kindFor(world, type) {
3150
+ const keys = typeof type === "string" ? void 0 : typePath(type);
3151
+ if (typeof type !== "string" && (keys === void 0 || keys.length === 0)) {
3152
+ const found = lookupKind(world, type);
3153
+ return found.ok ? found.kind : null;
3154
+ }
3059
3155
  let memo = kindMemos.get(world);
3060
3156
  if (memo === void 0 || memo.size >= MAX_KINDS) {
3061
3157
  memo = {
@@ -3089,877 +3185,477 @@ function nodeOf(first, keys) {
3089
3185
  }
3090
3186
  /** This function tells if a table of code has the name. An entry of a document can hold another value than a text. */
3091
3187
  function codeIn(table, name) {
3092
- return typeof name === "string" && Object.hasOwn(table, name);
3093
- }
3094
- /**
3095
- * This function finds the walker of a step document through the ladder of the verb `step` (VERB.LADDER). The rungs
3096
- * are the own entry, then the kind, then the default of the world. A rung answers only with a walker that the
3097
- * navigator has. A resolution and `check` use this function, thus they agree on `#STEP?`.
3098
- *
3099
- * @param nav - The world and the walkers.
3100
- * @param step - A step of a path that is not a key.
3101
- * @returns The walker, or `undefined` when no rung answers.
3102
- */
3103
- function walkerOf(nav, step) {
3104
- const walkers = nav.walkers;
3105
- if (walkers === void 0 || !isEnvelope(step)) return void 0;
3106
- const answer = answerOf(nav.world, ownEntries(step), kindFor(nav.world, step.type), "step", (name) => codeIn(walkers, name));
3107
- return answer === void 0 ? void 0 : walkers[answer.name];
3108
- }
3109
- /** The answer of `plainStep` for a field that the value does not have. A field can hold `undefined`. */
3110
- const NOTHING = /* @__PURE__ */ Symbol("nothing");
3111
- /** The own fields of a value: the items and the length of a list, and the own properties of an object. */
3112
- function plainStep(thing, key) {
3113
- if (Array.isArray(thing)) {
3114
- if (key === "length") return thing.length;
3115
- const index = typeof key === "number" ? key : /^\d+$/.test(key) ? Number(key) : -1;
3116
- return index >= 0 && index < thing.length ? thing[index] : NOTHING;
3117
- }
3118
- if (typeof thing === "object" && thing !== null) {
3119
- const name = String(key);
3120
- return Object.hasOwn(thing, name) ? thing[name] : NOTHING;
3121
- }
3122
- return NOTHING;
3123
- }
3124
- /**
3125
- * This function tells if a value can be an envelope by its field `type`. An envelope has its own field `type`, thus
3126
- * a value without that field is not an envelope, and the full test is not necessary.
3127
- */
3128
- function mayBeEnvelope(thing) {
3129
- return typeof thing === "object" && thing !== null && thing.type !== void 0;
3130
- }
3131
- /**
3132
- * This function answers one step of a path on a thing, through the ladder of the verb `deref`. A host thing
3133
- * answers for itself (own). A document asks its own entry, then its kind, then the default of the world
3134
- * (VERB.LADDER). A rung answers only with a `deref` that the navigator has. When no rung answers, the step goes into
3135
- * the value: an own field of an object, or an item of a list. A value without a type is data, thus the step goes
3136
- * into it at once.
3137
- *
3138
- * @param nav - The world and the code of the evaluators.
3139
- * @param thing - The thing that the path reached.
3140
- * @param key - The key of the step.
3141
- * @returns What the step reaches and the rung that answered, or `undefined` when it reaches nothing.
3142
- */
3143
- function derefStep(nav, thing, key) {
3144
- if (isHostThing(thing)) {
3145
- const reached = thing.deref(key);
3146
- return reached !== void 0 || thing.has?.(key) === true ? {
3147
- thing: reached,
3148
- by: "own"
3149
- } : void 0;
3150
- }
3151
- if (nav.plain !== true && mayBeEnvelope(thing) && isEnvelope(thing)) {
3152
- const envelope = thing;
3153
- const derefs = nav.derefs;
3154
- const answer = derefs === void 0 ? void 0 : answerOf(nav.world, ownEntries(envelope), kindFor(nav.world, envelope.type), "deref", (name) => codeIn(derefs, name));
3155
- if (answer !== void 0) {
3156
- const code = derefs[answer.name];
3157
- const reached = code?.(envelope, key);
3158
- return reached !== void 0 || code?.has?.(envelope, key) === true ? {
3159
- thing: reached,
3160
- by: answer.rung
3161
- } : void 0;
3162
- }
3163
- const reached = plainStep(envelope.value, key);
3164
- return reached === NOTHING ? void 0 : {
3165
- thing: reached,
3166
- by: "default"
3167
- };
3168
- }
3169
- const reached = plainStep(thing, key);
3170
- return reached === NOTHING ? void 0 : {
3171
- thing: reached,
3172
- by: "default"
3173
- };
3174
- }
3175
- /**
3176
- * This function tells if a thing is a reference document: an envelope of the type `ref` with a list for its path.
3177
- *
3178
- * @param thing - The thing.
3179
- * @returns `true` for a reference document.
3180
- */
3181
- function isRef(thing) {
3182
- if (typeof thing !== "object" || thing === null) return false;
3183
- const type = thing.type;
3184
- if (type === void 0 || typeof type === "string" && type !== "ref") return false;
3185
- if (!isEnvelope(thing) || !Array.isArray(thing.value)) return false;
3186
- const path = typePath(thing.type);
3187
- return path !== void 0 && path.length === 1 && path[0] === "ref";
3188
- }
3189
- const worlds = /* @__PURE__ */ new WeakMap();
3190
- /**
3191
- * This function makes the thing of the root `world`: the entries of the world as JSON. An alias is a reference
3192
- * document in it, thus a walk through the world follows each alias (collapse). The thing of a world is made one
3193
- * time.
3194
- *
3195
- * @param world - The world.
3196
- * @returns The thing.
3197
- */
3198
- function worldThing(world) {
3199
- let thing = worlds.get(world);
3200
- if (thing === void 0) {
3201
- thing = entriesAsJson(world.kinds);
3202
- worlds.set(world, thing);
3203
- }
3204
- return thing;
3205
- }
3206
- /**
3207
- * This function makes a context. The world comes from the navigator when the call gives none.
3208
- *
3209
- * @param parts - The roots to set.
3210
- * @returns The context.
3211
- */
3212
- function context(parts = {}) {
3213
- return {
3214
- self: parts.self ?? null,
3215
- names: parts.names ?? {},
3216
- world: parts.world ?? null,
3217
- event: parts.event ?? null,
3218
- caps: parts.caps ?? []
3219
- };
3220
- }
3221
- const MAX_COLLAPSE$1 = 64;
3222
- /** The reason of a resolution that reaches the bound of collapses without a cycle that it found (DEREF.CHAIN-REASON). It is a plain string, thus a bundle drops it (PKG.PURE). */
3223
- const CHAIN_REASON = "The path follows more than 64 references. One resolution follows at most 64.";
3224
- const NO_HOPS$1 = /* @__PURE__ */ Object.freeze([]);
3225
- /** A value that can be a reference document: a record with the type `ref`. The full check comes after. */
3226
- function mayBeRef(thing) {
3227
- return typeof thing === "object" && thing !== null && thing.type === "ref";
3228
- }
3229
- /** This function tells if each step of a path from an index is a key. */
3230
- function keysFrom(path, start) {
3231
- for (let index = start; index < path.length; index += 1) if (!isKey(path[index])) return false;
3232
- return true;
3233
- }
3234
- /** This function tells if a root has a value of its own for the short path: each root except `caps`. */
3235
- function quickRoot(root) {
3236
- return root === "names" || root === "self" || root === "event" || root === "world";
3237
- }
3238
- /**
3239
- * This function resolves the common path without a record of hops: a root, then keys. Plain values answer the
3240
- * keys, or a host thing answers all of them in one call. It gives `undefined` when the path needs the full
3241
- * algorithm. Examples are a host thing without `resolve`, an envelope, a reference to follow, a step document and a
3242
- * failure of a step (for its exact reason).
3243
- */
3244
- function resolveQuick(nav, ctx, path) {
3245
- const root = path[0];
3246
- if (!quickRoot(root)) return void 0;
3247
- if (nav.roots !== void 0 && !nav.roots.includes(root)) return void 0;
3248
- if (nav.adopt !== void 0) return void 0;
3249
- return walkQuick(ctx[root], path, nav.plain === true, false);
3250
- }
3251
- /**
3252
- * This function walks the steps of the short path from the value of the root (DEREF.QUICK). `resolveQuick` and each
3253
- * compiled path use it, thus the two cannot disagree. It gives `undefined` when the path needs the full algorithm.
3254
- *
3255
- * @param start - The value of the root.
3256
- * @param path - The steps. The walk starts at the index 1.
3257
- * @param plain - `true` for a plain navigation.
3258
- * @param keyed - `true` when each step after the root is a key. The walk then does not test the steps again.
3259
- */
3260
- function walkQuick(start, path, plain, keyed) {
3261
- let here = start;
3262
- for (let index = 1; index < path.length; index += 1) {
3263
- if (typeof here !== "object" || here === null) return void 0;
3264
- const type = plain ? void 0 : here.type;
3265
- if (type === "ref") return void 0;
3266
- if (here[THING] === true) {
3267
- const thing = here;
3268
- if (thing.resolve === void 0 || !(keyed || keysFrom(path, index))) return void 0;
3269
- const keys = path.slice(index);
3270
- const reached = thing.resolve(keys);
3271
- if (reached === void 0) return {
3272
- ok: false,
3273
- code: "#N/A",
3274
- reason: `The path ${keys.join(".")} reaches nothing.`,
3275
- hops: NO_HOPS$1
3276
- };
3277
- if (!plain && mayBeRef(reached.thing)) return void 0;
3278
- return {
3279
- ok: true,
3280
- thing: reached.thing,
3281
- hops: NO_HOPS$1
3282
- };
3283
- }
3284
- const step = path[index];
3285
- if (Array.isArray(here)) {
3286
- if (typeof step !== "number" || !Number.isInteger(step) || step < 0 || step >= here.length) return void 0;
3287
- here = here[step];
3288
- continue;
3289
- }
3290
- if (typeof step !== "string" || !Object.hasOwn(here, step)) return void 0;
3291
- if (type !== void 0 && isEnvelope(here)) return void 0;
3292
- here = here[step];
3293
- }
3294
- if (!plain && mayBeRef(here)) return void 0;
3295
- return {
3296
- ok: true,
3297
- thing: here,
3298
- hops: NO_HOPS$1
3299
- };
3300
- }
3301
- /** The root whose value starts the short path of a compiled path. `FULL` takes the full algorithm at once. */
3302
- const FULL = 0;
3303
- const FROM_NAMES = 1;
3304
- const FROM_SELF = 2;
3305
- const FROM_EVENT = 3;
3306
- const FROM_WORLD = 4;
3307
- /**
3308
- * A compiled path as an object with fields (PLAN.LEAN). The code of `resolve` is on the class, thus each compiled path
3309
- * keeps only its fields and makes no closure.
3310
- */
3311
- var StaticPath = class {
3312
- constructor(path, nav, known, from, plain) {
3313
- this.path = path;
3314
- this.nav = nav;
3315
- this.known = known;
3316
- this.from = from;
3317
- this.plain = plain;
3318
- }
3319
- resolve(ctx) {
3320
- const from = this.from;
3321
- if (from !== FULL) {
3322
- const quick = walkQuick(from === FROM_NAMES ? ctx.names : from === FROM_WORLD ? ctx.world : from === FROM_SELF ? ctx.self : ctx.event, this.path, this.plain, true);
3323
- if (quick !== void 0) return quick;
3324
- }
3325
- return resolveFully$1(this.nav, ctx, this.path, void 0, this.known);
3326
- }
3327
- };
3328
- /**
3329
- * This function compiles one static path for one navigator. The resolver gives the same thing, error and reason as
3330
- * `resolve` without hops (PLAN.PATH-SAME). It keeps no value of a context.
3331
- *
3332
- * - Some paths take the full algorithm at once, because the short path cannot answer them. A path from `caps` or from
3333
- * a closed root is one. A path with a step document and each path of a navigator with `adopt` are others.
3334
- * - Each other path walks the short path from its root, and it takes the full algorithm when the values need it.
3335
- * - The walker of each step document comes from the ladder one time, here. The navigator and the step document do
3336
- * not change, thus the answer does not change either.
3337
- *
3338
- * An evaluator of a language calls this function in its `compile`, with the field `machine` of the input, and reads the
3339
- * result with `resolveCompiled` (PLAN.PATH-EXPORT).
3340
- *
3341
- * @param nav - The navigator. A plan compiles its paths for its machine.
3342
- * @param path - The steps. The first step is a root. The compiled path keeps this list, thus the host must not change it.
3343
- * @returns The compiled path.
3344
- */
3345
- function compilePath(nav, path) {
3346
- const keyed = keysFrom(path, 1);
3347
- return new StaticPath(path, nav, keyed ? void 0 : walkersOf(nav, path), startOf(nav, path, keyed), nav.plain === true);
3348
- }
3349
- /** This function gives the root that starts the short path of a compiled path, or `FULL`. */
3350
- function startOf(nav, path, keyed) {
3351
- const root = path[0];
3352
- if (!keyed || !quickRoot(root) || nav.adopt !== void 0) return FULL;
3353
- if (nav.roots !== void 0 && !nav.roots.includes(root)) return FULL;
3354
- return root === "names" ? FROM_NAMES : root === "self" ? FROM_SELF : root === "event" ? FROM_EVENT : FROM_WORLD;
3355
- }
3356
- /**
3357
- * This function asks the ladder of the verb `step` for each step document of a path. A step whose lookup throws
3358
- * stays unknown, thus the full algorithm asks the ladder again for it.
3359
- */
3360
- function walkersOf(nav, path) {
3361
- if (nav.walkers === void 0) return void 0;
3362
- const out = new Array(path.length);
3363
- for (let index = 1; index < path.length; index += 1) {
3364
- const step = path[index];
3365
- if (isKey(step)) continue;
3366
- try {
3367
- out[index] = walkerOf(nav, step) ?? null;
3368
- } catch {}
3369
- }
3370
- return out;
3371
- }
3372
- /**
3373
- * This function resolves a path from a context, and records each hop.
3374
- *
3375
- * The first step is a root of the context. Each later step is a key or a step document. A key goes up the ladder
3376
- * of the verb `deref` on the thing that the path reached. A step document is evaluated by the walker that the
3377
- * ladder of the verb `step` gives, with the thing that the path reached. After each hop, a reference document is
3378
- * followed until the path reaches something else (collapse), except in a plain navigation.
3379
- *
3380
- * The codes of a failure:
3381
- *
3382
- * - `#REF!`: the path has no root, or a root that is not open here.
3383
- * - `#NAME?`: the root `names` has no such name.
3384
- * - `#N/A`: a step reaches nothing.
3385
- * - `#STEP?`: a step is not a key and not a step document.
3386
- * - `#CYCLE!`: the references form a cycle, or the resolution follows more than 64 references. The reason tells
3387
- * which (DEREF.CHAIN-REASON).
3388
- *
3389
- * @param nav - The world and the code of the evaluators.
3390
- * @param ctx - The context.
3391
- * @param path - The steps.
3392
- * @param options - `hops: false` does not record the hops.
3393
- * @returns What the path reached and each hop, or an error.
3394
- */
3395
- function resolve(nav, ctx, path, options = {}) {
3396
- if (options.hops === false) {
3397
- const quick = resolveQuick(nav, ctx, path);
3398
- if (quick !== void 0) return quick;
3399
- }
3400
- return resolveFully$1(nav, ctx, path, options.hops === false ? void 0 : [], void 0);
3401
- }
3402
- /** The functions of the last navigator that gave a walker its input. A walk with the same navigator makes no new functions. */
3403
- let lastSteps;
3404
- /**
3405
- * This function gives the functions `deref` and `has` of the input of a walker. They depend only on the navigator,
3406
- * thus the function keeps the functions of the last navigator (K170).
3407
- */
3408
- function walkSteps(nav) {
3409
- if (lastSteps !== void 0 && lastSteps.nav === nav) return lastSteps;
3410
- const adopt = nav.adopt;
3411
- lastSteps = {
3412
- nav,
3413
- deref: adopt === void 0 ? (thing, key) => derefStep(nav, thing, key)?.thing : (thing, key) => {
3414
- const reached = derefStep(nav, thing, key);
3415
- return reached === void 0 ? void 0 : adopt(reached.thing);
3416
- },
3417
- has: (thing, key) => derefStep(nav, thing, key) !== void 0
3418
- };
3419
- return lastSteps;
3420
- }
3421
- /**
3422
- * This function resolves a path with the full algorithm of `resolve`.
3423
- *
3424
- * @param nav - The world and the code of the evaluators.
3425
- * @param ctx - The context.
3426
- * @param path - The steps.
3427
- * @param hops - The list that gets each hop, or `undefined` for no record.
3428
- * @param known - The walker of each step document of the path, from `compilePath`. A reference that a step reaches has its own steps, and the ladder answers them.
3429
- * @returns What the path reached and each hop, or an error.
3430
- */
3431
- function resolveFully$1(nav, ctx, path, hops, known) {
3432
- const done = hops ?? NO_HOPS$1;
3433
- const failed = (code, reason) => ({
3434
- ok: false,
3435
- code,
3436
- reason,
3437
- hops: done
3438
- });
3439
- let collapses = 0;
3440
- let open;
3441
- const adopt = nav.adopt ?? ((value) => value);
3442
- const collapse = (thing) => {
3443
- let here = thing;
3444
- if (nav.plain === true) return {
3445
- ok: true,
3446
- thing: here,
3447
- hops: done
3448
- };
3449
- while (isRef(here)) {
3450
- if (open?.includes(here) === true) return failed("#CYCLE!", "The references form a cycle.");
3451
- collapses += 1;
3452
- if (collapses > MAX_COLLAPSE$1) return failed("#CYCLE!", CHAIN_REASON);
3453
- open ??= [];
3454
- open.push(here);
3455
- const inner = walk(here.value, void 0);
3456
- open.pop();
3457
- if (!inner.ok) return inner;
3458
- here = adopt(inner.thing);
3459
- hops?.push({
3460
- step: "collapse",
3461
- thing: here,
3462
- by: "collapse"
3463
- });
3464
- }
3465
- return {
3466
- ok: true,
3467
- thing: here,
3468
- hops: done
3469
- };
3470
- };
3471
- const walk = (steps, walkers) => {
3472
- const root = steps[0];
3473
- if (typeof root !== "string" || !ROOTS.includes(root)) return failed("#REF!", `A path starts with a root: ${ROOTS.join(", ")}.`);
3474
- if (nav.roots !== void 0 && !nav.roots.includes(root)) return failed("#REF!", `The root ${root} is not open here. The open roots are ${nav.roots.join(", ")}.`);
3475
- let here = adopt(ctx[root]);
3476
- hops?.push({
3477
- step: root,
3478
- thing: here,
3479
- by: "root"
3480
- });
3481
- const first = collapse(here);
3482
- if (!first.ok) return first;
3483
- here = first.thing;
3484
- for (let index = 1; index < steps.length; index += 1) {
3485
- const step = steps[index];
3486
- if (isHostThing(here) && here.resolve !== void 0 && keysFrom(steps, index)) {
3487
- const keys = steps.slice(index);
3488
- const reached = here.resolve(keys);
3489
- if (reached === void 0) return failed("#N/A", `The path ${keys.join(".")} reaches nothing.`);
3490
- const thing = adopt(reached.thing);
3491
- hops?.push({
3492
- step: keys,
3493
- thing,
3494
- by: "own"
3495
- });
3496
- return collapse(thing);
3497
- }
3498
- if (isKey(step)) {
3499
- const reached = derefStep(nav, here, step);
3500
- if (reached === void 0) {
3501
- if (root === "names" && index === 1) return failed("#NAME?", `The context has no name ${String(step)}.`);
3502
- return failed("#N/A", `The step ${String(step)} reaches nothing.`);
3503
- }
3504
- here = adopt(reached.thing);
3505
- hops?.push({
3506
- step,
3507
- thing: here,
3508
- by: reached.by
3509
- });
3510
- } else {
3511
- const given = walkers?.[index];
3512
- const walker = given === void 0 ? walkerOf(nav, step) : given ?? void 0;
3513
- if (walker === void 0) return failed("#STEP?", "A step is a key, or a document of a kind with the verb step.");
3514
- const envelope = step;
3515
- const { deref, has } = walkSteps(nav);
3516
- const result = walker(hops === void 0 ? {
3517
- data: envelope.value,
3518
- here,
3519
- context: ctx,
3520
- deref,
3521
- has
3522
- } : {
3523
- data: envelope.value,
3524
- here,
3525
- context: ctx,
3526
- deref,
3527
- has,
3528
- visit: (key, thing) => hops.push({
3529
- step: key,
3530
- thing,
3531
- by: "step"
3532
- })
3533
- });
3534
- if (!result.ok) return failed(result.code ?? "#N/A", result.reason);
3535
- here = adopt(result.thing);
3536
- hops?.push({
3537
- step: envelope,
3538
- thing: here,
3539
- by: "step"
3540
- });
3541
- }
3542
- const next = collapse(here);
3543
- if (!next.ok) return next;
3544
- here = next.thing;
3545
- }
3546
- return {
3547
- ok: true,
3548
- thing: here,
3549
- hops: done
3550
- };
3551
- };
3552
- if (path.length === 0) return failed("#REF!", "A path has at least one step: its root.");
3553
- return walk(path, known);
3188
+ return typeof name === "string" && Object.hasOwn(table, name);
3554
3189
  }
3555
3190
  /**
3556
- * This function gives the value of a thing: the value that a host thing gives, or else the thing itself.
3191
+ * This function finds the walker of a step document through the ladder of the verb `step` (VERB.LADDER). The rungs
3192
+ * are the own entry, then the kind, then the default of the world. A rung answers only with a walker that the
3193
+ * navigator has. A resolution and `check` use this function, thus they agree on `#STEP?`.
3557
3194
  *
3558
- * @param thing - The thing.
3559
- * @returns The value.
3195
+ * @param nav - The world and the walkers.
3196
+ * @param step - A step of a path that is not a key.
3197
+ * @returns The walker, or `undefined` when no rung answers.
3560
3198
  */
3561
- function valueOfThing(thing) {
3562
- return isHostThing(thing) ? thing.toJson() : thing;
3199
+ function walkerOf(nav, step) {
3200
+ const walkers = nav.walkers;
3201
+ if (walkers === void 0 || !isEnvelope(step)) return void 0;
3202
+ const answer = answerOf(nav.world, ownEntries(step), kindFor(nav.world, step.type), "step", (name) => codeIn(walkers, name));
3203
+ return answer === void 0 ? void 0 : walkers[answer.name];
3563
3204
  }
3564
- // src/classify.ts
3565
- function isStrictSuperset(larger, smaller) {
3566
- return larger.length > smaller.length && smaller.every((name) => larger.includes(name));
3205
+ /** The answer of `plainStep` for a field that the value does not have. A field can hold `undefined`. */
3206
+ const NOTHING = /* @__PURE__ */ Symbol("nothing");
3207
+ /** The own fields of a value: the items and the length of a list, and the own properties of an object. */
3208
+ function plainStep(thing, key) {
3209
+ if (Array.isArray(thing)) {
3210
+ if (key === "length") return thing.length;
3211
+ const index = typeof key === "number" ? key : /^\d+$/.test(key) ? Number(key) : -1;
3212
+ return index >= 0 && index < thing.length ? thing[index] : NOTHING;
3213
+ }
3214
+ if (typeof thing === "object" && thing !== null) {
3215
+ const name = String(key);
3216
+ return Object.hasOwn(thing, name) ? thing[name] : NOTHING;
3217
+ }
3218
+ return NOTHING;
3567
3219
  }
3568
3220
  /**
3569
- * This function proposes a kind for a value without a type, from the fields that the value has.
3570
- * A shape applies when the value has each field of the shape. The most specific shapes are the ones that
3571
- * no other applicable shape contains. A host uses a classifier when data comes in, and then tags the data.
3572
- * The ladder does not call a classifier.
3573
- *
3574
- * @param shapes - The shapes to examine.
3575
- * @param value - The value without a type.
3576
- * @returns The proposed kind, or an error with the candidates.
3221
+ * This function tells if a value can be an envelope by its field `type`. An envelope has its own field `type`, thus
3222
+ * a value without that field is not an envelope, and the full test is not necessary.
3577
3223
  */
3578
- function classify(shapes, value) {
3579
- const applicable = isRecord(value) ? shapes.filter((shape) => shape.fields.every((name) => field(value, name) !== void 0)) : [];
3580
- const best = applicable.filter((shape) => !applicable.some((other) => isStrictSuperset(other.fields, shape.fields)));
3581
- const candidates = best.map((shape) => shape.name);
3582
- const only = best.length === 1 ? best[0] : void 0;
3583
- if (only !== void 0) return {
3584
- kind: only.kind,
3585
- candidates
3586
- };
3587
- return {
3588
- candidates,
3589
- error: best.length === 0 ? "no-match" : "ambiguous"
3590
- };
3224
+ function mayBeEnvelope(thing) {
3225
+ return typeof thing === "object" && thing !== null && thing.type !== void 0;
3591
3226
  }
3592
3227
  /**
3593
- * This function puts a value in an envelope with a type. The value does not change.
3228
+ * This function answers one step of a path on a thing, through the ladder of the verb `deref`. A host thing
3229
+ * answers for itself (own). A document asks its own entry, then its kind, then the default of the world
3230
+ * (VERB.LADDER). A rung answers only with a `deref` that the navigator has. When no rung answers, the step goes into
3231
+ * the value: an own field of an object, or an item of a list. A value without a type is data, thus the step goes
3232
+ * into it at once.
3594
3233
  *
3595
- * @param value - The value.
3596
- * @param kind - The name of the kind.
3597
- * @returns The envelope.
3234
+ * @param nav - The world and the code of the evaluators.
3235
+ * @param thing - The thing that the path reached.
3236
+ * @param key - The key of the step.
3237
+ * @returns What the step reaches and the rung that answered, or `undefined` when it reaches nothing.
3598
3238
  */
3599
- function tag(value, kind) {
3600
- return typed(kind, value);
3601
- }
3602
- // src/parts.ts
3603
- var Bad$1 = class {
3604
- reason;
3605
- at;
3606
- constructor(reason, at) {
3607
- this.reason = reason;
3608
- this.at = at;
3239
+ function derefStep(nav, thing, key) {
3240
+ if (isHostThing(thing)) {
3241
+ const reached = thing.deref(key);
3242
+ return reached !== void 0 || thing.has?.(key) === true ? {
3243
+ thing: reached,
3244
+ by: "own"
3245
+ } : void 0;
3609
3246
  }
3610
- };
3611
- /** This function sets an own data property. Only the key `__proto__` needs `defineProperty`. */
3612
- function setOwn$4(target, key, value) {
3613
- if (key === "__proto__") Object.defineProperty(target, key, {
3614
- value,
3615
- enumerable: true,
3616
- writable: true,
3617
- configurable: true
3618
- });
3619
- else target[key] = value;
3620
- }
3621
- const NO_SLOTS = /* @__PURE__ */ Object.freeze([]);
3622
- function hasSlots(template) {
3623
- return template.t !== "data";
3624
- }
3625
- /** This function gives the shape of a part with the default type `of` and the value type `expect` of its container. */
3626
- function termOf$1(of, expect) {
3627
- return {
3628
- shape: "term",
3629
- ...of === void 0 ? {} : { of },
3630
- ...expect === void 0 ? {} : { expect }
3247
+ if (nav.plain !== true && mayBeEnvelope(thing) && isEnvelope(thing)) {
3248
+ const envelope = thing;
3249
+ const derefs = nav.derefs;
3250
+ const answer = derefs === void 0 ? void 0 : answerOf(nav.world, ownEntries(envelope), kindFor(nav.world, envelope.type), "deref", (name) => codeIn(derefs, name));
3251
+ if (answer !== void 0) {
3252
+ const code = derefs[answer.name];
3253
+ const reached = code?.(envelope, key);
3254
+ return reached !== void 0 || code?.has?.(envelope, key) === true ? {
3255
+ thing: reached,
3256
+ by: answer.rung
3257
+ } : void 0;
3258
+ }
3259
+ const reached = plainStep(envelope.value, key);
3260
+ return reached === NOTHING ? void 0 : {
3261
+ thing: reached,
3262
+ by: "default"
3263
+ };
3264
+ }
3265
+ const reached = plainStep(thing, key);
3266
+ return reached === NOTHING ? void 0 : {
3267
+ thing: reached,
3268
+ by: "default"
3631
3269
  };
3632
3270
  }
3633
- /** This function tells if a shape holds only data: no value of the shape can hold a part. */
3634
- function isData(shape) {
3635
- return shape.shape === "none" || shape.shape === "text" || shape.shape === "number" || shape.shape === "one";
3636
- }
3637
- /** This function gives the reason why a value is not data of a shape, or `undefined` when it is. */
3638
- function dataFault(spec, item) {
3639
- if (spec.shape === "text") return typeof item === "string" ? void 0 : "The value must be a text.";
3640
- if (spec.shape === "one") return spec.values.some((value) => docEquals(value, item)) ? void 0 : `The value must be one of ${JSON.stringify(spec.values)}.`;
3641
- if (typeof item !== "number") return "The value must be a number.";
3642
- if (spec.whole === true && !Number.isInteger(item)) return "The value must be a whole number.";
3643
- if (spec.min !== void 0 && !(item >= spec.min)) return `The value must be ${String(spec.min)} or more.`;
3644
- if (spec.max !== void 0 && !(item <= spec.max)) return `The value must be ${String(spec.max)} or less.`;
3645
- }
3646
- /** This function stops a split when a part has a type that its position does not permit. */
3647
- function kindFault(kinds, item, of, path) {
3648
- const type = isEnvelope(item) ? typePath(item.type) : of === void 0 ? void 0 : [of];
3649
- if (type !== void 0 && kinds.some((kind) => kind.length <= type.length && kind.every((key, index) => String(key) === String(type[index])))) return;
3650
- const names = kinds.map((kind) => kind.join(".")).join(", ");
3651
- throw new Bad$1(`${isEnvelope(item) ? `The kind ${typeName(item.type)} is not permitted here.` : "A value without an envelope is not permitted here."} The permitted kinds are ${names}.`, path);
3652
- }
3653
3271
  /**
3654
- * This function splits a value into its parts, by the shape that its kind declares. The evaluator, the view and
3655
- * the static kit use the same split, thus each one sees the same parts.
3272
+ * This function tells if a thing is a reference document: an envelope of the type `ref` with a list for its path.
3656
3273
  *
3657
- * @param shape - The shape of the value. The default is data.
3658
- * @param value - The value of the document.
3659
- * @returns The parts and a way to fill their places, or the reason why the value does not have the shape.
3274
+ * @param thing - The thing.
3275
+ * @returns `true` for a reference document.
3660
3276
  */
3661
- function splitParts(shape, value) {
3662
- if (shape === void 0 || shape.shape === "none") return {
3663
- ok: true,
3664
- parts: NO_SLOTS,
3665
- data: value,
3666
- fill: () => value
3667
- };
3668
- const parts = [];
3669
- const slot = (item, path, of, address = false, expect) => {
3670
- parts.push({
3671
- path,
3672
- key: path.join("."),
3673
- item,
3674
- ...of === void 0 ? {} : { of },
3675
- ...address ? { address: true } : {},
3676
- ...expect === void 0 ? {} : { expect }
3677
- });
3678
- return {
3679
- t: "slot",
3680
- index: parts.length - 1
3681
- };
3682
- };
3683
- const deep = (item, path, of, expect) => {
3684
- if (isEnvelope(item)) return slot(item, path, of, false, expect);
3685
- if (Array.isArray(item)) {
3686
- const items = item.map((child, index) => deep(child, [...path, index], of, expect));
3687
- return items.some(hasSlots) ? {
3688
- t: "list",
3689
- items
3690
- } : {
3691
- t: "data",
3692
- value: item
3693
- };
3694
- }
3695
- if (isRecord(item)) {
3696
- const fields = Object.keys(item).map((key) => [key, deep(item[key], [...path, key], of, expect)]);
3697
- return fields.some(([, child]) => hasSlots(child)) ? {
3698
- t: "record",
3699
- fields
3700
- } : {
3701
- t: "data",
3702
- value: item
3703
- };
3704
- }
3705
- return {
3706
- t: "data",
3707
- value: item
3708
- };
3709
- };
3710
- const walk = (spec, item, path) => {
3711
- if (spec === void 0 || spec.shape === "none") return {
3712
- t: "data",
3713
- value: item
3714
- };
3715
- if (spec.shape === "text" || spec.shape === "number" || spec.shape === "one") {
3716
- const reason = dataFault(spec, item);
3717
- if (reason !== void 0) throw new Bad$1(reason, path);
3718
- return {
3719
- t: "data",
3720
- value: item
3721
- };
3722
- }
3723
- if (spec.shape === "term") {
3724
- if (spec.kinds !== void 0) kindFault(spec.kinds, item, spec.of, path);
3725
- return slot(item, path, spec.of, spec.address === true, spec.expect);
3726
- }
3727
- if (spec.shape === "deep") return deep(item, path, spec.of, spec.expect);
3728
- if (spec.shape === "list") {
3729
- if (!Array.isArray(item)) throw new Bad$1("The value must be a list.", path);
3730
- const list = item;
3731
- if (spec.distinct === true) {
3732
- const twice = list.findIndex((child, index) => list.slice(0, index).some((before) => docEquals(before, child)));
3733
- if (twice !== -1) throw new Bad$1("The items of the list must be different.", [...path, twice]);
3734
- }
3735
- const each = spec.item ?? termOf$1(spec.of, spec.expect);
3736
- const items = list.map((child, index) => walk(each, child, [...path, index]));
3737
- return isData(each) ? {
3738
- t: "data",
3739
- value: item
3740
- } : {
3741
- t: "list",
3742
- items
3277
+ function isRef(thing) {
3278
+ if (typeof thing !== "object" || thing === null) return false;
3279
+ const type = thing.type;
3280
+ if (type === void 0 || typeof type === "string" && type !== "ref") return false;
3281
+ if (!isEnvelope(thing) || !Array.isArray(thing.value)) return false;
3282
+ const path = typePath(thing.type);
3283
+ return path !== void 0 && path.length === 1 && path[0] === "ref";
3284
+ }
3285
+ const worlds = /* @__PURE__ */ new WeakMap();
3286
+ /**
3287
+ * This function makes the thing of the root `world`: the entries of the world as JSON. An alias is a reference
3288
+ * document in it, thus a walk through the world follows each alias (collapse). The thing of a world is made one
3289
+ * time.
3290
+ *
3291
+ * @param world - The world.
3292
+ * @returns The thing.
3293
+ */
3294
+ function worldThing(world) {
3295
+ let thing = worlds.get(world);
3296
+ if (thing === void 0) {
3297
+ thing = entriesAsJson(world.kinds);
3298
+ worlds.set(world, thing);
3299
+ }
3300
+ return thing;
3301
+ }
3302
+ /**
3303
+ * This function makes a context. The world comes from the navigator when the call gives none.
3304
+ *
3305
+ * @param parts - The roots to set.
3306
+ * @returns The context.
3307
+ */
3308
+ function context(parts = {}) {
3309
+ return {
3310
+ self: parts.self ?? null,
3311
+ names: parts.names ?? {},
3312
+ world: parts.world ?? null,
3313
+ event: parts.event ?? null,
3314
+ caps: parts.caps ?? []
3315
+ };
3316
+ }
3317
+ const MAX_COLLAPSE$1 = 64;
3318
+ /** The reason of a resolution that reaches the bound of collapses without a cycle that it found (DEREF.CHAIN-REASON). It is a plain string, thus a bundle drops it (PKG.PURE). */
3319
+ const CHAIN_REASON = "The path follows more than 64 references. One resolution follows at most 64.";
3320
+ const NO_HOPS$1 = /* @__PURE__ */ Object.freeze([]);
3321
+ /** A value that can be a reference document: a record with the type `ref`. The full check comes after. */
3322
+ function mayBeRef(thing) {
3323
+ return typeof thing === "object" && thing !== null && thing.type === "ref";
3324
+ }
3325
+ /** This function tells if each step of a path from an index is a key. */
3326
+ function keysFrom(path, start) {
3327
+ for (let index = start; index < path.length; index += 1) if (!isKey(path[index])) return false;
3328
+ return true;
3329
+ }
3330
+ /** This function tells if a root has a value of its own for the short path: each root except `caps`. */
3331
+ function quickRoot(root) {
3332
+ return root === "names" || root === "self" || root === "event" || root === "world";
3333
+ }
3334
+ /**
3335
+ * This function resolves the common path without a record of hops: a root, then keys. Plain values answer the
3336
+ * keys, or a host thing answers all of them in one call. It gives `undefined` when the path needs the full
3337
+ * algorithm. Examples are a host thing without `resolve`, an envelope, a reference to follow, a step document and a
3338
+ * failure of a step (for its exact reason).
3339
+ */
3340
+ function resolveQuick(nav, ctx, path) {
3341
+ const root = path[0];
3342
+ if (!quickRoot(root)) return void 0;
3343
+ if (nav.roots !== void 0 && !nav.roots.includes(root)) return void 0;
3344
+ if (nav.adopt !== void 0) return void 0;
3345
+ return walkQuick(ctx[root], path, nav.plain === true, false);
3346
+ }
3347
+ /**
3348
+ * This function walks the steps of the short path from the value of the root (DEREF.QUICK). `resolveQuick` and each
3349
+ * compiled path use it, thus the two cannot disagree. It gives `undefined` when the path needs the full algorithm.
3350
+ *
3351
+ * @param start - The value of the root.
3352
+ * @param path - The steps. The walk starts at the index 1.
3353
+ * @param plain - `true` for a plain navigation.
3354
+ * @param keyed - `true` when each step after the root is a key. The walk then does not test the steps again.
3355
+ */
3356
+ function walkQuick(start, path, plain, keyed) {
3357
+ let here = start;
3358
+ for (let index = 1; index < path.length; index += 1) {
3359
+ if (typeof here !== "object" || here === null) return void 0;
3360
+ const type = plain ? void 0 : here.type;
3361
+ if (type === "ref") return void 0;
3362
+ if (here[THING] === true) {
3363
+ const thing = here;
3364
+ if (thing.resolve === void 0 || !(keyed || keysFrom(path, index))) return void 0;
3365
+ const keys = path.slice(index);
3366
+ const reached = thing.resolve(keys);
3367
+ if (reached === void 0) return {
3368
+ ok: false,
3369
+ code: "#N/A",
3370
+ reason: `The path ${keys.join(".")} reaches nothing.`,
3371
+ hops: NO_HOPS$1
3743
3372
  };
3744
- }
3745
- if (!isRecord(item)) throw new Bad$1("The value must be a record.", path);
3746
- if (spec.shape === "map") {
3747
- const each = spec.item ?? termOf$1(spec.of, spec.expect);
3373
+ if (!plain && mayBeRef(reached.thing)) return void 0;
3748
3374
  return {
3749
- t: "record",
3750
- fields: Object.keys(item).map((key) => [key, walk(each, item[key], [...path, key])])
3375
+ ok: true,
3376
+ thing: reached.thing,
3377
+ hops: NO_HOPS$1
3751
3378
  };
3752
3379
  }
3753
- for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad$1(`The field ${name} is missing.`, path);
3754
- const named = Array.isArray(spec.fields) ? Object.fromEntries(spec.fields.map((name) => [name, termOf$1(spec.of, spec.expect)])) : spec.fields;
3755
- const fields = [];
3756
- for (const key of Object.keys(item)) {
3757
- if (spec.closed === true && !Object.hasOwn(named, key)) throw new Bad$1(`The field ${key} is not a field of this kind.`, [...path, key]);
3758
- const fieldShape = Object.hasOwn(named, key) ? named[key] : spec.rest;
3759
- fields.push([key, walk(fieldShape, item[key], [...path, key])]);
3380
+ const step = path[index];
3381
+ if (Array.isArray(here)) {
3382
+ if (typeof step !== "number" || !Number.isInteger(step) || step < 0 || step >= here.length) return void 0;
3383
+ here = here[step];
3384
+ continue;
3760
3385
  }
3761
- return {
3762
- t: "record",
3763
- fields
3764
- };
3765
- };
3766
- let template;
3767
- try {
3768
- template = walk(shape, value, []);
3769
- } catch (error) {
3770
- if (error instanceof Bad$1) return {
3771
- ok: false,
3772
- reason: error.reason,
3773
- at: error.at
3774
- };
3775
- throw error;
3386
+ if (typeof step !== "string" || !Object.hasOwn(here, step)) return void 0;
3387
+ if (type !== void 0 && isEnvelope(here)) return void 0;
3388
+ here = here[step];
3776
3389
  }
3777
- const strip = (node) => {
3778
- if (node.t === "data") return node.value;
3779
- if (node.t === "slot") return void 0;
3780
- if (node.t === "list") return node.items.every((child) => child.t === "slot") ? null : node.items.map((child) => strip(child) ?? null);
3781
- const out = {};
3782
- for (const [key, child] of node.fields) {
3783
- const kept = strip(child);
3784
- if (kept !== void 0) setOwn$4(out, key, kept);
3785
- }
3786
- return out;
3787
- };
3788
- const fillWith = (node, handles) => {
3789
- if (node.t === "data") return node.value;
3790
- if (node.t === "slot") return handles[node.index];
3791
- if (node.t === "list") return node.items.map((child) => fillWith(child, handles));
3792
- const out = {};
3793
- for (const [key, child] of node.fields) setOwn$4(out, key, fillWith(child, handles));
3794
- return out;
3795
- };
3390
+ if (!plain && mayBeRef(here)) return void 0;
3796
3391
  return {
3797
3392
  ok: true,
3798
- parts,
3799
- data: strip(template) ?? null,
3800
- fill: (handles) => fillWith(template, handles)
3393
+ thing: here,
3394
+ hops: NO_HOPS$1
3801
3395
  };
3802
3396
  }
3397
+ /** The root whose value starts the short path of a compiled path. `FULL` takes the full algorithm at once. */
3398
+ const FULL = 0;
3399
+ const FROM_NAMES = 1;
3400
+ const FROM_SELF = 2;
3401
+ const FROM_EVENT = 3;
3402
+ const FROM_WORLD = 4;
3803
3403
  /**
3804
- * This function reads one document by the contracts of the world. It finds the kind of the type. A bare value gets
3805
- * the type that its position declares. Then the function splits the value by the shape of the kind. The plan, the
3806
- * reference interpreter and the static kit read each document with this function. Thus they see the same parts.
3807
- *
3808
- * @param world - The world of the kinds.
3809
- * @param value - The document, or a bare value.
3810
- * @param declaredType - The type that the position of a bare value declares.
3811
- * @returns The document, its kind and its parts, or the reason why the value is not a document.
3404
+ * A compiled path as an object with fields (PLAN.LEAN). The code of `resolve` is on the class, thus each compiled path
3405
+ * keeps only its fields and makes no closure.
3812
3406
  */
3813
- function partsOf(world, value, declaredType) {
3814
- const envelope = isEnvelope(value) ? value : void 0;
3815
- if (envelope === void 0 && declaredType === void 0) return {
3816
- ok: false,
3817
- code: "#PART?",
3818
- reason: "The value has no envelope, and its position declares no type."
3819
- };
3820
- const doc = envelope ?? {
3821
- type: declaredType,
3822
- value
3823
- };
3824
- const found = lookupKind(world, doc.type);
3825
- const kind = found.ok ? found.kind : void 0;
3826
- const split = splitParts(kind?.parts, doc.value);
3827
- const typePath = found.ok ? found.path : void 0;
3828
- if (split.ok) return {
3829
- ok: true,
3830
- doc,
3831
- declared: envelope === void 0,
3832
- kind,
3833
- typePath,
3834
- split
3835
- };
3836
- const where = split.at.length === 0 ? "" : ` (at ${split.at.join(".")})`;
3837
- const reason = `${split.reason}${where} The kind is ${typeName(doc.type)}.`;
3838
- return {
3839
- ok: true,
3840
- doc,
3841
- declared: envelope === void 0,
3842
- kind,
3843
- typePath,
3844
- split: {
3845
- ok: false,
3846
- reason,
3847
- at: split.at
3407
+ var StaticPath = class {
3408
+ constructor(path, nav, known, from, plain) {
3409
+ this.path = path;
3410
+ this.nav = nav;
3411
+ this.known = known;
3412
+ this.from = from;
3413
+ this.plain = plain;
3414
+ }
3415
+ resolve(ctx) {
3416
+ const from = this.from;
3417
+ if (from !== FULL) {
3418
+ const quick = walkQuick(from === FROM_NAMES ? ctx.names : from === FROM_WORLD ? ctx.world : from === FROM_SELF ? ctx.self : ctx.event, this.path, this.plain, true);
3419
+ if (quick !== void 0) return quick;
3848
3420
  }
3849
- };
3421
+ return resolveFully$1(this.nav, ctx, this.path, void 0, this.known);
3422
+ }
3423
+ };
3424
+ /**
3425
+ * This function compiles one static path for one navigator. The resolver gives the same thing, error and reason as
3426
+ * `resolve` without hops (PLAN.PATH-SAME). It keeps no value of a context.
3427
+ *
3428
+ * - Some paths take the full algorithm at once, because the short path cannot answer them. A path from `caps` or from
3429
+ * a closed root is one. A path with a step document and each path of a navigator with `adopt` are others.
3430
+ * - Each other path walks the short path from its root, and it takes the full algorithm when the values need it.
3431
+ * - The walker of each step document comes from the ladder one time, here. The navigator and the step document do
3432
+ * not change, thus the answer does not change either.
3433
+ *
3434
+ * An evaluator of a language calls this function in its `compile`, with the field `machine` of the input, and reads the
3435
+ * result with `resolveCompiled` (PLAN.PATH-EXPORT).
3436
+ *
3437
+ * @param nav - The navigator. A plan compiles its paths for its machine.
3438
+ * @param path - The steps. The first step is a root. The compiled path keeps this list, thus the host must not change it.
3439
+ * @returns The compiled path.
3440
+ */
3441
+ function compilePath(nav, path) {
3442
+ const keyed = keysFrom(path, 1);
3443
+ return new StaticPath(path, nav, keyed ? void 0 : walkersOf(nav, path), startOf(nav, path, keyed), nav.plain === true);
3444
+ }
3445
+ /** This function gives the root that starts the short path of a compiled path, or `FULL`. */
3446
+ function startOf(nav, path, keyed) {
3447
+ const root = path[0];
3448
+ if (!keyed || !quickRoot(root) || nav.adopt !== void 0) return FULL;
3449
+ if (nav.roots !== void 0 && !nav.roots.includes(root)) return FULL;
3450
+ return root === "names" ? FROM_NAMES : root === "self" ? FROM_SELF : root === "event" ? FROM_EVENT : FROM_WORLD;
3451
+ }
3452
+ /**
3453
+ * This function asks the ladder of the verb `step` for each step document of a path. A step whose lookup throws
3454
+ * stays unknown, thus the full algorithm asks the ladder again for it.
3455
+ */
3456
+ function walkersOf(nav, path) {
3457
+ if (nav.walkers === void 0) return void 0;
3458
+ const out = new Array(path.length);
3459
+ for (let index = 1; index < path.length; index += 1) {
3460
+ const step = path[index];
3461
+ if (isKey(step)) continue;
3462
+ try {
3463
+ out[index] = walkerOf(nav, step) ?? null;
3464
+ } catch {}
3465
+ }
3466
+ return out;
3850
3467
  }
3851
3468
  /**
3852
- * This function tells if the path of a part matches a pattern of a scope rule. The key `"*"` of a pattern matches
3853
- * each key.
3469
+ * This function resolves a path from a context, and records each hop.
3854
3470
  *
3855
- * @param path - The path of the part.
3856
- * @param pattern - The pattern.
3857
- * @returns `true` when the path matches.
3471
+ * The first step is a root of the context. Each later step is a key or a step document. A key goes up the ladder
3472
+ * of the verb `deref` on the thing that the path reached. A step document is evaluated by the walker that the
3473
+ * ladder of the verb `step` gives, with the thing that the path reached. After each hop, a reference document is
3474
+ * followed until the path reaches something else (collapse), except in a plain navigation.
3475
+ *
3476
+ * The codes of a failure:
3477
+ *
3478
+ * - `#REF!`: the path has no root, or a root that is not open here.
3479
+ * - `#NAME?`: the root `names` has no such name.
3480
+ * - `#N/A`: a step reaches nothing.
3481
+ * - `#STEP?`: a step is not a key and not a step document.
3482
+ * - `#CYCLE!`: the references form a cycle, or the resolution follows more than 64 references. The reason tells
3483
+ * which (DEREF.CHAIN-REASON).
3484
+ *
3485
+ * @param nav - The world and the code of the evaluators.
3486
+ * @param ctx - The context.
3487
+ * @param path - The steps.
3488
+ * @param options - `hops: false` does not record the hops.
3489
+ * @returns What the path reached and each hop, or an error.
3858
3490
  */
3859
- function pathMatches(path, pattern) {
3860
- if (path.length !== pattern.length) return false;
3861
- for (let index = 0; index < path.length; index += 1) {
3862
- const want = pattern[index];
3863
- if (want !== "*" && String(want) !== String(path[index])) return false;
3491
+ function resolve(nav, ctx, path, options = {}) {
3492
+ if (options.hops === false) {
3493
+ const quick = resolveQuick(nav, ctx, path);
3494
+ if (quick !== void 0) return quick;
3864
3495
  }
3865
- return true;
3496
+ return resolveFully$1(nav, ctx, path, options.hops === false ? void 0 : [], void 0);
3866
3497
  }
3498
+ /** The functions of the last navigator that gave a walker its input. A walk with the same navigator makes no new functions. */
3499
+ let lastSteps;
3867
3500
  /**
3868
- * This function tells if a list of rules in the form of the lazy rules covers a part (D24, D119). A rule without
3869
- * `in` covers each part. With `after: n`, a rule covers only the parts after the first `n` parts that it matches.
3870
- *
3871
- * @param rules - The rules.
3872
- * @param shape - The shape of the parts of the parent.
3873
- * @param value - The value of the parent.
3874
- * @param slot - The path of the part in the value.
3875
- * @returns `true` when a rule covers the part.
3501
+ * This function gives the functions `deref` and `has` of the input of a walker. They depend only on the navigator,
3502
+ * thus the function keeps the functions of the last navigator (K170).
3876
3503
  */
3877
- function rulesCover(rules, shape, value, slot) {
3878
- for (const rule of rules) {
3879
- if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(slot, pattern))) continue;
3880
- const after = rule.after ?? 0;
3881
- if (after <= 0) return true;
3882
- const split = splitParts(shape, value);
3883
- let count = 0;
3884
- for (const part of split.ok ? split.parts : []) {
3885
- if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(part.path, pattern))) continue;
3886
- if (part.path.length === slot.length && pathMatches(part.path, slot)) {
3887
- if (count >= after) return true;
3888
- break;
3889
- }
3890
- count += 1;
3891
- }
3892
- }
3893
- return false;
3894
- }
3895
- function valueAt(value, path) {
3896
- let here = value;
3897
- for (const key of path) if (Array.isArray(here)) here = here[Number(key)];
3898
- else if (isRecord(here) && Object.hasOwn(here, String(key))) here = here[String(key)];
3899
- else return void 0;
3900
- return here;
3901
- }
3902
- function headerName(item) {
3903
- return isEnvelope(item) && typeof item.name === "string" ? item.name : void 0;
3904
- }
3905
- function namesOf(source, value, covered) {
3906
- if ("fixed" in source) return source.fixed;
3907
- if ("keysAt" in source) {
3908
- const at = valueAt(value, source.keysAt);
3909
- return isRecord(at) ? Object.keys(at) : [];
3910
- }
3911
- if ("listAt" in source) {
3912
- const at = valueAt(value, source.listAt);
3913
- return Array.isArray(at) ? at.filter((item) => typeof item === "string") : [];
3914
- }
3915
- if ("textAt" in source) {
3916
- const at = valueAt(value, source.textAt);
3917
- if (typeof at === "string") return [at];
3918
- return source.otherwise === void 0 ? [] : [source.otherwise];
3919
- }
3920
- return covered.map((slot) => headerName(slot.item)).filter((name) => name !== void 0);
3504
+ function walkSteps(nav) {
3505
+ if (lastSteps !== void 0 && lastSteps.nav === nav) return lastSteps;
3506
+ const adopt = nav.adopt;
3507
+ lastSteps = {
3508
+ nav,
3509
+ deref: adopt === void 0 ? (thing, key) => derefStep(nav, thing, key)?.thing : (thing, key) => {
3510
+ const reached = derefStep(nav, thing, key);
3511
+ return reached === void 0 ? void 0 : adopt(reached.thing);
3512
+ },
3513
+ has: (thing, key) => derefStep(nav, thing, key) !== void 0
3514
+ };
3515
+ return lastSteps;
3921
3516
  }
3922
3517
  /**
3923
- * This function gives the names that the scope rules of a kind give each part, and the names that only later parts
3924
- * see. `check`, `conforms` and the plan read the scope rules with it.
3518
+ * This function resolves a path with the full algorithm of `resolve`.
3925
3519
  *
3926
- * @param rules - The scope rules of the kind.
3927
- * @param value - The value of the document.
3928
- * @param slots - The parts of the value, in order.
3929
- * @returns The names that each part sees, and the names that only the later parts see, by the index of the part.
3520
+ * @param nav - The world and the code of the evaluators.
3521
+ * @param ctx - The context.
3522
+ * @param path - The steps.
3523
+ * @param hops - The list that gets each hop, or `undefined` for no record.
3524
+ * @param known - The walker of each step document of the path, from `compilePath`. A reference that a step reaches has its own steps, and the ladder answers them.
3525
+ * @returns What the path reached and each hop, or an error.
3930
3526
  */
3931
- function scopesOf(rules, value, slots) {
3932
- const sees = slots.map(() => []);
3933
- const later = slots.map(() => []);
3934
- for (const rule of rules ?? []) {
3935
- const covered = slots.map((slot, index) => ({
3936
- slot,
3937
- index
3938
- })).filter(({ slot }) => rule.in.some((pattern) => pathMatches(slot.path, pattern)));
3939
- if (rule.sequential !== true) {
3940
- const names = namesOf(rule.names, value, covered.map(({ slot }) => slot));
3941
- for (const { index } of covered) sees[index]?.push(...names);
3942
- continue;
3943
- }
3944
- if ("headers" in rule.names) {
3945
- covered.forEach(({ index }, position) => {
3946
- const before = covered.slice(0, position).map(({ slot }) => headerName(slot.item)).filter((name) => name !== void 0);
3947
- const after = covered.slice(position).map(({ slot }) => headerName(slot.item)).filter((name) => name !== void 0);
3948
- sees[index]?.push(...before);
3949
- later[index]?.push(...after);
3527
+ function resolveFully$1(nav, ctx, path, hops, known) {
3528
+ const done = hops ?? NO_HOPS$1;
3529
+ const failed = (code, reason) => ({
3530
+ ok: false,
3531
+ code,
3532
+ reason,
3533
+ hops: done
3534
+ });
3535
+ let collapses = 0;
3536
+ let open;
3537
+ const adopt = nav.adopt ?? ((value) => value);
3538
+ const collapse = (thing) => {
3539
+ let here = thing;
3540
+ if (nav.plain === true) return {
3541
+ ok: true,
3542
+ thing: here,
3543
+ hops: done
3544
+ };
3545
+ while (isRef(here)) {
3546
+ if (open?.includes(here) === true) return failed("#CYCLE!", "The references form a cycle.");
3547
+ collapses += 1;
3548
+ if (collapses > MAX_COLLAPSE$1) return failed("#CYCLE!", CHAIN_REASON);
3549
+ open ??= [];
3550
+ open.push(here);
3551
+ const inner = walk(here.value, void 0);
3552
+ open.pop();
3553
+ if (!inner.ok) return inner;
3554
+ here = adopt(inner.thing);
3555
+ hops?.push({
3556
+ step: "collapse",
3557
+ thing: here,
3558
+ by: "collapse"
3950
3559
  });
3951
- continue;
3952
3560
  }
3953
- const names = namesOf(rule.names, value, covered.map(({ slot }) => slot));
3954
- covered.forEach(({ index }, position) => {
3955
- if (position > 0) sees[index]?.push(...names);
3956
- else later[index]?.push(...names);
3561
+ return {
3562
+ ok: true,
3563
+ thing: here,
3564
+ hops: done
3565
+ };
3566
+ };
3567
+ const walk = (steps, walkers) => {
3568
+ const root = steps[0];
3569
+ if (typeof root !== "string" || !ROOTS.includes(root)) return failed("#REF!", `A path starts with a root: ${ROOTS.join(", ")}.`);
3570
+ if (nav.roots !== void 0 && !nav.roots.includes(root)) return failed("#REF!", `The root ${root} is not open here. The open roots are ${nav.roots.join(", ")}.`);
3571
+ let here = adopt(ctx[root]);
3572
+ hops?.push({
3573
+ step: root,
3574
+ thing: here,
3575
+ by: "root"
3957
3576
  });
3958
- }
3959
- return {
3960
- sees,
3961
- later
3577
+ const first = collapse(here);
3578
+ if (!first.ok) return first;
3579
+ here = first.thing;
3580
+ for (let index = 1; index < steps.length; index += 1) {
3581
+ const step = steps[index];
3582
+ if (isHostThing(here) && here.resolve !== void 0 && keysFrom(steps, index)) {
3583
+ const keys = steps.slice(index);
3584
+ const reached = here.resolve(keys);
3585
+ if (reached === void 0) return failed("#N/A", `The path ${keys.join(".")} reaches nothing.`);
3586
+ const thing = adopt(reached.thing);
3587
+ hops?.push({
3588
+ step: keys,
3589
+ thing,
3590
+ by: "own"
3591
+ });
3592
+ return collapse(thing);
3593
+ }
3594
+ if (isKey(step)) {
3595
+ const reached = derefStep(nav, here, step);
3596
+ if (reached === void 0) {
3597
+ if (root === "names" && index === 1) return failed("#NAME?", `The context has no name ${String(step)}.`);
3598
+ return failed("#N/A", `The step ${String(step)} reaches nothing.`);
3599
+ }
3600
+ here = adopt(reached.thing);
3601
+ hops?.push({
3602
+ step,
3603
+ thing: here,
3604
+ by: reached.by
3605
+ });
3606
+ } else {
3607
+ const given = walkers?.[index];
3608
+ const walker = given === void 0 ? walkerOf(nav, step) : given ?? void 0;
3609
+ if (walker === void 0) return failed("#STEP?", "A step is a key, or a document of a kind with the verb step.");
3610
+ const envelope = step;
3611
+ const { deref, has } = walkSteps(nav);
3612
+ const result = walker(hops === void 0 ? {
3613
+ data: envelope.value,
3614
+ here,
3615
+ context: ctx,
3616
+ deref,
3617
+ has
3618
+ } : {
3619
+ data: envelope.value,
3620
+ here,
3621
+ context: ctx,
3622
+ deref,
3623
+ has,
3624
+ visit: (key, thing) => hops.push({
3625
+ step: key,
3626
+ thing,
3627
+ by: "step"
3628
+ })
3629
+ });
3630
+ if (!result.ok) return failed(result.code ?? "#N/A", result.reason);
3631
+ here = adopt(result.thing);
3632
+ hops?.push({
3633
+ step: envelope,
3634
+ thing: here,
3635
+ by: "step"
3636
+ });
3637
+ }
3638
+ const next = collapse(here);
3639
+ if (!next.ok) return next;
3640
+ here = next.thing;
3641
+ }
3642
+ return {
3643
+ ok: true,
3644
+ thing: here,
3645
+ hops: done
3646
+ };
3962
3647
  };
3648
+ if (path.length === 0) return failed("#REF!", "A path has at least one step: its root.");
3649
+ return walk(path, known);
3650
+ }
3651
+ /**
3652
+ * This function gives the value of a thing: the value that a host thing gives, or else the thing itself.
3653
+ *
3654
+ * @param thing - The thing.
3655
+ * @returns The value.
3656
+ */
3657
+ function valueOfThing(thing) {
3658
+ return isHostThing(thing) ? thing.toJson() : thing;
3963
3659
  }
3964
3660
  // src/evaluate.ts
3965
3661
  /**
@@ -4519,14 +4215,14 @@ var Session = class {
4519
4215
  /**
4520
4216
  * This function adds work to the count of the evaluation (WORK.LIMIT). One count is on the runtime of the root, thus
4521
4217
  * each equation of a tree adds to it. After the end of the evaluation, each entry from the host starts a new count
4522
- * (WORK.AFTER).
4218
+ * (WORK.AFTER). An entry is a point with no application of a closure that runs, on any runtime of the evaluation.
4523
4219
  *
4524
4220
  * @param points - The work.
4525
4221
  * @throws {Failure} The error `#WORK!`, when the count is over the limit of the machine.
4526
4222
  */
4527
4223
  spend(points) {
4528
4224
  const root = this.top ?? this;
4529
- const work = (root.top === root && (this.applying ?? 0) === 0 ? 0 : root.work ?? 0) + points;
4225
+ const work = (root.top === root && (root.active ?? 0) === 0 ? 0 : root.work ?? 0) + points;
4530
4226
  root.work = work;
4531
4227
  const limit = this.machine.maxWork ?? 2e5;
4532
4228
  if (work > limit) throw new Failure(workFailure(limit));
@@ -5905,104 +5601,447 @@ function record(s, result) {
5905
5601
  };
5906
5602
  }
5907
5603
  /**
5908
- * This function evaluates a document, and records each evaluation in a trace.
5909
- *
5910
- * The verb of the options goes up the ladder for each document. The default verb is `eval`. The kind of the document
5911
- * tells where its parts are. The evaluator gets each part sealed: it can evaluate the part, and it cannot read its
5912
- * value.
5913
- *
5914
- * A failure gives an error value, and the function does not throw. The function records each effect in its order,
5915
- * and the host does not do it. A mock can answer each effect at once (RUN.MOCK).
5604
+ * This function evaluates a document, and records each evaluation in a trace.
5605
+ *
5606
+ * The verb of the options goes up the ladder for each document. The default verb is `eval`. The kind of the document
5607
+ * tells where its parts are. The evaluator gets each part sealed: it can evaluate the part, and it cannot read its
5608
+ * value.
5609
+ *
5610
+ * A failure gives an error value, and the function does not throw. The function records each effect in its order,
5611
+ * and the host does not do it. A mock can answer each effect at once (RUN.MOCK).
5612
+ *
5613
+ * @param machine - The world and the code of the evaluators.
5614
+ * @param doc - The document, as JSON.
5615
+ * @param context - The names and the capabilities at the root.
5616
+ * @param options - The type of a bare root value, or the options: that type, the mock of the host, the verb and a list for the reads.
5617
+ * @returns The result, the trace and the effects in their order.
5618
+ */
5619
+ function evaluate(machine, doc, context = makeContext(), options) {
5620
+ const given = typeof options === "string" ? { declaredType: options } : options ?? {};
5621
+ const declaredType = given.declaredType;
5622
+ const plan = prepare(machine, doc, {
5623
+ trace: true,
5624
+ ...declaredType === void 0 ? {} : { declaredType },
5625
+ ...given.verb === void 0 ? {} : { verb: given.verb },
5626
+ ...given.guards === void 0 ? {} : { guards: given.guards }
5627
+ });
5628
+ const ctx = rootContext(machine, context);
5629
+ const s = new Session(machine, ctx.caps, false, true, given.perform, void 0, void 0, readingOf(given.reads, ctx));
5630
+ return record(s, plan.code(ctx, s));
5631
+ }
5632
+ /**
5633
+ * This function runs a document: an evaluation in which the host does each effect. A runner waits for its
5634
+ * parts and for its effects, thus a step can read the result of the step before. The part of the run before the
5635
+ * first wait happens at once, in the call. The run records a trace.
5636
+ *
5637
+ * @param machine - The world, the evaluators and the runners.
5638
+ * @param doc - The document, as JSON.
5639
+ * @param context - The names and the capabilities at the root.
5640
+ * @param options - The host code that does the effects, the type of a bare root value, a signal, the verb and a list for the reads.
5641
+ * @returns The result, the trace and the effects in their order, when the run ends.
5642
+ */
5643
+ async function run(machine, doc, context = makeContext(), options = {}) {
5644
+ const plan = prepare(machine, doc, {
5645
+ trace: true,
5646
+ ...options.declaredType === void 0 ? {} : { declaredType: options.declaredType },
5647
+ ...options.guards === void 0 ? {} : { guards: options.guards },
5648
+ ...options.verb === void 0 ? {} : { verb: options.verb }
5649
+ });
5650
+ const ctx = rootContext(machine, context);
5651
+ const s = new Session(machine, ctx.caps, true, true, options.perform, void 0, void 0, readingOf(options.reads, ctx));
5652
+ const result = await driveWaiting(plan.runCode()(ctx, s), options.signal);
5653
+ s.top = s;
5654
+ return record(s, result);
5655
+ }
5656
+ /**
5657
+ * This function finds a node of a trace by its path.
5658
+ *
5659
+ * @param trace - The root of the trace.
5660
+ * @param path - The keys from the root.
5661
+ * @returns The first evaluation at that path, or `undefined` when the document did not evaluate.
5662
+ */
5663
+ function nodeAt(trace, path) {
5664
+ const want = path.map(String);
5665
+ let node = trace;
5666
+ let at = 0;
5667
+ while (node !== void 0 && at < want.length) {
5668
+ const here = node;
5669
+ node = here.children.find((child) => {
5670
+ const tail = child.path.slice(here.path.length);
5671
+ return tail.length > 0 && tail.every((key, index) => key === want[at + index]);
5672
+ });
5673
+ if (node !== void 0) at += node.path.length - here.path.length;
5674
+ }
5675
+ return node;
5676
+ }
5677
+ /**
5678
+ * This function lists the nodes of a trace in the order of their start.
5679
+ *
5680
+ * @param trace - The root of the trace.
5681
+ * @returns Each node, the root first.
5682
+ */
5683
+ function flatten(trace) {
5684
+ const out = [];
5685
+ const stack = [trace];
5686
+ while (stack.length > 0) {
5687
+ const node = stack.pop();
5688
+ out.push(node);
5689
+ for (let index = node.children.length - 1; index >= 0; index -= 1) stack.push(node.children[index]);
5690
+ }
5691
+ return out.sort((a, b) => a.enter - b.enter);
5692
+ }
5693
+ /**
5694
+ * This function lists the errors of a trace: each node whose result is an error and whose parts did not fail
5695
+ * the same way. These nodes are where each error started.
5696
+ *
5697
+ * @param trace - The root of the trace.
5698
+ * @returns The errors, in the order of their start.
5699
+ */
5700
+ function failures(trace) {
5701
+ return flatten(trace).filter((node) => !node.result.ok && !node.children.some((child) => !child.result.ok && child.result.error === node.result.error)).map((node) => node.result.error);
5702
+ }
5703
+ // src/language.ts
5704
+ const VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
5705
+ function numbers$1(version) {
5706
+ const found = VERSION.exec(version);
5707
+ if (found === null) throw new TypeError(`A language version has the form MAJOR.MINOR.PATCH. The text ${JSON.stringify(version)} does not.`);
5708
+ return [
5709
+ Number(found[1]),
5710
+ Number(found[2]),
5711
+ Number(found[3])
5712
+ ];
5713
+ }
5714
+ /**
5715
+ * This function tells if a version satisfies a lowest version, by the rules of a caret range of SemVer. The first
5716
+ * number that is not zero stays the same, and the version is not lower.
5717
+ */
5718
+ function compatible(version, lowest) {
5719
+ const have = numbers$1(version);
5720
+ const want = numbers$1(lowest);
5721
+ const stable = want.findIndex((part) => part !== 0);
5722
+ const fixed = stable < 0 ? 3 : stable + 1;
5723
+ for (let index = 0; index < 3; index += 1) {
5724
+ const [a, b] = [have[index], want[index]];
5725
+ if (a !== b) return index >= fixed && a > b;
5726
+ }
5727
+ return true;
5728
+ }
5729
+ /** This function gives the JSON text of a value with its keys in order. A value that is not JSON is an error. */
5730
+ function canonical(value, path) {
5731
+ if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
5732
+ if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value);
5733
+ if (Array.isArray(value)) return `[${value.map((item, index) => canonical(item, [...path, index])).join(",")}]`;
5734
+ if (!isRecord(value)) throw new TypeError(`The data half of a language is JSON. The value at ${JSON.stringify(path)} is not.`);
5735
+ return `{${Object.keys(value).filter((key) => value[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key], [...path, key])}`).join(",")}}`;
5736
+ }
5737
+ function frozen(value) {
5738
+ if (typeof value !== "object" || value === null) return value;
5739
+ for (const item of Object.values(value)) frozen(item);
5740
+ return Object.freeze(value);
5741
+ }
5742
+ /**
5743
+ * This function makes one value of a language. The data half is JSON, thus a host can store it and compare it. The
5744
+ * code half binds the evaluator names of the world.
5745
+ *
5746
+ * The language keeps a frozen copy of its data half, thus a later change to the input changes nothing.
5747
+ *
5748
+ * @param definition - The name, the version, the world, the needed languages and the code.
5749
+ * @returns The language.
5750
+ * @throws {TypeError} A version in the definition is not `MAJOR.MINOR.PATCH`, the name is empty, or the
5751
+ * data half is not JSON.
5752
+ */
5753
+ function defineLanguage(definition) {
5754
+ if (definition.name === "") throw new TypeError("A language has a name.");
5755
+ numbers$1(definition.version);
5756
+ const requires = definition.requires ?? {};
5757
+ for (const name of Object.keys(requires)) numbers$1(requires[name]);
5758
+ const data = canonical({
5759
+ requires,
5760
+ world: definition.world ?? {}
5761
+ }, []);
5762
+ const copy = frozen(JSON.parse(data));
5763
+ const language = {
5764
+ name: definition.name,
5765
+ version: definition.version,
5766
+ world: copy.world,
5767
+ requires: copy.requires,
5768
+ data
5769
+ };
5770
+ return Object.freeze(definition.code === void 0 ? language : {
5771
+ ...language,
5772
+ code: definition.code
5773
+ });
5774
+ }
5775
+ function partOf(language) {
5776
+ const { code, world } = language;
5777
+ return typeof code === "function" ? (prev) => ({
5778
+ ...code(prev),
5779
+ world
5780
+ }) : {
5781
+ ...code,
5782
+ world
5783
+ };
5784
+ }
5785
+ /**
5786
+ * This function merges languages into one machine, in the order of the arguments, with `mergeMachines`.
5787
+ *
5788
+ * - A language comes after each language that it names in `requires`, at a compatible version (LANG.REQUIRES).
5789
+ * - One language that comes twice counts once. Thus two languages can share a base.
5790
+ * - Two versions of one name, or two data halves under one name and one version, are conflicts (LANG.COMPOSE).
5791
+ *
5792
+ * @param languages - The languages.
5793
+ * @returns The machine.
5794
+ * @throws {MergeError} The languages do not fit, or their merge has a conflict. The error lists each conflict.
5795
+ */
5796
+ function compose(...languages) {
5797
+ const conflicts = [];
5798
+ const parts = [];
5799
+ const seen = /* @__PURE__ */ new Map();
5800
+ languages.forEach((language, index) => {
5801
+ const earlier = seen.get(language.name);
5802
+ const conflict = (name, other, reason) => {
5803
+ conflicts.push({
5804
+ path: ["languages", name],
5805
+ parts: [Math.min(other, index), Math.max(other, index)],
5806
+ reason
5807
+ });
5808
+ };
5809
+ if (earlier !== void 0) {
5810
+ if (earlier.language.version !== language.version) conflict(language.name, earlier.index, "Two versions of one language.");
5811
+ else if (earlier.language.data !== language.data) conflict(language.name, earlier.index, "Two languages with one name and one version differ.");
5812
+ else if (earlier.language.code !== language.code) parts.push(partOf(language));
5813
+ return;
5814
+ }
5815
+ for (const name of Object.keys(language.requires)) {
5816
+ const needed = language.requires[name];
5817
+ const found = seen.get(name);
5818
+ if (found === void 0) {
5819
+ const later = languages.findIndex((other) => other.name === name);
5820
+ if (later < 0) conflict(name, index, `A language requires ${name}, and the composition does not have it.`);
5821
+ else conflict(name, later, `A language requires ${name}, and ${name} comes after it.`);
5822
+ } else if (!compatible(found.language.version, needed)) conflict(name, found.index, `A language requires ${name} ${needed}, and the composition has ${found.language.version}.`);
5823
+ }
5824
+ seen.set(language.name, {
5825
+ language,
5826
+ index
5827
+ });
5828
+ parts.push(partOf(language));
5829
+ });
5830
+ if (conflicts.length > 0) throw new MergeError(conflicts);
5831
+ return mergeMachines(...parts);
5832
+ }
5833
+ /**
5834
+ * This function makes the language of the boundary kind `lang` (K38, D193). A document of the kind holds the name of a
5835
+ * language and a document in that language: `{ type: "lang", value: { language, doc } }`. The machine of the named
5836
+ * language prepares and evaluates the inner document, as a module of another language (COMPOSE.BOUNDARY).
5837
+ *
5838
+ * The boundary is closed. The inner document gets no names, no capabilities and no node as `self`. Only its result
5839
+ * crosses the boundary. Thus an effect in the inner document fails with `#CAP!`, and the inner machine cannot read the
5840
+ * names of the outer document.
5841
+ *
5842
+ * @param machines - The machine of each language, by the name that a document gives.
5843
+ * @returns The language, for `compose`.
5844
+ */
5845
+ function boundary(machines) {
5846
+ const plans = /* @__PURE__ */ new Map();
5847
+ const planOf = (name) => {
5848
+ let found = plans.get(name);
5849
+ if (found === void 0 && Object.hasOwn(machines, name)) {
5850
+ found = planner(machines[name]);
5851
+ plans.set(name, found);
5852
+ }
5853
+ return found;
5854
+ };
5855
+ return defineLanguage({
5856
+ name: "boundary",
5857
+ version: "1.0.0",
5858
+ world: { kinds: { lang: {
5859
+ verbs: { eval: "boundary.lang" },
5860
+ summary: "A document in another language. The machine of that language evaluates it, with no names and no capabilities."
5861
+ } } },
5862
+ code: { evaluators: { "boundary.lang": (input) => {
5863
+ const { data, place } = input;
5864
+ if (!isRecord(data) || typeof data["language"] !== "string" || !("doc" in data)) return fail("#VALUE!", "A document of the kind lang has the value { language, doc }.", { place });
5865
+ const plans = planOf(data["language"]);
5866
+ if (plans === void 0) return fail("#NAME?", `The boundary knows no language ${JSON.stringify(data["language"])}.`, { place });
5867
+ return evaluateWithin(plans(data["doc"]), makeContext(), input[RUNTIME]);
5868
+ } } }
5869
+ });
5870
+ }
5871
+ // src/steps.ts
5872
+ /**
5873
+ * This function makes a ladder of steps, and it checks the declaration (STEPS.LADDER). The list of steps must have one
5874
+ * step or more, with no name two times. The step of each construct must be a step of the list.
5916
5875
  *
5917
- * @param machine - The world and the code of the evaluators.
5918
- * @param doc - The document, as JSON.
5919
- * @param context - The names and the capabilities at the root.
5920
- * @param options - The type of a bare root value, or the options: that type, the mock of the host, the verb and a list for the reads.
5921
- * @returns The result, the trace and the effects in their order.
5876
+ * @param steps - The names of the steps, from the lowest to the highest.
5877
+ * @param constructs - The step that each construct needs.
5878
+ * @returns The ladder, frozen.
5879
+ * @throws TypeError for a declaration that is not valid, because it is a defect of the language.
5922
5880
  */
5923
- function evaluate(machine, doc, context = makeContext(), options) {
5924
- const given = typeof options === "string" ? { declaredType: options } : options ?? {};
5925
- const declaredType = given.declaredType;
5926
- const plan = prepare(machine, doc, {
5927
- trace: true,
5928
- ...declaredType === void 0 ? {} : { declaredType },
5929
- ...given.verb === void 0 ? {} : { verb: given.verb },
5930
- ...given.guards === void 0 ? {} : { guards: given.guards }
5881
+ function stepLadder(steps, constructs) {
5882
+ if (steps.length === 0) throw new TypeError("a ladder of steps needs one step or more");
5883
+ const seen = /* @__PURE__ */ new Set();
5884
+ for (const step of steps) {
5885
+ if (typeof step !== "string") throw new TypeError(`the step ${String(step)} is not a name`);
5886
+ if (seen.has(step)) throw new TypeError(`the step "${step}" is in the ladder two times`);
5887
+ seen.add(step);
5888
+ }
5889
+ for (const [construct, step] of Object.entries(constructs)) if (!seen.has(step)) throw new TypeError(`the construct "${construct}" needs the step "${String(step)}", which is not a step of the ladder`);
5890
+ return Object.freeze({
5891
+ steps: Object.freeze([...steps]),
5892
+ constructs: Object.freeze({ ...constructs })
5931
5893
  });
5932
- const ctx = rootContext(machine, context);
5933
- const s = new Session(machine, ctx.caps, false, true, given.perform, void 0, void 0, readingOf(given.reads, ctx));
5934
- return record(s, plan.code(ctx, s));
5935
5894
  }
5936
5895
  /**
5937
- * This function runs a document: an evaluation in which the host does each effect. A runner waits for its
5938
- * parts and for its effects, thus a step can read the result of the step before. The part of the run before the
5939
- * first wait happens at once, in the call. The run records a trace.
5896
+ * This function tells if a value is a step of a ladder. A host uses it to check its option for the highest step.
5940
5897
  *
5941
- * @param machine - The world, the evaluators and the runners.
5942
- * @param doc - The document, as JSON.
5943
- * @param context - The names and the capabilities at the root.
5944
- * @param options - The host code that does the effects, the type of a bare root value, a signal, the verb and a list for the reads.
5945
- * @returns The result, the trace and the effects in their order, when the run ends.
5898
+ * @param ladder - The ladder.
5899
+ * @param value - The value.
5900
+ * @returns `true` when the value is the name of a step of the ladder.
5946
5901
  */
5947
- async function run(machine, doc, context = makeContext(), options = {}) {
5948
- const plan = prepare(machine, doc, {
5949
- trace: true,
5950
- ...options.declaredType === void 0 ? {} : { declaredType: options.declaredType },
5951
- ...options.guards === void 0 ? {} : { guards: options.guards },
5952
- ...options.verb === void 0 ? {} : { verb: options.verb }
5953
- });
5954
- const ctx = rootContext(machine, context);
5955
- const s = new Session(machine, ctx.caps, true, true, options.perform, void 0, void 0, readingOf(options.reads, ctx));
5956
- const result = await driveWaiting(plan.runCode()(ctx, s), options.signal);
5957
- s.top = s;
5958
- return record(s, result);
5902
+ function isStep(ladder, value) {
5903
+ return typeof value === "string" && ladder.steps.includes(value);
5959
5904
  }
5960
5905
  /**
5961
- * This function finds a node of a trace by its path.
5906
+ * This function gives the position of a step in its ladder. The lowest step has the position 0.
5962
5907
  *
5963
- * @param trace - The root of the trace.
5964
- * @param path - The keys from the root.
5965
- * @returns The first evaluation at that path, or `undefined` when the document did not evaluate.
5908
+ * @param ladder - The ladder.
5909
+ * @param step - The step.
5910
+ * @returns The position.
5911
+ * @throws TypeError for a name that is not a step of the ladder.
5966
5912
  */
5967
- function nodeAt(trace, path) {
5968
- const want = path.map(String);
5969
- let node = trace;
5970
- let at = 0;
5971
- while (node !== void 0 && at < want.length) {
5972
- const here = node;
5973
- node = here.children.find((child) => {
5974
- const tail = child.path.slice(here.path.length);
5975
- return tail.length > 0 && tail.every((key, index) => key === want[at + index]);
5976
- });
5977
- if (node !== void 0) at += node.path.length - here.path.length;
5978
- }
5979
- return node;
5913
+ function stepRank(ladder, step) {
5914
+ const rank = ladder.steps.indexOf(step);
5915
+ if (rank < 0) throw new TypeError(`"${String(step)}" is not a step of the ladder. The steps are ${ladder.steps.join(", ")}`);
5916
+ return rank;
5917
+ }
5918
+ function pathOf(visit) {
5919
+ const path = [];
5920
+ for (let v = visit; v?.key !== void 0; v = v.parent) path.push(v.key);
5921
+ return path.reverse();
5980
5922
  }
5981
5923
  /**
5982
- * This function lists the nodes of a trace in the order of their start.
5924
+ * This function gives the lowest step that a document needs, with the reason (STEPS.LOWEST, STEPS.REASON). The step is
5925
+ * the highest step of the constructs of its nodes. The reason is the first node in document order with that step. The
5926
+ * walk uses its own stack, thus a deep document does not overflow (STEPS.LINEAR). It visits a shared node one time,
5927
+ * and it stops at the first node with the highest step of the ladder.
5983
5928
  *
5984
- * @param trace - The root of the trace.
5985
- * @returns Each node, the root first.
5929
+ * @param ladder - The ladder of the language.
5930
+ * @param walk - The construct and the child nodes of a node.
5931
+ * @param root - The root node of the document.
5932
+ * @returns The step, and the reason when the step is not the lowest step.
5986
5933
  */
5987
- function flatten(trace) {
5988
- const out = [];
5989
- const stack = [trace];
5990
- while (stack.length > 0) {
5991
- const node = stack.pop();
5992
- out.push(node);
5993
- for (let index = node.children.length - 1; index >= 0; index -= 1) stack.push(node.children[index]);
5934
+ function stepOf(ladder, walk, root) {
5935
+ const top = ladder.steps.length - 1;
5936
+ let best = 0;
5937
+ let reason;
5938
+ const seen = /* @__PURE__ */ new Set();
5939
+ const todo = [{
5940
+ node: root,
5941
+ key: void 0,
5942
+ parent: void 0
5943
+ }];
5944
+ for (let visit = todo.pop(); visit !== void 0; visit = todo.pop()) {
5945
+ const { node } = visit;
5946
+ if (typeof node === "object" && node !== null) {
5947
+ if (seen.has(node)) continue;
5948
+ seen.add(node);
5949
+ }
5950
+ const construct = walk.construct(node);
5951
+ const step = construct === void 0 || !Object.hasOwn(ladder.constructs, construct) ? void 0 : ladder.constructs[construct];
5952
+ const rank = step === void 0 ? 0 : ladder.steps.indexOf(step);
5953
+ if (rank > best) {
5954
+ best = rank;
5955
+ reason = {
5956
+ construct,
5957
+ step,
5958
+ path: pathOf(visit),
5959
+ node
5960
+ };
5961
+ if (best === top) break;
5962
+ }
5963
+ const kids = [...walk.children(node)];
5964
+ for (let i = kids.length - 1; i >= 0; i--) {
5965
+ const [key, child] = kids[i];
5966
+ todo.push({
5967
+ node: child,
5968
+ key,
5969
+ parent: visit
5970
+ });
5971
+ }
5994
5972
  }
5995
- return out.sort((a, b) => a.enter - b.enter);
5973
+ const step = ladder.steps[best];
5974
+ return reason === void 0 ? { step } : {
5975
+ step,
5976
+ reason
5977
+ };
5996
5978
  }
5997
5979
  /**
5998
- * This function lists the errors of a trace: each node whose result is an error and whose parts did not fail
5999
- * the same way. These nodes are where each error started.
5980
+ * This function compares the step of a document with the highest step that the host accepts (STEPS.MAX). The limit
5981
+ * changes only which documents the host accepts. The language evaluates an accepted document as before, thus a limit
5982
+ * does not change a value.
6000
5983
  *
6001
- * @param trace - The root of the trace.
6002
- * @returns The errors, in the order of their start.
5984
+ * @param ladder - The ladder of the language.
5985
+ * @param need - The step of the document, from `stepOf`.
5986
+ * @param maxStep - The highest step that the host accepts.
5987
+ * @returns `undefined` when the host accepts the document, or the refusal that names the needed step.
5988
+ * @throws TypeError when `maxStep` or the step of `need` is not a step of the ladder.
6003
5989
  */
6004
- function failures(trace) {
6005
- return flatten(trace).filter((node) => !node.result.ok && !node.children.some((child) => !child.result.ok && child.result.error === node.result.error)).map((node) => node.result.error);
5990
+ function checkStep(ladder, need, maxStep) {
5991
+ const limit = stepRank(ladder, maxStep);
5992
+ if (stepRank(ladder, need.step) <= limit) return void 0;
5993
+ const head = `the document needs the step ${need.step}, and the host accepts the steps up to ${maxStep}`;
5994
+ const reason = need.reason;
5995
+ if (reason === void 0) return {
5996
+ needed: need.step,
5997
+ maxStep,
5998
+ message: head
5999
+ };
6000
+ const where = reason.path.length === 0 ? "at the root" : `at the path ${JSON.stringify(reason.path)}`;
6001
+ return {
6002
+ needed: need.step,
6003
+ maxStep,
6004
+ reason,
6005
+ message: `${head}. The construct "${reason.construct}" ${where} needs the step ${reason.step}`
6006
+ };
6007
+ }
6008
+ // src/classify.ts
6009
+ function isStrictSuperset(larger, smaller) {
6010
+ return larger.length > smaller.length && smaller.every((name) => larger.includes(name));
6011
+ }
6012
+ /**
6013
+ * This function proposes a kind for a value without a type, from the fields that the value has.
6014
+ * A shape applies when the value has each field of the shape. The most specific shapes are the ones that
6015
+ * no other applicable shape contains. A host uses a classifier when data comes in, and then tags the data.
6016
+ * The ladder does not call a classifier.
6017
+ *
6018
+ * @param shapes - The shapes to examine.
6019
+ * @param value - The value without a type.
6020
+ * @returns The proposed kind, or an error with the candidates.
6021
+ */
6022
+ function classify(shapes, value) {
6023
+ const applicable = isRecord(value) ? shapes.filter((shape) => shape.fields.every((name) => field(value, name) !== void 0)) : [];
6024
+ const best = applicable.filter((shape) => !applicable.some((other) => isStrictSuperset(other.fields, shape.fields)));
6025
+ const candidates = best.map((shape) => shape.name);
6026
+ const only = best.length === 1 ? best[0] : void 0;
6027
+ if (only !== void 0) return {
6028
+ kind: only.kind,
6029
+ candidates
6030
+ };
6031
+ return {
6032
+ candidates,
6033
+ error: best.length === 0 ? "no-match" : "ambiguous"
6034
+ };
6035
+ }
6036
+ /**
6037
+ * This function puts a value in an envelope with a type. The value does not change.
6038
+ *
6039
+ * @param value - The value.
6040
+ * @param kind - The name of the kind.
6041
+ * @returns The envelope.
6042
+ */
6043
+ function tag(value, kind) {
6044
+ return typed(kind, value);
6006
6045
  }
6007
6046
  // src/stdlib.ts
6008
6047
  /**
@@ -8922,71 +8961,12 @@ function indexed(graph, options) {
8922
8961
  };
8923
8962
  }
8924
8963
  /**
8925
- * This function finds the strongly connected components with the algorithm of Tarjan. It keeps its own stack of
8926
- * calls in two arrays, thus a long chain does not overflow the stack of the host. Each component comes after each
8927
- * component that its nodes reach: the deepest component comes first.
8964
+ * This function finds the strongly connected components with `strongComponentsCompact` of
8965
+ * `@mark1russell7/collections` (K249). The search keeps its own stack, thus a long chain does not overflow the stack
8966
+ * of the host. Each component comes after each component that its nodes reach: the deepest component comes first.
8928
8967
  */
8929
8968
  function strong(graph) {
8930
- const { size, start, targets } = graph;
8931
- const order = new Int32Array(size).fill(-1);
8932
- const low = new Int32Array(size);
8933
- const of = new Int32Array(size).fill(-1);
8934
- const open = new Int32Array(size);
8935
- const onOpen = new Uint8Array(size);
8936
- const calls = new Int32Array(size);
8937
- const next = new Int32Array(size);
8938
- const list = [];
8939
- let top = 0;
8940
- let count = 0;
8941
- const enter = (node, depth) => {
8942
- order[node] = count;
8943
- low[node] = count;
8944
- count += 1;
8945
- open[top] = node;
8946
- top += 1;
8947
- onOpen[node] = 1;
8948
- calls[depth] = node;
8949
- next[depth] = start[node];
8950
- };
8951
- for (let root = 0; root < size; root += 1) {
8952
- if (order[root] !== -1) continue;
8953
- enter(root, 0);
8954
- let depth = 1;
8955
- while (depth > 0) {
8956
- const node = calls[depth - 1];
8957
- const edge = next[depth - 1];
8958
- if (edge < start[node + 1]) {
8959
- next[depth - 1] = edge + 1;
8960
- const to = targets[edge];
8961
- if (order[to] === -1) {
8962
- enter(to, depth);
8963
- depth += 1;
8964
- } else if (onOpen[to] === 1 && order[to] < low[node]) low[node] = order[to];
8965
- continue;
8966
- }
8967
- depth -= 1;
8968
- if (low[node] === order[node]) {
8969
- const members = [];
8970
- let member;
8971
- do {
8972
- top -= 1;
8973
- member = open[top];
8974
- onOpen[member] = 0;
8975
- of[member] = list.length;
8976
- members.push(member);
8977
- } while (member !== node);
8978
- list.push(members.sort((a, b) => a - b));
8979
- }
8980
- if (depth > 0) {
8981
- const reader = calls[depth - 1];
8982
- if (low[node] < low[reader]) low[reader] = low[node];
8983
- }
8984
- }
8985
- }
8986
- return {
8987
- of,
8988
- list
8989
- };
8969
+ return strongComponentsCompact(graph.size, graph.start, graph.targets);
8990
8970
  }
8991
8971
  /** This function tells if a component has a cycle: two or more nodes, or one node with an edge to itself. */
8992
8972
  function cyclic(graph, members) {
@@ -12358,7 +12338,9 @@ function formulaCode(profile) {
12358
12338
  const level = (clock.applying ?? 0) + 1;
12359
12339
  if (level > limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
12360
12340
  rt.spend?.(1);
12341
+ const root = clock.top ?? clock;
12361
12342
  clock.applying = level;
12343
+ root.active = (root.active ?? 0) + 1;
12362
12344
  try {
12363
12345
  const scope = { ...ctx.names };
12364
12346
  names.forEach((name, index) => setOwn$2(scope, name, args[index]));
@@ -12370,6 +12352,7 @@ function formulaCode(profile) {
12370
12352
  return result.value;
12371
12353
  } finally {
12372
12354
  clock.applying = level - 1;
12355
+ root.active = (root.active ?? 1) - 1;
12373
12356
  }
12374
12357
  };
12375
12358
  Object.defineProperty(closure, CLOSURE$3, { value: { params: names } });
@@ -13185,7 +13168,7 @@ function evaluateRoot(machine, doc, context, options, outer, meter) {
13185
13168
  */
13186
13169
  function spend(env, points) {
13187
13170
  const meter = env.meter;
13188
- if (meter.ended && env.applying === 0) meter.spent = 0;
13171
+ if (meter.ended && meter.active === 0) meter.spent = 0;
13189
13172
  meter.spent += points;
13190
13173
  if (meter.spent > env.maxWork) throw new Failure(workFailure(env.maxWork));
13191
13174
  }
@@ -13236,7 +13219,8 @@ function envOf(machine, options, running, root, outer, meter) {
13236
13219
  maxWork: machine.maxWork ?? 2e5,
13237
13220
  meter: meter ?? {
13238
13221
  spent: 0,
13239
- ended: false
13222
+ ended: false,
13223
+ active: 0
13240
13224
  },
13241
13225
  nested: meter !== void 0,
13242
13226
  reading: outer ?? (options.reads === void 0 ? void 0 : {
@@ -13922,13 +13906,15 @@ function formulaDefinitions(profile = {}) {
13922
13906
  if (!Array.isArray(params) || !params.every((param) => typeof param === "string") || new Set(params).size !== params.length) return fail("#VALUE!", "The params of fn are a list of different texts.");
13923
13907
  const names = params;
13924
13908
  const body = partNamed$1(parts, "body");
13925
- const clock = activeEnvs[activeEnvs.length - 1] ?? {
13909
+ const maker = activeEnvs[activeEnvs.length - 1];
13910
+ const clock = maker ?? {
13926
13911
  applying: 0,
13927
13912
  maxDepth: 1e3,
13928
13913
  maxWork: 2e5,
13929
13914
  meter: {
13930
13915
  spent: 0,
13931
- ended: false
13916
+ ended: false,
13917
+ active: 0
13932
13918
  }
13933
13919
  };
13934
13920
  const limit = Math.ceil(clock.maxDepth / 4);
@@ -13936,18 +13922,21 @@ function formulaDefinitions(profile = {}) {
13936
13922
  if (clock.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
13937
13923
  spend(clock, 1);
13938
13924
  clock.applying += 1;
13925
+ clock.meter.active += 1;
13939
13926
  try {
13940
13927
  const scope = {};
13941
13928
  for (const key of Object.keys(context.names)) setField$2(scope, key, context.names[key]);
13942
13929
  names.forEach((name, index) => setField$2(scope, name, args[index]));
13943
- const result = body.evaluate({
13930
+ const scoped = {
13944
13931
  ...context,
13945
13932
  names: scope
13946
- });
13933
+ };
13934
+ const result = maker === void 0 ? body.evaluate(scoped) : within(maker, () => body.evaluate(scoped));
13947
13935
  if (!result.ok) throw new Failure(result.error);
13948
13936
  return result.value;
13949
13937
  } finally {
13950
13938
  clock.applying -= 1;
13939
+ clock.meter.active -= 1;
13951
13940
  }
13952
13941
  };
13953
13942
  Object.defineProperty(closure, CLOSURE$2, { value: { params: names } });
@@ -14444,6 +14433,11 @@ function apply(p, c, target, args) {
14444
14433
  }
14445
14434
  const limit = Math.ceil(p.maxDepth / 4);
14446
14435
  if (c.applying >= limit) return back(c, fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`));
14436
+ p.work += 1;
14437
+ if (p.work > p.maxWork) return back(c, {
14438
+ ok: false,
14439
+ error: workFailure(p.maxWork)
14440
+ });
14447
14441
  pushed(c, {
14448
14442
  f: "return",
14449
14443
  place: closure.place.concat(closure.body.path)
@@ -14470,6 +14464,9 @@ function hostClosure(p, value, closure) {
14470
14464
  const fn = (...args) => {
14471
14465
  const limit = Math.ceil(p.maxDepth / 4);
14472
14466
  if (p.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
14467
+ p.work = (p.ended && p.applying === 0 ? 0 : p.work) + 1;
14468
+ if (p.work > p.maxWork) throw new Failure(workFailure(p.maxWork));
14469
+ const before = p.applying;
14473
14470
  p.applying += 1;
14474
14471
  try {
14475
14472
  const place = closure.place.concat(closure.body.path);
@@ -14486,7 +14483,7 @@ function hostClosure(p, value, closure) {
14486
14483
  if (!end.result.ok) throw new Failure(end.result.error);
14487
14484
  return forHost(p, end, end.result.value);
14488
14485
  } finally {
14489
- p.applying -= 1;
14486
+ p.applying = before;
14490
14487
  }
14491
14488
  };
14492
14489
  Object.defineProperty(fn, CLOSURE$1, { value: { params: closure.params } });
@@ -14817,7 +14814,7 @@ function cause(p, ctx, kind, payload, place) {
14817
14814
  const count = counts.get(at) ?? 0;
14818
14815
  counts.set(at, count + 1);
14819
14816
  const effect = {
14820
- index: effects.length,
14817
+ index: p.before + effects.length,
14821
14818
  kind: text,
14822
14819
  path: keys,
14823
14820
  payload,
@@ -14923,7 +14920,8 @@ function evaluateDoc(p, c) {
14923
14920
  } catch (error) {
14924
14921
  return back(c, thrown(error, `the evaluator ${name}`));
14925
14922
  }
14926
- const defined = own$1(p.definitions.evaluators, name);
14923
+ const standard = code === own$1(STD_EVALUATORS, name) ? own$1(STD_DEFINITIONS.evaluators, name) : void 0;
14924
+ const defined = own$1(p.definitions.evaluators, name) ?? standard;
14927
14925
  if (defined !== void 0) return hostEvaluator(p, c, name, defined, doc, keys, read.data, read.slots, site);
14928
14926
  return back(c, fail("#NOEVAL", `The stepper has no definition of the compiled evaluator ${name}.`));
14929
14927
  }
@@ -15080,7 +15078,11 @@ function programOf(machine, options) {
15080
15078
  effects: options.effects ?? [],
15081
15079
  perform: options.perform,
15082
15080
  counts: /* @__PURE__ */ new Map(),
15083
- applying: 0
15081
+ before: 0,
15082
+ applying: 0,
15083
+ maxWork: machine.maxWork ?? 2e5,
15084
+ work: 0,
15085
+ ended: false
15084
15086
  };
15085
15087
  }
15086
15088
  /**
@@ -15136,10 +15138,21 @@ function stepperNext(machine, configuration, options = {}) {
15136
15138
  };
15137
15139
  else stack[stack.length - 1] = { ...top };
15138
15140
  }
15139
- return advance(programOf(machine, options), {
15141
+ const p = programOf(machine, options);
15142
+ p.work = configuration.work ?? 0;
15143
+ for (const [at, count] of Object.entries(configuration.counts ?? {})) p.counts.set(at, count);
15144
+ p.before = options.effects === void 0 ? configuration.effected ?? 0 : 0;
15145
+ const next = advance(p, {
15140
15146
  ...configuration,
15141
15147
  stack
15142
15148
  });
15149
+ const effected = p.before + p.effects.length;
15150
+ return {
15151
+ ...next,
15152
+ ...p.work === 0 ? {} : { work: p.work },
15153
+ ...p.counts.size === 0 ? {} : { counts: Object.fromEntries(p.counts) },
15154
+ ...effected === 0 ? {} : { effected }
15155
+ };
15143
15156
  }
15144
15157
  /**
15145
15158
  * This function evaluates a document with an explicit stack (K95, D158). It gives the result of `reference` for each
@@ -15157,6 +15170,7 @@ function stepper(machine, doc, context = makeContext(), options = {}) {
15157
15170
  const p = programOf(machine, options);
15158
15171
  try {
15159
15172
  const end = drive$1(p, stepperStart(machine, doc, context, options));
15173
+ p.ended = true;
15160
15174
  return end.result.ok ? ok(forHost(p, end, end.result.value)) : end.result;
15161
15175
  } catch (error) {
15162
15176
  return placed(thrown(error, "the stepper"), []);
@@ -18908,7 +18922,10 @@ function generate(world, options) {
18908
18922
  value
18909
18923
  };
18910
18924
  if (header !== void 0) out["name"] = header;
18911
- if (options.own !== void 0 && options.own.length > 0 && rng.chance(.03)) out["own"] = { eval: rng.pick(options.own) };
18925
+ if (options.own !== void 0 && options.own.length > 0 && rng.chance(.03)) {
18926
+ const code = rng.pick(options.own);
18927
+ if ((kindOf(type)?.scope ?? []).length === 0) out["own"] = { eval: code };
18928
+ }
18912
18929
  return out;
18913
18930
  };
18914
18931
  /**
@@ -22556,6 +22573,6 @@ function samplesAt(values, closed, depth) {
22556
22573
  function typeFromSamples(values, options = {}) {
22557
22574
  return samplesAt(values, options.closed === true, 0);
22558
22575
  }
22559
- export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, GENERATION_LIMIT, Held, JOURNAL, MAX_SYNTAX_ISSUES, MergeError, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_DEFINITIONS, STD_DOMAINS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_SYNTAX, STD_WALKERS, STD_WORLD, THING, WORK_LIMIT, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, agreeTypes, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, boundariesOf, capKeys, check, checkCycles, checkLatent, checkStep, checkSteps, checkSyntax, checkWorld, circularOf, classify, codecLaws, collectOf, compilePath, components, compose, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, defineLanguage, derefStep, describe, docEquals, documentKey, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeLog, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, ifRunner, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapDocs, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partGrants, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, resolveCompiled, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stepLadder, stepOf, stepRank, stepper, stepperNext, stepperStart, stored, syntaxFormat, tag, thrown, toJson, treeNodeEvaluator, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
22576
+ export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, GENERATION_LIMIT, Held, JOURNAL, MAX_SYNTAX_ISSUES, MergeError, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_DEFINITIONS, STD_DOMAINS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_SYNTAX, STD_WALKERS, STD_WORLD, THING, WORK_LIMIT, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, agreeTypes, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, boundariesOf, boundary, capKeys, check, checkCycles, checkLatent, checkStep, checkSteps, checkSyntax, checkWorld, circularOf, classify, codecLaws, collectOf, compilePath, components, compose, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, defineLanguage, derefStep, describe, docEquals, documentKey, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeLog, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, ifRunner, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapDocs, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partGrants, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, resolveCompiled, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stepLadder, stepOf, stepRank, stepper, stepperNext, stepperStart, stored, syntaxFormat, tag, thrown, toJson, treeNodeEvaluator, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
22560
22577
 
22561
22578
  //# sourceMappingURL=index.js.map