@mark1russell7/coeval 0.27.0 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -2579,1387 +2579,1082 @@ function restrictMachine(machine, paths) {
2579
2579
  ...tables.domains === void 0 ? {} : { domains: tables.domains }
2580
2580
  };
2581
2581
  }
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;
2582
+ // src/parts.ts
2583
+ var Bad$1 = class {
2584
+ reason;
2585
+ at;
2586
+ constructor(reason, at) {
2587
+ this.reason = reason;
2588
+ this.at = at;
2605
2589
  }
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
2590
+ };
2591
+ /** This function sets an own data property. Only the key `__proto__` needs `defineProperty`. */
2592
+ function setOwn$4(target, key, value) {
2593
+ if (key === "__proto__") Object.defineProperty(target, key, {
2594
+ value,
2595
+ enumerable: true,
2596
+ writable: true,
2597
+ configurable: true
2652
2598
  });
2599
+ else target[key] = value;
2653
2600
  }
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
- };
2601
+ const NO_SLOTS = /* @__PURE__ */ Object.freeze([]);
2602
+ function hasSlots(template) {
2603
+ return template.t !== "data";
2663
2604
  }
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);
2605
+ /** This function gives the shape of a part with the default type `of` and the value type `expect` of its container. */
2606
+ function termOf$1(of, expect) {
2607
+ return {
2608
+ shape: "term",
2609
+ ...of === void 0 ? {} : { of },
2610
+ ...expect === void 0 ? {} : { expect }
2611
+ };
2711
2612
  }
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;
2613
+ /** This function tells if a shape holds only data: no value of the shape can hold a part. */
2614
+ function isData(shape) {
2615
+ return shape.shape === "none" || shape.shape === "text" || shape.shape === "number" || shape.shape === "one";
2721
2616
  }
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;
2617
+ /** This function gives the reason why a value is not data of a shape, or `undefined` when it is. */
2618
+ function dataFault(spec, item) {
2619
+ if (spec.shape === "text") return typeof item === "string" ? void 0 : "The value must be a text.";
2620
+ if (spec.shape === "one") return spec.values.some((value) => docEquals(value, item)) ? void 0 : `The value must be one of ${JSON.stringify(spec.values)}.`;
2621
+ if (typeof item !== "number") return "The value must be a number.";
2622
+ if (spec.whole === true && !Number.isInteger(item)) return "The value must be a whole number.";
2623
+ if (spec.min !== void 0 && !(item >= spec.min)) return `The value must be ${String(spec.min)} or more.`;
2624
+ if (spec.max !== void 0 && !(item <= spec.max)) return `The value must be ${String(spec.max)} or less.`;
2733
2625
  }
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);
2626
+ /** This function stops a split when a part has a type that its position does not permit. */
2627
+ function kindFault(kinds, item, of, path) {
2628
+ const type = isEnvelope(item) ? typePath(item.type) : of === void 0 ? void 0 : [of];
2629
+ if (type !== void 0 && kinds.some((kind) => kind.length <= type.length && kind.every((key, index) => String(key) === String(type[index])))) return;
2630
+ const names = kinds.map((kind) => kind.join(".")).join(", ");
2631
+ 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
2632
  }
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
2633
  /**
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.
2634
+ * This function splits a value into its parts, by the shape that its kind declares. The evaluator, the view and
2635
+ * the static kit use the same split, thus each one sees the same parts.
2750
2636
  *
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.
2637
+ * @param shape - The shape of the value. The default is data.
2638
+ * @param value - The value of the document.
2639
+ * @returns The parts and a way to fill their places, or the reason why the value does not have the shape.
2758
2640
  */
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"
2641
+ function splitParts(shape, value) {
2642
+ if (shape === void 0 || shape.shape === "none") return {
2643
+ ok: true,
2644
+ parts: NO_SLOTS,
2645
+ data: value,
2646
+ fill: () => value
2764
2647
  };
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"
2648
+ const parts = [];
2649
+ const slot = (item, path, of, address = false, expect) => {
2650
+ parts.push({
2651
+ path,
2652
+ key: path.join("."),
2653
+ item,
2654
+ ...of === void 0 ? {} : { of },
2655
+ ...address ? { address: true } : {},
2656
+ ...expect === void 0 ? {} : { expect }
2657
+ });
2658
+ return {
2659
+ t: "slot",
2660
+ index: parts.length - 1
2661
+ };
2770
2662
  };
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
- });
2663
+ const deep = (item, path, of, expect) => {
2664
+ if (isEnvelope(item)) return slot(item, path, of, false, expect);
2665
+ if (Array.isArray(item)) {
2666
+ const items = item.map((child, index) => deep(child, [...path, index], of, expect));
2667
+ return items.some(hasSlots) ? {
2668
+ t: "list",
2669
+ items
2670
+ } : {
2671
+ t: "data",
2672
+ value: item
2673
+ };
2674
+ }
2675
+ if (isRecord(item)) {
2676
+ const fields = Object.keys(item).map((key) => [key, deep(item[key], [...path, key], of, expect)]);
2677
+ return fields.some(([, child]) => hasSlots(child)) ? {
2678
+ t: "record",
2679
+ fields
2680
+ } : {
2681
+ t: "data",
2682
+ value: item
2683
+ };
2684
+ }
2800
2685
  return {
2801
- verb,
2802
- evaluator: own,
2803
- rung: "own",
2804
- steps
2686
+ t: "data",
2687
+ value: item
2805
2688
  };
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
- });
2689
+ };
2690
+ const walk = (spec, item, path) => {
2691
+ if (spec === void 0 || spec.shape === "none") return {
2692
+ t: "data",
2693
+ value: item
2694
+ };
2695
+ if (spec.shape === "text" || spec.shape === "number" || spec.shape === "one") {
2696
+ const reason = dataFault(spec, item);
2697
+ if (reason !== void 0) throw new Bad$1(reason, path);
2827
2698
  return {
2828
- verb,
2829
- error: "unknown-kind",
2830
- steps
2699
+ t: "data",
2700
+ value: item
2831
2701
  };
2832
2702
  }
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
- });
2703
+ if (spec.shape === "term") {
2704
+ if (spec.kinds !== void 0) kindFault(spec.kinds, item, spec.of, path);
2705
+ return slot(item, path, spec.of, spec.address === true, spec.expect);
2706
+ }
2707
+ if (spec.shape === "deep") return deep(item, path, spec.of, spec.expect);
2708
+ if (spec.shape === "list") {
2709
+ if (!Array.isArray(item)) throw new Bad$1("The value must be a list.", path);
2710
+ const list = item;
2711
+ if (spec.distinct === true) {
2712
+ const twice = list.findIndex((child, index) => list.slice(0, index).some((before) => docEquals(before, child)));
2713
+ if (twice !== -1) throw new Bad$1("The items of the list must be different.", [...path, twice]);
2714
+ }
2715
+ const each = spec.item ?? termOf$1(spec.of, spec.expect);
2716
+ const items = list.map((child, index) => walk(each, child, [...path, index]));
2717
+ return isData(each) ? {
2718
+ t: "data",
2719
+ value: item
2720
+ } : {
2721
+ t: "list",
2722
+ items
2723
+ };
2724
+ }
2725
+ if (!isRecord(item)) throw new Bad$1("The value must be a record.", path);
2726
+ if (spec.shape === "map") {
2727
+ const each = spec.item ?? termOf$1(spec.of, spec.expect);
2842
2728
  return {
2843
- verb,
2844
- evaluator: entry,
2845
- rung: "kind",
2846
- steps
2729
+ t: "record",
2730
+ fields: Object.keys(item).map((key) => [key, walk(each, item[key], [...path, key])])
2847
2731
  };
2848
2732
  }
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
- });
2733
+ for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad$1(`The field ${name} is missing.`, path);
2734
+ const named = Array.isArray(spec.fields) ? Object.fromEntries(spec.fields.map((name) => [name, termOf$1(spec.of, spec.expect)])) : spec.fields;
2735
+ const fields = [];
2736
+ for (const key of Object.keys(item)) {
2737
+ if (spec.closed === true && !Object.hasOwn(named, key)) throw new Bad$1(`The field ${key} is not a field of this kind.`, [...path, key]);
2738
+ const fieldShape = Object.hasOwn(named, key) ? named[key] : spec.rest;
2739
+ fields.push([key, walk(fieldShape, item[key], [...path, key])]);
2740
+ }
2863
2741
  return {
2864
- verb,
2865
- evaluator: fallback,
2866
- rung: "default",
2867
- steps
2742
+ t: "record",
2743
+ fields
2744
+ };
2745
+ };
2746
+ let template;
2747
+ try {
2748
+ template = walk(shape, value, []);
2749
+ } catch (error) {
2750
+ if (error instanceof Bad$1) return {
2751
+ ok: false,
2752
+ reason: error.reason,
2753
+ at: error.at
2868
2754
  };
2755
+ throw error;
2869
2756
  }
2870
- steps.push({
2871
- rung: "default",
2872
- outcome: "no-entry"
2873
- });
2757
+ const strip = (node) => {
2758
+ if (node.t === "data") return node.value;
2759
+ if (node.t === "slot") return void 0;
2760
+ if (node.t === "list") return node.items.every((child) => child.t === "slot") ? null : node.items.map((child) => strip(child) ?? null);
2761
+ const out = {};
2762
+ for (const [key, child] of node.fields) {
2763
+ const kept = strip(child);
2764
+ if (kept !== void 0) setOwn$4(out, key, kept);
2765
+ }
2766
+ return out;
2767
+ };
2768
+ const fillWith = (node, handles) => {
2769
+ if (node.t === "data") return node.value;
2770
+ if (node.t === "slot") return handles[node.index];
2771
+ if (node.t === "list") return node.items.map((child) => fillWith(child, handles));
2772
+ const out = {};
2773
+ for (const [key, child] of node.fields) setOwn$4(out, key, fillWith(child, handles));
2774
+ return out;
2775
+ };
2874
2776
  return {
2875
- verb,
2876
- error: "no-answer",
2877
- steps
2777
+ ok: true,
2778
+ parts,
2779
+ data: strip(template) ?? null,
2780
+ fill: (handles) => fillWith(template, handles)
2878
2781
  };
2879
2782
  }
2880
- // src/steps.ts
2881
2783
  /**
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.
2784
+ * This function reads one document by the contracts of the world. It finds the kind of the type. A bare value gets
2785
+ * the type that its position declares. Then the function splits the value by the shape of the kind. The plan, the
2786
+ * reference interpreter and the static kit read each document with this function. Thus they see the same parts.
2884
2787
  *
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.
2788
+ * @param world - The world of the kinds.
2789
+ * @param value - The document, or a bare value.
2790
+ * @param declaredType - The type that the position of a bare value declares.
2791
+ * @returns The document, its kind and its parts, or the reason why the value is not a document.
2889
2792
  */
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
- });
2793
+ function partsOf(world, value, declaredType) {
2794
+ const envelope = isEnvelope(value) ? value : void 0;
2795
+ if (envelope === void 0 && declaredType === void 0) return {
2796
+ ok: false,
2797
+ code: "#PART?",
2798
+ reason: "The value has no envelope, and its position declares no type."
2799
+ };
2800
+ const doc = envelope ?? {
2801
+ type: declaredType,
2802
+ value
2803
+ };
2804
+ const found = lookupKind(world, doc.type);
2805
+ const kind = found.ok ? found.kind : void 0;
2806
+ const split = splitParts(kind?.parts, doc.value);
2807
+ const typePath = found.ok ? found.path : void 0;
2808
+ if (split.ok) return {
2809
+ ok: true,
2810
+ doc,
2811
+ declared: envelope === void 0,
2812
+ kind,
2813
+ typePath,
2814
+ split
2815
+ };
2816
+ const where = split.at.length === 0 ? "" : ` (at ${split.at.join(".")})`;
2817
+ const reason = `${split.reason}${where} The kind is ${typeName(doc.type)}.`;
2818
+ return {
2819
+ ok: true,
2820
+ doc,
2821
+ declared: envelope === void 0,
2822
+ kind,
2823
+ typePath,
2824
+ split: {
2825
+ ok: false,
2826
+ reason,
2827
+ at: split.at
2828
+ }
2829
+ };
2903
2830
  }
2904
2831
  /**
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.
2832
+ * This function tells if the path of a part matches a pattern of a scope rule. The key `"*"` of a pattern matches
2833
+ * each key.
2906
2834
  *
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.
2835
+ * @param path - The path of the part.
2836
+ * @param pattern - The pattern.
2837
+ * @returns `true` when the path matches.
2910
2838
  */
2911
- function isStep(ladder, value) {
2912
- return typeof value === "string" && ladder.steps.includes(value);
2839
+ function pathMatches(path, pattern) {
2840
+ if (path.length !== pattern.length) return false;
2841
+ for (let index = 0; index < path.length; index += 1) {
2842
+ const want = pattern[index];
2843
+ if (want !== "*" && String(want) !== String(path[index])) return false;
2844
+ }
2845
+ return true;
2913
2846
  }
2914
2847
  /**
2915
- * This function gives the position of a step in its ladder. The lowest step has the position 0.
2848
+ * This function tells if a list of rules in the form of the lazy rules covers a part (D24, D119). A rule without
2849
+ * `in` covers each part. With `after: n`, a rule covers only the parts after the first `n` parts that it matches.
2916
2850
  *
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.
2851
+ * @param rules - The rules.
2852
+ * @param shape - The shape of the parts of the parent.
2853
+ * @param value - The value of the parent.
2854
+ * @param slot - The path of the part in the value.
2855
+ * @returns `true` when a rule covers the part.
2921
2856
  */
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;
2857
+ function rulesCover(rules, shape, value, slot) {
2858
+ for (const rule of rules) {
2859
+ if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(slot, pattern))) continue;
2860
+ const after = rule.after ?? 0;
2861
+ if (after <= 0) return true;
2862
+ const split = splitParts(shape, value);
2863
+ let count = 0;
2864
+ for (const part of split.ok ? split.parts : []) {
2865
+ if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(part.path, pattern))) continue;
2866
+ if (part.path.length === slot.length && pathMatches(part.path, slot)) {
2867
+ if (count >= after) return true;
2868
+ break;
2869
+ }
2870
+ count += 1;
2871
+ }
2872
+ }
2873
+ return false;
2926
2874
  }
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();
2875
+ function valueAt(value, path) {
2876
+ let here = value;
2877
+ for (const key of path) if (Array.isArray(here)) here = here[Number(key)];
2878
+ else if (isRecord(here) && Object.hasOwn(here, String(key))) here = here[String(key)];
2879
+ else return void 0;
2880
+ return here;
2881
+ }
2882
+ function headerName(item) {
2883
+ return isEnvelope(item) && typeof item.name === "string" ? item.name : void 0;
2884
+ }
2885
+ function namesOf(source, value, covered) {
2886
+ if ("fixed" in source) return source.fixed;
2887
+ if ("keysAt" in source) {
2888
+ const at = valueAt(value, source.keysAt);
2889
+ return isRecord(at) ? Object.keys(at) : [];
2890
+ }
2891
+ if ("listAt" in source) {
2892
+ const at = valueAt(value, source.listAt);
2893
+ return Array.isArray(at) ? at.filter((item) => typeof item === "string") : [];
2894
+ }
2895
+ if ("textAt" in source) {
2896
+ const at = valueAt(value, source.textAt);
2897
+ if (typeof at === "string") return [at];
2898
+ return source.otherwise === void 0 ? [] : [source.otherwise];
2899
+ }
2900
+ return covered.map((slot) => headerName(slot.item)).filter((name) => name !== void 0);
2931
2901
  }
2932
2902
  /**
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.
2903
+ * This function gives the names that the scope rules of a kind give each part, and the names that only later parts
2904
+ * see. `check`, `conforms` and the plan read the scope rules with it.
2937
2905
  *
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.
2906
+ * @param rules - The scope rules of the kind.
2907
+ * @param value - The value of the document.
2908
+ * @param slots - The parts of the value, in order.
2909
+ * @returns The names that each part sees, and the names that only the later parts see, by the index of the part.
2942
2910
  */
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;
2911
+ function scopesOf(rules, value, slots) {
2912
+ const sees = slots.map(() => []);
2913
+ const later = slots.map(() => []);
2914
+ for (const rule of rules ?? []) {
2915
+ const covered = slots.map((slot, index) => ({
2916
+ slot,
2917
+ index
2918
+ })).filter(({ slot }) => rule.in.some((pattern) => pathMatches(slot.path, pattern)));
2919
+ if (rule.sequential !== true) {
2920
+ const names = namesOf(rule.names, value, covered.map(({ slot }) => slot));
2921
+ for (const { index } of covered) sees[index]?.push(...names);
2922
+ continue;
2971
2923
  }
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
2924
+ if ("headers" in rule.names) {
2925
+ covered.forEach(({ index }, position) => {
2926
+ const before = covered.slice(0, position).map(({ slot }) => headerName(slot.item)).filter((name) => name !== void 0);
2927
+ const after = covered.slice(position).map(({ slot }) => headerName(slot.item)).filter((name) => name !== void 0);
2928
+ sees[index]?.push(...before);
2929
+ later[index]?.push(...after);
2979
2930
  });
2931
+ continue;
2980
2932
  }
2933
+ const names = namesOf(rule.names, value, covered.map(({ slot }) => slot));
2934
+ covered.forEach(({ index }, position) => {
2935
+ if (position > 0) sees[index]?.push(...names);
2936
+ else later[index]?.push(...names);
2937
+ });
2981
2938
  }
2982
- const step = ladder.steps[best];
2983
- return reason === void 0 ? { step } : {
2984
- step,
2985
- reason
2939
+ return {
2940
+ sees,
2941
+ later
2986
2942
  };
2987
2943
  }
2944
+ // src/ladder.ts
2945
+ /** The rungs of the ladder, in the order that a question visits them. */
2946
+ const RUNGS = [
2947
+ "own",
2948
+ "kind",
2949
+ "default"
2950
+ ];
2951
+ function entryOf$1(verbs, verb) {
2952
+ return verbs !== void 0 && Object.hasOwn(verbs, verb) ? verbs[verb] : void 0;
2953
+ }
2988
2954
  /**
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.
2955
+ * This function finds the kind that a type names, and follows each alias. It gives `undefined` for an unknown
2956
+ * type.
2992
2957
  *
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.
2958
+ * @param world - The world.
2959
+ * @param type - The reference to the type.
2960
+ * @returns The kind, or `undefined`.
2998
2961
  */
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
- };
2962
+ function kindOf(world, type) {
2963
+ const found = lookupKind(world, type);
2964
+ return found.ok ? found.kind : void 0;
3016
2965
  }
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
2966
  /**
3024
- * This function tells if a thing is a host thing.
2967
+ * This function finds a kind by a text type. It is the same as `kindOf` for a one-key reference.
3025
2968
  *
3026
- * @param thing - The thing.
3027
- * @returns `true` for a host thing.
2969
+ * @param world - The world.
2970
+ * @param name - The text of the type.
2971
+ * @returns The kind, or `undefined`.
3028
2972
  */
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;
2973
+ function kindNamed(world, name) {
2974
+ return kindOf(world, name);
3044
2975
  }
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();
2976
+ /** A test that passes each name. A rung of `answerOf` then answers with each entry that it has. */
2977
+ const EACH_NAME = () => true;
3048
2978
  /**
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`.
2979
+ * This function finds the evaluator of a verb without the record of the rungs. It visits the rungs of `ask` in the
2980
+ * same order: the own entry, then the kind, then the default of the world (VERB.LADDER). A plan without a trace,
2981
+ * `deref` and the walkers of steps use it, thus each verb has one ladder.
2982
+ *
2983
+ * @param world - The world, for its defaults.
2984
+ * @param own - The own entries of the document, when it has some.
2985
+ * @param kind - The kind of the document. `undefined` skips the kind rung, as for a value without a type. `null` is
2986
+ * a kind that the world does not have: the question stops there, as in `ask`.
2987
+ * @param verb - The verb, for example `eval`, `format`, `deref` or `step`.
2988
+ * @param has - The test of a name. A rung answers only with a name that passes it. The default passes each name.
2989
+ * @returns The evaluator name and its rung, or `undefined` when no rung answers.
3052
2990
  */
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
- }
3059
- let memo = kindMemos.get(world);
3060
- if (memo === void 0 || memo.size >= MAX_KINDS) {
3061
- memo = {
3062
- first: /* @__PURE__ */ new Map(),
3063
- size: 0
3064
- };
3065
- kindMemos.set(world, memo);
3066
- }
3067
- const node = keys === void 0 ? nodeAt$1(memo.first, type) : nodeOf(memo.first, keys);
3068
- if (node.kind === void 0) {
3069
- const found = lookupKind(world, type);
3070
- node.kind = found.ok ? found.kind : null;
3071
- memo.size += 1;
3072
- }
3073
- return node.kind;
3074
- }
3075
- /** This function gives the node of one key in a level of the memo, and makes it when the level does not have it. */
3076
- function nodeAt$1(level, key) {
3077
- let node = level.get(key);
3078
- if (node === void 0) {
3079
- node = {};
3080
- level.set(key, node);
3081
- }
3082
- return node;
3083
- }
3084
- /** This function gives the node of the keys of a type in the memo. */
3085
- function nodeOf(first, keys) {
3086
- let node = nodeAt$1(first, keys[0]);
3087
- for (let index = 1; index < keys.length; index += 1) node = nodeAt$1(node.next ??= /* @__PURE__ */ new Map(), keys[index]);
3088
- return node;
3089
- }
3090
- /** This function tells if a table of code has the name. An entry of a document can hold another value than a text. */
3091
- function codeIn(table, name) {
3092
- return typeof name === "string" && Object.hasOwn(table, name);
2991
+ function answerOf(world, own, kind, verb, has = EACH_NAME) {
2992
+ const ownName = entryOf$1(own, verb);
2993
+ if (ownName !== void 0 && has(ownName)) return {
2994
+ name: ownName,
2995
+ rung: "own"
2996
+ };
2997
+ if (kind === null) return void 0;
2998
+ const kindName = kind === void 0 ? void 0 : entryOf$1(kind.verbs, verb);
2999
+ if (kindName !== void 0 && has(kindName)) return {
3000
+ name: kindName,
3001
+ rung: "kind"
3002
+ };
3003
+ const fallback = entryOf$1(world.defaults, verb);
3004
+ return fallback !== void 0 && has(fallback) ? {
3005
+ name: fallback,
3006
+ rung: "default"
3007
+ } : void 0;
3093
3008
  }
3094
3009
  /**
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?`.
3010
+ * This function asks a document a question, and gives the evaluator that answers it.
3098
3011
  *
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.
3012
+ * The question visits the rungs in order: the own entry of the envelope, then its kind, then the default of the
3013
+ * world. The type comes from the envelope, or else from the type that the position declares. The type is a
3014
+ * reference into the world. The ladder does not guess a type from the shape of a value. Each verb has this ladder:
3015
+ * `eval`, `deref`, `step` and each verb of a language (VERB.LADDER).
3137
3016
  *
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.
3017
+ * @param world - The kinds and the defaults.
3018
+ * @param doc - The header of the document: an envelope, or `{}` for a bare value.
3019
+ * @param verb - The verb of the question, for example `eval` or `view`.
3020
+ * @param options - The type that the position declares.
3021
+ * @returns The answer, with the record of each rung that the question visited.
3142
3022
  */
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;
3023
+ function ask(world, doc, verb, options = {}) {
3024
+ const steps = [];
3025
+ const own = entryOf$1(doc.own, verb);
3026
+ if (own !== void 0) {
3027
+ steps.push({
3028
+ rung: "own",
3029
+ outcome: "answers",
3030
+ evaluator: own
3031
+ });
3032
+ return {
3033
+ verb,
3034
+ evaluator: own,
3035
+ rung: "own",
3036
+ steps
3037
+ };
3150
3038
  }
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;
3039
+ steps.push({
3040
+ rung: "own",
3041
+ outcome: "no-entry"
3042
+ });
3043
+ const type = doc.type ?? options.declaredType;
3044
+ if (type === void 0) steps.push({
3045
+ rung: "kind",
3046
+ outcome: "skipped"
3047
+ });
3048
+ else {
3049
+ const source = doc.type === void 0 ? "container" : "document";
3050
+ const name = typeName(type);
3051
+ const kind = kindOf(world, type);
3052
+ if (kind === void 0) {
3053
+ steps.push({
3054
+ rung: "kind",
3055
+ outcome: "unknown-kind",
3056
+ kind: name,
3057
+ source
3058
+ });
3059
+ return {
3060
+ verb,
3061
+ error: "unknown-kind",
3062
+ steps
3063
+ };
3162
3064
  }
3163
- const reached = plainStep(envelope.value, key);
3164
- return reached === NOTHING ? void 0 : {
3165
- thing: reached,
3166
- by: "default"
3065
+ const entry = entryOf$1(kind.verbs, verb);
3066
+ if (entry !== void 0) {
3067
+ steps.push({
3068
+ rung: "kind",
3069
+ outcome: "answers",
3070
+ evaluator: entry,
3071
+ kind: name,
3072
+ source
3073
+ });
3074
+ return {
3075
+ verb,
3076
+ evaluator: entry,
3077
+ rung: "kind",
3078
+ steps
3079
+ };
3080
+ }
3081
+ steps.push({
3082
+ rung: "kind",
3083
+ outcome: "no-entry",
3084
+ kind: name,
3085
+ source
3086
+ });
3087
+ }
3088
+ const fallback = entryOf$1(world.defaults, verb);
3089
+ if (fallback !== void 0) {
3090
+ steps.push({
3091
+ rung: "default",
3092
+ outcome: "answers",
3093
+ evaluator: fallback
3094
+ });
3095
+ return {
3096
+ verb,
3097
+ evaluator: fallback,
3098
+ rung: "default",
3099
+ steps
3167
3100
  };
3168
3101
  }
3169
- const reached = plainStep(thing, key);
3170
- return reached === NOTHING ? void 0 : {
3171
- thing: reached,
3172
- by: "default"
3102
+ steps.push({
3103
+ rung: "default",
3104
+ outcome: "no-entry"
3105
+ });
3106
+ return {
3107
+ verb,
3108
+ error: "no-answer",
3109
+ steps
3173
3110
  };
3174
3111
  }
3112
+ // src/deref.ts
3175
3113
  /**
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.
3114
+ * The brand of a host thing: an object of the host that answers the steps of a path itself. The brand is a
3115
+ * global symbol, thus two copies of the kernel in one program know the things of each other.
3180
3116
  */
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();
3117
+ const THING = /* @__PURE__ */ Symbol.for("coeval.thing");
3190
3118
  /**
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.
3119
+ * This function tells if a thing is a host thing.
3194
3120
  *
3195
- * @param world - The world.
3196
- * @returns The thing.
3121
+ * @param thing - The thing.
3122
+ * @returns `true` for a host thing.
3197
3123
  */
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;
3124
+ function isHostThing(thing) {
3125
+ return typeof thing === "object" && thing !== null && thing[THING] === true;
3205
3126
  }
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;
3127
+ /** The roots of a context. Each path starts with one of them. */
3128
+ const ROOTS = [
3129
+ "self",
3130
+ "names",
3131
+ "world",
3132
+ "event",
3133
+ "caps"
3134
+ ];
3135
+ /** This function gives the own entries of an envelope, when it has a record of them. */
3136
+ function ownEntries(envelope) {
3137
+ const own = field(envelope, "own");
3138
+ return isRecord(own) ? own : void 0;
3371
3139
  }
3140
+ /** The most kinds in the memo of one world. A larger memo starts again, thus the types of the data cannot fill the memory. */
3141
+ const MAX_KINDS = 1e3;
3142
+ const kindMemos = /* @__PURE__ */ new WeakMap();
3372
3143
  /**
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.
3144
+ * This function gives the kind of a type for the ladder: `null` when the world does not have the kind. The result
3145
+ * depends only on the world and on the keys of the type, thus a memo for each world keeps it (PLAN.KIND-MEMO). A
3146
+ * world does not change after a plan or a resolution uses it, as for `worldThing`.
3394
3147
  */
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;
3148
+ function kindFor(world, type) {
3149
+ const keys = typeof type === "string" ? void 0 : typePath(type);
3150
+ if (typeof type !== "string" && (keys === void 0 || keys.length === 0)) {
3151
+ const found = lookupKind(world, type);
3152
+ return found.ok ? found.kind : null;
3399
3153
  }
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
3154
+ let memo = kindMemos.get(world);
3155
+ if (memo === void 0 || memo.size >= MAX_KINDS) {
3156
+ memo = {
3157
+ first: /* @__PURE__ */ new Map(),
3158
+ size: 0
3550
3159
  };
3551
- };
3552
- if (path.length === 0) return failed("#REF!", "A path has at least one step: its root.");
3553
- return walk(path, known);
3160
+ kindMemos.set(world, memo);
3161
+ }
3162
+ const node = keys === void 0 ? nodeAt$1(memo.first, type) : nodeOf(memo.first, keys);
3163
+ if (node.kind === void 0) {
3164
+ const found = lookupKind(world, type);
3165
+ node.kind = found.ok ? found.kind : null;
3166
+ memo.size += 1;
3167
+ }
3168
+ return node.kind;
3169
+ }
3170
+ /** This function gives the node of one key in a level of the memo, and makes it when the level does not have it. */
3171
+ function nodeAt$1(level, key) {
3172
+ let node = level.get(key);
3173
+ if (node === void 0) {
3174
+ node = {};
3175
+ level.set(key, node);
3176
+ }
3177
+ return node;
3178
+ }
3179
+ /** This function gives the node of the keys of a type in the memo. */
3180
+ function nodeOf(first, keys) {
3181
+ let node = nodeAt$1(first, keys[0]);
3182
+ for (let index = 1; index < keys.length; index += 1) node = nodeAt$1(node.next ??= /* @__PURE__ */ new Map(), keys[index]);
3183
+ return node;
3184
+ }
3185
+ /** This function tells if a table of code has the name. An entry of a document can hold another value than a text. */
3186
+ function codeIn(table, name) {
3187
+ return typeof name === "string" && Object.hasOwn(table, name);
3554
3188
  }
3555
3189
  /**
3556
- * This function gives the value of a thing: the value that a host thing gives, or else the thing itself.
3190
+ * This function finds the walker of a step document through the ladder of the verb `step` (VERB.LADDER). The rungs
3191
+ * are the own entry, then the kind, then the default of the world. A rung answers only with a walker that the
3192
+ * navigator has. A resolution and `check` use this function, thus they agree on `#STEP?`.
3557
3193
  *
3558
- * @param thing - The thing.
3559
- * @returns The value.
3194
+ * @param nav - The world and the walkers.
3195
+ * @param step - A step of a path that is not a key.
3196
+ * @returns The walker, or `undefined` when no rung answers.
3560
3197
  */
3561
- function valueOfThing(thing) {
3562
- return isHostThing(thing) ? thing.toJson() : thing;
3198
+ function walkerOf(nav, step) {
3199
+ const walkers = nav.walkers;
3200
+ if (walkers === void 0 || !isEnvelope(step)) return void 0;
3201
+ const answer = answerOf(nav.world, ownEntries(step), kindFor(nav.world, step.type), "step", (name) => codeIn(walkers, name));
3202
+ return answer === void 0 ? void 0 : walkers[answer.name];
3563
3203
  }
3564
- // src/classify.ts
3565
- function isStrictSuperset(larger, smaller) {
3566
- return larger.length > smaller.length && smaller.every((name) => larger.includes(name));
3204
+ /** The answer of `plainStep` for a field that the value does not have. A field can hold `undefined`. */
3205
+ const NOTHING = /* @__PURE__ */ Symbol("nothing");
3206
+ /** The own fields of a value: the items and the length of a list, and the own properties of an object. */
3207
+ function plainStep(thing, key) {
3208
+ if (Array.isArray(thing)) {
3209
+ if (key === "length") return thing.length;
3210
+ const index = typeof key === "number" ? key : /^\d+$/.test(key) ? Number(key) : -1;
3211
+ return index >= 0 && index < thing.length ? thing[index] : NOTHING;
3212
+ }
3213
+ if (typeof thing === "object" && thing !== null) {
3214
+ const name = String(key);
3215
+ return Object.hasOwn(thing, name) ? thing[name] : NOTHING;
3216
+ }
3217
+ return NOTHING;
3567
3218
  }
3568
3219
  /**
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.
3220
+ * This function tells if a value can be an envelope by its field `type`. An envelope has its own field `type`, thus
3221
+ * a value without that field is not an envelope, and the full test is not necessary.
3577
3222
  */
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
- };
3223
+ function mayBeEnvelope(thing) {
3224
+ return typeof thing === "object" && thing !== null && thing.type !== void 0;
3591
3225
  }
3592
3226
  /**
3593
- * This function puts a value in an envelope with a type. The value does not change.
3227
+ * This function answers one step of a path on a thing, through the ladder of the verb `deref`. A host thing
3228
+ * answers for itself (own). A document asks its own entry, then its kind, then the default of the world
3229
+ * (VERB.LADDER). A rung answers only with a `deref` that the navigator has. When no rung answers, the step goes into
3230
+ * 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
3231
+ * into it at once.
3594
3232
  *
3595
- * @param value - The value.
3596
- * @param kind - The name of the kind.
3597
- * @returns The envelope.
3233
+ * @param nav - The world and the code of the evaluators.
3234
+ * @param thing - The thing that the path reached.
3235
+ * @param key - The key of the step.
3236
+ * @returns What the step reaches and the rung that answered, or `undefined` when it reaches nothing.
3598
3237
  */
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;
3238
+ function derefStep(nav, thing, key) {
3239
+ if (isHostThing(thing)) {
3240
+ const reached = thing.deref(key);
3241
+ return reached !== void 0 || thing.has?.(key) === true ? {
3242
+ thing: reached,
3243
+ by: "own"
3244
+ } : void 0;
3609
3245
  }
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 }
3246
+ if (nav.plain !== true && mayBeEnvelope(thing) && isEnvelope(thing)) {
3247
+ const envelope = thing;
3248
+ const derefs = nav.derefs;
3249
+ const answer = derefs === void 0 ? void 0 : answerOf(nav.world, ownEntries(envelope), kindFor(nav.world, envelope.type), "deref", (name) => codeIn(derefs, name));
3250
+ if (answer !== void 0) {
3251
+ const code = derefs[answer.name];
3252
+ const reached = code?.(envelope, key);
3253
+ return reached !== void 0 || code?.has?.(envelope, key) === true ? {
3254
+ thing: reached,
3255
+ by: answer.rung
3256
+ } : void 0;
3257
+ }
3258
+ const reached = plainStep(envelope.value, key);
3259
+ return reached === NOTHING ? void 0 : {
3260
+ thing: reached,
3261
+ by: "default"
3262
+ };
3263
+ }
3264
+ const reached = plainStep(thing, key);
3265
+ return reached === NOTHING ? void 0 : {
3266
+ thing: reached,
3267
+ by: "default"
3631
3268
  };
3632
3269
  }
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);
3270
+ /**
3271
+ * This function tells if a thing is a reference document: an envelope of the type `ref` with a list for its path.
3272
+ *
3273
+ * @param thing - The thing.
3274
+ * @returns `true` for a reference document.
3275
+ */
3276
+ function isRef(thing) {
3277
+ if (typeof thing !== "object" || thing === null) return false;
3278
+ const type = thing.type;
3279
+ if (type === void 0 || typeof type === "string" && type !== "ref") return false;
3280
+ if (!isEnvelope(thing) || !Array.isArray(thing.value)) return false;
3281
+ const path = typePath(thing.type);
3282
+ return path !== void 0 && path.length === 1 && path[0] === "ref";
3652
3283
  }
3284
+ const worlds = /* @__PURE__ */ new WeakMap();
3653
3285
  /**
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.
3286
+ * This function makes the thing of the root `world`: the entries of the world as JSON. An alias is a reference
3287
+ * document in it, thus a walk through the world follows each alias (collapse). The thing of a world is made one
3288
+ * time.
3656
3289
  *
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.
3290
+ * @param world - The world.
3291
+ * @returns The thing.
3660
3292
  */
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
- };
3293
+ function worldThing(world) {
3294
+ let thing = worlds.get(world);
3295
+ if (thing === void 0) {
3296
+ thing = entriesAsJson(world.kinds);
3297
+ worlds.set(world, thing);
3298
+ }
3299
+ return thing;
3300
+ }
3301
+ /**
3302
+ * This function makes a context. The world comes from the navigator when the call gives none.
3303
+ *
3304
+ * @param parts - The roots to set.
3305
+ * @returns The context.
3306
+ */
3307
+ function context(parts = {}) {
3308
+ return {
3309
+ self: parts.self ?? null,
3310
+ names: parts.names ?? {},
3311
+ world: parts.world ?? null,
3312
+ event: parts.event ?? null,
3313
+ caps: parts.caps ?? []
3709
3314
  };
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
3315
+ }
3316
+ const MAX_COLLAPSE$1 = 64;
3317
+ /** 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). */
3318
+ const CHAIN_REASON = "The path follows more than 64 references. One resolution follows at most 64.";
3319
+ const NO_HOPS$1 = /* @__PURE__ */ Object.freeze([]);
3320
+ /** A value that can be a reference document: a record with the type `ref`. The full check comes after. */
3321
+ function mayBeRef(thing) {
3322
+ return typeof thing === "object" && thing !== null && thing.type === "ref";
3323
+ }
3324
+ /** This function tells if each step of a path from an index is a key. */
3325
+ function keysFrom(path, start) {
3326
+ for (let index = start; index < path.length; index += 1) if (!isKey(path[index])) return false;
3327
+ return true;
3328
+ }
3329
+ /** This function tells if a root has a value of its own for the short path: each root except `caps`. */
3330
+ function quickRoot(root) {
3331
+ return root === "names" || root === "self" || root === "event" || root === "world";
3332
+ }
3333
+ /**
3334
+ * This function resolves the common path without a record of hops: a root, then keys. Plain values answer the
3335
+ * keys, or a host thing answers all of them in one call. It gives `undefined` when the path needs the full
3336
+ * algorithm. Examples are a host thing without `resolve`, an envelope, a reference to follow, a step document and a
3337
+ * failure of a step (for its exact reason).
3338
+ */
3339
+ function resolveQuick(nav, ctx, path) {
3340
+ const root = path[0];
3341
+ if (!quickRoot(root)) return void 0;
3342
+ if (nav.roots !== void 0 && !nav.roots.includes(root)) return void 0;
3343
+ if (nav.adopt !== void 0) return void 0;
3344
+ return walkQuick(ctx[root], path, nav.plain === true, false);
3345
+ }
3346
+ /**
3347
+ * This function walks the steps of the short path from the value of the root (DEREF.QUICK). `resolveQuick` and each
3348
+ * compiled path use it, thus the two cannot disagree. It gives `undefined` when the path needs the full algorithm.
3349
+ *
3350
+ * @param start - The value of the root.
3351
+ * @param path - The steps. The walk starts at the index 1.
3352
+ * @param plain - `true` for a plain navigation.
3353
+ * @param keyed - `true` when each step after the root is a key. The walk then does not test the steps again.
3354
+ */
3355
+ function walkQuick(start, path, plain, keyed) {
3356
+ let here = start;
3357
+ for (let index = 1; index < path.length; index += 1) {
3358
+ if (typeof here !== "object" || here === null) return void 0;
3359
+ const type = plain ? void 0 : here.type;
3360
+ if (type === "ref") return void 0;
3361
+ if (here[THING] === true) {
3362
+ const thing = here;
3363
+ if (thing.resolve === void 0 || !(keyed || keysFrom(path, index))) return void 0;
3364
+ const keys = path.slice(index);
3365
+ const reached = thing.resolve(keys);
3366
+ if (reached === void 0) return {
3367
+ ok: false,
3368
+ code: "#N/A",
3369
+ reason: `The path ${keys.join(".")} reaches nothing.`,
3370
+ hops: NO_HOPS$1
3743
3371
  };
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);
3372
+ if (!plain && mayBeRef(reached.thing)) return void 0;
3748
3373
  return {
3749
- t: "record",
3750
- fields: Object.keys(item).map((key) => [key, walk(each, item[key], [...path, key])])
3374
+ ok: true,
3375
+ thing: reached.thing,
3376
+ hops: NO_HOPS$1
3751
3377
  };
3752
3378
  }
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])]);
3379
+ const step = path[index];
3380
+ if (Array.isArray(here)) {
3381
+ if (typeof step !== "number" || !Number.isInteger(step) || step < 0 || step >= here.length) return void 0;
3382
+ here = here[step];
3383
+ continue;
3760
3384
  }
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;
3385
+ if (typeof step !== "string" || !Object.hasOwn(here, step)) return void 0;
3386
+ if (type !== void 0 && isEnvelope(here)) return void 0;
3387
+ here = here[step];
3776
3388
  }
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
- };
3389
+ if (!plain && mayBeRef(here)) return void 0;
3796
3390
  return {
3797
3391
  ok: true,
3798
- parts,
3799
- data: strip(template) ?? null,
3800
- fill: (handles) => fillWith(template, handles)
3392
+ thing: here,
3393
+ hops: NO_HOPS$1
3801
3394
  };
3802
3395
  }
3396
+ /** The root whose value starts the short path of a compiled path. `FULL` takes the full algorithm at once. */
3397
+ const FULL = 0;
3398
+ const FROM_NAMES = 1;
3399
+ const FROM_SELF = 2;
3400
+ const FROM_EVENT = 3;
3401
+ const FROM_WORLD = 4;
3803
3402
  /**
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.
3403
+ * A compiled path as an object with fields (PLAN.LEAN). The code of `resolve` is on the class, thus each compiled path
3404
+ * keeps only its fields and makes no closure.
3812
3405
  */
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
3406
+ var StaticPath = class {
3407
+ constructor(path, nav, known, from, plain) {
3408
+ this.path = path;
3409
+ this.nav = nav;
3410
+ this.known = known;
3411
+ this.from = from;
3412
+ this.plain = plain;
3413
+ }
3414
+ resolve(ctx) {
3415
+ const from = this.from;
3416
+ if (from !== FULL) {
3417
+ 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);
3418
+ if (quick !== void 0) return quick;
3848
3419
  }
3849
- };
3420
+ return resolveFully$1(this.nav, ctx, this.path, void 0, this.known);
3421
+ }
3422
+ };
3423
+ /**
3424
+ * This function compiles one static path for one navigator. The resolver gives the same thing, error and reason as
3425
+ * `resolve` without hops (PLAN.PATH-SAME). It keeps no value of a context.
3426
+ *
3427
+ * - Some paths take the full algorithm at once, because the short path cannot answer them. A path from `caps` or from
3428
+ * a closed root is one. A path with a step document and each path of a navigator with `adopt` are others.
3429
+ * - Each other path walks the short path from its root, and it takes the full algorithm when the values need it.
3430
+ * - The walker of each step document comes from the ladder one time, here. The navigator and the step document do
3431
+ * not change, thus the answer does not change either.
3432
+ *
3433
+ * An evaluator of a language calls this function in its `compile`, with the field `machine` of the input, and reads the
3434
+ * result with `resolveCompiled` (PLAN.PATH-EXPORT).
3435
+ *
3436
+ * @param nav - The navigator. A plan compiles its paths for its machine.
3437
+ * @param path - The steps. The first step is a root. The compiled path keeps this list, thus the host must not change it.
3438
+ * @returns The compiled path.
3439
+ */
3440
+ function compilePath(nav, path) {
3441
+ const keyed = keysFrom(path, 1);
3442
+ return new StaticPath(path, nav, keyed ? void 0 : walkersOf(nav, path), startOf(nav, path, keyed), nav.plain === true);
3443
+ }
3444
+ /** This function gives the root that starts the short path of a compiled path, or `FULL`. */
3445
+ function startOf(nav, path, keyed) {
3446
+ const root = path[0];
3447
+ if (!keyed || !quickRoot(root) || nav.adopt !== void 0) return FULL;
3448
+ if (nav.roots !== void 0 && !nav.roots.includes(root)) return FULL;
3449
+ return root === "names" ? FROM_NAMES : root === "self" ? FROM_SELF : root === "event" ? FROM_EVENT : FROM_WORLD;
3850
3450
  }
3851
3451
  /**
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.
3854
- *
3855
- * @param path - The path of the part.
3856
- * @param pattern - The pattern.
3857
- * @returns `true` when the path matches.
3452
+ * This function asks the ladder of the verb `step` for each step document of a path. A step whose lookup throws
3453
+ * stays unknown, thus the full algorithm asks the ladder again for it.
3858
3454
  */
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;
3455
+ function walkersOf(nav, path) {
3456
+ if (nav.walkers === void 0) return void 0;
3457
+ const out = new Array(path.length);
3458
+ for (let index = 1; index < path.length; index += 1) {
3459
+ const step = path[index];
3460
+ if (isKey(step)) continue;
3461
+ try {
3462
+ out[index] = walkerOf(nav, step) ?? null;
3463
+ } catch {}
3864
3464
  }
3865
- return true;
3465
+ return out;
3866
3466
  }
3867
3467
  /**
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.
3468
+ * This function resolves a path from a context, and records each hop.
3870
3469
  *
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.
3470
+ * 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
3471
+ * of the verb `deref` on the thing that the path reached. A step document is evaluated by the walker that the
3472
+ * ladder of the verb `step` gives, with the thing that the path reached. After each hop, a reference document is
3473
+ * followed until the path reaches something else (collapse), except in a plain navigation.
3474
+ *
3475
+ * The codes of a failure:
3476
+ *
3477
+ * - `#REF!`: the path has no root, or a root that is not open here.
3478
+ * - `#NAME?`: the root `names` has no such name.
3479
+ * - `#N/A`: a step reaches nothing.
3480
+ * - `#STEP?`: a step is not a key and not a step document.
3481
+ * - `#CYCLE!`: the references form a cycle, or the resolution follows more than 64 references. The reason tells
3482
+ * which (DEREF.CHAIN-REASON).
3483
+ *
3484
+ * @param nav - The world and the code of the evaluators.
3485
+ * @param ctx - The context.
3486
+ * @param path - The steps.
3487
+ * @param options - `hops: false` does not record the hops.
3488
+ * @returns What the path reached and each hop, or an error.
3876
3489
  */
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
- }
3490
+ function resolve(nav, ctx, path, options = {}) {
3491
+ if (options.hops === false) {
3492
+ const quick = resolveQuick(nav, ctx, path);
3493
+ if (quick !== void 0) return quick;
3892
3494
  }
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;
3495
+ return resolveFully$1(nav, ctx, path, options.hops === false ? void 0 : [], void 0);
3904
3496
  }
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);
3497
+ /** The functions of the last navigator that gave a walker its input. A walk with the same navigator makes no new functions. */
3498
+ let lastSteps;
3499
+ /**
3500
+ * This function gives the functions `deref` and `has` of the input of a walker. They depend only on the navigator,
3501
+ * thus the function keeps the functions of the last navigator (K170).
3502
+ */
3503
+ function walkSteps(nav) {
3504
+ if (lastSteps !== void 0 && lastSteps.nav === nav) return lastSteps;
3505
+ const adopt = nav.adopt;
3506
+ lastSteps = {
3507
+ nav,
3508
+ deref: adopt === void 0 ? (thing, key) => derefStep(nav, thing, key)?.thing : (thing, key) => {
3509
+ const reached = derefStep(nav, thing, key);
3510
+ return reached === void 0 ? void 0 : adopt(reached.thing);
3511
+ },
3512
+ has: (thing, key) => derefStep(nav, thing, key) !== void 0
3513
+ };
3514
+ return lastSteps;
3921
3515
  }
3922
3516
  /**
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.
3517
+ * This function resolves a path with the full algorithm of `resolve`.
3925
3518
  *
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.
3519
+ * @param nav - The world and the code of the evaluators.
3520
+ * @param ctx - The context.
3521
+ * @param path - The steps.
3522
+ * @param hops - The list that gets each hop, or `undefined` for no record.
3523
+ * @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.
3524
+ * @returns What the path reached and each hop, or an error.
3930
3525
  */
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);
3526
+ function resolveFully$1(nav, ctx, path, hops, known) {
3527
+ const done = hops ?? NO_HOPS$1;
3528
+ const failed = (code, reason) => ({
3529
+ ok: false,
3530
+ code,
3531
+ reason,
3532
+ hops: done
3533
+ });
3534
+ let collapses = 0;
3535
+ let open;
3536
+ const adopt = nav.adopt ?? ((value) => value);
3537
+ const collapse = (thing) => {
3538
+ let here = thing;
3539
+ if (nav.plain === true) return {
3540
+ ok: true,
3541
+ thing: here,
3542
+ hops: done
3543
+ };
3544
+ while (isRef(here)) {
3545
+ if (open?.includes(here) === true) return failed("#CYCLE!", "The references form a cycle.");
3546
+ collapses += 1;
3547
+ if (collapses > MAX_COLLAPSE$1) return failed("#CYCLE!", CHAIN_REASON);
3548
+ open ??= [];
3549
+ open.push(here);
3550
+ const inner = walk(here.value, void 0);
3551
+ open.pop();
3552
+ if (!inner.ok) return inner;
3553
+ here = adopt(inner.thing);
3554
+ hops?.push({
3555
+ step: "collapse",
3556
+ thing: here,
3557
+ by: "collapse"
3950
3558
  });
3951
- continue;
3952
3559
  }
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);
3957
- });
3958
- }
3959
- return {
3960
- sees,
3961
- later
3560
+ return {
3561
+ ok: true,
3562
+ thing: here,
3563
+ hops: done
3564
+ };
3565
+ };
3566
+ const walk = (steps, walkers) => {
3567
+ const root = steps[0];
3568
+ if (typeof root !== "string" || !ROOTS.includes(root)) return failed("#REF!", `A path starts with a root: ${ROOTS.join(", ")}.`);
3569
+ 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(", ")}.`);
3570
+ let here = adopt(ctx[root]);
3571
+ hops?.push({
3572
+ step: root,
3573
+ thing: here,
3574
+ by: "root"
3575
+ });
3576
+ const first = collapse(here);
3577
+ if (!first.ok) return first;
3578
+ here = first.thing;
3579
+ for (let index = 1; index < steps.length; index += 1) {
3580
+ const step = steps[index];
3581
+ if (isHostThing(here) && here.resolve !== void 0 && keysFrom(steps, index)) {
3582
+ const keys = steps.slice(index);
3583
+ const reached = here.resolve(keys);
3584
+ if (reached === void 0) return failed("#N/A", `The path ${keys.join(".")} reaches nothing.`);
3585
+ const thing = adopt(reached.thing);
3586
+ hops?.push({
3587
+ step: keys,
3588
+ thing,
3589
+ by: "own"
3590
+ });
3591
+ return collapse(thing);
3592
+ }
3593
+ if (isKey(step)) {
3594
+ const reached = derefStep(nav, here, step);
3595
+ if (reached === void 0) {
3596
+ if (root === "names" && index === 1) return failed("#NAME?", `The context has no name ${String(step)}.`);
3597
+ return failed("#N/A", `The step ${String(step)} reaches nothing.`);
3598
+ }
3599
+ here = adopt(reached.thing);
3600
+ hops?.push({
3601
+ step,
3602
+ thing: here,
3603
+ by: reached.by
3604
+ });
3605
+ } else {
3606
+ const given = walkers?.[index];
3607
+ const walker = given === void 0 ? walkerOf(nav, step) : given ?? void 0;
3608
+ if (walker === void 0) return failed("#STEP?", "A step is a key, or a document of a kind with the verb step.");
3609
+ const envelope = step;
3610
+ const { deref, has } = walkSteps(nav);
3611
+ const result = walker(hops === void 0 ? {
3612
+ data: envelope.value,
3613
+ here,
3614
+ context: ctx,
3615
+ deref,
3616
+ has
3617
+ } : {
3618
+ data: envelope.value,
3619
+ here,
3620
+ context: ctx,
3621
+ deref,
3622
+ has,
3623
+ visit: (key, thing) => hops.push({
3624
+ step: key,
3625
+ thing,
3626
+ by: "step"
3627
+ })
3628
+ });
3629
+ if (!result.ok) return failed(result.code ?? "#N/A", result.reason);
3630
+ here = adopt(result.thing);
3631
+ hops?.push({
3632
+ step: envelope,
3633
+ thing: here,
3634
+ by: "step"
3635
+ });
3636
+ }
3637
+ const next = collapse(here);
3638
+ if (!next.ok) return next;
3639
+ here = next.thing;
3640
+ }
3641
+ return {
3642
+ ok: true,
3643
+ thing: here,
3644
+ hops: done
3645
+ };
3962
3646
  };
3647
+ if (path.length === 0) return failed("#REF!", "A path has at least one step: its root.");
3648
+ return walk(path, known);
3649
+ }
3650
+ /**
3651
+ * This function gives the value of a thing: the value that a host thing gives, or else the thing itself.
3652
+ *
3653
+ * @param thing - The thing.
3654
+ * @returns The value.
3655
+ */
3656
+ function valueOfThing(thing) {
3657
+ return isHostThing(thing) ? thing.toJson() : thing;
3963
3658
  }
3964
3659
  // src/evaluate.ts
3965
3660
  /**
@@ -4519,14 +4214,14 @@ var Session = class {
4519
4214
  /**
4520
4215
  * This function adds work to the count of the evaluation (WORK.LIMIT). One count is on the runtime of the root, thus
4521
4216
  * 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).
4217
+ * (WORK.AFTER). An entry is a point with no application of a closure that runs, on any runtime of the evaluation.
4523
4218
  *
4524
4219
  * @param points - The work.
4525
4220
  * @throws {Failure} The error `#WORK!`, when the count is over the limit of the machine.
4526
4221
  */
4527
4222
  spend(points) {
4528
4223
  const root = this.top ?? this;
4529
- const work = (root.top === root && (this.applying ?? 0) === 0 ? 0 : root.work ?? 0) + points;
4224
+ const work = (root.top === root && (root.active ?? 0) === 0 ? 0 : root.work ?? 0) + points;
4530
4225
  root.work = work;
4531
4226
  const limit = this.machine.maxWork ?? 2e5;
4532
4227
  if (work > limit) throw new Failure(workFailure(limit));
@@ -5905,104 +5600,447 @@ function record(s, result) {
5905
5600
  };
5906
5601
  }
5907
5602
  /**
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.
5603
+ * This function evaluates a document, and records each evaluation in a trace.
5604
+ *
5605
+ * The verb of the options goes up the ladder for each document. The default verb is `eval`. The kind of the document
5606
+ * tells where its parts are. The evaluator gets each part sealed: it can evaluate the part, and it cannot read its
5607
+ * value.
5608
+ *
5609
+ * A failure gives an error value, and the function does not throw. The function records each effect in its order,
5610
+ * and the host does not do it. A mock can answer each effect at once (RUN.MOCK).
5611
+ *
5612
+ * @param machine - The world and the code of the evaluators.
5613
+ * @param doc - The document, as JSON.
5614
+ * @param context - The names and the capabilities at the root.
5615
+ * @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.
5616
+ * @returns The result, the trace and the effects in their order.
5617
+ */
5618
+ function evaluate(machine, doc, context = makeContext(), options) {
5619
+ const given = typeof options === "string" ? { declaredType: options } : options ?? {};
5620
+ const declaredType = given.declaredType;
5621
+ const plan = prepare(machine, doc, {
5622
+ trace: true,
5623
+ ...declaredType === void 0 ? {} : { declaredType },
5624
+ ...given.verb === void 0 ? {} : { verb: given.verb },
5625
+ ...given.guards === void 0 ? {} : { guards: given.guards }
5626
+ });
5627
+ const ctx = rootContext(machine, context);
5628
+ const s = new Session(machine, ctx.caps, false, true, given.perform, void 0, void 0, readingOf(given.reads, ctx));
5629
+ return record(s, plan.code(ctx, s));
5630
+ }
5631
+ /**
5632
+ * This function runs a document: an evaluation in which the host does each effect. A runner waits for its
5633
+ * parts and for its effects, thus a step can read the result of the step before. The part of the run before the
5634
+ * first wait happens at once, in the call. The run records a trace.
5635
+ *
5636
+ * @param machine - The world, the evaluators and the runners.
5637
+ * @param doc - The document, as JSON.
5638
+ * @param context - The names and the capabilities at the root.
5639
+ * @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.
5640
+ * @returns The result, the trace and the effects in their order, when the run ends.
5641
+ */
5642
+ async function run(machine, doc, context = makeContext(), options = {}) {
5643
+ const plan = prepare(machine, doc, {
5644
+ trace: true,
5645
+ ...options.declaredType === void 0 ? {} : { declaredType: options.declaredType },
5646
+ ...options.guards === void 0 ? {} : { guards: options.guards },
5647
+ ...options.verb === void 0 ? {} : { verb: options.verb }
5648
+ });
5649
+ const ctx = rootContext(machine, context);
5650
+ const s = new Session(machine, ctx.caps, true, true, options.perform, void 0, void 0, readingOf(options.reads, ctx));
5651
+ const result = await driveWaiting(plan.runCode()(ctx, s), options.signal);
5652
+ s.top = s;
5653
+ return record(s, result);
5654
+ }
5655
+ /**
5656
+ * This function finds a node of a trace by its path.
5657
+ *
5658
+ * @param trace - The root of the trace.
5659
+ * @param path - The keys from the root.
5660
+ * @returns The first evaluation at that path, or `undefined` when the document did not evaluate.
5661
+ */
5662
+ function nodeAt(trace, path) {
5663
+ const want = path.map(String);
5664
+ let node = trace;
5665
+ let at = 0;
5666
+ while (node !== void 0 && at < want.length) {
5667
+ const here = node;
5668
+ node = here.children.find((child) => {
5669
+ const tail = child.path.slice(here.path.length);
5670
+ return tail.length > 0 && tail.every((key, index) => key === want[at + index]);
5671
+ });
5672
+ if (node !== void 0) at += node.path.length - here.path.length;
5673
+ }
5674
+ return node;
5675
+ }
5676
+ /**
5677
+ * This function lists the nodes of a trace in the order of their start.
5678
+ *
5679
+ * @param trace - The root of the trace.
5680
+ * @returns Each node, the root first.
5681
+ */
5682
+ function flatten(trace) {
5683
+ const out = [];
5684
+ const stack = [trace];
5685
+ while (stack.length > 0) {
5686
+ const node = stack.pop();
5687
+ out.push(node);
5688
+ for (let index = node.children.length - 1; index >= 0; index -= 1) stack.push(node.children[index]);
5689
+ }
5690
+ return out.sort((a, b) => a.enter - b.enter);
5691
+ }
5692
+ /**
5693
+ * This function lists the errors of a trace: each node whose result is an error and whose parts did not fail
5694
+ * the same way. These nodes are where each error started.
5695
+ *
5696
+ * @param trace - The root of the trace.
5697
+ * @returns The errors, in the order of their start.
5698
+ */
5699
+ function failures(trace) {
5700
+ 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);
5701
+ }
5702
+ // src/language.ts
5703
+ const VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
5704
+ function numbers$1(version) {
5705
+ const found = VERSION.exec(version);
5706
+ if (found === null) throw new TypeError(`A language version has the form MAJOR.MINOR.PATCH. The text ${JSON.stringify(version)} does not.`);
5707
+ return [
5708
+ Number(found[1]),
5709
+ Number(found[2]),
5710
+ Number(found[3])
5711
+ ];
5712
+ }
5713
+ /**
5714
+ * This function tells if a version satisfies a lowest version, by the rules of a caret range of SemVer. The first
5715
+ * number that is not zero stays the same, and the version is not lower.
5716
+ */
5717
+ function compatible(version, lowest) {
5718
+ const have = numbers$1(version);
5719
+ const want = numbers$1(lowest);
5720
+ const stable = want.findIndex((part) => part !== 0);
5721
+ const fixed = stable < 0 ? 3 : stable + 1;
5722
+ for (let index = 0; index < 3; index += 1) {
5723
+ const [a, b] = [have[index], want[index]];
5724
+ if (a !== b) return index >= fixed && a > b;
5725
+ }
5726
+ return true;
5727
+ }
5728
+ /** This function gives the JSON text of a value with its keys in order. A value that is not JSON is an error. */
5729
+ function canonical(value, path) {
5730
+ if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
5731
+ if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value);
5732
+ if (Array.isArray(value)) return `[${value.map((item, index) => canonical(item, [...path, index])).join(",")}]`;
5733
+ if (!isRecord(value)) throw new TypeError(`The data half of a language is JSON. The value at ${JSON.stringify(path)} is not.`);
5734
+ return `{${Object.keys(value).filter((key) => value[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key], [...path, key])}`).join(",")}}`;
5735
+ }
5736
+ function frozen(value) {
5737
+ if (typeof value !== "object" || value === null) return value;
5738
+ for (const item of Object.values(value)) frozen(item);
5739
+ return Object.freeze(value);
5740
+ }
5741
+ /**
5742
+ * This function makes one value of a language. The data half is JSON, thus a host can store it and compare it. The
5743
+ * code half binds the evaluator names of the world.
5744
+ *
5745
+ * The language keeps a frozen copy of its data half, thus a later change to the input changes nothing.
5746
+ *
5747
+ * @param definition - The name, the version, the world, the needed languages and the code.
5748
+ * @returns The language.
5749
+ * @throws {TypeError} A version in the definition is not `MAJOR.MINOR.PATCH`, the name is empty, or the
5750
+ * data half is not JSON.
5751
+ */
5752
+ function defineLanguage(definition) {
5753
+ if (definition.name === "") throw new TypeError("A language has a name.");
5754
+ numbers$1(definition.version);
5755
+ const requires = definition.requires ?? {};
5756
+ for (const name of Object.keys(requires)) numbers$1(requires[name]);
5757
+ const data = canonical({
5758
+ requires,
5759
+ world: definition.world ?? {}
5760
+ }, []);
5761
+ const copy = frozen(JSON.parse(data));
5762
+ const language = {
5763
+ name: definition.name,
5764
+ version: definition.version,
5765
+ world: copy.world,
5766
+ requires: copy.requires,
5767
+ data
5768
+ };
5769
+ return Object.freeze(definition.code === void 0 ? language : {
5770
+ ...language,
5771
+ code: definition.code
5772
+ });
5773
+ }
5774
+ function partOf(language) {
5775
+ const { code, world } = language;
5776
+ return typeof code === "function" ? (prev) => ({
5777
+ ...code(prev),
5778
+ world
5779
+ }) : {
5780
+ ...code,
5781
+ world
5782
+ };
5783
+ }
5784
+ /**
5785
+ * This function merges languages into one machine, in the order of the arguments, with `mergeMachines`.
5786
+ *
5787
+ * - A language comes after each language that it names in `requires`, at a compatible version (LANG.REQUIRES).
5788
+ * - One language that comes twice counts once. Thus two languages can share a base.
5789
+ * - Two versions of one name, or two data halves under one name and one version, are conflicts (LANG.COMPOSE).
5790
+ *
5791
+ * @param languages - The languages.
5792
+ * @returns The machine.
5793
+ * @throws {MergeError} The languages do not fit, or their merge has a conflict. The error lists each conflict.
5794
+ */
5795
+ function compose(...languages) {
5796
+ const conflicts = [];
5797
+ const parts = [];
5798
+ const seen = /* @__PURE__ */ new Map();
5799
+ languages.forEach((language, index) => {
5800
+ const earlier = seen.get(language.name);
5801
+ const conflict = (name, other, reason) => {
5802
+ conflicts.push({
5803
+ path: ["languages", name],
5804
+ parts: [Math.min(other, index), Math.max(other, index)],
5805
+ reason
5806
+ });
5807
+ };
5808
+ if (earlier !== void 0) {
5809
+ if (earlier.language.version !== language.version) conflict(language.name, earlier.index, "Two versions of one language.");
5810
+ else if (earlier.language.data !== language.data) conflict(language.name, earlier.index, "Two languages with one name and one version differ.");
5811
+ else if (earlier.language.code !== language.code) parts.push(partOf(language));
5812
+ return;
5813
+ }
5814
+ for (const name of Object.keys(language.requires)) {
5815
+ const needed = language.requires[name];
5816
+ const found = seen.get(name);
5817
+ if (found === void 0) {
5818
+ const later = languages.findIndex((other) => other.name === name);
5819
+ if (later < 0) conflict(name, index, `A language requires ${name}, and the composition does not have it.`);
5820
+ else conflict(name, later, `A language requires ${name}, and ${name} comes after it.`);
5821
+ } else if (!compatible(found.language.version, needed)) conflict(name, found.index, `A language requires ${name} ${needed}, and the composition has ${found.language.version}.`);
5822
+ }
5823
+ seen.set(language.name, {
5824
+ language,
5825
+ index
5826
+ });
5827
+ parts.push(partOf(language));
5828
+ });
5829
+ if (conflicts.length > 0) throw new MergeError(conflicts);
5830
+ return mergeMachines(...parts);
5831
+ }
5832
+ /**
5833
+ * This function makes the language of the boundary kind `lang` (K38, D193). A document of the kind holds the name of a
5834
+ * language and a document in that language: `{ type: "lang", value: { language, doc } }`. The machine of the named
5835
+ * language prepares and evaluates the inner document, as a module of another language (COMPOSE.BOUNDARY).
5913
5836
  *
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).
5837
+ * The boundary is closed. The inner document gets no names, no capabilities and no node as `self`. Only its result
5838
+ * crosses the boundary. Thus an effect in the inner document fails with `#CAP!`, and the inner machine cannot read the
5839
+ * names of the outer document.
5916
5840
  *
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.
5841
+ * @param machines - The machine of each language, by the name that a document gives.
5842
+ * @returns The language, for `compose`.
5922
5843
  */
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 }
5844
+ function boundary(machines) {
5845
+ const plans = /* @__PURE__ */ new Map();
5846
+ const planOf = (name) => {
5847
+ let found = plans.get(name);
5848
+ if (found === void 0 && Object.hasOwn(machines, name)) {
5849
+ found = planner(machines[name]);
5850
+ plans.set(name, found);
5851
+ }
5852
+ return found;
5853
+ };
5854
+ return defineLanguage({
5855
+ name: "boundary",
5856
+ version: "1.0.0",
5857
+ world: { kinds: { lang: {
5858
+ verbs: { eval: "boundary.lang" },
5859
+ summary: "A document in another language. The machine of that language evaluates it, with no names and no capabilities."
5860
+ } } },
5861
+ code: { evaluators: { "boundary.lang": (input) => {
5862
+ const { data, place } = input;
5863
+ 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 });
5864
+ const plans = planOf(data["language"]);
5865
+ if (plans === void 0) return fail("#NAME?", `The boundary knows no language ${JSON.stringify(data["language"])}.`, { place });
5866
+ return evaluateWithin(plans(data["doc"]), makeContext(), input[RUNTIME]);
5867
+ } } }
5931
5868
  });
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
5869
  }
5870
+ // src/steps.ts
5936
5871
  /**
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.
5872
+ * This function makes a ladder of steps, and it checks the declaration (STEPS.LADDER). The list of steps must have one
5873
+ * step or more, with no name two times. The step of each construct must be a step of the list.
5940
5874
  *
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.
5875
+ * @param steps - The names of the steps, from the lowest to the highest.
5876
+ * @param constructs - The step that each construct needs.
5877
+ * @returns The ladder, frozen.
5878
+ * @throws TypeError for a declaration that is not valid, because it is a defect of the language.
5946
5879
  */
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 }
5880
+ function stepLadder(steps, constructs) {
5881
+ if (steps.length === 0) throw new TypeError("a ladder of steps needs one step or more");
5882
+ const seen = /* @__PURE__ */ new Set();
5883
+ for (const step of steps) {
5884
+ if (typeof step !== "string") throw new TypeError(`the step ${String(step)} is not a name`);
5885
+ if (seen.has(step)) throw new TypeError(`the step "${step}" is in the ladder two times`);
5886
+ seen.add(step);
5887
+ }
5888
+ 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`);
5889
+ return Object.freeze({
5890
+ steps: Object.freeze([...steps]),
5891
+ constructs: Object.freeze({ ...constructs })
5953
5892
  });
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);
5959
5893
  }
5960
5894
  /**
5961
- * This function finds a node of a trace by its path.
5895
+ * This function tells if a value is a step of a ladder. A host uses it to check its option for the highest step.
5962
5896
  *
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.
5897
+ * @param ladder - The ladder.
5898
+ * @param value - The value.
5899
+ * @returns `true` when the value is the name of a step of the ladder.
5966
5900
  */
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;
5901
+ function isStep(ladder, value) {
5902
+ return typeof value === "string" && ladder.steps.includes(value);
5980
5903
  }
5981
5904
  /**
5982
- * This function lists the nodes of a trace in the order of their start.
5905
+ * This function gives the position of a step in its ladder. The lowest step has the position 0.
5983
5906
  *
5984
- * @param trace - The root of the trace.
5985
- * @returns Each node, the root first.
5907
+ * @param ladder - The ladder.
5908
+ * @param step - The step.
5909
+ * @returns The position.
5910
+ * @throws TypeError for a name that is not a step of the ladder.
5986
5911
  */
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]);
5912
+ function stepRank(ladder, step) {
5913
+ const rank = ladder.steps.indexOf(step);
5914
+ if (rank < 0) throw new TypeError(`"${String(step)}" is not a step of the ladder. The steps are ${ladder.steps.join(", ")}`);
5915
+ return rank;
5916
+ }
5917
+ function pathOf(visit) {
5918
+ const path = [];
5919
+ for (let v = visit; v?.key !== void 0; v = v.parent) path.push(v.key);
5920
+ return path.reverse();
5921
+ }
5922
+ /**
5923
+ * This function gives the lowest step that a document needs, with the reason (STEPS.LOWEST, STEPS.REASON). The step is
5924
+ * the highest step of the constructs of its nodes. The reason is the first node in document order with that step. The
5925
+ * walk uses its own stack, thus a deep document does not overflow (STEPS.LINEAR). It visits a shared node one time,
5926
+ * and it stops at the first node with the highest step of the ladder.
5927
+ *
5928
+ * @param ladder - The ladder of the language.
5929
+ * @param walk - The construct and the child nodes of a node.
5930
+ * @param root - The root node of the document.
5931
+ * @returns The step, and the reason when the step is not the lowest step.
5932
+ */
5933
+ function stepOf(ladder, walk, root) {
5934
+ const top = ladder.steps.length - 1;
5935
+ let best = 0;
5936
+ let reason;
5937
+ const seen = /* @__PURE__ */ new Set();
5938
+ const todo = [{
5939
+ node: root,
5940
+ key: void 0,
5941
+ parent: void 0
5942
+ }];
5943
+ for (let visit = todo.pop(); visit !== void 0; visit = todo.pop()) {
5944
+ const { node } = visit;
5945
+ if (typeof node === "object" && node !== null) {
5946
+ if (seen.has(node)) continue;
5947
+ seen.add(node);
5948
+ }
5949
+ const construct = walk.construct(node);
5950
+ const step = construct === void 0 || !Object.hasOwn(ladder.constructs, construct) ? void 0 : ladder.constructs[construct];
5951
+ const rank = step === void 0 ? 0 : ladder.steps.indexOf(step);
5952
+ if (rank > best) {
5953
+ best = rank;
5954
+ reason = {
5955
+ construct,
5956
+ step,
5957
+ path: pathOf(visit),
5958
+ node
5959
+ };
5960
+ if (best === top) break;
5961
+ }
5962
+ const kids = [...walk.children(node)];
5963
+ for (let i = kids.length - 1; i >= 0; i--) {
5964
+ const [key, child] = kids[i];
5965
+ todo.push({
5966
+ node: child,
5967
+ key,
5968
+ parent: visit
5969
+ });
5970
+ }
5994
5971
  }
5995
- return out.sort((a, b) => a.enter - b.enter);
5972
+ const step = ladder.steps[best];
5973
+ return reason === void 0 ? { step } : {
5974
+ step,
5975
+ reason
5976
+ };
5996
5977
  }
5997
5978
  /**
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.
5979
+ * This function compares the step of a document with the highest step that the host accepts (STEPS.MAX). The limit
5980
+ * changes only which documents the host accepts. The language evaluates an accepted document as before, thus a limit
5981
+ * does not change a value.
6000
5982
  *
6001
- * @param trace - The root of the trace.
6002
- * @returns The errors, in the order of their start.
5983
+ * @param ladder - The ladder of the language.
5984
+ * @param need - The step of the document, from `stepOf`.
5985
+ * @param maxStep - The highest step that the host accepts.
5986
+ * @returns `undefined` when the host accepts the document, or the refusal that names the needed step.
5987
+ * @throws TypeError when `maxStep` or the step of `need` is not a step of the ladder.
6003
5988
  */
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);
5989
+ function checkStep(ladder, need, maxStep) {
5990
+ const limit = stepRank(ladder, maxStep);
5991
+ if (stepRank(ladder, need.step) <= limit) return void 0;
5992
+ const head = `the document needs the step ${need.step}, and the host accepts the steps up to ${maxStep}`;
5993
+ const reason = need.reason;
5994
+ if (reason === void 0) return {
5995
+ needed: need.step,
5996
+ maxStep,
5997
+ message: head
5998
+ };
5999
+ const where = reason.path.length === 0 ? "at the root" : `at the path ${JSON.stringify(reason.path)}`;
6000
+ return {
6001
+ needed: need.step,
6002
+ maxStep,
6003
+ reason,
6004
+ message: `${head}. The construct "${reason.construct}" ${where} needs the step ${reason.step}`
6005
+ };
6006
+ }
6007
+ // src/classify.ts
6008
+ function isStrictSuperset(larger, smaller) {
6009
+ return larger.length > smaller.length && smaller.every((name) => larger.includes(name));
6010
+ }
6011
+ /**
6012
+ * This function proposes a kind for a value without a type, from the fields that the value has.
6013
+ * A shape applies when the value has each field of the shape. The most specific shapes are the ones that
6014
+ * no other applicable shape contains. A host uses a classifier when data comes in, and then tags the data.
6015
+ * The ladder does not call a classifier.
6016
+ *
6017
+ * @param shapes - The shapes to examine.
6018
+ * @param value - The value without a type.
6019
+ * @returns The proposed kind, or an error with the candidates.
6020
+ */
6021
+ function classify(shapes, value) {
6022
+ const applicable = isRecord(value) ? shapes.filter((shape) => shape.fields.every((name) => field(value, name) !== void 0)) : [];
6023
+ const best = applicable.filter((shape) => !applicable.some((other) => isStrictSuperset(other.fields, shape.fields)));
6024
+ const candidates = best.map((shape) => shape.name);
6025
+ const only = best.length === 1 ? best[0] : void 0;
6026
+ if (only !== void 0) return {
6027
+ kind: only.kind,
6028
+ candidates
6029
+ };
6030
+ return {
6031
+ candidates,
6032
+ error: best.length === 0 ? "no-match" : "ambiguous"
6033
+ };
6034
+ }
6035
+ /**
6036
+ * This function puts a value in an envelope with a type. The value does not change.
6037
+ *
6038
+ * @param value - The value.
6039
+ * @param kind - The name of the kind.
6040
+ * @returns The envelope.
6041
+ */
6042
+ function tag(value, kind) {
6043
+ return typed(kind, value);
6006
6044
  }
6007
6045
  // src/stdlib.ts
6008
6046
  /**
@@ -12358,7 +12396,9 @@ function formulaCode(profile) {
12358
12396
  const level = (clock.applying ?? 0) + 1;
12359
12397
  if (level > limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
12360
12398
  rt.spend?.(1);
12399
+ const root = clock.top ?? clock;
12361
12400
  clock.applying = level;
12401
+ root.active = (root.active ?? 0) + 1;
12362
12402
  try {
12363
12403
  const scope = { ...ctx.names };
12364
12404
  names.forEach((name, index) => setOwn$2(scope, name, args[index]));
@@ -12370,6 +12410,7 @@ function formulaCode(profile) {
12370
12410
  return result.value;
12371
12411
  } finally {
12372
12412
  clock.applying = level - 1;
12413
+ root.active = (root.active ?? 1) - 1;
12373
12414
  }
12374
12415
  };
12375
12416
  Object.defineProperty(closure, CLOSURE$3, { value: { params: names } });
@@ -13185,7 +13226,7 @@ function evaluateRoot(machine, doc, context, options, outer, meter) {
13185
13226
  */
13186
13227
  function spend(env, points) {
13187
13228
  const meter = env.meter;
13188
- if (meter.ended && env.applying === 0) meter.spent = 0;
13229
+ if (meter.ended && meter.active === 0) meter.spent = 0;
13189
13230
  meter.spent += points;
13190
13231
  if (meter.spent > env.maxWork) throw new Failure(workFailure(env.maxWork));
13191
13232
  }
@@ -13236,7 +13277,8 @@ function envOf(machine, options, running, root, outer, meter) {
13236
13277
  maxWork: machine.maxWork ?? 2e5,
13237
13278
  meter: meter ?? {
13238
13279
  spent: 0,
13239
- ended: false
13280
+ ended: false,
13281
+ active: 0
13240
13282
  },
13241
13283
  nested: meter !== void 0,
13242
13284
  reading: outer ?? (options.reads === void 0 ? void 0 : {
@@ -13922,13 +13964,15 @@ function formulaDefinitions(profile = {}) {
13922
13964
  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
13965
  const names = params;
13924
13966
  const body = partNamed$1(parts, "body");
13925
- const clock = activeEnvs[activeEnvs.length - 1] ?? {
13967
+ const maker = activeEnvs[activeEnvs.length - 1];
13968
+ const clock = maker ?? {
13926
13969
  applying: 0,
13927
13970
  maxDepth: 1e3,
13928
13971
  maxWork: 2e5,
13929
13972
  meter: {
13930
13973
  spent: 0,
13931
- ended: false
13974
+ ended: false,
13975
+ active: 0
13932
13976
  }
13933
13977
  };
13934
13978
  const limit = Math.ceil(clock.maxDepth / 4);
@@ -13936,18 +13980,21 @@ function formulaDefinitions(profile = {}) {
13936
13980
  if (clock.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
13937
13981
  spend(clock, 1);
13938
13982
  clock.applying += 1;
13983
+ clock.meter.active += 1;
13939
13984
  try {
13940
13985
  const scope = {};
13941
13986
  for (const key of Object.keys(context.names)) setField$2(scope, key, context.names[key]);
13942
13987
  names.forEach((name, index) => setField$2(scope, name, args[index]));
13943
- const result = body.evaluate({
13988
+ const scoped = {
13944
13989
  ...context,
13945
13990
  names: scope
13946
- });
13991
+ };
13992
+ const result = maker === void 0 ? body.evaluate(scoped) : within(maker, () => body.evaluate(scoped));
13947
13993
  if (!result.ok) throw new Failure(result.error);
13948
13994
  return result.value;
13949
13995
  } finally {
13950
13996
  clock.applying -= 1;
13997
+ clock.meter.active -= 1;
13951
13998
  }
13952
13999
  };
13953
14000
  Object.defineProperty(closure, CLOSURE$2, { value: { params: names } });
@@ -14444,6 +14491,11 @@ function apply(p, c, target, args) {
14444
14491
  }
14445
14492
  const limit = Math.ceil(p.maxDepth / 4);
14446
14493
  if (c.applying >= limit) return back(c, fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`));
14494
+ p.work += 1;
14495
+ if (p.work > p.maxWork) return back(c, {
14496
+ ok: false,
14497
+ error: workFailure(p.maxWork)
14498
+ });
14447
14499
  pushed(c, {
14448
14500
  f: "return",
14449
14501
  place: closure.place.concat(closure.body.path)
@@ -14470,6 +14522,9 @@ function hostClosure(p, value, closure) {
14470
14522
  const fn = (...args) => {
14471
14523
  const limit = Math.ceil(p.maxDepth / 4);
14472
14524
  if (p.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
14525
+ p.work = (p.ended && p.applying === 0 ? 0 : p.work) + 1;
14526
+ if (p.work > p.maxWork) throw new Failure(workFailure(p.maxWork));
14527
+ const before = p.applying;
14473
14528
  p.applying += 1;
14474
14529
  try {
14475
14530
  const place = closure.place.concat(closure.body.path);
@@ -14486,7 +14541,7 @@ function hostClosure(p, value, closure) {
14486
14541
  if (!end.result.ok) throw new Failure(end.result.error);
14487
14542
  return forHost(p, end, end.result.value);
14488
14543
  } finally {
14489
- p.applying -= 1;
14544
+ p.applying = before;
14490
14545
  }
14491
14546
  };
14492
14547
  Object.defineProperty(fn, CLOSURE$1, { value: { params: closure.params } });
@@ -14817,7 +14872,7 @@ function cause(p, ctx, kind, payload, place) {
14817
14872
  const count = counts.get(at) ?? 0;
14818
14873
  counts.set(at, count + 1);
14819
14874
  const effect = {
14820
- index: effects.length,
14875
+ index: p.before + effects.length,
14821
14876
  kind: text,
14822
14877
  path: keys,
14823
14878
  payload,
@@ -14923,7 +14978,8 @@ function evaluateDoc(p, c) {
14923
14978
  } catch (error) {
14924
14979
  return back(c, thrown(error, `the evaluator ${name}`));
14925
14980
  }
14926
- const defined = own$1(p.definitions.evaluators, name);
14981
+ const standard = code === own$1(STD_EVALUATORS, name) ? own$1(STD_DEFINITIONS.evaluators, name) : void 0;
14982
+ const defined = own$1(p.definitions.evaluators, name) ?? standard;
14927
14983
  if (defined !== void 0) return hostEvaluator(p, c, name, defined, doc, keys, read.data, read.slots, site);
14928
14984
  return back(c, fail("#NOEVAL", `The stepper has no definition of the compiled evaluator ${name}.`));
14929
14985
  }
@@ -15080,7 +15136,11 @@ function programOf(machine, options) {
15080
15136
  effects: options.effects ?? [],
15081
15137
  perform: options.perform,
15082
15138
  counts: /* @__PURE__ */ new Map(),
15083
- applying: 0
15139
+ before: 0,
15140
+ applying: 0,
15141
+ maxWork: machine.maxWork ?? 2e5,
15142
+ work: 0,
15143
+ ended: false
15084
15144
  };
15085
15145
  }
15086
15146
  /**
@@ -15136,10 +15196,21 @@ function stepperNext(machine, configuration, options = {}) {
15136
15196
  };
15137
15197
  else stack[stack.length - 1] = { ...top };
15138
15198
  }
15139
- return advance(programOf(machine, options), {
15199
+ const p = programOf(machine, options);
15200
+ p.work = configuration.work ?? 0;
15201
+ for (const [at, count] of Object.entries(configuration.counts ?? {})) p.counts.set(at, count);
15202
+ p.before = options.effects === void 0 ? configuration.effected ?? 0 : 0;
15203
+ const next = advance(p, {
15140
15204
  ...configuration,
15141
15205
  stack
15142
15206
  });
15207
+ const effected = p.before + p.effects.length;
15208
+ return {
15209
+ ...next,
15210
+ ...p.work === 0 ? {} : { work: p.work },
15211
+ ...p.counts.size === 0 ? {} : { counts: Object.fromEntries(p.counts) },
15212
+ ...effected === 0 ? {} : { effected }
15213
+ };
15143
15214
  }
15144
15215
  /**
15145
15216
  * This function evaluates a document with an explicit stack (K95, D158). It gives the result of `reference` for each
@@ -15157,6 +15228,7 @@ function stepper(machine, doc, context = makeContext(), options = {}) {
15157
15228
  const p = programOf(machine, options);
15158
15229
  try {
15159
15230
  const end = drive$1(p, stepperStart(machine, doc, context, options));
15231
+ p.ended = true;
15160
15232
  return end.result.ok ? ok(forHost(p, end, end.result.value)) : end.result;
15161
15233
  } catch (error) {
15162
15234
  return placed(thrown(error, "the stepper"), []);
@@ -18908,7 +18980,10 @@ function generate(world, options) {
18908
18980
  value
18909
18981
  };
18910
18982
  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) };
18983
+ if (options.own !== void 0 && options.own.length > 0 && rng.chance(.03)) {
18984
+ const code = rng.pick(options.own);
18985
+ if ((kindOf(type)?.scope ?? []).length === 0) out["own"] = { eval: code };
18986
+ }
18912
18987
  return out;
18913
18988
  };
18914
18989
  /**
@@ -22556,6 +22631,6 @@ function samplesAt(values, closed, depth) {
22556
22631
  function typeFromSamples(values, options = {}) {
22557
22632
  return samplesAt(values, options.closed === true, 0);
22558
22633
  }
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 };
22634
+ 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
22635
 
22561
22636
  //# sourceMappingURL=index.js.map