@mark1russell7/coeval 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/doc.ts
1
+ // src/doc.ts
2
2
  /** The keys that an envelope can have. */
3
3
  const ENVELOPE_KEYS = [
4
4
  "type",
@@ -240,8 +240,7 @@ function equalWith(a, b, rule) {
240
240
  }
241
241
  return true;
242
242
  }
243
- //#endregion
244
- //#region src/errors.ts
243
+ // src/errors.ts
245
244
  /**
246
245
  * This function makes a result with a value.
247
246
  *
@@ -354,8 +353,7 @@ function describe(value) {
354
353
  return "(a value without a text)";
355
354
  }
356
355
  }
357
- //#endregion
358
- //#region src/world.ts
356
+ // src/world.ts
359
357
  /**
360
358
  * This function gives the type of a bare equation of a kind (D42). It is the type `of` of the shape of its parts, or
361
359
  * else the type `of` of the shape `rest` of a record. The plan, the reference and `check` read it with this one function.
@@ -568,8 +566,7 @@ function kindDocument(name, kind) {
568
566
  function looksLikeKind(value) {
569
567
  return isRecord(value) && isRecord(field(value, "verbs"));
570
568
  }
571
- //#endregion
572
- //#region src/types.ts
569
+ // src/types.ts
573
570
  /**
574
571
  * The domains of the kernel. `unknown` and `never` are not domains: they are the top and the bottom of the types.
575
572
  * A machine that does not name one of these domains gets it from this table.
@@ -577,18 +574,22 @@ function looksLikeKind(value) {
577
574
  const STD_DOMAINS = {
578
575
  null: {
579
576
  is: (value) => value === null,
577
+ values: [null],
580
578
  summary: "The value null."
581
579
  },
582
580
  undefined: {
583
581
  is: (value) => value === void 0,
582
+ values: [void 0],
584
583
  summary: "The value undefined. A document holds it as the extension ext.undefined."
585
584
  },
586
585
  bool: {
587
586
  is: (value) => typeof value === "boolean",
587
+ values: [true, false],
588
588
  summary: "A truth value: true or false."
589
589
  },
590
590
  number: {
591
591
  is: (value) => typeof value === "number",
592
+ samples: [0, -1],
592
593
  summary: "A number of the host, also NaN, an infinity and -0."
593
594
  },
594
595
  text: {
@@ -598,6 +599,12 @@ const STD_DOMAINS = {
598
599
  };
599
600
  /** The deepest term that a value type can have. A deeper term reads as `unknown`, thus a check stays total. */
600
601
  const MAX_TYPE_DEPTH = 256;
602
+ /** The most values that the finite rule of `fits` reads for one type (TYPE.FITS-FINITE). A type with more values is not finite for the rule. */
603
+ const MAX_FINITE_VALUES = 64;
604
+ /** The most domains of covers that the cover rule of `fits` tests for one type (TYPE.FITS-COVER). A larger test gives `false`. */
605
+ const MAX_COVER_STEPS = 64;
606
+ /** The most records that one split of `fits` builds, with each split inside its work (TYPE.FITS-PATH, D89). A larger split gives `false`. */
607
+ const MAX_SPLIT_RECORDS = 64;
601
608
  /** The keys that each term permits beside its own key. */
602
609
  const TERM_KEYS = {
603
610
  list: ["list"],
@@ -620,7 +627,7 @@ function domainOf(name, domains) {
620
627
  return typeof found === "object" && found !== null && typeof found.is === "function" ? found : void 0;
621
628
  }
622
629
  /** This function gives the term key of a record, when the record has exactly one term key and no other key. */
623
- function termOf$1(term) {
630
+ function termOf$2(term) {
624
631
  const keys = Object.keys(term);
625
632
  const own = keys.filter((key) => TERMS.includes(key));
626
633
  if (own.length !== 1) return void 0;
@@ -638,7 +645,7 @@ function formOf(type, domains) {
638
645
  };
639
646
  }
640
647
  if (!isRecord(type)) return TOP;
641
- const term = termOf$1(type);
648
+ const term = termOf$2(type);
642
649
  if (term === "list") return {
643
650
  t: "list",
644
651
  item: type["list"]
@@ -745,39 +752,419 @@ function member(value, type, domains) {
745
752
  return memberAt(value, type, domains, 0);
746
753
  }
747
754
  /** This function tells if the record type `a` fits the record type `b`: width, closed records and optional fields. */
748
- function recordFits(a, b, domains, depth, gradual) {
755
+ function recordFits(a, b, domains, depth, gradual, budget) {
749
756
  if (b.closed && (!a.closed || Object.keys(a.fields).some((key) => !Object.hasOwn(b.fields, key)))) return false;
750
757
  for (const key of Object.keys(b.fields)) {
751
758
  const want = b.fields[key];
752
759
  const needed = !b.optional.has(key);
753
760
  if (Object.hasOwn(a.fields, key)) {
754
761
  if (needed && a.optional.has(key)) return false;
755
- if (!fitsAt(a.fields[key], want, domains, depth, gradual)) return false;
762
+ if (!fitsAt(a.fields[key], want, domains, depth, gradual, true, budget)) return false;
756
763
  } else if (needed) return false;
757
764
  else if (!a.closed && formOf(want, domains).t !== "top") return false;
758
765
  }
759
766
  return true;
760
767
  }
768
+ /** This function adds a value to a list of distinct values, by `docEquals`. */
769
+ function addValue(out, value) {
770
+ if (!out.some((item) => docEquals(item, value))) out.push(value);
771
+ }
772
+ /**
773
+ * This function gives the values of a base type with a finite list. It reads the list of the first domain of the line
774
+ * with at most 64 values, and it keeps only the members of the type. Thus the list of a parent serves each domain under it.
775
+ */
776
+ function baseValues(name, domains) {
777
+ const domain = domainOf(name, domains);
778
+ if (domain === void 0) return void 0;
779
+ const line = Array.isArray(domain.values) || !Array.isArray(domain.under) ? [name] : lineOf(name, domains);
780
+ for (const each of line) {
781
+ const values = domainOf(each, domains)?.values;
782
+ if (!Array.isArray(values) || values.length > MAX_FINITE_VALUES) continue;
783
+ const out = [];
784
+ for (let index = 0; index < values.length; index += 1) if (inDomain(values[index], name, domains)) addValue(out, values[index]);
785
+ return out;
786
+ }
787
+ }
788
+ /** This function gives a copy of a record with one more field. */
789
+ function withField(record, key, value) {
790
+ const out = {};
791
+ for (const name of Object.keys(record)) setOwn$6(out, name, record[name]);
792
+ setOwn$6(out, key, value);
793
+ return out;
794
+ }
795
+ /**
796
+ * This function gives the members of a record type, when they are few. A record with a needed field without members
797
+ * has no members. Only a closed record with a finite list for each field has a finite list.
798
+ */
799
+ function recordValues(form, domains, depth) {
800
+ let out = [{}];
801
+ let finite = form.closed;
802
+ for (const key of Object.keys(form.fields)) {
803
+ const values = valuesOf$1(form.fields[key], domains, depth);
804
+ const optional = form.optional.has(key);
805
+ if (values === void 0) {
806
+ finite = false;
807
+ continue;
808
+ }
809
+ if (values.length === 0 && !optional) return [];
810
+ if (!finite) continue;
811
+ if (out.length * (values.length + (optional ? 1 : 0)) > MAX_FINITE_VALUES) {
812
+ finite = false;
813
+ continue;
814
+ }
815
+ out = out.flatMap((record) => [...optional ? [record] : [], ...values.map((value) => withField(record, key, value))]);
816
+ }
817
+ return finite ? out : void 0;
818
+ }
819
+ /**
820
+ * This function gives a list of the members of a type, when the type has at most 64 members (TYPE.FITS-FINITE). Each
821
+ * other type gives `undefined`. Such a type is `unknown`, a base type without a finite list, or a function type. A
822
+ * list that can hold an item and an open record with members are also such types.
823
+ */
824
+ function valuesOf$1(type, domains, depth) {
825
+ if (depth > MAX_TYPE_DEPTH) return void 0;
826
+ const form = formOf(type, domains);
827
+ const next = depth + 1;
828
+ switch (form.t) {
829
+ case "bottom": return [];
830
+ case "base": return baseValues(form.name, domains);
831
+ case "list": return valuesOf$1(form.item, domains, next)?.length === 0 ? [[]] : void 0;
832
+ case "record": return recordValues(form, domains, next);
833
+ case "one":
834
+ case "union": {
835
+ const out = [];
836
+ const items = form.t === "one" ? form.values : form.members;
837
+ for (const item of items) {
838
+ const values = form.t === "one" ? [item] : valuesOf$1(item, domains, next);
839
+ if (values === void 0) return void 0;
840
+ for (const value of values) addValue(out, value);
841
+ if (out.length > MAX_FINITE_VALUES) return void 0;
842
+ }
843
+ return out;
844
+ }
845
+ default: return;
846
+ }
847
+ }
848
+ /** This function gives the members of a type at one depth, for `membersOf`. */
849
+ function membersAt(type, domains, samples, depth) {
850
+ const finite = valuesOf$1(type, domains, depth);
851
+ if (finite !== void 0) return finite;
852
+ const form = formOf(type, domains);
853
+ if (form.t !== "union" || depth > MAX_TYPE_DEPTH) return samples.filter((sample) => member(sample, type, domains));
854
+ const out = [];
855
+ for (const item of form.members) for (const value of membersAt(item, domains, samples, depth + 1)) addValue(out, value);
856
+ return out;
857
+ }
858
+ /**
859
+ * This function gives members of a type for a test of a declaration (D86). A type with at most 64 members gives each
860
+ * member, from the lists `values` of its domains (TYPE.FITS-FINITE). A union gives the members of each of its types.
861
+ * Each other type gives the samples that are its members. The samples of the domains come after the given samples (D99).
862
+ * The kernel does not export the function.
863
+ *
864
+ * @param type - The type.
865
+ * @param domains - The domains of the machine.
866
+ * @param samples - The values to test when the type has no full list of members.
867
+ * @returns Distinct members of the type.
868
+ */
869
+ function membersOf(type, domains, samples) {
870
+ return membersAt(type, domains, withDomainSamples(samples, domains), 0);
871
+ }
872
+ /**
873
+ * This function adds the samples of the domains to a palette (D99). It reads the list `samples` of each domain of the
874
+ * table and of each standard domain that the table does not replace. The result holds each value one time.
875
+ */
876
+ function withDomainSamples(palette, domains) {
877
+ const out = [];
878
+ for (const value of palette) addValue(out, value);
879
+ const names = /* @__PURE__ */ new Set([...Object.keys(STD_DOMAINS), ...domains === void 0 ? [] : Object.keys(domains)]);
880
+ for (const name of names) {
881
+ const samples = domainOf(name, domains)?.samples;
882
+ if (Array.isArray(samples)) for (const value of samples) addValue(out, value);
883
+ }
884
+ return out;
885
+ }
886
+ /**
887
+ * This function finds the false covers of a language from samples (D94). A cover is false when a sample of the covered
888
+ * domain is in no domain of the cover. The function tests each valid cover of each domain of the table. It ignores a
889
+ * cover that does not count by the line rule of D85, because `fits` ignores it too. It also ignores a sample outside
890
+ * the covered domain.
891
+ *
892
+ * The samples of the domains come after the given samples (D99). `conforms` and a test of `fits` use the function. The
893
+ * kernel does not export it.
894
+ *
895
+ * @param domains - The domains of the language, by their names.
896
+ * @param samples - The samples of each covered domain, by the name of the domain.
897
+ * @returns Each sample that breaks a cover, in the order of the domains, the covers and the samples.
898
+ */
899
+ function falseCovers(domains, samples) {
900
+ const out = [];
901
+ for (const [name, domain] of Object.entries(domains)) {
902
+ const covers = domain.covers;
903
+ if (!Array.isArray(covers)) continue;
904
+ const values = withDomainSamples((Object.hasOwn(samples, name) ? samples[name] : void 0) ?? [], domains);
905
+ for (const cover of covers) {
906
+ if (!validCover(name, cover, domains)) continue;
907
+ for (const value of values) if (member(value, name, domains) && !cover.some((part) => member(value, part, domains))) out.push({
908
+ domain: name,
909
+ cover,
910
+ value
911
+ });
912
+ }
913
+ }
914
+ return out;
915
+ }
916
+ /** This function holds the rules of the shapes of `fits`: base types, lists, records and functions. */
917
+ function shapeFits(a, b, domains, next, gradual, budget) {
918
+ if (a.t === "base") return b.t === "base" && lineOf(a.name, domains).has(b.name);
919
+ if (a.t === "list") return b.t === "list" && fitsAt(a.item, b.item, domains, next, gradual, true, budget);
920
+ if (a.t === "record") return b.t === "record" && recordFits(a, b, domains, next, gradual, budget);
921
+ if (a.t !== "fn" || b.t !== "fn" || a.params.length > b.params.length) return false;
922
+ return a.params.every((param, index) => fitsAt(b.params[index], param, domains, next, gradual, true, budget)) && fitsAt(a.to, b.to, domains, next, gradual, true, budget);
923
+ }
761
924
  /**
762
925
  * This function is the relation `fits` at one depth of two types. The order of its tests is the order of the rules of
763
926
  * `fits`. Without `gradual`, `unknown` is only the top: it fits only `unknown`. The join uses this strict form.
927
+ *
928
+ * When the rules of the shapes refuse a type with few members, the finite rule tests each member (TYPE.FITS-FINITE).
929
+ * The cover rule and the split rule come after it. Without `finite`, the call skips these three rules. The members of
930
+ * a union in `expected` get such calls, because the call for the union tests `found` against the full union.
931
+ *
932
+ * The budget is the budget of the outer split, when the call is part of the work of a split (TYPE.FITS-PATH, D89).
764
933
  */
765
- function fitsAt(found, expected, domains, depth, gradual = true) {
934
+ function fitsAt(found, expected, domains, depth, gradual = true, finite = true, budget) {
766
935
  if (depth > MAX_TYPE_DEPTH) return true;
767
936
  const a = formOf(found, domains);
768
937
  const b = formOf(expected, domains);
769
938
  const next = depth + 1;
770
939
  if (b.t === "top" || a.t === "bottom") return true;
771
940
  if (a.t === "top") return gradual;
772
- if (a.t === "union") return a.members.every((item) => fitsAt(item, expected, domains, next, gradual));
941
+ if (a.t === "union") return a.members.every((item) => fitsAt(item, expected, domains, next, gradual, true, budget));
773
942
  if (a.t === "one") return a.values.every((item) => memberAt(item, expected, domains, next));
774
- if (b.t === "bottom") return false;
775
- if (b.t === "union") return b.members.some((item) => fitsAt(found, item, domains, next, gradual));
776
- if (a.t === "base") return b.t === "base" && lineOf(a.name, domains).has(b.name);
777
- if (a.t === "list") return b.t === "list" && fitsAt(a.item, b.item, domains, next, gradual);
778
- if (a.t === "record") return b.t === "record" && recordFits(a, b, domains, next, gradual);
779
- if (b.t !== "fn" || a.params.length > b.params.length) return false;
780
- return a.params.every((param, index) => fitsAt(b.params[index], param, domains, next, gradual)) && fitsAt(a.to, b.to, domains, next, gradual);
943
+ if (b.t === "union" ? b.members.some((item) => fitsAt(found, item, domains, next, gradual, false, budget)) : b.t !== "bottom" && shapeFits(a, b, domains, next, gradual, budget)) return true;
944
+ if (!finite || a.t === "fn") return false;
945
+ const values = valuesOf$1(found, domains, next);
946
+ if (values !== void 0) return values.every((value) => memberAt(value, expected, domains, next));
947
+ if (a.t === "base") return (b.t === "union" || b.t === "one") && lineCovered(a.name, expected, domains, depth, gradual, void 0);
948
+ return a.t === "record" && (b.t === "union" || b.t === "one" && a.closed) && splitFits(found, a, expected, domains, depth, gradual, budget);
949
+ }
950
+ /**
951
+ * This function is the cover rule of `fits` (TYPE.FITS-COVER, D85). A base type fits when a domain of its line has a
952
+ * cover, and each domain of the cover fits `expected`. The function makes the state at the first domain with covers.
953
+ */
954
+ function lineCovered(name, expected, domains, depth, gradual, state) {
955
+ let now = state;
956
+ for (const each of lineOf(name, domains)) {
957
+ if (!Array.isArray(domainOf(each, domains)?.covers)) continue;
958
+ now ??= {
959
+ held: /* @__PURE__ */ new Map(),
960
+ left: MAX_COVER_STEPS
961
+ };
962
+ if (covered(each, expected, domains, depth, gradual, now)) return true;
963
+ }
964
+ return false;
965
+ }
966
+ /**
967
+ * This function tells if a cover of one domain holds the domain in `expected`. A cover that is empty, or that names
968
+ * the domain or a name that is not under it, does not count. Each domain of a cover costs one step, and the rule
969
+ * stops after 64 steps.
970
+ */
971
+ function covered(name, expected, domains, depth, gradual, state) {
972
+ const known = state.held.get(name);
973
+ if (known !== void 0) return known;
974
+ state.held.set(name, false);
975
+ const covers = domainOf(name, domains)?.covers;
976
+ if (!Array.isArray(covers)) return false;
977
+ for (const cover of covers) {
978
+ if (!Array.isArray(cover) || cover.length === 0) continue;
979
+ let held = true;
980
+ for (const part of cover) {
981
+ state.left -= 1;
982
+ if (state.left < 0) return false;
983
+ if (typeof part !== "string" || part === name || !lineOf(part, domains).has(name) || !partFits(part, expected, domains, depth, gradual, state)) {
984
+ held = false;
985
+ break;
986
+ }
987
+ }
988
+ if (held) {
989
+ state.held.set(name, true);
990
+ return true;
991
+ }
992
+ }
993
+ return false;
994
+ }
995
+ /** This function tells if a domain of a cover fits `expected`. It tries the rules of the shapes, the finite rule and its own covers. */
996
+ function partFits(part, expected, domains, depth, gradual, state) {
997
+ if (fitsAt(part, expected, domains, depth, gradual, false)) return true;
998
+ const values = valuesOf$1(part, domains, depth + 1);
999
+ if (values !== void 0) return values.every((value) => memberAt(value, expected, domains, depth + 1));
1000
+ return lineCovered(part, expected, domains, depth, gradual, state);
1001
+ }
1002
+ /**
1003
+ * This function gives the fields that the split rule can split, in the order of the split (TYPE.FITS-PATH, D89). The
1004
+ * fields of the record come first, in the order of the keys. Then the paths of the next depth follow, and so on. A path
1005
+ * goes into a field only when the field is a record without a finite list. A field with a finite list of two or more
1006
+ * cases is a split. An optional field also has the absent case.
1007
+ *
1008
+ * The type splits follow each value split, in the same order (D90). A base type with a valid cover in its line splits
1009
+ * into the domains of a cover, and it tries each valid cover (D102). A union without a finite list splits into its
1010
+ * members. The prefix is the path of `a`.
1011
+ */
1012
+ function splitsOf(a, domains, depth, prefix = []) {
1013
+ const out = [];
1014
+ const later = [];
1015
+ let level = [{
1016
+ path: prefix,
1017
+ form: a
1018
+ }];
1019
+ for (let at = depth + 1; level.length > 0 && at <= MAX_TYPE_DEPTH; at += 1) {
1020
+ const deeper = [];
1021
+ for (const { path, form } of level) for (const key of Object.keys(form.fields)) {
1022
+ const values = valuesOf$1(form.fields[key], domains, at);
1023
+ const optional = form.optional.has(key);
1024
+ if (values !== void 0) {
1025
+ if (values.length + (optional ? 1 : 0) > 1) out.push({
1026
+ path: [...path, key],
1027
+ values,
1028
+ optional
1029
+ });
1030
+ continue;
1031
+ }
1032
+ const inner = formOf(form.fields[key], domains);
1033
+ if (inner.t === "record") deeper.push({
1034
+ path: [...path, key],
1035
+ form: inner
1036
+ });
1037
+ else if (inner.t === "union") later.push({
1038
+ path: [...path, key],
1039
+ types: inner.members,
1040
+ optional
1041
+ });
1042
+ else if (inner.t === "base") {
1043
+ const covers = coversOf(inner.name, domains, false);
1044
+ if (covers.length > 0) later.push({
1045
+ path: [...path, key],
1046
+ covers,
1047
+ optional
1048
+ });
1049
+ }
1050
+ }
1051
+ level = deeper;
1052
+ }
1053
+ return later.length === 0 ? out : [...out, ...later];
1054
+ }
1055
+ /** This function tells if a cover of a domain is valid by the line rule of D85. Such a cover is not empty, and each name in it is a domain under the domain. */
1056
+ function validCover(name, cover, domains) {
1057
+ return Array.isArray(cover) && cover.length > 0 && cover.every((part) => typeof part === "string" && part !== name && lineOf(part, domains).has(name));
1058
+ }
1059
+ /**
1060
+ * This function gives the valid covers of a base type for a type split (D90, D102). The order is the order of the line,
1061
+ * then the order of the covers of each domain. With `own`, only the domain of the type itself counts.
1062
+ */
1063
+ function coversOf(name, domains, own) {
1064
+ const out = [];
1065
+ for (const each of own ? [name] : lineOf(name, domains)) {
1066
+ const covers = domainOf(each, domains)?.covers;
1067
+ if (!Array.isArray(covers)) continue;
1068
+ for (const cover of covers) if (validCover(each, cover, domains)) out.push(cover);
1069
+ }
1070
+ return out;
1071
+ }
1072
+ /**
1073
+ * This function gives the splits of a case of a type split, at the path of the case (D90). A case with a finite list
1074
+ * splits by its members. A base type splits by a cover of its own domain, because the covers of its parents hold it
1075
+ * already. A union splits by its members, and a record splits by the paths into its fields.
1076
+ */
1077
+ function againOf(type, path, domains, depth) {
1078
+ const at = depth + path.length;
1079
+ const values = valuesOf$1(type, domains, at);
1080
+ if (values !== void 0) return values.length > 1 ? [{
1081
+ path,
1082
+ values,
1083
+ optional: false
1084
+ }] : [];
1085
+ const form = formOf(type, domains);
1086
+ if (form.t === "record") return splitsOf(form, domains, at, path);
1087
+ if (form.t === "union") return [{
1088
+ path,
1089
+ types: form.members,
1090
+ optional: false
1091
+ }];
1092
+ const covers = form.t === "base" ? coversOf(form.name, domains, true) : [];
1093
+ return covers.length === 0 ? [] : [{
1094
+ path,
1095
+ covers,
1096
+ optional: false
1097
+ }];
1098
+ }
1099
+ /**
1100
+ * This function gives a copy of a record type with one field narrowed at a path. A case type replaces the field. The
1101
+ * absent case removes the field of a closed record, and it gives an optional field of type `never` in an open record.
1102
+ */
1103
+ function narrowAt(type, path, at, narrowed, domains) {
1104
+ const form = formOf(type, domains);
1105
+ const key = path[at];
1106
+ if (form.t !== "record" || key === void 0) return type;
1107
+ const last = at + 1 === path.length;
1108
+ const fields = {};
1109
+ for (const name of Object.keys(form.fields)) if (name !== key) setOwn$6(fields, name, form.fields[name]);
1110
+ else if (!last) setOwn$6(fields, name, narrowAt(form.fields[name], path, at + 1, narrowed, domains));
1111
+ else if (narrowed !== void 0) setOwn$6(fields, name, narrowed);
1112
+ else if (!form.closed) setOwn$6(fields, name, "never");
1113
+ const optional = [...form.optional].filter((name) => !last || name !== key || narrowed === void 0 && !form.closed);
1114
+ return {
1115
+ record: fields,
1116
+ ...optional.length === 0 ? {} : { optional },
1117
+ ...form.closed ? { closed: true } : {}
1118
+ };
1119
+ }
1120
+ /**
1121
+ * This function is the split rule of `fits` (TYPE.FITS-FINITE, D84, TYPE.FITS-PATH, D89). A record type fits when each
1122
+ * record of its split fits. A split takes the first field in the order of `splitsOf`. Each member of the field gives a
1123
+ * record with the field narrowed to that member. An optional field also gives a record without the field. A type split
1124
+ * narrows the field to each case type instead (TYPE.FITS-SPLIT-TYPE, D90).
1125
+ *
1126
+ * A record of the split that does not fit splits the next such field. A record of a type split first splits its case
1127
+ * again, at the same path. One budget of 64 records serves the outer split and each split inside its work, at each
1128
+ * depth. Thus nested splits do not multiply the work.
1129
+ *
1130
+ * A cover split tries each valid cover of its field until one fits (D102). Each try takes from the same budget.
1131
+ */
1132
+ function splitFits(found, a, expected, domains, depth, gradual, budget) {
1133
+ const splits = splitsOf(a, domains, depth);
1134
+ if (splits.length === 0) return false;
1135
+ return casesFit(found, a.closed, splits, 0, expected, domains, depth, gradual, budget ?? { left: MAX_SPLIT_RECORDS });
1136
+ }
1137
+ /** This function tells if each record of the split of one field fits `expected`. It splits the next field for a record that does not fit. */
1138
+ function casesFit(type, closed, splits, index, expected, domains, depth, gradual, budget) {
1139
+ const split = splits[index];
1140
+ if (split === void 0) return false;
1141
+ if (split.covers !== void 0) {
1142
+ for (const cover of split.covers) {
1143
+ const tried = [...splits];
1144
+ tried[index] = {
1145
+ path: split.path,
1146
+ types: cover,
1147
+ optional: split.optional
1148
+ };
1149
+ if (casesFit(type, closed, tried, index, expected, domains, depth, gradual, budget)) return true;
1150
+ }
1151
+ return false;
1152
+ }
1153
+ const cases = (split.values?.map((value) => ({ one: [value] })) ?? split.types ?? []).map((each) => narrowAt(type, split.path, 0, each, domains));
1154
+ if (split.optional) cases.push(narrowAt(type, split.path, 0, void 0, domains));
1155
+ for (const [at, record] of cases.entries()) {
1156
+ budget.left -= 1;
1157
+ if (budget.left < 0) return false;
1158
+ if (fitsAt(record, expected, domains, depth, gradual, false, budget)) continue;
1159
+ const values = closed ? valuesOf$1(record, domains, depth + 1) : void 0;
1160
+ if (values !== void 0) {
1161
+ if (values.every((value) => memberAt(value, expected, domains, depth + 1))) continue;
1162
+ return false;
1163
+ }
1164
+ const again = split.types !== void 0 && at < split.types.length ? againOf(split.types[at], split.path, domains, depth) : [];
1165
+ if (!casesFit(record, closed, again.length === 0 ? splits : [...again, ...splits.slice(index + 1)], again.length === 0 ? index + 1 : 0, expected, domains, depth, gradual, budget)) return false;
1166
+ }
1167
+ return true;
781
1168
  }
782
1169
  /**
783
1170
  * This function tells if each value of the type `found` can be where the type `expected` must be (TYPE.FITS). Each
@@ -794,9 +1181,35 @@ function fitsAt(found, expected, domains, depth, gradual = true) {
794
1181
  * field is `unknown`.
795
1182
  * - A function fits when it has the same or fewer parameters, each expected parameter fits its parameter, and its
796
1183
  * result fits.
797
- *
798
- * The relation is sound: a member of `found` is a member of `expected` when no `unknown` is in the types. It is not
799
- * complete. For example, `bool` does not fit `{ "one": [true, false] }`. The function does not throw.
1184
+ * - The finite rule comes after these rules (TYPE.FITS-FINITE). A type with at most 64 members fits when each member
1185
+ * is a member of `expected`. Thus `bool` fits `{ "one": [true, false] }`.
1186
+ * - A base type has few members when its domain or a parent declares `values`, as `null`, `undefined` and `bool` do.
1187
+ * A union, a `one`, a closed record of such types and a list of `never` also have few members.
1188
+ * - The cover rule comes next (TYPE.FITS-COVER, D85). A base type fits a union or a `one` when each domain of a cover
1189
+ * fits. The cover is in `covers` of a domain of its line. Each domain of a cover is under the covered
1190
+ * domain. Thus a cover of `number` by `neg` and `nonneg` gives `number` a fit against `neg | nonneg`.
1191
+ * - The split rule comes last (D84). An open record, or a closed record with more than 64 members, splits a field with
1192
+ * few members over a union. A closed record also splits over a `one`. Each record of the split narrows the field to
1193
+ * one member, and each record must fit.
1194
+ * Thus `{ "record": { "a": "bool" } }` fits a union of a record for each value of `a`.
1195
+ * - A split also narrows a field of a record in a field, by its path (TYPE.FITS-PATH, D89). The fields of the record
1196
+ * split first, then the paths of each next depth, in the order of the keys. A path goes into a record without a
1197
+ * finite list. Thus `{a: {x: bool}}` fits the union of `{a: {x: true}}` and `{a: {x: false}}`.
1198
+ * - A type split comes after each value split (TYPE.FITS-SPLIT-TYPE, D90). A field of a base type with a valid cover in
1199
+ * its line splits into the domains of a cover. A field of a union without a finite list splits into its
1200
+ * members. A case that does not fit splits again at its path, by the same rules. A base type there uses only the
1201
+ * covers of its own domain. Thus `{a: number}` fits `{a: neg} | {a: nonneg}` when `neg` and `nonneg` cover `number`.
1202
+ * - A field with more than one valid cover tries each cover until one fits (TYPE.FITS-SPLIT-COVERS, D102). The order
1203
+ * is the order of the line, then the order of the covers of each domain.
1204
+ *
1205
+ * The relation is sound: a member of `found` is a member of `expected` when no `unknown` is in the types
1206
+ * (TYPE.FITS-SOUND). The finite rule trusts `values`, and the cover rule trusts `covers`. Thus a list without a member
1207
+ * or a false cover makes the relation unsound for that domain.
1208
+ *
1209
+ * The relation is not complete. A split builds at most 64 records, with each split inside its work at each depth. The
1210
+ * failed tries of covers take from these 64 records too. A domain without `values` gets no finite rule, and
1211
+ * neither does a type with more than 64 members that is not a record. The cover rule tests at most 64 domains of
1212
+ * covers. The function does not throw.
800
1213
  *
801
1214
  * @param found - The type that a part has.
802
1215
  * @param expected - The type that the position needs.
@@ -807,7 +1220,7 @@ function fits(found, expected, domains) {
807
1220
  return fitsAt(found, expected, domains, 0);
808
1221
  }
809
1222
  /** This function sets an own field of a new record. Only the key `__proto__` needs `defineProperty`. */
810
- function setOwn$5(target, key, value) {
1223
+ function setOwn$6(target, key, value) {
811
1224
  if (key === "__proto__") Object.defineProperty(target, key, {
812
1225
  value,
813
1226
  enumerable: true,
@@ -826,10 +1239,10 @@ function joinRecords(a, b, domains, depth) {
826
1239
  const inA = Object.hasOwn(a.fields, key);
827
1240
  const inB = Object.hasOwn(b.fields, key);
828
1241
  if (inA && inB) {
829
- setOwn$5(fields, key, joinAt(a.fields[key], b.fields[key], domains, depth));
1242
+ setOwn$6(fields, key, joinAt(a.fields[key], b.fields[key], domains, depth));
830
1243
  if (a.optional.has(key) || b.optional.has(key)) optional.push(key);
831
1244
  } else if (closed) {
832
- setOwn$5(fields, key, inA ? a.fields[key] : b.fields[key]);
1245
+ setOwn$6(fields, key, inA ? a.fields[key] : b.fields[key]);
833
1246
  optional.push(key);
834
1247
  }
835
1248
  }
@@ -932,7 +1345,7 @@ function valueText$1(value) {
932
1345
  function textAt(type, depth, wrap) {
933
1346
  if (depth > MAX_TYPE_DEPTH) return "unknown";
934
1347
  if (typeof type === "string") return type;
935
- const term = isRecord(type) ? termOf$1(type) : void 0;
1348
+ const term = isRecord(type) ? termOf$2(type) : void 0;
936
1349
  if (!isRecord(type) || term === void 0) return "unknown";
937
1350
  const next = depth + 1;
938
1351
  const group = (items) => items.length === 0 ? "never" : items.length > 1 && wrap ? `(${items.join(" | ")})` : items.join(" | ");
@@ -1155,7 +1568,7 @@ function typeIssues(type, domains) {
1155
1568
  if (here !== "unknown" && here !== "never" && domainOf(here, domains) === void 0) issue(`The machine has no domain ${here}.`);
1156
1569
  continue;
1157
1570
  }
1158
- const term = isRecord(here) ? termOf$1(here) : void 0;
1571
+ const term = isRecord(here) ? termOf$2(here) : void 0;
1159
1572
  if (!isRecord(here) || term === void 0) {
1160
1573
  issue(`A value type is a text, or a record with one of the keys ${TERMS.join(", ")} and the keys that go with it.`);
1161
1574
  continue;
@@ -1211,8 +1624,7 @@ function typeIssues(type, domains) {
1211
1624
  }
1212
1625
  return issues;
1213
1626
  }
1214
- //#endregion
1215
- //#region src/merge.ts
1627
+ // src/merge.ts
1216
1628
  /** The exception of a merge with conflicts. It lists each conflict of the merge, not only the first. */
1217
1629
  var MergeError = class extends Error {
1218
1630
  conflicts;
@@ -1233,7 +1645,7 @@ function keyOf(path) {
1233
1645
  return JSON.stringify(path.map(String));
1234
1646
  }
1235
1647
  /** This function sets an own data property. An assignment to the key `__proto__` changes the prototype. */
1236
- function setOwn$4(target, key, value) {
1648
+ function setOwn$5(target, key, value) {
1237
1649
  if (key === "__proto__") Object.defineProperty(target, key, {
1238
1650
  value,
1239
1651
  enumerable: true,
@@ -1250,7 +1662,7 @@ function defined(value) {
1250
1662
  if (Array.isArray(value)) return value.map(defined);
1251
1663
  if (!isRecord(value)) return value;
1252
1664
  const out = {};
1253
- for (const key of Object.keys(value)) if (value[key] !== void 0) setOwn$4(out, key, defined(value[key]));
1665
+ for (const key of Object.keys(value)) if (value[key] !== void 0) setOwn$5(out, key, defined(value[key]));
1254
1666
  return out;
1255
1667
  }
1256
1668
  /** Two values are the same when they are equal by `docEquals`. A function and a host value are equal only to themselves. */
@@ -1259,23 +1671,39 @@ function same(a, b) {
1259
1671
  }
1260
1672
  /**
1261
1673
  * Two domains are the same when they are one object. They are also the same when they have the same test `is`,
1262
- * parents, summary and steps. Thus two languages that give one test under one name give one domain.
1674
+ * parents, summary, steps, codec, list of values, samples and covers. Thus two languages that give one test under one name give one
1675
+ * domain. Two codecs are the same when they have the same functions `encode` and `decode` (D80).
1263
1676
  */
1264
1677
  function sameDomain(a, b) {
1265
- return a === b || a.is === b.is && same(a.under ?? [], b.under ?? []) && a.summary === b.summary && same(a.steps ?? {}, b.steps ?? {});
1678
+ if (a === b) return true;
1679
+ const fields = {
1680
+ is: a.is === b.is,
1681
+ under: same(a.under ?? [], b.under ?? []),
1682
+ summary: a.summary === b.summary,
1683
+ steps: same(a.steps ?? {}, b.steps ?? {}),
1684
+ codec: same(a.codec ?? null, b.codec ?? null),
1685
+ values: same(a.values ?? null, b.values ?? null),
1686
+ samples: same(a.samples ?? null, b.samples ?? null),
1687
+ covers: same(a.covers ?? [], b.covers ?? [])
1688
+ };
1689
+ return Object.values(fields).every(Boolean);
1266
1690
  }
1267
1691
  /**
1268
- * This function makes a part of a merge that adds parents or steps to a domain of an earlier part (TYPE.PARENTS). An
1269
- * example is a domain of another language. The part reads the domain from the merge before it (`prev`). It gives a
1270
- * copy with the same test and summary, and it names `["domains", name]` in `replaces` (D17). A domain of the kernel
1271
- * that the earlier parts do not name comes from `STD_DOMAINS`.
1692
+ * This function makes a part of a merge that adds parents, steps or covers to a domain of an earlier part
1693
+ * (TYPE.PARENTS). An example is a domain of another language. The part reads the domain from the merge before it
1694
+ * (`prev`). It gives a copy with the same test, summary, codec, list of values and samples, and it names
1695
+ * `["domains", name]` in `replaces` (D17).
1696
+ * A domain of the kernel that the earlier parts do not name comes from `STD_DOMAINS`.
1697
+ *
1698
+ * An extension does not change the codec. Thus each member keeps its document (D80).
1272
1699
  *
1273
1700
  * A new parent adds its test to the domain (TYPE.MEMBER). Thus `fits` stays sound, but a value that fails the test of
1274
1701
  * the parent is no longer a member. The language that adds the parent keeps the signatures of the other language
1275
- * true. A name without a domain gives an empty part, and `typeIssues` reports each use of that name.
1702
+ * true. A new parent of a domain in a cover of another domain can make that cover false (D85). A name without a
1703
+ * domain gives an empty part, and `typeIssues` reports each use of that name.
1276
1704
  *
1277
1705
  * @param name - The name of the domain.
1278
- * @param more - The parents and the steps to add.
1706
+ * @param more - The parents, the steps and the covers to add.
1279
1707
  * @returns The part, as a function of the merge before it.
1280
1708
  */
1281
1709
  function extendDomain(name, more) {
@@ -1288,14 +1716,22 @@ function extendDomain(name, more) {
1288
1716
  ...found.steps,
1289
1717
  ...more.steps
1290
1718
  };
1291
- const domain = {
1719
+ const covers = [...found.covers ?? []];
1720
+ for (const cover of more.covers ?? []) if (!covers.some((each) => same(each, cover))) covers.push([...cover]);
1721
+ const fields = {
1292
1722
  is: found.is,
1293
- ...under.length === 0 ? {} : { under },
1294
- ...found.summary === void 0 ? {} : { summary: found.summary },
1295
- ...Object.keys(steps).length === 0 ? {} : { steps }
1723
+ under: under.length === 0 ? void 0 : under,
1724
+ summary: found.summary,
1725
+ steps: Object.keys(steps).length === 0 ? void 0 : steps,
1726
+ codec: found.codec,
1727
+ values: found.values,
1728
+ samples: found.samples,
1729
+ covers: covers.length === 0 ? void 0 : covers
1296
1730
  };
1731
+ const domain = {};
1732
+ for (const [key, value] of Object.entries(fields)) if (value !== void 0) domain[key] = value;
1297
1733
  const domains = {};
1298
- setOwn$4(domains, name, domain);
1734
+ setOwn$5(domains, name, domain);
1299
1735
  return {
1300
1736
  domains,
1301
1737
  replaces: [["domains", name]]
@@ -1345,10 +1781,10 @@ function mergeLeaf(m, table, key, later, path, part, replaces, equal, reason) {
1345
1781
  if (later === void 0) return;
1346
1782
  const earlier = own$2(table, key);
1347
1783
  if (earlier === void 0) {
1348
- setOwn$4(table, key, later);
1784
+ setOwn$5(table, key, later);
1349
1785
  m.give(path, part);
1350
1786
  } else if (replaces.has(keyOf(path))) {
1351
- setOwn$4(table, key, later);
1787
+ setOwn$5(table, key, later);
1352
1788
  m.replace(path, part);
1353
1789
  } else if (!equal(earlier, later)) m.clash(path, part, reason);
1354
1790
  }
@@ -1369,9 +1805,9 @@ function mergeEntries(m, into, from, path, part, replaces) {
1369
1805
  const at = [...path, key];
1370
1806
  const earlier = own$2(into, key);
1371
1807
  if (earlier === void 0) {
1372
- setOwn$4(into, key, later);
1808
+ setOwn$5(into, key, later);
1373
1809
  m.give(at, part);
1374
- } else setOwn$4(into, key, mergeEntry(m, earlier, later, at, part, replaces));
1810
+ } else setOwn$5(into, key, mergeEntry(m, earlier, later, at, part, replaces));
1375
1811
  }
1376
1812
  }
1377
1813
  /** This function merges two entries at one path. Two namespaces merge key by key, and their fallbacks merge too. */
@@ -1524,8 +1960,8 @@ function mergeCode(m, draft, part, index, replaces) {
1524
1960
  const runnerPath = ["runners", name];
1525
1961
  if (replaces.has(keyOf(evaluatorPath)) || replaces.has(keyOf(runnerPath))) {
1526
1962
  if (evaluator === void 0) delete draft.evaluators[name];
1527
- else setOwn$4(draft.evaluators, name, evaluator);
1528
- if (runner !== void 0) setOwn$4(draft.runners ??= {}, name, runner);
1963
+ else setOwn$5(draft.evaluators, name, evaluator);
1964
+ if (runner !== void 0) setOwn$5(draft.runners ??= {}, name, runner);
1529
1965
  else if (draft.runners !== void 0) delete draft.runners[name];
1530
1966
  m.replace(evaluatorPath, index);
1531
1967
  m.replace(runnerPath, index);
@@ -1648,7 +2084,7 @@ function removeEntry(entries, path) {
1648
2084
  }
1649
2085
  const out = { ...entries };
1650
2086
  if (next === void 0) delete out[key];
1651
- else setOwn$4(out, key, next);
2087
+ else setOwn$5(out, key, next);
1652
2088
  return out;
1653
2089
  }
1654
2090
  /**
@@ -1734,8 +2170,7 @@ function restrictMachine(machine, paths) {
1734
2170
  ...tables.domains === void 0 ? {} : { domains: tables.domains }
1735
2171
  };
1736
2172
  }
1737
- //#endregion
1738
- //#region src/ladder.ts
2173
+ // src/ladder.ts
1739
2174
  /** The rungs of the ladder, in the order that a question visits them. */
1740
2175
  const RUNGS = [
1741
2176
  "own",
@@ -1903,8 +2338,7 @@ function ask(world, doc, verb, options = {}) {
1903
2338
  steps
1904
2339
  };
1905
2340
  }
1906
- //#endregion
1907
- //#region src/deref.ts
2341
+ // src/deref.ts
1908
2342
  /**
1909
2343
  * The brand of a host thing: an object of the host that answers the steps of a path itself. The brand is a
1910
2344
  * global symbol, thus two copies of the kernel in one program know the things of each other.
@@ -2043,11 +2477,12 @@ function derefStep(nav, thing, key) {
2043
2477
  const derefs = nav.derefs;
2044
2478
  const answer = derefs === void 0 ? void 0 : answerOf(nav.world, ownEntries(envelope), kindFor(nav.world, envelope.type), "deref", (name) => codeIn(derefs, name));
2045
2479
  if (answer !== void 0) {
2046
- const reached = derefs[answer.name]?.(envelope, key);
2047
- return reached === void 0 ? void 0 : {
2480
+ const code = derefs[answer.name];
2481
+ const reached = code?.(envelope, key);
2482
+ return reached !== void 0 || code?.has?.(envelope, key) === true ? {
2048
2483
  thing: reached,
2049
2484
  by: answer.rung
2050
- };
2485
+ } : void 0;
2051
2486
  }
2052
2487
  const reached = plainStep(envelope.value, key);
2053
2488
  return reached === NOTHING ? void 0 : {
@@ -2285,6 +2720,25 @@ function resolve(nav, ctx, path, options = {}) {
2285
2720
  }
2286
2721
  return resolveFully$1(nav, ctx, path, options.hops === false ? void 0 : [], void 0);
2287
2722
  }
2723
+ /** The functions of the last navigator that gave a walker its input. A walk with the same navigator makes no new functions. */
2724
+ let lastSteps;
2725
+ /**
2726
+ * This function gives the functions `deref` and `has` of the input of a walker. They depend only on the navigator,
2727
+ * thus the function keeps the functions of the last navigator (K170).
2728
+ */
2729
+ function walkSteps(nav) {
2730
+ if (lastSteps !== void 0 && lastSteps.nav === nav) return lastSteps;
2731
+ const adopt = nav.adopt;
2732
+ lastSteps = {
2733
+ nav,
2734
+ deref: adopt === void 0 ? (thing, key) => derefStep(nav, thing, key)?.thing : (thing, key) => {
2735
+ const reached = derefStep(nav, thing, key);
2736
+ return reached === void 0 ? void 0 : adopt(reached.thing);
2737
+ },
2738
+ has: (thing, key) => derefStep(nav, thing, key) !== void 0
2739
+ };
2740
+ return lastSteps;
2741
+ }
2288
2742
  /**
2289
2743
  * This function resolves a path with the full algorithm of `resolve`.
2290
2744
  *
@@ -2379,20 +2833,19 @@ function resolveFully$1(nav, ctx, path, hops, known) {
2379
2833
  const walker = given === void 0 ? walkerOf(nav, step) : given ?? void 0;
2380
2834
  if (walker === void 0) return failed("#STEP?", "A step is a key, or a document of a kind with the verb step.");
2381
2835
  const envelope = step;
2382
- const deref = (thing, key) => {
2383
- const reached = derefStep(nav, thing, key);
2384
- return reached === void 0 ? void 0 : adopt(reached.thing);
2385
- };
2836
+ const { deref, has } = walkSteps(nav);
2386
2837
  const result = walker(hops === void 0 ? {
2387
2838
  data: envelope.value,
2388
2839
  here,
2389
2840
  context: ctx,
2390
- deref
2841
+ deref,
2842
+ has
2391
2843
  } : {
2392
2844
  data: envelope.value,
2393
2845
  here,
2394
2846
  context: ctx,
2395
2847
  deref,
2848
+ has,
2396
2849
  visit: (key, thing) => hops.push({
2397
2850
  step: key,
2398
2851
  thing,
@@ -2429,8 +2882,7 @@ function resolveFully$1(nav, ctx, path, hops, known) {
2429
2882
  function valueOfThing(thing) {
2430
2883
  return isHostThing(thing) ? thing.toJson() : thing;
2431
2884
  }
2432
- //#endregion
2433
- //#region src/classify.ts
2885
+ // src/classify.ts
2434
2886
  function isStrictSuperset(larger, smaller) {
2435
2887
  return larger.length > smaller.length && smaller.every((name) => larger.includes(name));
2436
2888
  }
@@ -2468,8 +2920,7 @@ function classify(shapes, value) {
2468
2920
  function tag(value, kind) {
2469
2921
  return typed(kind, value);
2470
2922
  }
2471
- //#endregion
2472
- //#region src/parts.ts
2923
+ // src/parts.ts
2473
2924
  var Bad = class {
2474
2925
  reason;
2475
2926
  at;
@@ -2479,7 +2930,7 @@ var Bad = class {
2479
2930
  }
2480
2931
  };
2481
2932
  /** This function sets an own data property. Only the key `__proto__` needs `defineProperty`. */
2482
- function setOwn$3(target, key, value) {
2933
+ function setOwn$4(target, key, value) {
2483
2934
  if (key === "__proto__") Object.defineProperty(target, key, {
2484
2935
  value,
2485
2936
  enumerable: true,
@@ -2493,7 +2944,7 @@ function hasSlots(template) {
2493
2944
  return template.t !== "data";
2494
2945
  }
2495
2946
  /** This function gives the shape of a part with the default type `of` and the value type `expect` of its container. */
2496
- function termOf(of, expect) {
2947
+ function termOf$1(of, expect) {
2497
2948
  return {
2498
2949
  shape: "term",
2499
2950
  ...of === void 0 ? {} : { of },
@@ -2602,7 +3053,7 @@ function splitParts(shape, value) {
2602
3053
  const twice = list.findIndex((child, index) => list.slice(0, index).some((before) => docEquals(before, child)));
2603
3054
  if (twice !== -1) throw new Bad("The items of the list must be different.", [...path, twice]);
2604
3055
  }
2605
- const each = spec.item ?? termOf(spec.of, spec.expect);
3056
+ const each = spec.item ?? termOf$1(spec.of, spec.expect);
2606
3057
  const items = list.map((child, index) => walk(each, child, [...path, index]));
2607
3058
  return isData(each) ? {
2608
3059
  t: "data",
@@ -2614,14 +3065,14 @@ function splitParts(shape, value) {
2614
3065
  }
2615
3066
  if (!isRecord(item)) throw new Bad("The value must be a record.", path);
2616
3067
  if (spec.shape === "map") {
2617
- const each = spec.item ?? termOf(spec.of, spec.expect);
3068
+ const each = spec.item ?? termOf$1(spec.of, spec.expect);
2618
3069
  return {
2619
3070
  t: "record",
2620
3071
  fields: Object.keys(item).map((key) => [key, walk(each, item[key], [...path, key])])
2621
3072
  };
2622
3073
  }
2623
3074
  for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad(`The field ${name} is missing.`, path);
2624
- const named = Array.isArray(spec.fields) ? Object.fromEntries(spec.fields.map((name) => [name, termOf(spec.of, spec.expect)])) : spec.fields;
3075
+ const named = Array.isArray(spec.fields) ? Object.fromEntries(spec.fields.map((name) => [name, termOf$1(spec.of, spec.expect)])) : spec.fields;
2625
3076
  const fields = [];
2626
3077
  for (const key of Object.keys(item)) {
2627
3078
  if (spec.closed === true && !Object.hasOwn(named, key)) throw new Bad(`The field ${key} is not a field of this kind.`, [...path, key]);
@@ -2651,7 +3102,7 @@ function splitParts(shape, value) {
2651
3102
  const out = {};
2652
3103
  for (const [key, child] of node.fields) {
2653
3104
  const kept = strip(child);
2654
- if (kept !== void 0) setOwn$3(out, key, kept);
3105
+ if (kept !== void 0) setOwn$4(out, key, kept);
2655
3106
  }
2656
3107
  return out;
2657
3108
  };
@@ -2660,7 +3111,7 @@ function splitParts(shape, value) {
2660
3111
  if (node.t === "slot") return handles[node.index];
2661
3112
  if (node.t === "list") return node.items.map((child) => fillWith(child, handles));
2662
3113
  const out = {};
2663
- for (const [key, child] of node.fields) setOwn$3(out, key, fillWith(child, handles));
3114
+ for (const [key, child] of node.fields) setOwn$4(out, key, fillWith(child, handles));
2664
3115
  return out;
2665
3116
  };
2666
3117
  return {
@@ -2803,8 +3254,7 @@ function scopesOf(rules, value, slots) {
2803
3254
  later
2804
3255
  };
2805
3256
  }
2806
- //#endregion
2807
- //#region src/evaluate.ts
3257
+ // src/evaluate.ts
2808
3258
  /**
2809
3259
  * This function makes a context with names and capabilities. The other roots are empty, and an evaluation sets
2810
3260
  * the world.
@@ -2918,10 +3368,19 @@ const GRANT = /* @__PURE__ */ Symbol("coeval.grant");
2918
3368
  /**
2919
3369
  * The key of the epoch of a grant (CAP.NARROW-KEPT). The epoch is the list of capabilities that the host gave the root
2920
3370
  * of the evaluation of the grant. A spread of a context keeps its epoch, as it keeps its grant. An
2921
- * effect and a resolution read a context of another epoch as a context without a grant.
3371
+ * effect and a resolution read a context of another epoch as a context without a grant. The root has no field of
3372
+ * the epoch, because its grant is the list of the host (`epochOf`).
2922
3373
  */
2923
3374
  const EPOCH = /* @__PURE__ */ Symbol("coeval.epoch");
2924
3375
  /**
3376
+ * This function gives the epoch of the grant of a context (CAP.NARROW-KEPT). A context without the field of the epoch
3377
+ * has the epoch of its grant. Only a root has no field, thus its grant is the list of the host. The root then has
3378
+ * one field fewer, and each evaluation makes it faster (K154).
3379
+ */
3380
+ function epochOf(ctx) {
3381
+ return ctx[EPOCH] ?? ctx[GRANT];
3382
+ }
3383
+ /**
2925
3384
  * This function gives the capabilities that a context and its grant both permit, the meet `intersectCaps` (CAP.MEET).
2926
3385
  * A context whose grant is its own list gives that list after one comparison. A context without a grant gives none.
2927
3386
  */
@@ -2941,10 +3400,36 @@ function granted(ctx) {
2941
3400
  return {
2942
3401
  ...ctx,
2943
3402
  caps,
2944
- [GRANT]: caps
3403
+ [GRANT]: caps,
3404
+ [EPOCH]: epochOf(ctx)
2945
3405
  };
2946
3406
  }
2947
3407
  /**
3408
+ * This function tells if a list of capabilities is equal to the epoch of the evaluation (CAP.EPOCH-EQUAL). An equal list
3409
+ * has the same length, and at each index the same text or the same keys in the same order. The runtime uses it only
3410
+ * when the two lists are not the same object. Thus a host that gives a new copy of its list for each evaluation keeps
3411
+ * the grant of a kept context.
3412
+ */
3413
+ function sameCaps(caps, epoch) {
3414
+ if (caps === void 0 || caps.length !== epoch.length) return false;
3415
+ for (let index = 0; index < caps.length; index += 1) {
3416
+ const a = caps[index];
3417
+ const b = epoch[index];
3418
+ if (a === b) continue;
3419
+ if (typeof a === "string" || typeof b === "string" || a.length !== b.length) return false;
3420
+ for (let key = 0; key < a.length; key += 1) if (!Object.is(a[key], b[key])) return false;
3421
+ }
3422
+ return true;
3423
+ }
3424
+ /**
3425
+ * This function tells if a context has the epoch of the evaluation: the same list, or an equal list (CAP.NARROW-KEPT,
3426
+ * CAP.EPOCH-EQUAL). The comparison of the entries happens only when the two lists are not the same object.
3427
+ */
3428
+ function inEpoch(ctx, epoch) {
3429
+ const own = epochOf(ctx);
3430
+ return own === epoch || sameCaps(own, epoch);
3431
+ }
3432
+ /**
2948
3433
  * This function gives a context of another epoch the epoch of the evaluation, without capabilities (CAP.NARROW-KEPT).
2949
3434
  * Thus the context reads as a context without a grant. The kernel cannot know the document of the context in this
2950
3435
  * evaluation.
@@ -2962,16 +3447,26 @@ function ungranted(ctx, epoch) {
2962
3447
  * The context has the meet of its list and its grant, and a context without a grant has none. Thus a read of the root
2963
3448
  * `caps` and a walker of a step document get the capabilities of the document from a widened context.
2964
3449
  * A context that the code narrowed keeps its own list. A context whose list does not change stays the same object.
2965
- * A context of another epoch has no capabilities (CAP.NARROW-KEPT).
3450
+ *
3451
+ * A context of another epoch has no capabilities (CAP.NARROW-KEPT). An equal list of the host is the same epoch
3452
+ * (CAP.EPOCH-EQUAL). The first test answers for a context of the epoch whose grant is its list, for example the root.
3453
+ * The other contexts go to `readableOther`, thus the hot part of the function stays small (K154).
2966
3454
  */
2967
3455
  function readable(ctx, epoch) {
2968
- if (ctx[EPOCH] !== epoch) return ctx.caps.length === 0 ? ctx : ungranted(ctx, epoch);
3456
+ const grant = ctx[GRANT];
3457
+ if (grant === ctx.caps && (ctx[EPOCH] ?? grant) === epoch) return ctx;
3458
+ return readableOther(ctx, epoch);
3459
+ }
3460
+ /** This function gives the result of `readable` for each other context: a context of another epoch or a narrowed context. */
3461
+ function readableOther(ctx, epoch) {
3462
+ if (!inEpoch(ctx, epoch)) return ctx.caps.length === 0 ? ctx : ungranted(ctx, epoch);
2969
3463
  const caps = grantedCaps(ctx);
2970
3464
  if (caps === ctx.caps || caps.length === 0 && ctx.caps.length === 0) return ctx;
2971
3465
  return {
2972
3466
  ...ctx,
2973
3467
  caps,
2974
- [GRANT]: caps
3468
+ [GRANT]: caps,
3469
+ [EPOCH]: epochOf(ctx)
2975
3470
  };
2976
3471
  }
2977
3472
  /**
@@ -2981,8 +3476,8 @@ function readable(ctx, epoch) {
2981
3476
  */
2982
3477
  function handed(parent, next) {
2983
3478
  const ctx = narrow(parent, next);
2984
- const epoch = parent[EPOCH];
2985
- if (ctx[GRANT] === ctx.caps && ctx[EPOCH] === epoch) return ctx;
3479
+ const epoch = epochOf(parent);
3480
+ if (ctx[GRANT] === ctx.caps && epochOf(ctx) === epoch) return ctx;
2986
3481
  return {
2987
3482
  ...ctx,
2988
3483
  [GRANT]: ctx.caps,
@@ -2990,7 +3485,7 @@ function handed(parent, next) {
2990
3485
  };
2991
3486
  }
2992
3487
  /** The text that names a resolution in the error of an exception of the host. */
2993
- const READ_FAILED = "the resolution of a path";
3488
+ const READ_FAILED$1 = "the resolution of a path";
2994
3489
  /**
2995
3490
  * This function gives what a resolution reached as a result: the thing, or the error with its code and its reason.
2996
3491
  * The record of a read and `verifyReads` share it.
@@ -3019,7 +3514,7 @@ function readAgain(nav, ctx, path, hops) {
3019
3514
  hops: found.hops
3020
3515
  } : { reached: reachedOf(found) };
3021
3516
  } catch (error) {
3022
- return { reached: thrown(error, READ_FAILED) };
3517
+ return { reached: thrown(error, READ_FAILED$1) };
3023
3518
  }
3024
3519
  }
3025
3520
  /**
@@ -3124,7 +3619,7 @@ function keptPath(nav, root, path) {
3124
3619
  } catch (error) {
3125
3620
  return {
3126
3621
  path: path.slice(0, index + 1),
3127
- reached: thrown(error, READ_FAILED)
3622
+ reached: thrown(error, READ_FAILED$1)
3128
3623
  };
3129
3624
  }
3130
3625
  if (step === void 0) return end(index);
@@ -3160,7 +3655,7 @@ function keptAgain(nav, ctx, path) {
3160
3655
  try {
3161
3656
  step = here.known(path[index]);
3162
3657
  } catch (error) {
3163
- return thrown(error, READ_FAILED);
3658
+ return thrown(error, READ_FAILED$1);
3164
3659
  }
3165
3660
  if (step === void 0) return void 0;
3166
3661
  known = true;
@@ -3197,6 +3692,11 @@ var Session = class {
3197
3692
  list;
3198
3693
  tick = 0;
3199
3694
  nextId = 0;
3695
+ /**
3696
+ * The count of the drives without a wait that are active at this time. In a run, an effect under such a drive does
3697
+ * not reach the host (RUN.HELD).
3698
+ */
3699
+ held = 0;
3200
3700
  current;
3201
3701
  holder;
3202
3702
  /**
@@ -3255,7 +3755,7 @@ var Session = class {
3255
3755
  } catch (error) {
3256
3756
  reading.list.push({
3257
3757
  path,
3258
- reached: thrown(error, READ_FAILED),
3758
+ reached: thrown(error, READ_FAILED$1),
3259
3759
  free
3260
3760
  });
3261
3761
  throw error;
@@ -3343,10 +3843,10 @@ var Session = class {
3343
3843
  * This function checks the capability of an effect, and records the effect with its address (RUN.ADDRESS). The
3344
3844
  * context keeps only the capabilities of its grant, thus compiled code cannot widen the context of its own effect
3345
3845
  * (CAP.NARROW-CODE). A context of another epoch has no capabilities, thus code cannot keep a context for a later
3346
- * evaluation with fewer capabilities (CAP.NARROW-KEPT).
3846
+ * evaluation with fewer capabilities (CAP.NARROW-KEPT). An equal list of the host is the same epoch (CAP.EPOCH-EQUAL).
3347
3847
  */
3348
3848
  record(given, kind, payload, place) {
3349
- const ctx = given[EPOCH] === this.epoch ? granted(given) : ungranted(given, this.epoch);
3849
+ const ctx = inEpoch(given, this.epoch) ? granted(given) : ungranted(given, this.epoch);
3350
3850
  const keys = typeof kind === "string" ? kind.split(".") : kind;
3351
3851
  const text = keys.join(".");
3352
3852
  if (!this.permitted(ctx, keys)) return fail("#CAP!", `The context has no capability for the effect ${text}.`, { place });
@@ -3404,6 +3904,11 @@ var Session = class {
3404
3904
  if ("ok" in made) return made;
3405
3905
  const perform = this.perform;
3406
3906
  if (!this.running || perform === void 0) return this.answer(made, place);
3907
+ if (this.held > 0) {
3908
+ made.outcome = fail("#CALC!", heldReason(made.kind), { place });
3909
+ yield HELD;
3910
+ return made.outcome;
3911
+ }
3407
3912
  let done;
3408
3913
  try {
3409
3914
  done = perform(made);
@@ -3429,6 +3934,7 @@ var Session = class {
3429
3934
  let failed = false;
3430
3935
  const active = [];
3431
3936
  let next = 0;
3937
+ let before = 0;
3432
3938
  const settle = (index, result) => {
3433
3939
  results[index] = result;
3434
3940
  if (failFast && !result.ok) failed = true;
@@ -3492,10 +3998,11 @@ var Session = class {
3492
3998
  };
3493
3999
  start();
3494
4000
  while (active.length > 0 && !failed) {
3495
- const chosen = journal?.next?.(address, active.map((item) => item.index));
4001
+ const chosen = journal?.next?.(address, active.map((item) => item.index), before);
3496
4002
  const pick = chosen === void 0 ? void 0 : active.find((item) => item.index === chosen);
3497
4003
  const settled = yield pick === void 0 ? Promise.race(active.map((item) => item.pending)) : pick.pending;
3498
4004
  journal?.settled?.(address, settled.item.index);
4005
+ before += 1;
3499
4006
  active.splice(active.indexOf(settled.item), 1);
3500
4007
  advance(settled.item.index, settled.item.steps, settled);
3501
4008
  start();
@@ -3581,6 +4088,18 @@ function holderNode() {
3581
4088
  function waitedReason(kindText) {
3582
4089
  return `${kindText} waits for effects, and its parent cannot wait. Give the parent a runner.`;
3583
4090
  }
4091
+ /**
4092
+ * This function gives the reason of an effect that a run does not give to the host: the parent of its runner cannot
4093
+ * wait (RUN.HELD). The plan and the reference give the same reason.
4094
+ *
4095
+ * @param kind - The kind of the effect.
4096
+ * @returns The reason.
4097
+ */
4098
+ function heldReason(kind) {
4099
+ return `The parent of the runner cannot wait, thus the host does not get the effect ${typeof kind === "string" ? kind : kind.join(".")}.`;
4100
+ }
4101
+ /** The wait of an effect that a run does not give to the host. A drive without a wait stops at it (RUN.HELD). */
4102
+ const HELD = /* @__PURE__ */ Promise.resolve(void 0);
3584
4103
  /** This function drives steps that cannot wait. A step that waits stops the steps, and gives `#CALC!`. */
3585
4104
  function drive$2(steps, kindText) {
3586
4105
  const step = steps.next();
@@ -4184,7 +4703,8 @@ function gated(rules, part) {
4184
4703
  return {
4185
4704
  ...ctx,
4186
4705
  caps,
4187
- [GRANT]: caps
4706
+ [GRANT]: caps,
4707
+ [EPOCH]: epochOf(ctx)
4188
4708
  };
4189
4709
  };
4190
4710
  return {
@@ -4208,10 +4728,19 @@ function placedRun(inner, place, name) {
4208
4728
  /**
4209
4729
  * This function gives the code of a runner under a parent that cannot wait: its steps, driven without a wait. An
4210
4730
  * evaluation and a run both drive them (RUN.DRIVE-NESTED). Only a step that really waits gives `#CALC!`, at the place
4211
- * of the runner, where the error started (RUN.WAIT).
4731
+ * of the runner, where the error started (RUN.WAIT). In a run, an effect under the runner does not reach the host,
4732
+ * because the parent cannot wait for its answer (RUN.HELD).
4212
4733
  */
4213
4734
  function runnerCode(run, place, kindText) {
4214
- return (ctx, rt) => placed(drive$2(run(ctx, rt), kindText), place);
4735
+ return (ctx, rt) => {
4736
+ if (!rt.running || !(rt instanceof Session)) return placed(drive$2(run(ctx, rt), kindText), place);
4737
+ rt.held += 1;
4738
+ try {
4739
+ return placed(drive$2(run(ctx, rt), kindText), place);
4740
+ } finally {
4741
+ rt.held -= 1;
4742
+ }
4743
+ };
4215
4744
  }
4216
4745
  /** This function gives the steps of a run of an evaluator. The code runs at the first step, and it does not wait. */
4217
4746
  function runOf(code) {
@@ -4223,6 +4752,30 @@ function runOf(code) {
4223
4752
  function fillOf(split, doc) {
4224
4753
  return (items) => split.parts.length === 0 ? doc.value : split.fill(items);
4225
4754
  }
4755
+ /**
4756
+ * The key of the runtime on the input of an evaluator. Only the kernel reads it. The node of a tree evaluates its
4757
+ * equations in the evaluation of this runtime, thus their reads go in its list (READS.EQUATION). A copy of the input
4758
+ * with a spread keeps the key.
4759
+ */
4760
+ const RUNTIME = /* @__PURE__ */ Symbol("coeval.runtime");
4761
+ /**
4762
+ * This function evaluates a plan inside the evaluation of another runtime, for example an equation of a tree inside
4763
+ * the evaluation of its tree (READS.EQUATION). The plan gets its own runtime, as in `plan.evaluate`. The reads of the
4764
+ * plan go in the record of the reads of `outer`. The context at the root of `outer` tells which reads are free
4765
+ * (READS.FREE). Without such a record, the function gives `plan.evaluate(context)`.
4766
+ *
4767
+ * @param plan - The plan.
4768
+ * @param context - The context of the plan.
4769
+ * @param outer - The runtime of the evaluation around the plan, or `undefined`.
4770
+ * @returns The result.
4771
+ */
4772
+ function evaluateWithin(plan, context, outer) {
4773
+ const reading = outer instanceof Session ? outer.reading : void 0;
4774
+ if (reading === void 0 || !(plan instanceof CompiledPlan)) return plan.evaluate(context);
4775
+ const machine = plan.machine;
4776
+ const ctx = rootContext(machine, context);
4777
+ return plan.code(ctx, new Session(machine, ctx.caps, false, plan.traced, void 0, void 0, void 0, reading));
4778
+ }
4226
4779
  function interpret(fn, input, fill) {
4227
4780
  const { kind, typePath, doc, data, place, machine } = input;
4228
4781
  const address = input.address === true ? { address: true } : {};
@@ -4249,7 +4802,8 @@ function interpret(fn, input, fill) {
4249
4802
  ...address,
4250
4803
  resolve: (path, options) => rt.resolve(ctx, path, options),
4251
4804
  effect: (effectKind, payload) => rt.effect(ctx, effectKind, payload, place),
4252
- fill: refill
4805
+ fill: refill,
4806
+ [RUNTIME]: rt
4253
4807
  });
4254
4808
  };
4255
4809
  }
@@ -4285,18 +4839,27 @@ function interpretRun(fn, input, fill) {
4285
4839
  /**
4286
4840
  * This function gives the context at the root of an evaluation. It is the context of the host, with the world of
4287
4841
  * the machine when the context has none. The host gives the capabilities, thus the root has the grant of each one
4288
- * (CAP.NARROW-CODE). The list of the host is also the epoch of the grant (CAP.NARROW-KEPT). An evaluation and
4289
- * `verifyReads` share it.
4842
+ * (CAP.NARROW-CODE). The list of the host is also the epoch of the grant (CAP.NARROW-KEPT). The root has no field of
4843
+ * the epoch, thus it has the shape of a context before K120 (K154). An evaluation and `verifyReads` share it.
4844
+ *
4845
+ * The function reads the epoch of the context one time, and one test keeps a context that is already a root (K169).
4290
4846
  *
4291
4847
  * @param machine - The machine.
4292
4848
  * @param ctx - The context of the host.
4293
4849
  * @returns The context at the root.
4294
4850
  */
4295
4851
  function rootContext(machine, ctx) {
4296
- if (ctx.world !== null && ctx[GRANT] === ctx.caps && ctx[EPOCH] === ctx.caps) return ctx;
4852
+ const epoch = ctx[EPOCH];
4853
+ if (ctx.world !== null && ctx[GRANT] === ctx.caps && (epoch === void 0 || epoch === ctx.caps)) return ctx;
4854
+ const world = ctx.world === null ? worldThing(machine.world) : ctx.world;
4855
+ if (epoch === void 0) return {
4856
+ ...ctx,
4857
+ world,
4858
+ [GRANT]: ctx.caps
4859
+ };
4297
4860
  return {
4298
4861
  ...ctx,
4299
- world: ctx.world === null ? worldThing(machine.world) : ctx.world,
4862
+ world,
4300
4863
  [GRANT]: ctx.caps,
4301
4864
  [EPOCH]: ctx.caps
4302
4865
  };
@@ -4518,8 +5081,7 @@ function flatten(trace) {
4518
5081
  function failures(trace) {
4519
5082
  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);
4520
5083
  }
4521
- //#endregion
4522
- //#region src/stdlib.ts
5084
+ // src/stdlib.ts
4523
5085
  /**
4524
5086
  * The world of the examples: small kinds for numbers, lists, conditions, names, sequences and effects.
4525
5087
  * Each kind names an evaluator for `eval` and a view for `view`. The site draws each document with its view.
@@ -4736,6 +5298,158 @@ const STD_WORLD = {
4736
5298
  },
4737
5299
  defaults: { view: "view.card" }
4738
5300
  };
5301
+ /**
5302
+ * The text syntax of the standard world (K162, D64). The syntax kit (D41) reads it, thus a host of `STD_WORLD` does
5303
+ * not write its own profile. The operators `>`, `+` and `*` make `greater`, `add` and `multiply`. A call form makes
5304
+ * each other kind, and `ref` uses the reference syntax of the kit.
5305
+ *
5306
+ * A literal in a place that takes a document gets its data envelope (K159, D65). Such a place is a part of `if`,
5307
+ * `list`, `seq` or `pure`, the value of `write`, or the whole text. The document after a header name is such a place
5308
+ * too. Thus `list(1, "a")` evaluates to `[1, "a"]`. The forms `add`, `multiply` and `greater` write an operator document that its operator
5309
+ * does not write, for example `add(5)` (K163).
5310
+ *
5311
+ * A host with more kinds spreads this profile and adds its forms to `calls.forms`. `STD_SYNTAX` stays the profile of
5312
+ * the formula kit.
5313
+ */
5314
+ const WORLD_SYNTAX = /* @__PURE__ */ Object.freeze({
5315
+ operators: [
5316
+ {
5317
+ symbol: ">",
5318
+ fixity: "infix",
5319
+ prec: 4,
5320
+ assoc: "none",
5321
+ kind: "greater"
5322
+ },
5323
+ {
5324
+ symbol: "+",
5325
+ fixity: "infix",
5326
+ prec: 5,
5327
+ assoc: "flat",
5328
+ kind: "add"
5329
+ },
5330
+ {
5331
+ symbol: "*",
5332
+ fixity: "infix",
5333
+ prec: 6,
5334
+ assoc: "flat",
5335
+ kind: "multiply"
5336
+ }
5337
+ ],
5338
+ calls: {
5339
+ ops: [],
5340
+ forms: [
5341
+ {
5342
+ name: "if",
5343
+ kind: "if",
5344
+ fields: [
5345
+ "test",
5346
+ "then",
5347
+ "else"
5348
+ ],
5349
+ min: 2,
5350
+ wrap: true
5351
+ },
5352
+ {
5353
+ name: "list",
5354
+ kind: "list",
5355
+ wrap: true
5356
+ },
5357
+ {
5358
+ name: "seq",
5359
+ kind: "seq",
5360
+ wrap: true
5361
+ },
5362
+ {
5363
+ name: "pure",
5364
+ kind: "pure",
5365
+ min: 1,
5366
+ wrap: true
5367
+ },
5368
+ {
5369
+ name: "log",
5370
+ kind: "log",
5371
+ min: 1
5372
+ },
5373
+ {
5374
+ name: "write",
5375
+ kind: "write",
5376
+ fields: ["key", "value"],
5377
+ wrap: ["value"]
5378
+ },
5379
+ {
5380
+ name: "math.sum",
5381
+ kind: "math.sum"
5382
+ },
5383
+ {
5384
+ name: "math.product",
5385
+ kind: "math.product"
5386
+ },
5387
+ {
5388
+ name: "number",
5389
+ kind: "number",
5390
+ args: "literal"
5391
+ },
5392
+ {
5393
+ name: "text",
5394
+ kind: "text",
5395
+ args: "literal"
5396
+ },
5397
+ {
5398
+ name: "bool",
5399
+ kind: "bool",
5400
+ args: "literal"
5401
+ },
5402
+ {
5403
+ name: "panel",
5404
+ kind: "panel",
5405
+ args: "named",
5406
+ fields: [
5407
+ "width",
5408
+ "height",
5409
+ "children"
5410
+ ]
5411
+ },
5412
+ {
5413
+ name: "box",
5414
+ kind: "box",
5415
+ args: "named",
5416
+ fields: [
5417
+ "width",
5418
+ "height",
5419
+ "children"
5420
+ ]
5421
+ },
5422
+ {
5423
+ name: "nearest",
5424
+ kind: "nearest",
5425
+ args: "named",
5426
+ fields: [
5427
+ "type",
5428
+ "follow",
5429
+ "self"
5430
+ ]
5431
+ },
5432
+ {
5433
+ name: "add",
5434
+ kind: "add"
5435
+ },
5436
+ {
5437
+ name: "multiply",
5438
+ kind: "multiply"
5439
+ },
5440
+ {
5441
+ name: "greater",
5442
+ kind: "greater"
5443
+ }
5444
+ ]
5445
+ },
5446
+ literals: { envelopes: {
5447
+ number: "number",
5448
+ text: "text",
5449
+ bool: "bool"
5450
+ } },
5451
+ header: { bind: "=" }
5452
+ });
4739
5453
  function isNumber(value) {
4740
5454
  return typeof value === "number" && Number.isFinite(value);
4741
5455
  }
@@ -4914,6 +5628,7 @@ function plainOf(value, path) {
4914
5628
  */
4915
5629
  function treeThing(input, build, outer) {
4916
5630
  const { parts, context, kind: type, place, machine } = input;
5631
+ const runtime = input[RUNTIME];
4917
5632
  const { tree, of } = contractOf$1(machine, input.typePath);
4918
5633
  const above = stateOf(outer);
4919
5634
  const up = above !== void 0 && above.build === build ? above : void 0;
@@ -5015,12 +5730,12 @@ function treeThing(input, build, outer) {
5015
5730
  read,
5016
5731
  equation(term, names) {
5017
5732
  if (machine === void 0) return fail("#NOEVAL", "The evaluation of an equation needs the machine.");
5018
- return equationPlan(machine, of, term).evaluate({
5733
+ return evaluateWithin(equationPlan(machine, of, term), {
5019
5734
  ...context,
5020
5735
  names,
5021
5736
  caps: NO_CAPS$1,
5022
5737
  self: node
5023
- });
5738
+ }, runtime);
5024
5739
  },
5025
5740
  childNames(child) {
5026
5741
  const children = read("children");
@@ -5267,8 +5982,7 @@ const STD_MACHINE = {
5267
5982
  };
5268
5983
  /** The capabilities of the examples at the root: the two effects of the standard world. */
5269
5984
  const STD_CAPS = ["log", "write"];
5270
- //#endregion
5271
- //#region src/order.ts
5985
+ // src/order.ts
5272
5986
  /**
5273
5987
  * This function finds the references that a sequence cannot resolve. A step can read only the steps before it.
5274
5988
  *
@@ -5364,8 +6078,7 @@ function layers(steps) {
5364
6078
  }
5365
6079
  return result;
5366
6080
  }
5367
- //#endregion
5368
- //#region src/context.ts
6081
+ // src/context.ts
5369
6082
  /** The parts of a context. A term can reach outside itself only through these parts. */
5370
6083
  const PARTS = [
5371
6084
  "self",
@@ -5653,8 +6366,7 @@ const CONSTRUCTS = [
5653
6366
  }
5654
6367
  }
5655
6368
  ];
5656
- //#endregion
5657
- //#region src/typing.ts
6369
+ // src/typing.ts
5658
6370
  /**
5659
6371
  * The value type of the root `caps`: a list of capabilities. A capability is a text, or a list of keys. The kernel
5660
6372
  * narrows the capabilities for each part, thus the host does not give this type.
@@ -5881,8 +6593,7 @@ function typePass(machine, nodes, verb, expect, rootTypes = {}) {
5881
6593
  places
5882
6594
  };
5883
6595
  }
5884
- //#endregion
5885
- //#region src/static.ts
6596
+ // src/static.ts
5886
6597
  /** The names of a walk without names. A walk does not change a set at any time: it makes a new set to add names. */
5887
6598
  const NO_NAMES = /* @__PURE__ */ new Set();
5888
6599
  /** This function gives the options of a walk without the names of the host. */
@@ -6310,7 +7021,7 @@ const DOWN_NAMES = /* @__PURE__ */ Object.freeze([
6310
7021
  const FOLD_NAMES = /* @__PURE__ */ Object.freeze(["acc", "item"]);
6311
7022
  /**
6312
7023
  * This function gives each equation of the tree contract of a kind, with the names that it sees (D42). An equation of
6313
- * `equations`, a `unit` and a `default` see no names.
7024
+ * `equations`, a `unit` and a `default` see no names. `check` and `factsOf` read the equations with this one function.
6314
7025
  */
6315
7026
  function equationsOf(kind) {
6316
7027
  const tree = kind.tree;
@@ -6564,8 +7275,7 @@ function checkAll(machine, doc, options, nodes, seen = /* @__PURE__ */ new Set()
6564
7275
  }
6565
7276
  return issues;
6566
7277
  }
6567
- //#endregion
6568
- //#region src/facts.ts
7278
+ // src/facts.ts
6569
7279
  /** The lazy rules that cover each part: the rules of a document whose evaluator the contract does not describe. */
6570
7280
  const EACH$1 = "each";
6571
7281
  /** An empty list. One frozen list serves each empty list of the facts, thus a store of many facts keeps less (PLAN.LEAN). */
@@ -6632,9 +7342,11 @@ function partLazy(above, parent, slot) {
6632
7342
  *
6633
7343
  * - `reads`: each free reference, with the root and the keys of its path. A read under a lazy part has the mark
6634
7344
  * `lazy`, for example a read in a branch of `if`. A read after a step document has `exact: false`. A kind that
6635
- * declares `reads` adds a read of each of its roots at each document of the kind.
7345
+ * declares `reads` adds a read of each of its roots at each document of the kind. The first document of a tree
7346
+ * kind also gets the lazy reads of the equations of its kind (FACTS.EQUATIONS). A read from `self` or from a name
7347
+ * of a rung is not one of them, because it is not free (READS.EQUATION).
6636
7348
  * - `side` and `effects`: from the contract of each kind.
6637
- * - `pure`: each kind declares `pure`, and the document has no effect and is not volatile.
7349
+ * - `pure`: each kind declares `pure`, also in an equation, and the document has no effect and is not volatile.
6638
7350
  * - `volatile`: a kind, an operation or a step document declares `volatile`, or the host marks a read.
6639
7351
  *
6640
7352
  * The hook `facts` of the machine answers for a name that a fallback kind covers, for example an operation. Its
@@ -6658,7 +7370,6 @@ function partLazy(above, parent, slot) {
6658
7370
  function factsOf(machine, doc, options = {}) {
6659
7371
  const world = machine.world;
6660
7372
  const hook = machine.facts;
6661
- const verb = options.verb ?? "eval";
6662
7373
  const reads = [];
6663
7374
  const effects = [];
6664
7375
  const above = /* @__PURE__ */ new Map();
@@ -6666,98 +7377,124 @@ function factsOf(machine, doc, options = {}) {
6666
7377
  let pure = true;
6667
7378
  let volatile = false;
6668
7379
  let size = 0;
7380
+ let seen;
6669
7381
  const note = (isPure, isVolatile) => {
6670
7382
  if (isPure !== true) pure = false;
6671
7383
  if (isVolatile === true) volatile = true;
6672
7384
  };
6673
- walk(world, doc, (v) => {
6674
- size += 1;
6675
- const up = v.parent === void 0 ? void 0 : above.get(v.parent);
6676
- const lazy = up !== void 0 && v.parent !== void 0 && (up.lazy || partLazy(up, v.parent, v.slot));
6677
- const kind = v.kind;
6678
- if (kind === void 0) {
6679
- pure = false;
6680
- above.set(v, {
6681
- lazy,
6682
- rules: void 0
6683
- });
6684
- return;
6685
- }
6686
- const code = codeOf(world, v.declared ? void 0 : v.doc.own, kind, verb, "eval");
6687
- const answer = code.name === void 0 ? void 0 : hook?.(v.typePath ?? [], code.name);
6688
- let roots;
6689
- if (code.described) {
6690
- note(answer?.pure ?? kind.pure, answer?.volatile ?? kind.volatile);
6691
- above.set(v, {
6692
- lazy,
6693
- rules: answer?.lazy ?? kind.lazy
6694
- });
6695
- roots = answer?.reads ?? kind.reads;
6696
- } else {
6697
- note(answer?.pure, answer?.volatile);
6698
- above.set(v, {
6699
- lazy,
6700
- rules: answer?.lazy ?? EACH$1
6701
- });
6702
- roots = answer?.reads;
6703
- }
6704
- for (const root of roots ?? NONE) {
6705
- const read = {
6706
- root,
6707
- keys: NONE,
6708
- exact: true,
6709
- lazy,
6710
- address: false,
6711
- path: [root],
6712
- place: tight(v.place),
6713
- at: tight(v.at)
6714
- };
6715
- reads.push(read);
6716
- if (options.volatile?.(read) === true) volatile = true;
6717
- }
6718
- if (kind.side === "run") side = "run";
6719
- for (const keys of declaredEffects(v)) {
6720
- const text = keys.join(".");
6721
- if (!effects.includes(text)) effects.push(text);
6722
- }
6723
- if (!isRef(v.doc)) return void 0;
6724
- const path = v.doc.value;
6725
- const root = path[0];
6726
- if (typeof root !== "string" || !ROOTS.includes(root)) return void 0;
6727
- let exact = true;
6728
- const keys = [];
6729
- for (let index = 1; index < path.length; index += 1) {
6730
- const step = path[index];
6731
- if (exact && isKey(step)) {
6732
- keys.push(step);
6733
- continue;
6734
- }
6735
- exact = false;
6736
- const found = isEnvelope(step) ? lookupKind(world, step.type) : void 0;
6737
- if (found?.ok !== true) {
6738
- pure = false;
6739
- continue;
6740
- }
6741
- const walker = codeOf(world, step.own, found.kind, "step", "step");
6742
- const stepAnswer = walker.name === void 0 ? void 0 : hook?.(found.path, walker.name);
6743
- if (walker.described) note(stepAnswer?.pure ?? found.kind.pure, stepAnswer?.volatile ?? found.kind.volatile);
6744
- else note(stepAnswer?.pure, stepAnswer?.volatile);
6745
- }
6746
- const first = path[1];
6747
- if (root === "names" && isKey(first) && v.names.has(String(first))) return void 0;
6748
- const read = {
6749
- root,
6750
- keys: tight(keys),
6751
- exact,
6752
- lazy,
6753
- address: v.address === true,
6754
- path,
6755
- place: tight(v.place),
6756
- at: tight(v.at)
6757
- };
7385
+ const add = (read) => {
6758
7386
  reads.push(read);
6759
7387
  if (options.volatile?.(read) === true) volatile = true;
6760
- }, options.declaredType === void 0 ? {} : { declaredType: options.declaredType });
7388
+ };
7389
+ /**
7390
+ * This function walks a document. Without `node`, it walks the document of the facts. With `node`, it walks an
7391
+ * equation of a tree kind, and each read gets the place of that node: the first document of the kind.
7392
+ */
7393
+ const scan = (term, walkOptions, verb, node) => {
7394
+ walk(world, term, (v) => {
7395
+ if (node === void 0) size += 1;
7396
+ const up = v.parent === void 0 ? void 0 : above.get(v.parent);
7397
+ const lazy = node !== void 0 || up !== void 0 && v.parent !== void 0 && (up.lazy || partLazy(up, v.parent, v.slot));
7398
+ const place = node ?? v;
7399
+ const kind = v.kind;
7400
+ if (kind === void 0) {
7401
+ pure = false;
7402
+ above.set(v, {
7403
+ lazy,
7404
+ rules: void 0
7405
+ });
7406
+ return;
7407
+ }
7408
+ const code = codeOf(world, v.declared ? void 0 : v.doc.own, kind, verb, "eval");
7409
+ const answer = code.name === void 0 ? void 0 : hook?.(v.typePath ?? [], code.name);
7410
+ let roots;
7411
+ if (code.described) {
7412
+ note(answer?.pure ?? kind.pure, answer?.volatile ?? kind.volatile);
7413
+ above.set(v, {
7414
+ lazy,
7415
+ rules: answer?.lazy ?? kind.lazy
7416
+ });
7417
+ roots = answer?.reads ?? kind.reads;
7418
+ } else {
7419
+ note(answer?.pure, answer?.volatile);
7420
+ above.set(v, {
7421
+ lazy,
7422
+ rules: answer?.lazy ?? EACH$1
7423
+ });
7424
+ roots = answer?.reads;
7425
+ }
7426
+ for (const root of roots ?? NONE) {
7427
+ if (node !== void 0 && root === "self") continue;
7428
+ add({
7429
+ root,
7430
+ keys: NONE,
7431
+ exact: true,
7432
+ lazy,
7433
+ address: false,
7434
+ path: [root],
7435
+ place: tight(place.place),
7436
+ at: tight(place.at)
7437
+ });
7438
+ }
7439
+ if (kind.side === "run") {
7440
+ if (node === void 0) side = "run";
7441
+ else pure = false;
7442
+ }
7443
+ for (const keys of declaredEffects(v)) {
7444
+ if (node !== void 0) {
7445
+ pure = false;
7446
+ continue;
7447
+ }
7448
+ const text = keys.join(".");
7449
+ if (!effects.includes(text)) effects.push(text);
7450
+ }
7451
+ if (kind.tree !== void 0 && !(seen ??= /* @__PURE__ */ new Set()).has(kind)) {
7452
+ seen.add(kind);
7453
+ const of = equationType(kind);
7454
+ for (const { term: equation, names } of equationsOf(kind)) scan(equation, of === void 0 ? { names } : {
7455
+ names,
7456
+ declaredType: of
7457
+ }, "eval", place);
7458
+ }
7459
+ if (!isRef(v.doc)) return void 0;
7460
+ const path = v.doc.value;
7461
+ const root = path[0];
7462
+ if (typeof root !== "string" || !ROOTS.includes(root)) return void 0;
7463
+ if (node !== void 0 && root === "self") return void 0;
7464
+ let exact = true;
7465
+ const keys = [];
7466
+ for (let index = 1; index < path.length; index += 1) {
7467
+ const step = path[index];
7468
+ if (exact && isKey(step)) {
7469
+ keys.push(step);
7470
+ continue;
7471
+ }
7472
+ exact = false;
7473
+ const found = isEnvelope(step) ? lookupKind(world, step.type) : void 0;
7474
+ if (found?.ok !== true) {
7475
+ pure = false;
7476
+ continue;
7477
+ }
7478
+ const walker = codeOf(world, step.own, found.kind, "step", "step");
7479
+ const stepAnswer = walker.name === void 0 ? void 0 : hook?.(found.path, walker.name);
7480
+ if (walker.described) note(stepAnswer?.pure ?? found.kind.pure, stepAnswer?.volatile ?? found.kind.volatile);
7481
+ else note(stepAnswer?.pure, stepAnswer?.volatile);
7482
+ }
7483
+ const first = path[1];
7484
+ if (root === "names" && isKey(first) && v.names.has(String(first))) return void 0;
7485
+ add({
7486
+ root,
7487
+ keys: tight(keys),
7488
+ exact,
7489
+ lazy,
7490
+ address: v.address === true,
7491
+ path,
7492
+ place: tight(place.place),
7493
+ at: tight(place.at)
7494
+ });
7495
+ }, walkOptions);
7496
+ };
7497
+ scan(doc, options.declaredType === void 0 ? {} : { declaredType: options.declaredType }, options.verb ?? "eval", void 0);
6761
7498
  return {
6762
7499
  reads: tight(reads),
6763
7500
  side,
@@ -6767,8 +7504,7 @@ function factsOf(machine, doc, options = {}) {
6767
7504
  size
6768
7505
  };
6769
7506
  }
6770
- //#endregion
6771
- //#region src/effects.ts
7507
+ // src/effects.ts
6772
7508
  /** Each capability: one capability with no keys. It permits each effect, because each kind starts with no keys (CAP.KEYS). */
6773
7509
  const EACH = /* @__PURE__ */ Object.freeze([[]]);
6774
7510
  /**
@@ -6848,8 +7584,7 @@ function checkLatent(machine, declared, body, options = {}) {
6848
7584
  }
6849
7585
  return issues;
6850
7586
  }
6851
- //#endregion
6852
- //#region src/codec.ts
7587
+ // src/codec.ts
6853
7588
  /** This function gives the codec of a domain, or `undefined` when the domain has no codec. */
6854
7589
  function codecOf(domain) {
6855
7590
  const codec = domain.codec;
@@ -6896,7 +7631,7 @@ function domainTypeOf(data, domains) {
6896
7631
  return domain !== void 0 && codecOf(domain) !== void 0 ? data["domain"] : "unknown";
6897
7632
  }
6898
7633
  /** This function sets an own data property. Only the key `__proto__` needs `defineProperty`. */
6899
- function setOwn$2(target, key, value) {
7634
+ function setOwn$3(target, key, value) {
6900
7635
  if (key === "__proto__") Object.defineProperty(target, key, {
6901
7636
  value,
6902
7637
  enumerable: true,
@@ -6971,7 +7706,7 @@ function encodeTerm(value, encoder) {
6971
7706
  else {
6972
7707
  const fields = {};
6973
7708
  const record = value;
6974
- for (const key of Object.keys(record)) setOwn$2(fields, key, encodeTerm(record[key], encoder));
7709
+ for (const key of Object.keys(record)) setOwn$3(fields, key, encodeTerm(record[key], encoder));
6975
7710
  out = {
6976
7711
  type: "record",
6977
7712
  value: fields
@@ -7020,8 +7755,7 @@ function encodeValue(machine, value) {
7020
7755
  function decodeValue(machine, doc) {
7021
7756
  return prepare(machine, doc, { declaredType: "lit" }).evaluate(makeContext());
7022
7757
  }
7023
- //#endregion
7024
- //#region src/formula.ts
7758
+ // src/formula.ts
7025
7759
  /** The mark of a field that the profile leaves out of a record. */
7026
7760
  const SKIPPED = /* @__PURE__ */ Symbol("skipped");
7027
7761
  /** The value of a name whose binding failed. A reference to the name gives the error. */
@@ -7067,7 +7801,7 @@ function strictTruthy(value) {
7067
7801
  * This function sets an own data property. Only the key `__proto__` needs `defineProperty`: an assignment to it
7068
7802
  * changes the prototype. An assignment is faster for each other key of a new plain object.
7069
7803
  */
7070
- function setOwn$1(target, key, value) {
7804
+ function setOwn$2(target, key, value) {
7071
7805
  if (key === "__proto__") Object.defineProperty(target, key, {
7072
7806
  value,
7073
7807
  enumerable: true,
@@ -7281,11 +8015,28 @@ function paramsOf(value) {
7281
8015
  }
7282
8016
  /**
7283
8017
  * This function makes the type rules of the formula kit for one profile (TYPE.SYNTH, D25). Each evaluator of the kit
7284
- * holds its rule. The rules read the rules of the profile that change a type: `truthy`, `logic`, `otherwise`, `omit`
7285
- * and `sigs`.
8018
+ * holds its rule. The rules read the rules of the profile that change a type: `truthy`, `truthType`, `logic`,
8019
+ * `otherwise`, `omit`, `sigs` and `extTypes`.
7286
8020
  */
7287
8021
  function formulaTypes(profile) {
7288
- const truth = profile.truthy === void 0 ? "bool" : void 0;
8022
+ const declared = profile.truthy !== void 0 && profile.truthType !== void 0;
8023
+ const truth = profile.truthy === void 0 ? "bool" : profile.truthType;
8024
+ /**
8025
+ * The need of a test or a term. The check examines a declared type of a truth as a contract, one time. A declared
8026
+ * type with a problem needs nothing, thus one problem gives one issue.
8027
+ */
8028
+ const truthPart = (input, what) => {
8029
+ if (truth === void 0) return {};
8030
+ if (!declared) return {
8031
+ expect: truth,
8032
+ what
8033
+ };
8034
+ const type = input.contract(truth, "truth type of the profile");
8035
+ return typeIssues(type, input.machine.domains).length > 0 ? {} : {
8036
+ expect: type,
8037
+ what
8038
+ };
8039
+ };
7289
8040
  const logicValue = profile.logic === "value";
7290
8041
  const otherwise = Object.hasOwn(profile, "otherwise") ? valueType(profile.otherwise) : "null";
7291
8042
  const lookup = (name) => {
@@ -7321,10 +8072,7 @@ function formulaTypes(profile) {
7321
8072
  };
7322
8073
  };
7323
8074
  const logic = (word) => ({
7324
- part: (_input, path) => truth === void 0 ? {} : {
7325
- expect: truth,
7326
- what: `term ${Number(path[0]) + 1} of ${word}`
7327
- },
8075
+ part: (input, path) => truthPart(input, `term ${Number(path[0]) + 1} of ${word}`),
7328
8076
  synth: (input) => {
7329
8077
  if (!logicValue) return "bool";
7330
8078
  if (input.paths.length === 0) return { one: [word === "and"] };
@@ -7373,7 +8121,7 @@ function formulaTypes(profile) {
7373
8121
  },
7374
8122
  synth: (input) => {
7375
8123
  const fields = {};
7376
- for (const path of input.paths) setOwn$1(fields, String(path[0]), input.typeOf(path));
8124
+ for (const path of input.paths) setOwn$2(fields, String(path[0]), input.typeOf(path));
7377
8125
  const keys = Object.keys(fields);
7378
8126
  return {
7379
8127
  record: fields,
@@ -7396,7 +8144,7 @@ function formulaTypes(profile) {
7396
8144
  part: (input, path) => {
7397
8145
  if (path[0] !== "body") return {};
7398
8146
  const names = {};
7399
- for (const each of input.paths) if (each[0] === "bind" && each.length === 2) setOwn$1(names, String(each[1]), input.typeOf(each));
8147
+ for (const each of input.paths) if (each[0] === "bind" && each.length === 2) setOwn$2(names, String(each[1]), input.typeOf(each));
7400
8148
  return {
7401
8149
  names,
7402
8150
  ...isUnknown(input.expected, input.machine.domains) ? {} : {
@@ -7412,7 +8160,7 @@ function formulaTypes(profile) {
7412
8160
  if (path[0] !== "body") return {};
7413
8161
  const want = fnOf(input.expected, input.machine.domains);
7414
8162
  const names = {};
7415
- paramsOf(input.doc.value).forEach((name, index) => setOwn$1(names, name, want?.params[index] ?? "unknown"));
8163
+ paramsOf(input.doc.value).forEach((name, index) => setOwn$2(names, name, want?.params[index] ?? "unknown"));
7416
8164
  return {
7417
8165
  names,
7418
8166
  ...want === void 0 || isUnknown(want.to, input.machine.domains) ? {} : {
@@ -7468,10 +8216,7 @@ function formulaTypes(profile) {
7468
8216
  } },
7469
8217
  "formula.if": {
7470
8218
  part: (input, path) => {
7471
- if (path[0] === "test") return truth === void 0 ? {} : {
7472
- expect: truth,
7473
- what: "test of if"
7474
- };
8219
+ if (path[0] === "test") return truthPart(input, "test of if");
7475
8220
  return isUnknown(input.expected, input.machine.domains) ? {} : {
7476
8221
  expect: input.expected,
7477
8222
  what: `${String(path[0])} branch of if`
@@ -7525,7 +8270,13 @@ function formulaTypes(profile) {
7525
8270
  },
7526
8271
  "formula.ext": { synth: (input) => {
7527
8272
  const name = nameOf(input);
7528
- if (profile.ext !== void 0 && Object.hasOwn(profile.ext, name)) return "unknown";
8273
+ if (profile.ext !== void 0 && Object.hasOwn(profile.ext, name)) {
8274
+ const types = profile.extTypes;
8275
+ const declared = types !== void 0 && Object.hasOwn(types, name) ? types[name] : void 0;
8276
+ if (declared === void 0) return "unknown";
8277
+ const type = input.contract(declared, `type of ext.${name} in extTypes`);
8278
+ return typeIssues(type, input.machine.domains).length > 0 ? "unknown" : type;
8279
+ }
7529
8280
  if (name === "undefined") return "undefined";
7530
8281
  if (name === "number") return "number";
7531
8282
  return name === "domain" ? domainTypeOf(input.doc.value, input.machine.domains) : "unknown";
@@ -7545,18 +8296,44 @@ function formulaTypes(profile) {
7545
8296
  function formulaEvaluators(profile = {}) {
7546
8297
  return { ...kitOf(profile).evaluators };
7547
8298
  }
8299
+ /** The evaluators of the kit that read the truth of a value. */
8300
+ const TRUTH_READERS = [
8301
+ "formula.if",
8302
+ "formula.and",
8303
+ "formula.or"
8304
+ ];
8305
+ /** The declared truth of each evaluator of the kit that reads a truth, for `conforms` (D86). */
8306
+ const truthByCode = /* @__PURE__ */ new WeakMap();
8307
+ /**
8308
+ * This function gives the declared truth of the profile of an evaluator of the kit (D86). Only `formula.if`,
8309
+ * `formula.and` and `formula.or` of a profile with an own `truthy` and a `truthType` have one. The kernel does not
8310
+ * export the function.
8311
+ *
8312
+ * @param code - The evaluator or the runner.
8313
+ * @returns The declared truth, or `undefined`.
8314
+ */
8315
+ function declaredTruthOf(code) {
8316
+ return (typeof code === "object" || typeof code === "function") && code !== null ? truthByCode.get(code) : void 0;
8317
+ }
7548
8318
  /** This function makes new evaluators of the formula kit for the fields of one profile. */
7549
8319
  function makeEvaluators(profile) {
7550
8320
  const evaluators = formulaCode(profile);
7551
8321
  const types = formulaTypes(profile);
8322
+ const { truthy, truthType } = profile;
8323
+ const truth = truthy === void 0 || truthType === void 0 ? void 0 : {
8324
+ truthy,
8325
+ truthType
8326
+ };
7552
8327
  const out = {};
7553
8328
  for (const name of Object.keys(evaluators)) {
7554
8329
  const evaluator = evaluators[name];
7555
8330
  const type = Object.hasOwn(types, name) ? types[name] : void 0;
7556
- out[name] = Object.freeze(type === void 0 ? evaluator : {
8331
+ const made = Object.freeze(type === void 0 ? evaluator : {
7557
8332
  compile: evaluator.compile,
7558
8333
  type
7559
8334
  });
8335
+ if (truth !== void 0 && TRUTH_READERS.includes(name)) truthByCode.set(made, truth);
8336
+ out[name] = made;
7560
8337
  }
7561
8338
  return Object.freeze(out);
7562
8339
  }
@@ -7565,7 +8342,9 @@ const PROFILE_KEYS = /* @__PURE__ */ Object.freeze([
7565
8342
  "ops",
7566
8343
  "lazy",
7567
8344
  "ext",
8345
+ "extTypes",
7568
8346
  "truthy",
8347
+ "truthType",
7569
8348
  "otherwise",
7570
8349
  "logic",
7571
8350
  "omit",
@@ -7750,7 +8529,7 @@ function formulaCode(profile) {
7750
8529
  if (!Array.isArray(values)) return values;
7751
8530
  const out = {};
7752
8531
  keys.forEach((key, index) => {
7753
- if (values[index] !== SKIPPED) setOwn$1(out, key, values[index]);
8532
+ if (values[index] !== SKIPPED) setOwn$2(out, key, values[index]);
7754
8533
  });
7755
8534
  return ok(out);
7756
8535
  };
@@ -7763,7 +8542,7 @@ function formulaCode(profile) {
7763
8542
  if (omit !== void 0 && omit(result.error)) continue;
7764
8543
  return result;
7765
8544
  }
7766
- setOwn$1(out, keys[index], result.value);
8545
+ setOwn$2(out, keys[index], result.value);
7767
8546
  }
7768
8547
  return ok(out);
7769
8548
  };
@@ -7780,7 +8559,7 @@ function formulaCode(profile) {
7780
8559
  const names = { ...ctx.names };
7781
8560
  for (const [name, part] of bindings) {
7782
8561
  const result = part.code(ctx, rt);
7783
- setOwn$1(names, name, result.ok ? result.value : new Held(result.error));
8562
+ setOwn$2(names, name, result.ok ? result.value : new Held(result.error));
7784
8563
  }
7785
8564
  return body.code({
7786
8565
  ...ctx,
@@ -7811,7 +8590,7 @@ function formulaCode(profile) {
7811
8590
  rt.keepsContext?.(ctx, reads);
7812
8591
  const closure = (...args) => {
7813
8592
  const scope = { ...ctx.names };
7814
- names.forEach((name, index) => setOwn$1(scope, name, args[index]));
8593
+ names.forEach((name, index) => setOwn$2(scope, name, args[index]));
7815
8594
  const result = body.code({
7816
8595
  ...ctx,
7817
8596
  names: scope
@@ -8079,12 +8858,12 @@ function formulaMachine(profile = {}, more = {}) {
8079
8858
  facts: kit.facts
8080
8859
  }, more);
8081
8860
  }
8082
- //#endregion
8083
- //#region src/syntax.ts
8861
+ // src/syntax.ts
8084
8862
  /**
8085
8863
  * The standard syntax of the formula kit. It gives the site and the playground a text form. The operators are
8086
8864
  * `or`, `and`, `not`, the comparisons, `+ - * / %`, a minus sign and `^`, from the loosest to the tightest. A call
8087
- * `name(args)` applies the operation `ops.name`. `if(test, then, else)` and `list(items)` make the constructs.
8865
+ * `name(args)` applies the operation `ops.name`. `if(test, then, else)` and `list(items)` make the constructs. The
8866
+ * text `total = 2 + 3` gives the document the header name `total` (D62).
8088
8867
  */
8089
8868
  const STD_SYNTAX = /* @__PURE__ */ Object.freeze({
8090
8869
  operators: [
@@ -8214,7 +8993,8 @@ const STD_SYNTAX = /* @__PURE__ */ Object.freeze({
8214
8993
  }, {
8215
8994
  name: "list",
8216
8995
  kind: "list"
8217
- }] }
8996
+ }] },
8997
+ header: { bind: "=" }
8218
8998
  });
8219
8999
  const NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
8220
9000
  const NAME_AT = /[A-Za-z_][A-Za-z0-9_]*/y;
@@ -8232,6 +9012,12 @@ const DEFAULT_ROOTS = [
8232
9012
  "event",
8233
9013
  "caps"
8234
9014
  ];
9015
+ const FORM_ARGS = [
9016
+ "list",
9017
+ "fields",
9018
+ "named",
9019
+ "literal"
9020
+ ];
8235
9021
  const compiledProfiles = /* @__PURE__ */ new WeakMap();
8236
9022
  function typeOfKind(kind) {
8237
9023
  const keys = kind.split(".");
@@ -8287,6 +9073,37 @@ function compileOps(profile, separator) {
8287
9073
  opWords
8288
9074
  };
8289
9075
  }
9076
+ /** This function examines the bind symbol of a header. A text with the symbol after a name was not valid before. */
9077
+ function compileBind(bind, separator, binary) {
9078
+ if (bind === void 0) return void 0;
9079
+ if (!SYMBOL.test(bind) || bind.includes(separator)) throw new TypeError(`The bind symbol "${bind}" is not a group of symbols.`);
9080
+ for (const symbol of binary.keys()) if (bind.startsWith(symbol)) throw new TypeError(`The bind symbol "${bind}" starts with the operator "${symbol}".`);
9081
+ return bind;
9082
+ }
9083
+ /** This function examines the field `wrap` of a call form (K159). A name that is not a field of the form throws. */
9084
+ function compileWrap(given, args) {
9085
+ const wrap = given.wrap;
9086
+ if (wrap === void 0 || wrap === false) return false;
9087
+ if (args === "literal") throw new TypeError(`The call form "${given.name}" with the arguments literal takes no wrap.`);
9088
+ if (wrap === true) return true;
9089
+ if (args === "list") throw new TypeError(`The call form "${given.name}" with the arguments list takes only the wrap true.`);
9090
+ for (const name of wrap) if (given.fields !== void 0 && !given.fields.includes(name)) throw new TypeError(`The call form "${given.name}" has no field ${name} for its wrap.`);
9091
+ return new Set(wrap);
9092
+ }
9093
+ /** This function gives the types of the data envelopes of a profile (K159), or `undefined` without them. */
9094
+ function compileEnvelopes(given) {
9095
+ if (given === void 0) return void 0;
9096
+ const out = {};
9097
+ for (const key of [
9098
+ "number",
9099
+ "text",
9100
+ "bool"
9101
+ ]) {
9102
+ const kind = given[key];
9103
+ if (kind !== void 0) out[key] = typeOfKind(kind);
9104
+ }
9105
+ return out;
9106
+ }
8290
9107
  function compileProfile(profile) {
8291
9108
  const cached = compiledProfiles.get(profile);
8292
9109
  if (cached !== void 0) return cached;
@@ -8301,13 +9118,22 @@ function compileProfile(profile) {
8301
9118
  const forms = /* @__PURE__ */ new Map();
8302
9119
  const formsByKind = /* @__PURE__ */ new Map();
8303
9120
  for (const given of calls.forms ?? []) {
8304
- if (!NAME.test(given.name)) throw new TypeError(`The call form "${given.name}" is not a plain name.`);
9121
+ const keys = given.name.split(".");
9122
+ if (!keys.every((key) => NAME.test(key))) throw new TypeError(`The call form "${given.name}" is not a plain name or a path of plain names.`);
9123
+ if (keys.length > 1 && refs.fields === false) throw new TypeError(`The call form "${given.name}" has dots, but the syntax has no field steps.`);
9124
+ if (keys.length > 1 && ops.opWords.has(keys[0])) throw new TypeError(`The call form "${given.name}" starts with the word operator "${keys[0]}".`);
8305
9125
  const { type, key } = typeOfKind(given.kind);
9126
+ const args = given.args ?? (given.fields === void 0 ? "list" : "fields");
9127
+ if (!FORM_ARGS.includes(args)) throw new TypeError(`The call form "${given.name}" has the unknown arguments ${String(args)}.`);
9128
+ if (args === "fields" !== (given.fields !== void 0) && args !== "named") throw new TypeError(`The call form "${given.name}" with the arguments ${args} ${args === "fields" ? "needs" : "takes no"} fields.`);
9129
+ if (given.min !== void 0 && (args === "named" || args === "literal")) throw new TypeError(`The call form "${given.name}" with the arguments ${args} takes no min.`);
8306
9130
  const form = {
8307
9131
  name: given.name,
8308
9132
  type,
9133
+ args,
8309
9134
  fields: given.fields,
8310
- min: given.min ?? given.fields?.length ?? 0
9135
+ min: given.min ?? given.fields?.length ?? 0,
9136
+ wrap: compileWrap(given, args)
8311
9137
  };
8312
9138
  forms.set(form.name, form);
8313
9139
  addTo(formsByKind, key, form);
@@ -8319,6 +9145,7 @@ function compileProfile(profile) {
8319
9145
  quote: strings === void 0 ? void 0 : strings.quote ?? "\"",
8320
9146
  doubled: strings !== void 0 && strings.escape === "double",
8321
9147
  words,
9148
+ envelopes: compileEnvelopes(literals.envelopes),
8322
9149
  bare: refs.bare ?? "names",
8323
9150
  roots,
8324
9151
  fields: refs.fields ?? true,
@@ -8335,6 +9162,7 @@ function compileProfile(profile) {
8335
9162
  forms,
8336
9163
  formsByKind,
8337
9164
  separator,
9165
+ bind: compileBind(profile.header?.bind, separator, ops.binary),
8338
9166
  reserved: /* @__PURE__ */ new Set([
8339
9167
  ...words.keys(),
8340
9168
  ...ops.opWords,
@@ -8361,6 +9189,37 @@ function opDoc(op, value) {
8361
9189
  value
8362
9190
  };
8363
9191
  }
9192
+ /** This function gives the kind of the data envelope of a literal (K159), or `undefined` when the literal has none. */
9193
+ function envelopeOf(syn, value) {
9194
+ const kinds = syn.envelopes;
9195
+ if (kinds === void 0 || !isScalar(value)) return void 0;
9196
+ return typeof value === "string" ? kinds.text : typeof value === "number" ? kinds.number : typeof value === "boolean" ? kinds.bool : void 0;
9197
+ }
9198
+ /** This function gives a literal in a place that takes a document its data envelope (K159). Each other document stays. */
9199
+ function envelop(syn, doc) {
9200
+ const kind = isEnvelope(doc) ? void 0 : envelopeOf(syn, doc);
9201
+ return kind === void 0 ? doc : {
9202
+ type: kind.type,
9203
+ value: doc
9204
+ };
9205
+ }
9206
+ /** This function tells if an argument of a form takes a document (K159). */
9207
+ function wraps(form, key) {
9208
+ return form.wrap === true || form.wrap !== false && form.wrap.has(String(key));
9209
+ }
9210
+ /** This function tells if a value is a literal that JSON writes exactly: a text, a finite number, a truth value or `null`. */
9211
+ function isScalar(value) {
9212
+ return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) && !Object.is(value, -0);
9213
+ }
9214
+ function setOwn$1(target, key, value) {
9215
+ if (key === "__proto__") Object.defineProperty(target, key, {
9216
+ value,
9217
+ enumerable: true,
9218
+ writable: true,
9219
+ configurable: true
9220
+ });
9221
+ else target[key] = value;
9222
+ }
8364
9223
  const ESCAPES = {
8365
9224
  "\"": "\"",
8366
9225
  "'": "'",
@@ -8384,10 +9243,10 @@ var Parser = class {
8384
9243
  parse() {
8385
9244
  this.skip();
8386
9245
  if (this.pos >= this.text.length) this.stop("The text is empty.", 0, 0);
8387
- const doc = this.expr(0);
9246
+ const doc = this.bound();
8388
9247
  this.skip();
8389
9248
  if (this.pos < this.text.length) this.stop("The text continues after the expression.", this.pos, this.tokenLength());
8390
- return doc;
9249
+ return envelop(this.syn, doc);
8391
9250
  }
8392
9251
  position() {
8393
9252
  return this.pos;
@@ -8409,6 +9268,60 @@ var Parser = class {
8409
9268
  tokenLength() {
8410
9269
  return (this.at(NAME_AT) ?? this.at(DIGITS_AT) ?? "x").length;
8411
9270
  }
9271
+ /**
9272
+ * This method reads an expression that can have a header name: `name = expr` (D62). The bind symbol of the profile
9273
+ * follows the name. A longer operator that starts with the symbol wins, for example `==` over `=`.
9274
+ */
9275
+ bound() {
9276
+ const name = this.bindingName();
9277
+ if (name === void 0) return this.expr(0);
9278
+ this.skip();
9279
+ const start = this.pos;
9280
+ const doc = this.expr(0);
9281
+ if (isEnvelope(doc)) {
9282
+ if (doc.name !== void 0) this.stop(`The document already has the name ${doc.name}.`, start, this.pos - start);
9283
+ return {
9284
+ ...doc,
9285
+ name
9286
+ };
9287
+ }
9288
+ const kind = envelopeOf(this.syn, doc);
9289
+ return kind === void 0 ? {
9290
+ type: "lit",
9291
+ value: doc,
9292
+ name
9293
+ } : {
9294
+ type: kind.type,
9295
+ value: doc,
9296
+ name
9297
+ };
9298
+ }
9299
+ /** This method reads a name and the bind symbol after it. Without them, it gives `undefined` and keeps the position. */
9300
+ bindingName() {
9301
+ const bind = this.syn.bind;
9302
+ if (bind === void 0) return void 0;
9303
+ this.skip();
9304
+ const back = this.pos;
9305
+ let name;
9306
+ if (this.text[this.pos] === "`") try {
9307
+ name = this.quoted();
9308
+ } catch (error) {
9309
+ if (!(error instanceof Stop)) throw error;
9310
+ }
9311
+ else {
9312
+ name = this.at(NAME_AT);
9313
+ if (name !== void 0) this.pos += name.length;
9314
+ }
9315
+ if (name !== void 0) {
9316
+ this.skip();
9317
+ const longer = this.syn.binarySymbols.some((symbol) => symbol.length > bind.length && symbol.startsWith(bind) && this.text.startsWith(symbol, this.pos));
9318
+ if (this.text.startsWith(bind, this.pos) && !longer) {
9319
+ this.pos += bind.length;
9320
+ return name;
9321
+ }
9322
+ }
9323
+ this.pos = back;
9324
+ }
8412
9325
  /** This method reads an expression by precedence climbing. It stops at an operator below `min`. */
8413
9326
  expr(min) {
8414
9327
  const start = this.pos;
@@ -8541,7 +9454,7 @@ var Parser = class {
8541
9454
  group() {
8542
9455
  const open = this.pos;
8543
9456
  this.pos += 1;
8544
- const inner = this.expr(0);
9457
+ const inner = this.bound();
8545
9458
  this.skip();
8546
9459
  if (this.text[this.pos] !== ")") {
8547
9460
  if (this.pos >= this.text.length) this.stop("A closing parenthesis is missing.", open, 1);
@@ -8591,6 +9504,11 @@ var Parser = class {
8591
9504
  }
8592
9505
  this.pos += 1;
8593
9506
  this.skip();
9507
+ if (this.text[this.pos] === "(") {
9508
+ path.push(this.group());
9509
+ allPlain = false;
9510
+ continue;
9511
+ }
8594
9512
  if (this.text[this.pos] === "`") {
8595
9513
  path.push(this.quoted());
8596
9514
  allPlain = false;
@@ -8606,7 +9524,7 @@ var Parser = class {
8606
9524
  const back = this.pos;
8607
9525
  this.skip();
8608
9526
  if (this.text[this.pos] === "(") {
8609
- if (!allPlain) this.stop("The name of a call is a plain name.", start, back - start);
9527
+ if (!allPlain) this.stop("Each key of the name of a call is a plain name.", start, back - start);
8610
9528
  return this.call(path.join("."), start, back - start);
8611
9529
  }
8612
9530
  this.pos = back;
@@ -8616,14 +9534,18 @@ var Parser = class {
8616
9534
  value: plain && this.syn.roots.has(first) ? path : [this.syn.bare, ...path]
8617
9535
  };
8618
9536
  }
8619
- call(name, start, nameLength) {
9537
+ /** This method reads the arguments of a call in parentheses. `item` reads one argument. */
9538
+ argumentsOf(item) {
8620
9539
  const open = this.pos;
8621
9540
  const args = [];
8622
9541
  this.pos += 1;
8623
9542
  this.skip();
8624
- if (this.text[this.pos] === ")") this.pos += 1;
8625
- else for (;;) {
8626
- args.push(this.expr(0));
9543
+ if (this.text[this.pos] === ")") {
9544
+ this.pos += 1;
9545
+ return args;
9546
+ }
9547
+ for (;;) {
9548
+ args.push(item());
8627
9549
  this.skip();
8628
9550
  if (this.text.startsWith(this.syn.separator, this.pos)) {
8629
9551
  this.pos += this.syn.separator.length;
@@ -8631,22 +9553,55 @@ var Parser = class {
8631
9553
  }
8632
9554
  if (this.text[this.pos] === ")") {
8633
9555
  this.pos += 1;
8634
- break;
9556
+ return args;
8635
9557
  }
8636
9558
  if (this.pos >= this.text.length) this.stop("A closing parenthesis is missing.", open, 1);
8637
9559
  this.stop(`A "${this.syn.separator}" or a closing parenthesis is missing.`, this.pos, this.tokenLength());
8638
9560
  }
9561
+ }
9562
+ /** This method reads the arguments `key: expr` of a form `named` into a record (SYNTAX.RECORD). */
9563
+ namedArguments(form) {
9564
+ const value = {};
9565
+ this.argumentsOf(() => {
9566
+ this.skip();
9567
+ const at = this.pos;
9568
+ let key;
9569
+ if (this.text[at] === "`") key = this.quoted();
9570
+ else {
9571
+ key = this.at(NAME_AT);
9572
+ if (key !== void 0) this.pos += key.length;
9573
+ }
9574
+ const end = this.pos;
9575
+ this.skip();
9576
+ if (key === void 0 || this.text[this.pos] !== ":") this.stop(`Each argument of the form ${form.name} is a key, a ":" and a document.`, at, Math.max(end - at, this.tokenLength()));
9577
+ if (form.fields !== void 0 && !form.fields.includes(key)) this.stop(`The form ${form.name} has no field ${key}.`, at, end - at);
9578
+ if (Object.hasOwn(value, key)) this.stop(`The form ${form.name} has the field ${key} two times.`, at, end - at);
9579
+ this.pos += 1;
9580
+ const arg = this.bound();
9581
+ setOwn$1(value, key, wraps(form, key) ? envelop(this.syn, arg) : arg);
9582
+ });
9583
+ return opDoc(form, value);
9584
+ }
9585
+ call(name, start, nameLength) {
8639
9586
  const form = this.syn.forms.get(name);
9587
+ if (form?.args === "named") return this.namedArguments(form);
9588
+ const args = this.argumentsOf(() => this.bound());
9589
+ if (form?.args === "literal") {
9590
+ const [only] = args;
9591
+ if (args.length !== 1 || !isScalar(only)) this.stop(`The form ${name} takes one literal that JSON writes.`, start, this.pos - start);
9592
+ return opDoc(form, only);
9593
+ }
8640
9594
  if (form !== void 0) {
8641
9595
  const most = form.fields?.length ?? Number.POSITIVE_INFINITY;
8642
9596
  if (args.length < form.min || args.length > most) {
8643
9597
  const range = most === form.min ? String(most) : most === Number.POSITIVE_INFINITY ? `${String(form.min)} or more` : `${String(form.min)} to ${String(most)}`;
8644
9598
  this.stop(`The form ${name} takes ${range} arguments.`, start, this.pos - start);
8645
9599
  }
8646
- if (form.fields === void 0) return opDoc(form, args);
9600
+ if (form.fields === void 0) return opDoc(form, form.wrap === true ? args.map((arg) => envelop(this.syn, arg)) : args);
8647
9601
  const value = {};
8648
9602
  args.forEach((arg, index) => {
8649
- value[form.fields?.[index]] = arg;
9603
+ const key = form.fields?.[index];
9604
+ value[key] = wraps(form, key) ? envelop(this.syn, arg) : arg;
8650
9605
  });
8651
9606
  return opDoc(form, value);
8652
9607
  }
@@ -8725,8 +9680,10 @@ function literalShape(syn, value) {
8725
9680
  function plainSegment(syn, name) {
8726
9681
  return NAME.test(name) && !syn.reserved.has(name) && !syn.patterns.some((p) => p.whole.test(name));
8727
9682
  }
8728
- function laterSegment(step) {
9683
+ /** This function gives the text of a later step of a path, or the step and its index when the step is a document. */
9684
+ function laterSegment(step, index) {
8729
9685
  if (typeof step === "string") return NAME.test(step) ? step : quoteName(step);
9686
+ if (isEnvelope(step)) return [index, step];
8730
9687
  return typeof step === "number" && Number.isSafeInteger(step) && step >= 0 ? String(step) : void 0;
8731
9688
  }
8732
9689
  function refShape(syn, value) {
@@ -8740,18 +9697,23 @@ function refShape(syn, value) {
8740
9697
  }
8741
9698
  const [root, ...rest] = value;
8742
9699
  if ((rest.length > 1 || root !== syn.bare && rest.length > 0) && !syn.fields) return none("This syntax has no field steps.");
8743
- const later = rest.slice(1).map(laterSegment);
8744
9700
  let first;
8745
- let tail = later;
8746
- if (root === syn.bare && typeof rest[0] === "string") first = plainSegment(syn, rest[0]) ? rest[0] : quoteName(rest[0]);
8747
- else if (typeof root === "string" && syn.roots.has(root) && !syn.patterns.some((p) => p.whole.test(root))) {
9701
+ let tail = [];
9702
+ if (root === syn.bare && typeof rest[0] === "string") {
9703
+ first = plainSegment(syn, rest[0]) ? rest[0] : quoteName(rest[0]);
9704
+ tail = rest.slice(1).map((step, index) => laterSegment(step, index + 2));
9705
+ } else if (typeof root === "string" && syn.roots.has(root) && !syn.patterns.some((p) => p.whole.test(root))) {
8748
9706
  first = root;
8749
- tail = rest.map(laterSegment);
9707
+ tail = rest.map((step, index) => laterSegment(step, index + 1));
8750
9708
  }
8751
9709
  if (first === void 0 || tail.includes(void 0)) return none("This syntax has no text for the path of the reference.");
8752
- return {
9710
+ const segments = [first, ...tail];
9711
+ return segments.every((segment) => typeof segment === "string") ? {
8753
9712
  tag: "text",
8754
- text: [first, ...tail].join(".")
9713
+ text: segments.join(".")
9714
+ } : {
9715
+ tag: "path",
9716
+ segments
8755
9717
  };
8756
9718
  }
8757
9719
  function callName(syn, keys) {
@@ -8760,13 +9722,58 @@ function callName(syn, keys) {
8760
9722
  if (syn.forms.has(name) || syn.opWords.has(keys[0])) return void 0;
8761
9723
  return syn.ops === true || syn.ops.has(name) ? name : void 0;
8762
9724
  }
8763
- function formShape(form, value) {
9725
+ const WRAPPED = "This syntax reads a literal in this place as its data envelope, thus a bare literal has no text here.";
9726
+ /**
9727
+ * This function gives the text of a document in a place that takes a document (K159). A data envelope of a literal
9728
+ * is the bare literal. A literal without its envelope has no text, because `parse` gives it the envelope. The
9729
+ * function gives `undefined` for each other document.
9730
+ */
9731
+ function wrappedShape(syn, doc) {
9732
+ if (syn.envelopes === void 0) return void 0;
9733
+ if (!isEnvelope(doc)) return envelopeOf(syn, doc) === void 0 ? void 0 : none(WRAPPED);
9734
+ if (doc.name !== void 0 || doc.own !== void 0 || !Object.hasOwn(doc, "value")) return void 0;
9735
+ const path = typePath(doc.type);
9736
+ if (path === void 0) return void 0;
9737
+ const key = JSON.stringify(path);
9738
+ if (key === JSON.stringify(["lit"])) return envelopeOf(syn, doc.value) === void 0 ? void 0 : none(WRAPPED);
9739
+ if (envelopeOf(syn, doc.value)?.key !== key) return void 0;
9740
+ const literal = literalShape(syn, doc.value);
9741
+ return literal.tag === "text" ? literal : void 0;
9742
+ }
9743
+ function formShape(syn, form, value) {
9744
+ if (form.args === "literal") {
9745
+ if (!isScalar(value)) return void 0;
9746
+ const literal = literalShape(syn, value);
9747
+ return literal.tag === "text" ? {
9748
+ tag: "text",
9749
+ text: `${form.name}(${literal.text})`
9750
+ } : void 0;
9751
+ }
9752
+ if (form.args === "named") {
9753
+ if (!isRecord(value)) return void 0;
9754
+ const keys = Object.keys(value);
9755
+ if (form.fields !== void 0 && !keys.every((key) => form.fields?.includes(key) === true)) return void 0;
9756
+ return {
9757
+ tag: "call",
9758
+ name: form.name,
9759
+ args: keys.map((key) => [
9760
+ key,
9761
+ value[key],
9762
+ wraps(form, key)
9763
+ ]),
9764
+ named: true
9765
+ };
9766
+ }
8764
9767
  if (form.fields === void 0) {
8765
9768
  if (!Array.isArray(value) || value.length < form.min) return void 0;
8766
9769
  return {
8767
9770
  tag: "call",
8768
9771
  name: form.name,
8769
- args: value.map((item, index) => [index, item])
9772
+ args: value.map((item, index) => [
9773
+ index,
9774
+ item,
9775
+ wraps(form, index)
9776
+ ])
8770
9777
  };
8771
9778
  }
8772
9779
  if (!isRecord(value)) return void 0;
@@ -8776,7 +9783,11 @@ function formShape(form, value) {
8776
9783
  return {
8777
9784
  tag: "call",
8778
9785
  name: form.name,
8779
- args: present.map((key) => [key, value[key]])
9786
+ args: present.map((key) => [
9787
+ key,
9788
+ value[key],
9789
+ wraps(form, key)
9790
+ ])
8780
9791
  };
8781
9792
  }
8782
9793
  function opShape(syn, key, terms) {
@@ -8789,7 +9800,16 @@ function opShape(syn, key, terms) {
8789
9800
  /** This function gives the shape of a document: a literal or a reference, an operator, a call, or no text. */
8790
9801
  function shapeOf(syn, doc) {
8791
9802
  if (!isEnvelope(doc)) return Array.isArray(doc) || isRecord(doc) ? none("This syntax has no text for a list or a record literal.") : literalShape(syn, doc);
8792
- if (doc.name !== void 0 || doc.own !== void 0) return none("This syntax has no text for the header of a document.");
9803
+ if (doc.own !== void 0) return none("This syntax has no text for the own entries of a document.");
9804
+ if (doc.name !== void 0) {
9805
+ if (syn.bind === void 0) return none("This syntax has no text for the name of a document.");
9806
+ const { name, ...rest } = doc;
9807
+ return {
9808
+ tag: "bind",
9809
+ name,
9810
+ doc: rest
9811
+ };
9812
+ }
8793
9813
  const path = typePath(doc.type);
8794
9814
  if (path === void 0) return none("This syntax has no text for a computed type.");
8795
9815
  const value = doc.value;
@@ -8810,7 +9830,7 @@ function shapeOf(syn, doc) {
8810
9830
  const op = Array.isArray(value) ? opShape(syn, key, value) : void 0;
8811
9831
  if (op !== void 0) return op;
8812
9832
  for (const form of syn.formsByKind.get(key) ?? []) {
8813
- const shape = formShape(form, value);
9833
+ const shape = formShape(syn, form, value);
8814
9834
  if (shape !== void 0) return shape;
8815
9835
  }
8816
9836
  const called = path[0] === "ops" && Array.isArray(value) ? callName(syn, path.slice(1)) : void 0;
@@ -8823,7 +9843,7 @@ function shapeOf(syn, doc) {
8823
9843
  }
8824
9844
  function levelOf(syn, doc) {
8825
9845
  const shape = shapeOf(syn, doc);
8826
- return shape.tag === "op" ? shape.op.prec : Number.POSITIVE_INFINITY;
9846
+ return shape.tag === "op" ? shape.op.prec : shape.tag === "bind" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;
8827
9847
  }
8828
9848
  /** This function tells if a term needs parentheses in its position, so that `parse` reads the same tree. */
8829
9849
  function needsGroup(op, index, level) {
@@ -8853,18 +9873,42 @@ function printNode(syn, doc, sub) {
8853
9873
  if (shape.tag === "text") return ok(shape.text);
8854
9874
  if (shape.tag === "none") return fail("#VALUE!", shape.reason);
8855
9875
  if (shape.tag === "op") return opText(syn, shape.op, shape.terms, sub);
9876
+ if (shape.tag === "bind") {
9877
+ const head = wrappedShape(syn, shape.doc);
9878
+ const inner = head === void 0 ? printNode(syn, shape.doc, sub) : head.tag === "text" ? ok(head.text) : fail("#VALUE!", WRAPPED);
9879
+ return inner.ok ? ok(`${NAME.test(shape.name) ? shape.name : quoteName(shape.name)} ${syn.bind} ${inner.value}`) : inner;
9880
+ }
9881
+ if (shape.tag === "path") {
9882
+ const texts = [];
9883
+ for (const segment of shape.segments) {
9884
+ if (typeof segment === "string") {
9885
+ texts.push(segment);
9886
+ continue;
9887
+ }
9888
+ const result = sub(segment[1], [segment[0]]);
9889
+ if (!result.ok) return result;
9890
+ texts.push(`(${result.value})`);
9891
+ }
9892
+ return ok(texts.join("."));
9893
+ }
8856
9894
  const texts = [];
8857
- for (const [key, arg] of shape.args) {
8858
- const result = sub(arg, [key]);
9895
+ for (const [key, arg, wrapped] of shape.args) {
9896
+ const result = sub(arg, [key], wrapped);
8859
9897
  if (!result.ok) return result;
8860
- texts.push(result.value);
9898
+ texts.push(shape.named === true ? `${NAME.test(String(key)) ? String(key) : quoteName(String(key))}: ${result.value}` : result.value);
8861
9899
  }
8862
9900
  return ok(`${shape.name}(${texts.join(`${syn.separator} `)})`);
8863
9901
  }
8864
9902
  function printTree(syn, doc, place) {
8865
- const result = printNode(syn, doc, (child, path) => printTree(syn, child, [...place, ...path]));
9903
+ const result = printNode(syn, doc, (child, path, wrapped) => (wrapped === true ? printPlace : printTree)(syn, child, [...place, ...path]));
8866
9904
  return result.ok || result.error.place !== void 0 ? result : fail(result.error.code, result.error.reason, { place });
8867
9905
  }
9906
+ /** This function writes a document in a place that takes a document, for example the whole text (K159). */
9907
+ function printPlace(syn, doc, place) {
9908
+ const shape = wrappedShape(syn, doc);
9909
+ if (shape === void 0) return printTree(syn, doc, place);
9910
+ return shape.tag === "text" ? ok(shape.text) : fail("#VALUE!", WRAPPED, { place });
9911
+ }
8868
9912
  /**
8869
9913
  * This function writes a document as text with the rules of a profile (SYNTAX.PRINT). It writes the fewest
8870
9914
  * parentheses that keep the tree. `parse` reads the text back to the same document (SYNTAX.ROUNDTRIP).
@@ -8877,7 +9921,7 @@ function printTree(syn, doc, place) {
8877
9921
  function print(profile, doc) {
8878
9922
  const syn = compileProfile(profile);
8879
9923
  try {
8880
- return printTree(syn, doc, []);
9924
+ return printPlace(syn, doc, []);
8881
9925
  } catch (error) {
8882
9926
  if (isStackOverflow(error)) return fail("#DEPTH!", "The document is too deep for the stack of the host.", { cause: error });
8883
9927
  throw error;
@@ -8895,7 +9939,9 @@ function syntaxFormat(profile) {
8895
9939
  const syn = compileProfile(profile);
8896
9940
  const code = ({ doc, parts, place }) => {
8897
9941
  const byPath = new Map(parts.map((part) => [JSON.stringify(part.path), part]));
8898
- return printNode(syn, doc, (child, path) => {
9942
+ return printNode(syn, doc, (child, path, wrapped) => {
9943
+ const own = wrapped === true ? wrappedShape(syn, child) : void 0;
9944
+ if (own !== void 0) return own.tag === "text" ? ok(own.text) : fail("#VALUE!", WRAPPED, { place: [...place, ...path] });
8899
9945
  const part = byPath.get(JSON.stringify(path));
8900
9946
  if (part === void 0) return printTree(syn, child, [...place, ...path]);
8901
9947
  const result = part.evaluate();
@@ -8908,8 +9954,7 @@ function syntaxFormat(profile) {
8908
9954
  evaluators: { "syntax.format": code }
8909
9955
  };
8910
9956
  }
8911
- //#endregion
8912
- //#region src/reference.ts
9957
+ // src/reference.ts
8913
9958
  function own$1(table, name) {
8914
9959
  return table !== void 0 && Object.hasOwn(table, name) ? table[name] : void 0;
8915
9960
  }
@@ -9016,6 +10061,54 @@ function resolveFully(machine, ctx, path, options) {
9016
10061
  hops: []
9017
10062
  };
9018
10063
  }
10064
+ /** The text that names a resolution in the error of an exception of the host (READS.RECORD). */
10065
+ const READ_FAILED = "the resolution of a path";
10066
+ /**
10067
+ * This function resolves a path for a document, and records the read when the evaluation has a list (REF.READS,
10068
+ * READS.RECORD). An exception of the host gives the error value of the read, and the exception goes on.
10069
+ */
10070
+ function readAt(env, ctx, path, options) {
10071
+ const reading = env.reading;
10072
+ if (reading === void 0) return resolveFully(env.machine, ctx, path, options);
10073
+ const free = freeIn(reading.root, ctx, path);
10074
+ let found;
10075
+ try {
10076
+ found = resolveFully(env.machine, ctx, path, options);
10077
+ } catch (error) {
10078
+ reading.list.push({
10079
+ path,
10080
+ reached: thrown(error, READ_FAILED),
10081
+ free
10082
+ });
10083
+ throw error;
10084
+ }
10085
+ reading.list.push(options?.hops === true ? {
10086
+ path,
10087
+ reached: reachedOf(found),
10088
+ free,
10089
+ hops: found.hops
10090
+ } : {
10091
+ path,
10092
+ reached: reachedOf(found),
10093
+ free
10094
+ });
10095
+ return found;
10096
+ }
10097
+ /**
10098
+ * This function tells if a read reads the context at the root of the evaluation (READS.FREE). The reference reads
10099
+ * the rule from SPEC. A name that a kind binds, a `self` that a kind sets and a path without a root are not free. A
10100
+ * name that a kind does not bind keeps its value from the root.
10101
+ */
10102
+ function freeIn(root, ctx, path) {
10103
+ const head = path[0];
10104
+ if (head === "self") return Object.is(ctx.self, root.self);
10105
+ if (head !== "names") return typeof head === "string" && ROOTS.includes(head);
10106
+ const name = path[1];
10107
+ if (ctx.names === root.names || !isKey(name)) return true;
10108
+ const key = String(name);
10109
+ const bound = Object.hasOwn(ctx.names, key);
10110
+ return bound === Object.hasOwn(root.names, key) && (!bound || Object.is(ctx.names[key], root.names[key]));
10111
+ }
9019
10112
  /**
9020
10113
  * This function causes an effect when the capabilities permit it (RUN.CAP, CAP.HOOK). It records the effect with its
9021
10114
  * address (RUN.ADDRESS) and its outcome (RUN.OUTCOME). The mock answers the effect at once (RUN.MOCK). Without a
@@ -9047,6 +10140,11 @@ function* causeAndWait(env, ctx, kind, payload, place) {
9047
10140
  if ("ok" in effect) return effect;
9048
10141
  const perform = env.perform;
9049
10142
  if (perform === void 0) return effect.outcome = ok(payload);
10143
+ if (env.held > 0) {
10144
+ effect.outcome = fail("#CALC!", heldReason(kind), { place });
10145
+ yield Promise.resolve(void 0);
10146
+ return effect.outcome;
10147
+ }
9050
10148
  let given;
9051
10149
  try {
9052
10150
  given = perform(effect);
@@ -9116,7 +10214,15 @@ function evaluateSeen(env, seen, at) {
9116
10214
  const { chosen } = seen;
9117
10215
  const { place } = at;
9118
10216
  if ("gap" in chosen) return fail("#NOEVAL", chosen.gap, { place });
9119
- if ("runner" in chosen) return drive$1(runSeen(env, seen, at, chosen.runner), place, seen.kindText);
10217
+ if ("runner" in chosen) {
10218
+ if (!env.running) return drive$1(runSeen(env, seen, at, chosen.runner), place, seen.kindText);
10219
+ env.held += 1;
10220
+ try {
10221
+ return drive$1(runSeen(env, seen, at, chosen.runner), place, seen.kindText);
10222
+ } finally {
10223
+ env.held -= 1;
10224
+ }
10225
+ }
9120
10226
  const input = evalInput(env, seen, at);
9121
10227
  try {
9122
10228
  return placed(chosen.evaluator(input), place);
@@ -9170,7 +10276,7 @@ function evalInput(env, seen, at) {
9170
10276
  place: at.place,
9171
10277
  machine: env.machine,
9172
10278
  ...at.address ? { address: true } : {},
9173
- resolve: (path, options) => resolveFully(env.machine, at.ctx, path, options),
10279
+ resolve: (path, options) => readAt(env, at.ctx, path, options),
9174
10280
  effect: (kind, payload) => causeFromEvaluator(env, at.ctx, kind, payload, at.place),
9175
10281
  fill
9176
10282
  };
@@ -9197,7 +10303,7 @@ function runInput(env, seen, at) {
9197
10303
  context: at.ctx,
9198
10304
  place: at.place,
9199
10305
  machine: env.machine,
9200
- resolve: (path, options) => resolveFully(env.machine, at.ctx, path, options),
10306
+ resolve: (path, options) => readAt(env, at.ctx, path, options),
9201
10307
  effect: (kind, payload) => causeAndWait(env, at.ctx, kind, payload, at.place),
9202
10308
  all: (list, options) => together(env, list, options),
9203
10309
  fill
@@ -9226,6 +10332,7 @@ function* together(env, list, options = {}) {
9226
10332
  outer.alls += 1;
9227
10333
  let failed = false;
9228
10334
  let started = 0;
10335
+ let before = 0;
9229
10336
  const end = (index, result) => {
9230
10337
  results[index] = result;
9231
10338
  if (failFast && !result.ok) failed = true;
@@ -9289,10 +10396,11 @@ function* together(env, list, options = {}) {
9289
10396
  };
9290
10397
  startMore();
9291
10398
  while (waiting.length > 0 && !failed) {
9292
- const chosen = env.journal?.next?.(address, waiting.map((waiter) => waiter.index));
10399
+ const chosen = env.journal?.next?.(address, waiting.map((waiter) => waiter.index), before);
9293
10400
  const pick = chosen === void 0 ? void 0 : waiting.find((waiter) => waiter.index === chosen);
9294
10401
  const resumed = yield pick === void 0 ? Promise.race(waiting.map((waiter) => waiter.next)) : pick.next;
9295
10402
  env.journal?.settled?.(address, resumed.waiter.index);
10403
+ before += 1;
9296
10404
  waiting.splice(waiting.indexOf(resumed.waiter), 1);
9297
10405
  goOn(resumed.waiter.index, resumed.waiter.steps, resumed);
9298
10406
  startMore();
@@ -9319,9 +10427,17 @@ function* together(env, list, options = {}) {
9319
10427
  * @returns The result.
9320
10428
  */
9321
10429
  function reference(machine, doc, context = makeContext(), options = {}) {
9322
- const env = envOf(machine, options, false);
10430
+ return evaluateRoot(machine, doc, context, options, void 0);
10431
+ }
10432
+ /**
10433
+ * This function evaluates a document from its root. An equation of a tree gives the record of its tree. Thus the
10434
+ * reads of the equation go in the list of the outer evaluation (REF.READS).
10435
+ */
10436
+ function evaluateRoot(machine, doc, context, options, outer) {
10437
+ const at = rootAt(machine, doc, context, options);
10438
+ const env = envOf(machine, options, false, at.ctx, outer);
9323
10439
  try {
9324
- return within(env, () => evaluateAt(env, rootAt(machine, doc, context, options)));
10440
+ return within(env, () => evaluateAt(env, at));
9325
10441
  } catch (error) {
9326
10442
  return placed(thrown(error, "the reference"), []);
9327
10443
  }
@@ -9342,11 +10458,15 @@ function reference(machine, doc, context = makeContext(), options = {}) {
9342
10458
  * @returns The result, when the run ends.
9343
10459
  */
9344
10460
  function referenceRun(machine, doc, context = makeContext(), options = {}) {
9345
- const env = envOf(machine, options, true);
9346
- return driveRun(env, stepsAt(env, rootAt(machine, doc, context, options)), options.signal).catch((error) => placed(thrown(error, "the reference"), []));
10461
+ const at = rootAt(machine, doc, context, options);
10462
+ const env = envOf(machine, options, true, at.ctx, void 0);
10463
+ return driveRun(env, stepsAt(env, at), options.signal).catch((error) => placed(thrown(error, "the reference"), []));
9347
10464
  }
9348
- /** This function makes the state of the reference for one evaluation or one run. */
9349
- function envOf(machine, options, running) {
10465
+ /**
10466
+ * This function makes the state of the reference for one evaluation or one run. The record of the reads comes from
10467
+ * the evaluation around it, or from the list of the options.
10468
+ */
10469
+ function envOf(machine, options, running, root, outer) {
9350
10470
  const perform = options.perform;
9351
10471
  return {
9352
10472
  machine,
@@ -9361,7 +10481,12 @@ function envOf(machine, options, running) {
9361
10481
  prefix: "",
9362
10482
  counts: /* @__PURE__ */ new Map(),
9363
10483
  alls: 0
9364
- }
10484
+ },
10485
+ held: 0,
10486
+ reading: outer ?? (options.reads === void 0 ? void 0 : {
10487
+ list: options.reads,
10488
+ root
10489
+ })
9365
10490
  };
9366
10491
  }
9367
10492
  /** This function gives the root position of a document. A context without a world gets the world of the machine. */
@@ -9436,7 +10561,8 @@ function refNodeOf(thing) {
9436
10561
  }
9437
10562
  /**
9438
10563
  * TREE.LADDER: an equation of the kind of a node evaluates in the reference. It gets the node as `self`, the names of
9439
- * its rung and no capabilities. A bare equation gets the type `of` of the parts of the kind.
10564
+ * its rung and no capabilities. A bare equation gets the type `of` of the parts of the kind. The reads of the
10565
+ * equation go in the record of the evaluation that made the node (REF.READS).
9440
10566
  */
9441
10567
  function equationOf(node, term, names) {
9442
10568
  const env = node.env;
@@ -9447,10 +10573,10 @@ function equationOf(node, term, names) {
9447
10573
  caps: [],
9448
10574
  self: node.thing
9449
10575
  };
9450
- return reference(env.machine, term, ctx, {
10576
+ return evaluateRoot(env.machine, term, ctx, {
9451
10577
  definitions: env.definitions,
9452
10578
  ...node.of === void 0 ? {} : { declaredType: node.of }
9453
- });
10579
+ }, env.reading);
9454
10580
  }
9455
10581
  function termIn(table, name) {
9456
10582
  return table === void 0 || !Object.hasOwn(table, name) ? void 0 : table[name];
@@ -9696,10 +10822,13 @@ function formulaDefinitions(profile = {}) {
9696
10822
  }
9697
10823
  const head = path[0] === "names" && typeof path[1] === "string" ? path[1] : void 0;
9698
10824
  const bound = head === void 0 ? void 0 : own$1(context.names, head);
9699
- if (bound instanceof Held) return {
9700
- ok: false,
9701
- error: bound.error
9702
- };
10825
+ if (bound instanceof Held) {
10826
+ walk(["names", head]);
10827
+ return {
10828
+ ok: false,
10829
+ error: bound.error
10830
+ };
10831
+ }
9703
10832
  const found = walk(steps);
9704
10833
  if (!found.ok) return fail(found.code, found.reason);
9705
10834
  if (address === true) return ok(found.thing);
@@ -9855,25 +10984,27 @@ function valuesOfStrict(parts) {
9855
10984
  }
9856
10985
  return { values };
9857
10986
  }
9858
- //#endregion
9859
- //#region src/replay.ts
10987
+ // src/replay.ts
9860
10988
  /**
9861
10989
  * This function makes a recorder (RUN.RECORD). The recorder gives each effect to the function `perform` of the host.
9862
10990
  * Its log keeps each effect with its address, its kind, its payload and the outcome that the kernel gives it. The log
9863
10991
  * also keeps the order in which the waits of each `all` settle.
9864
10992
  *
10993
+ * The recorder gives each call of its journal to the journal of the inner function, for example of a replayer. Thus a
10994
+ * recording of a replay settles the waits in the order of the replayer, and it gives the same log (RUN.REPLAY-ORDER).
10995
+ *
9865
10996
  * @param perform - The function of the host. Without it, each effect gives its payload, as in a run without a host.
9866
10997
  * @returns The function `perform` for the run, and the log.
9867
10998
  */
9868
10999
  function recorder(perform) {
9869
11000
  const seen = [];
9870
11001
  const settles = [];
9871
- const journal = { settled: (all, item) => {
11002
+ const journal = relay(perform, (all, item) => {
9872
11003
  settles.push({
9873
11004
  all,
9874
11005
  item
9875
11006
  });
9876
- } };
11007
+ });
9877
11008
  const host = (effect) => {
9878
11009
  const entry = {
9879
11010
  effect,
@@ -9903,14 +11034,17 @@ function recorder(perform) {
9903
11034
  * recorded error comes again with its code, its reason, its place and its cause. The waits of each `all` settle in the
9904
11035
  * recorded order. An effect that the log does not have at its address gives `#REPLAY!` (RUN.REPLAY-MISMATCH).
9905
11036
  *
9906
- * A replayer keeps its place in the order of the waits, thus each run needs a new replayer.
11037
+ * One replayer serves more than one run, also two runs at the same time (RUN.REPLAY-RUNS). The kernel tells the journal
11038
+ * the number of the waits of each `all` that settled before, thus the replayer keeps no state of a run. When the
11039
+ * recorded item of a wait does not wait in the run, that wait follows the order of the host.
9907
11040
  *
9908
- * @param log - The log of a recorder.
9909
- * @param options - `wait: false` for an evaluation.
11041
+ * @param log - The log of a recorder, or of `decodeLog`.
11042
+ * @param options - `wait: false` for an evaluation, and the rule of the host for payloads.
9910
11043
  * @returns The function `perform` for the replay.
9911
11044
  */
9912
11045
  function replayer(log, options = {}) {
9913
11046
  const wait = options.wait !== false;
11047
+ const equal = options.equal;
9914
11048
  const entries = /* @__PURE__ */ new Map();
9915
11049
  for (const entry of log.effects) entries.set(entry.address, entry);
9916
11050
  const order = /* @__PURE__ */ new Map();
@@ -9919,16 +11053,19 @@ function replayer(log, options = {}) {
9919
11053
  if (items === void 0) order.set(settle.all, [settle.item]);
9920
11054
  else items.push(settle.item);
9921
11055
  }
9922
- const journal = { next: (all, waiting) => {
11056
+ let places;
11057
+ const journal = { next: (all, waiting, before) => {
9923
11058
  const items = order.get(all);
9924
- const item = items?.[0];
9925
- if (items === void 0 || item === void 0 || !waiting.includes(item)) return void 0;
9926
- items.shift();
11059
+ if (items === void 0) return void 0;
11060
+ const at = before ?? (places ??= /* @__PURE__ */ new Map()).get(all) ?? 0;
11061
+ const item = items[at];
11062
+ if (item === void 0 || !waiting.includes(item)) return void 0;
11063
+ if (before === void 0) places?.set(all, at + 1);
9927
11064
  return item;
9928
11065
  } };
9929
11066
  const perform = (effect) => {
9930
11067
  const entry = effect.address === void 0 ? void 0 : entries.get(effect.address);
9931
- const wrong = mismatch(effect, entry);
11068
+ const wrong = mismatch(effect, entry, equal);
9932
11069
  if (wrong !== void 0 || entry === void 0) throw wrong;
9933
11070
  const outcome = entry.outcome;
9934
11071
  const failure = outcome === void 0 ? replayError(effect, `The log has no outcome for the effect ${effect.kind} at ${effect.address ?? ""}: the recorded run stopped before the answer.`) : outcome.ok ? void 0 : new Failure(outcome.error);
@@ -9940,59 +11077,998 @@ function replayer(log, options = {}) {
9940
11077
  return Object.assign(perform, { [JOURNAL]: journal });
9941
11078
  }
9942
11079
  /** This function gives the error of an effect that the log does not have at its address, or `undefined`. */
9943
- function mismatch(effect, entry) {
11080
+ function mismatch(effect, entry, equal) {
9944
11081
  const at = effect.address ?? "";
9945
11082
  if (entry === void 0) return replayError(effect, `The log has no effect at the address ${at}, and the run asks for the effect ${effect.kind}.`);
9946
11083
  if (entry.kind !== effect.kind) return replayError(effect, `The log has the effect ${entry.kind} at the address ${at}, and the run asks for the effect ${effect.kind}.`);
9947
- if (!docEquals(entry.payload, effect.payload)) return replayError(effect, `The effect ${effect.kind} at the address ${at} has another payload than the log.`);
11084
+ if (!equalWith(entry.payload, effect.payload, equal)) return replayError(effect, `The effect ${effect.kind} at the address ${at} has another payload than the log.`);
9948
11085
  }
9949
11086
  /** This function gives the exception that carries `#REPLAY!` to the kernel, with the place of the effect. */
9950
11087
  function replayError(effect, reason) {
9951
11088
  return new Failure(fail("#REPLAY!", reason, { place: effect.place }).error);
9952
11089
  }
9953
- //#endregion
9954
- //#region src/agree.ts
9955
- /** The tiers that `agree` compares when its options name none. */
9956
- const DEFAULT_TIERS = /* @__PURE__ */ Object.freeze([
9957
- "reference",
9958
- "traced",
9959
- "again",
9960
- "folds",
9961
- "fixed"
9962
- ]);
9963
11090
  /**
9964
- * This function tells if two values are the same for `agree`. Lists and plain records compare item by item and field
9965
- * by field, and the order of the fields does not matter. Each other leaf compares with `Object.is`, thus `-0` is not
9966
- * `0`, and `NaN` is `NaN`. The identity of a list or of a plain record is not compared.
9967
- *
9968
- * Two closures of `fn` are the same when they have the same parameters. Two `Held` values are the same when their
9969
- * errors have the same code and place. Each other object is the same only as itself, unless the rule of the caller
9970
- * tells otherwise.
11091
+ * This function gives a journal that tells a function of its own each wait that settles. It gives each call to the
11092
+ * journal of the inner function `perform`, when that function has one.
9971
11093
  *
9972
- * `docEquals` and `sameResult` use the same walk (D20). `docEquals` has no rules for closures, for `Held` values and
9973
- * for a rule of the caller. `sameResult` is for an early cutoff, thus a closure is the same there only as itself, and
9974
- * two errors also need the same reason.
9975
- *
9976
- * @param a - The first value.
9977
- * @param b - The second value.
9978
- * @param equal - The rule of the caller for other values. It answers first, and `undefined` gives the rules above.
9979
- * @returns `true` when the values are the same.
11094
+ * @param perform - The inner function.
11095
+ * @param settled - The function of its own.
11096
+ * @returns The journal.
9980
11097
  */
9981
- function sameValue(a, b, equal) {
9982
- return equalWith(a, b, equal === void 0 ? sameInTiers : (x, y) => equal(x, y) ?? sameInTiers(x, y));
11098
+ function relay(perform, settled) {
11099
+ const inner = perform === void 0 ? void 0 : perform[JOURNAL];
11100
+ const tell = (all, item) => {
11101
+ settled(all, item);
11102
+ inner?.settled?.(all, item);
11103
+ };
11104
+ if (inner?.next === void 0) return { settled: tell };
11105
+ return {
11106
+ settled: tell,
11107
+ next: (all, waiting, before) => inner.next?.(all, waiting, before)
11108
+ };
9983
11109
  }
9984
- /** The rules of `sameValue` for the values that two tiers make again: closures and held errors. */
9985
- function sameInTiers(x, y) {
9986
- if (isClosure(x) || isClosure(y)) return isClosure(x) && isClosure(y) && docEquals(closureParams(x), closureParams(y));
9987
- if (x instanceof Held || y instanceof Held) return x instanceof Held && y instanceof Held && errorDiffers(x.error, y.error, false) === void 0;
11110
+ /** This function tells if a key is a field of an error value that the JSON form keeps. */
11111
+ function errorField(key) {
11112
+ return key === "code" || key === "reason" || key === "place" || key === "cause";
9988
11113
  }
9989
- const CLOSURE = /* @__PURE__ */ Symbol.for("coeval.closure");
9990
- /** This function gives the parameters of a closure of `fn`, or `undefined` for another function. */
9991
- function closureParams(fn) {
9992
- return fn[CLOSURE]?.params;
11114
+ /** This function tells if a key is a field of an exception that the JSON form keeps in a field of its own, or drops. */
11115
+ function ownField(key) {
11116
+ return key === "name" || key === "message" || key === "stack" || key === "cause";
9993
11117
  }
9994
- function codeAndPlace(error) {
9995
- return error.place === void 0 ? error.code : `${error.code} at [${error.place.join(", ")}]`;
11118
+ /** This function tells if a key is a field of the JSON form of an exception. */
11119
+ function exceptionField(key) {
11120
+ return key === "name" || key === "message" || key === "fields" || key === "parts" || key === "dropped" || key === "hidden" || key === "cause" || key === "exception" || key === "loop" || key === "causeParts";
11121
+ }
11122
+ /**
11123
+ * The own fields that are not enumerable and that the JSON form keeps in `hidden` (D77). The standard classes define
11124
+ * them: `errors` of `AggregateError`, `error` and `suppressed` of `SuppressedError`.
11125
+ */
11126
+ const HIDDEN = /* @__PURE__ */ Object.freeze([
11127
+ "errors",
11128
+ "error",
11129
+ "suppressed"
11130
+ ]);
11131
+ /** The result of `readField` for a field that the walk of `causeJson` cannot read. */
11132
+ const MISSING = /* @__PURE__ */ Symbol("missing");
11133
+ /**
11134
+ * This function tells if a value holds a hole of a list at some depth. `encodeValue` writes a hole as `undefined`. Thus
11135
+ * the walk of `causeJson` keeps such a value in parts, and the hole keeps its mark (D82).
11136
+ */
11137
+ function holdsHole(value) {
11138
+ const seen = /* @__PURE__ */ new Set();
11139
+ const stack = [value];
11140
+ while (stack.length > 0) {
11141
+ const at = stack.pop();
11142
+ if (typeof at !== "object" || at === null || seen.has(at) || !(Array.isArray(at) || isRecord(at))) continue;
11143
+ seen.add(at);
11144
+ if (Array.isArray(at)) for (let item = 0; item < at.length; item += 1) {
11145
+ if (!Object.hasOwn(at, item)) return true;
11146
+ stack.push(at[item]);
11147
+ }
11148
+ else for (const key of Object.keys(at)) stack.push(at[key]);
11149
+ }
11150
+ return false;
11151
+ }
11152
+ /**
11153
+ * This function gives the lists and the plain records that the walk of `causeJson` keeps as containers of parts, also
11154
+ * with a term document (D101). Such a container is at two places of the walk, or it holds such a container at some depth.
11155
+ * It reads the values as the walk does: the fields of an exception, its hidden fields and its cause, and the items of a
11156
+ * container. A term document gives a copy at each place, thus a shared container cannot be one.
11157
+ */
11158
+ function sharedOf(root) {
11159
+ const seen = /* @__PURE__ */ new Set();
11160
+ const twice = [];
11161
+ const owners = /* @__PURE__ */ new Map();
11162
+ const stack = [[root, void 0]];
11163
+ for (let next = stack.pop(); next !== void 0; next = stack.pop()) {
11164
+ const [at, owner] = next;
11165
+ if (typeof at !== "object" || at === null) continue;
11166
+ const container = Array.isArray(at) || isRecord(at);
11167
+ if (!container && !(at instanceof Error)) continue;
11168
+ if (container && owner !== void 0) {
11169
+ const list = owners.get(at);
11170
+ if (list === void 0) owners.set(at, [owner]);
11171
+ else list.push(owner);
11172
+ }
11173
+ if (seen.has(at)) {
11174
+ if (container) twice.push(at);
11175
+ continue;
11176
+ }
11177
+ seen.add(at);
11178
+ if (Array.isArray(at)) {
11179
+ for (let item = 0; item < at.length; item += 1) if (Object.hasOwn(at, item)) stack.push([readField(at, item), at]);
11180
+ } else if (container) for (const key of Object.keys(at)) stack.push([readField(at, key), at]);
11181
+ else {
11182
+ for (const key of Object.keys(at)) if (!ownField(key)) stack.push([readField(at, key), void 0]);
11183
+ for (const key of HIDDEN) if (Object.getOwnPropertyDescriptor(at, key)?.enumerable === false) stack.push([readField(at, key), void 0]);
11184
+ if (Object.hasOwn(at, "cause")) stack.push([readField(at, "cause"), void 0]);
11185
+ }
11186
+ }
11187
+ const shared = /* @__PURE__ */ new Set();
11188
+ for (let at = twice.pop(); at !== void 0; at = twice.pop()) {
11189
+ if (shared.has(at)) continue;
11190
+ shared.add(at);
11191
+ for (const owner of owners.get(at) ?? []) twice.push(owner);
11192
+ }
11193
+ return shared;
11194
+ }
11195
+ /**
11196
+ * This function tells if the walk of `causeJson` keeps a value with a term document as a container of parts (D101). The
11197
+ * value is in the set of `sharedOf`. A member of a domain stays a term document, because its codec makes it again.
11198
+ */
11199
+ function wholeOf(shared, value, term) {
11200
+ if (typeof value !== "object" || value === null || !shared.has(value)) return false;
11201
+ const type = isRecord(term) ? term["type"] : void 0;
11202
+ return !(Array.isArray(type) && type[0] === "ext" && type[1] === "domain");
11203
+ }
11204
+ /**
11205
+ * This function tells if a list or a plain record holds an exception at some depth (D87). It reads the items as the
11206
+ * walk of `causeJson` does, thus a container cause of an error value with an exception gets a form.
11207
+ */
11208
+ function holdsException(value) {
11209
+ const seen = /* @__PURE__ */ new Set();
11210
+ const stack = [value];
11211
+ while (stack.length > 0) {
11212
+ const at = stack.pop();
11213
+ if (at instanceof Error) return true;
11214
+ if (typeof at !== "object" || at === null || seen.has(at) || !(Array.isArray(at) || isRecord(at))) continue;
11215
+ seen.add(at);
11216
+ if (Array.isArray(at)) {
11217
+ for (let item = 0; item < at.length; item += 1) if (Object.hasOwn(at, item)) stack.push(readField(at, item));
11218
+ } else for (const key of Object.keys(at)) stack.push(readField(at, key));
11219
+ }
11220
+ return false;
11221
+ }
11222
+ /** This function gives the field of a cause for its form after the walk (D76, D87). A cause without a form has no field. */
11223
+ function causeOf(built) {
11224
+ const form = built.form;
11225
+ if (form === void 0) return { names: built.names };
11226
+ if (Array.isArray(form) || "record" in form || "share" in form) return {
11227
+ link: { causeParts: form },
11228
+ names: built.names
11229
+ };
11230
+ return {
11231
+ link: "value" in form ? { cause: form.value } : form,
11232
+ names: built.names
11233
+ };
11234
+ }
11235
+ /** This function gives the term document of a value of an exception, or `undefined` when the value has none. */
11236
+ function termOrNothing(machine, value) {
11237
+ if (holdsHole(value)) return void 0;
11238
+ try {
11239
+ return encodeValue(machine, value);
11240
+ } catch {
11241
+ return;
11242
+ }
11243
+ }
11244
+ /** This function reads a field of a value, or gives `MISSING` when the read throws. */
11245
+ function readField(value, key) {
11246
+ try {
11247
+ return value[key];
11248
+ } catch {
11249
+ return MISSING;
11250
+ }
11251
+ }
11252
+ /** This function gives the forms of the parts with a form, with their keys, in the order of the keys. */
11253
+ function keptOf(keys, built) {
11254
+ const kept = [];
11255
+ for (let place = 0; place < keys.length; place += 1) {
11256
+ const form = built[place]?.form;
11257
+ if (form !== void 0) kept.push([keys[place], form]);
11258
+ }
11259
+ return kept;
11260
+ }
11261
+ /**
11262
+ * This function writes a cause without a term document as JSON (RUN.REPLAY-CAUSES, RUN.REPLAY-HIDDEN, RUN.REPLAY-FIELDS).
11263
+ * The cause is an exception with its hidden fields and its causes, or a container with an exception (D87). A host
11264
+ * makes the exception, thus a part without a term document is a note in `dropped`, not a refusal (D75, D76).
11265
+ *
11266
+ * The walk gives each exception an index in the order of a depth-first walk. It takes the fields in `parts` in the
11267
+ * order of their keys, the hidden fields in the order of `HIDDEN`, then the cause (D78). A list or a plain record
11268
+ * without a term document is a container of parts, with its items in their order (D82). The cause of an error value
11269
+ * is a container only when it holds an exception (D87). The cause of an exception is a container as a field is (D100).
11270
+ * A value that is an earlier exception of the walk is its index in `loop` (D77).
11271
+ *
11272
+ * A container that an earlier place holds is its index in `share`, also a container that holds itself (D88). A container
11273
+ * of `sharedOf` is a container of parts also with a term document, thus each share gives one object (D101). The value
11274
+ * `tried` marks a root that `encodeValue` cannot write. The walk is a loop, thus a long chain does not overflow the stack.
11275
+ */
11276
+ function causeJson(machine, root, shared, tried) {
11277
+ const items = [];
11278
+ const index = /* @__PURE__ */ new Map();
11279
+ const holders = /* @__PURE__ */ new Map();
11280
+ const tasks = [];
11281
+ const later = (children) => {
11282
+ for (let place = children.length - 1; place >= 0; place -= 1) tasks.push(children[place]);
11283
+ };
11284
+ const hold = (name, value, keep, children) => {
11285
+ const at = items.length;
11286
+ holders.set(value, at);
11287
+ const list = Array.isArray(value);
11288
+ const keys = list ? [] : Object.keys(value);
11289
+ const slots = [];
11290
+ items.push({
11291
+ name,
11292
+ list,
11293
+ keep,
11294
+ keys,
11295
+ slots
11296
+ });
11297
+ const size = list ? value.length : keys.length;
11298
+ for (let place = 0; place < size; place += 1) {
11299
+ const key = list ? place : keys[place];
11300
+ const item = list && !Object.hasOwn(value, place) ? MISSING : readField(value, key);
11301
+ const put = (part) => {
11302
+ slots[place] = part;
11303
+ };
11304
+ children.push({
11305
+ value: item,
11306
+ name: `${name}.${key}`,
11307
+ tried: false,
11308
+ nest: true,
11309
+ keep: false,
11310
+ put
11311
+ });
11312
+ }
11313
+ return at;
11314
+ };
11315
+ const open = (current) => {
11316
+ const at = items.length;
11317
+ index.set(current, index.size);
11318
+ const fields = [];
11319
+ const linked = [];
11320
+ for (const key of Object.keys(current)) {
11321
+ if (ownField(key)) continue;
11322
+ const value = readField(current, key);
11323
+ const term = value === MISSING ? void 0 : termOrNothing(machine, value);
11324
+ if (term === void 0) linked.push([
11325
+ key,
11326
+ value,
11327
+ true
11328
+ ]);
11329
+ else if (wholeOf(shared, value, term)) linked.push([
11330
+ key,
11331
+ value,
11332
+ false
11333
+ ]);
11334
+ else fields.push([key, term]);
11335
+ }
11336
+ const node = {
11337
+ head: {
11338
+ name: String(current.name),
11339
+ message: String(current.message),
11340
+ ...fields.length === 0 ? {} : { fields: Object.fromEntries(fields) }
11341
+ },
11342
+ keys: linked.map(([key]) => key),
11343
+ parts: [],
11344
+ hiddenKeys: [],
11345
+ hidden: []
11346
+ };
11347
+ items.push(node);
11348
+ const children = [];
11349
+ for (let place = 0; place < linked.length; place += 1) {
11350
+ const [key, value, without] = linked[place];
11351
+ const put = (part) => {
11352
+ node.parts[place] = part;
11353
+ };
11354
+ children.push({
11355
+ value,
11356
+ name: key,
11357
+ tried: without,
11358
+ nest: true,
11359
+ keep: false,
11360
+ put
11361
+ });
11362
+ }
11363
+ for (const key of HIDDEN) {
11364
+ if (Object.getOwnPropertyDescriptor(current, key)?.enumerable !== false) continue;
11365
+ const place = node.hiddenKeys.length;
11366
+ node.hiddenKeys.push(key);
11367
+ const value = readField(current, key);
11368
+ const put = (part) => {
11369
+ node.hidden[place] = part;
11370
+ };
11371
+ children.push({
11372
+ value,
11373
+ name: key,
11374
+ tried: false,
11375
+ nest: true,
11376
+ keep: Array.isArray(value),
11377
+ put
11378
+ });
11379
+ }
11380
+ if (Object.hasOwn(current, "cause")) {
11381
+ const put = (part) => {
11382
+ node.cause = part;
11383
+ };
11384
+ children.push({
11385
+ value: current.cause,
11386
+ name: "cause",
11387
+ tried: false,
11388
+ nest: true,
11389
+ keep: false,
11390
+ put
11391
+ });
11392
+ }
11393
+ later(children);
11394
+ return at;
11395
+ };
11396
+ let top = { none: "cause" };
11397
+ tasks.push({
11398
+ value: root,
11399
+ name: "cause",
11400
+ tried,
11401
+ nest: false,
11402
+ keep: false,
11403
+ put: (part) => {
11404
+ top = part;
11405
+ }
11406
+ });
11407
+ for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {
11408
+ const value = task.value;
11409
+ if (value === MISSING) {
11410
+ task.put({ none: task.name });
11411
+ continue;
11412
+ }
11413
+ const loop = index.get(value);
11414
+ if (loop !== void 0) {
11415
+ task.put({ loop });
11416
+ continue;
11417
+ }
11418
+ const container = Array.isArray(value) || isRecord(value);
11419
+ const held = container ? holders.get(value) : void 0;
11420
+ if (held !== void 0) {
11421
+ if (task.keep) items[held].keep = true;
11422
+ task.put({
11423
+ same: held,
11424
+ name: task.name
11425
+ });
11426
+ continue;
11427
+ }
11428
+ const term = task.tried || task.keep ? void 0 : termOrNothing(machine, value);
11429
+ const whole = term !== void 0 && wholeOf(shared, value, term);
11430
+ if (term !== void 0 && !whole) task.put({ value: term });
11431
+ else if (value instanceof Error) task.put({ node: open(value) });
11432
+ else if (container && (whole || task.nest || holdsException(value))) {
11433
+ const children = [];
11434
+ task.put({ holder: hold(task.name, value, task.keep || whole, children) });
11435
+ later(children);
11436
+ } else task.put({ none: task.name });
11437
+ }
11438
+ const { formed, shares } = formsOf(items);
11439
+ const forms = [];
11440
+ const builtOf = (part) => {
11441
+ if ("none" in part) return { names: [part.none] };
11442
+ if ("node" in part) return {
11443
+ form: { exception: forms[part.node] },
11444
+ names: []
11445
+ };
11446
+ if ("holder" in part) return forms[part.holder];
11447
+ if ("same" in part) return formed[part.same] === true ? {
11448
+ form: { share: shares[part.same] },
11449
+ names: []
11450
+ } : { names: [part.name] };
11451
+ return {
11452
+ form: part,
11453
+ names: []
11454
+ };
11455
+ };
11456
+ for (let at = items.length - 1; at >= 0; at -= 1) {
11457
+ const item = items[at];
11458
+ if ("slots" in item) {
11459
+ if (formed[at] !== true) {
11460
+ forms[at] = { names: [item.name] };
11461
+ continue;
11462
+ }
11463
+ const built = Array.from(item.slots, builtOf);
11464
+ const form = item.list ? built.map((part) => part.form ?? { dropped: true }) : { record: Object.fromEntries(keptOf(item.keys, built)) };
11465
+ forms[at] = {
11466
+ form,
11467
+ names: built.flatMap((part) => part.names)
11468
+ };
11469
+ continue;
11470
+ }
11471
+ const { head, keys, parts, hiddenKeys, hidden, cause } = item;
11472
+ const linked = Array.from(parts, builtOf);
11473
+ const kept = Array.from(hidden, builtOf);
11474
+ const link = cause === void 0 ? { names: [] } : causeOf(builtOf(cause));
11475
+ const dropped = [
11476
+ ...linked,
11477
+ ...kept,
11478
+ link
11479
+ ].flatMap((part) => part.names);
11480
+ const partsOf = keptOf(keys, linked);
11481
+ const hiddenOf = keptOf(hiddenKeys, kept);
11482
+ forms[at] = {
11483
+ ...head,
11484
+ ...partsOf.length === 0 ? {} : { parts: Object.fromEntries(partsOf) },
11485
+ ...dropped.length === 0 ? {} : { dropped },
11486
+ ...hiddenOf.length === 0 ? {} : { hidden: Object.fromEntries(hiddenOf) },
11487
+ ...link.link
11488
+ };
11489
+ }
11490
+ return causeOf(builtOf(top));
11491
+ }
11492
+ /**
11493
+ * This function tells which containers of the walk of `causeJson` get a form, and it gives each such container its
11494
+ * index for `share` (D88). A container gets a form when it is a hidden list, or when an item has a form. A share has
11495
+ * the form of its container. Thus a cycle of containers without another form has no form. The index counts the
11496
+ * containers with a form in the order of the walk, as `decodeLog` meets them.
11497
+ */
11498
+ function formsOf(items) {
11499
+ const formed = [];
11500
+ const users = /* @__PURE__ */ new Map();
11501
+ const work = [];
11502
+ for (let at = 0; at < items.length; at += 1) {
11503
+ const item = items[at];
11504
+ if (!("slots" in item)) continue;
11505
+ let seed = item.keep;
11506
+ for (const part of item.slots) {
11507
+ const on = "holder" in part ? part.holder : "same" in part ? part.same : void 0;
11508
+ if (on === void 0) seed ||= !("none" in part);
11509
+ else {
11510
+ const list = users.get(on);
11511
+ if (list === void 0) users.set(on, [at]);
11512
+ else list.push(at);
11513
+ }
11514
+ }
11515
+ if (seed) {
11516
+ formed[at] = true;
11517
+ work.push(at);
11518
+ }
11519
+ }
11520
+ for (let at = work.pop(); at !== void 0; at = work.pop()) for (const user of users.get(at) ?? []) {
11521
+ if (formed[user] === true) continue;
11522
+ formed[user] = true;
11523
+ work.push(user);
11524
+ }
11525
+ const shares = [];
11526
+ let count = 0;
11527
+ for (let at = 0; at < items.length; at += 1) {
11528
+ if (formed[at] !== true) continue;
11529
+ shares[at] = count;
11530
+ count += 1;
11531
+ }
11532
+ return {
11533
+ formed,
11534
+ shares
11535
+ };
11536
+ }
11537
+ /** This function gives the message of an exception, or a short text for another value. */
11538
+ function messageOf(error) {
11539
+ return error instanceof Error ? error.message : describe(error);
11540
+ }
11541
+ /** This function writes a value of a log as a term document, or throws a `TypeError` that names the value. */
11542
+ function termOf(machine, value, what) {
11543
+ try {
11544
+ return encodeValue(machine, value);
11545
+ } catch (error) {
11546
+ throw new TypeError(`encodeLog cannot write ${what()}: ${messageOf(error)}`);
11547
+ }
11548
+ }
11549
+ /** This function writes an error value of a log as JSON, or throws a `TypeError` that names the error. */
11550
+ function errorJson(machine, error, what) {
11551
+ for (const key of Object.keys(error)) if (!errorField(key)) throw new TypeError(`encodeLog cannot write ${what()}: the error has the field ${key}, and the JSON form has no field for it.`);
11552
+ const base = {
11553
+ code: error.code,
11554
+ reason: error.reason,
11555
+ ...error.place === void 0 ? {} : { place: error.place }
11556
+ };
11557
+ if (!Object.hasOwn(error, "cause")) return base;
11558
+ const cause = error.cause;
11559
+ const shared = sharedOf(cause);
11560
+ let term;
11561
+ let failure;
11562
+ try {
11563
+ term = encodeValue(machine, cause);
11564
+ } catch (thrown) {
11565
+ failure = thrown;
11566
+ }
11567
+ if (term !== void 0 && !wholeOf(shared, cause, term)) return {
11568
+ ...base,
11569
+ cause: term
11570
+ };
11571
+ const { link, names } = causeJson(machine, cause, shared, term === void 0);
11572
+ if (link === void 0) throw new TypeError(`encodeLog cannot write the cause of ${what()}: ${messageOf(failure)}`);
11573
+ return {
11574
+ ...base,
11575
+ ...link,
11576
+ ...names.length === 0 ? {} : { dropped: names }
11577
+ };
11578
+ }
11579
+ /**
11580
+ * This function writes a log as JSON (RUN.REPLAY-JSON, D75). Then `JSON.stringify` gives the text of a golden file.
11581
+ *
11582
+ * - Each payload and each value of an outcome is a term document of `encodeValue`. Thus `NaN`, `-0` and `undefined`
11583
+ * stay exact, and a member of a domain with a codec is `ext.domain`.
11584
+ * - An error keeps its code, its reason, its place and its cause. A cause that `encodeValue` cannot write and that is
11585
+ * an exception keeps its name and its message in the field `exception`.
11586
+ * - An exception also keeps its own fields that `encodeValue` writes, and the chain of its causes (RUN.REPLAY-CAUSES).
11587
+ * The list `dropped` names each other own field. A cause that is an earlier exception of the chain is its index in `loop`.
11588
+ * - An exception keeps the hidden fields of the standard classes in `hidden`, for example `errors` of an
11589
+ * `AggregateError` (RUN.REPLAY-HIDDEN, D77). Each exception in them has the rule of a cause.
11590
+ * - An enumerable field without a term document that is an exception, a list or a plain record is in `parts`
11591
+ * (RUN.REPLAY-FIELDS, D78, D82). An item of a list without a form is the mark `dropped` at its place.
11592
+ * - A cause without a term document that is a list or a plain record with an exception is in `causeParts`
11593
+ * (RUN.REPLAY-CAUSE-PARTS, D87). The rule is the same for the cause of an exception and of an error value.
11594
+ * - The cause of an exception is also in `causeParts` without an exception in it, when an item has a form
11595
+ * (RUN.REPLAY-CAUSE-ITEMS, D100). Each item without a form is a name in `dropped`, for example `cause.send`.
11596
+ * - A list or a record of parts that an earlier place of one error holds is the part `share` with its index
11597
+ * (RUN.REPLAY-SHARED, D88). This rule also covers a container that holds itself.
11598
+ * - A list or a plain record with a term document that two places of one error share is a container of parts
11599
+ * (RUN.REPLAY-SHARED-VALUES, D101). Each later place is a share. A member of a domain stays a term document.
11600
+ * - An outcome that the log does not have stays absent.
11601
+ *
11602
+ * @param machine - The machine of the run, or only its domains.
11603
+ * @param log - The log of a recorder.
11604
+ * @returns The JSON form. `decodeLog` gives the log again.
11605
+ * @throws {TypeError} A value has no term document, for example a closure, a host thing, a symbol, or a value that no
11606
+ * domain with a codec holds. The message names the effect and its address. A part of an exception is not a refusal.
11607
+ */
11608
+ function encodeLog(machine, log) {
11609
+ return {
11610
+ version: 1,
11611
+ effects: log.effects.map((entry) => {
11612
+ const at = (field) => () => `the ${field} of the effect ${entry.kind} at the address ${entry.address}`;
11613
+ const head = {
11614
+ address: entry.address,
11615
+ kind: entry.kind,
11616
+ payload: termOf(machine, entry.payload, at("payload"))
11617
+ };
11618
+ const outcome = entry.outcome;
11619
+ if (outcome === void 0) return {
11620
+ ...head,
11621
+ waited: entry.waited
11622
+ };
11623
+ const json = outcome.ok ? {
11624
+ ok: true,
11625
+ value: termOf(machine, outcome.value, at("outcome"))
11626
+ } : {
11627
+ ok: false,
11628
+ error: errorJson(machine, outcome.error, at("outcome"))
11629
+ };
11630
+ return {
11631
+ ...head,
11632
+ outcome: json,
11633
+ waited: entry.waited
11634
+ };
11635
+ }),
11636
+ settles: log.settles.map((settle) => ({
11637
+ all: settle.all,
11638
+ item: settle.item
11639
+ }))
11640
+ };
11641
+ }
11642
+ /** This function gives an exception with a name and a message. A standard name gives an instance of its class. */
11643
+ function exception(name, message) {
11644
+ const made = standard(name, message);
11645
+ if (made.name !== name) made.name = name;
11646
+ return made;
11647
+ }
11648
+ /**
11649
+ * This function gives an instance of the standard class with a name, or an `Error`. An `AggregateError` gets an empty
11650
+ * list `errors`, and a `SuppressedError` gets `undefined` for `error` and `suppressed`, as their constructors do.
11651
+ */
11652
+ function standard(name, message) {
11653
+ switch (name) {
11654
+ case "TypeError": return new TypeError(message);
11655
+ case "RangeError": return new RangeError(message);
11656
+ case "SyntaxError": return new SyntaxError(message);
11657
+ case "ReferenceError": return new ReferenceError(message);
11658
+ case "AggregateError": return new AggregateError([], message);
11659
+ case "SuppressedError": return typeof SuppressedError === "function" ? new SuppressedError(void 0, void 0, message) : new Error(message);
11660
+ default: return new Error(message);
11661
+ }
11662
+ }
11663
+ /** This function gives an exception a field that is not enumerable, as the constructor of `Error` does for `cause`. */
11664
+ function hide(error, key, value) {
11665
+ Object.defineProperty(error, key, {
11666
+ value,
11667
+ writable: true,
11668
+ enumerable: false,
11669
+ configurable: true
11670
+ });
11671
+ }
11672
+ /** This function gives the failed result of a JSON form that `decodeLog` cannot read. */
11673
+ function bad(place, reason) {
11674
+ return fail("#VALUE!", `decodeLog cannot read the log: ${reason}`, { place });
11675
+ }
11676
+ /** This function reads a term document of a log again, with the formula kit and the domains of the machine. */
11677
+ function readTerm(kit, doc, place) {
11678
+ const value = decodeValue(kit, doc);
11679
+ return value.ok ? value : bad(place, `the term document gives ${value.error.code}: ${value.error.reason}`);
11680
+ }
11681
+ /** This function reads the JSON form of an error value again. */
11682
+ function readError(kit, data, place) {
11683
+ if (!isRecord(data) || typeof data["code"] !== "string" || !data["code"].startsWith("#") || typeof data["reason"] !== "string") return bad(place, "an error is a record with a code that starts with # and a reason.");
11684
+ for (const key of Object.keys(data)) if (!errorField(key) && key !== "exception" && key !== "causeParts" && key !== "dropped") return bad(place, `an error has no field ${key}.`);
11685
+ const keys = data["place"];
11686
+ if (keys !== void 0 && !(Array.isArray(keys) && keys.every((key) => isKey(key)))) return bad([...place, "place"], "a place is a list of texts and numbers.");
11687
+ const dropped = data["dropped"];
11688
+ if (dropped !== void 0 && !(Array.isArray(dropped) && dropped.every((name) => typeof name === "string"))) return bad([...place, "dropped"], "the list dropped holds texts.");
11689
+ const error = {
11690
+ code: data["code"],
11691
+ reason: data["reason"]
11692
+ };
11693
+ if (keys !== void 0) error.place = keys;
11694
+ const record = data;
11695
+ const links = LINKS.filter((key) => key !== "loop" && Object.hasOwn(record, key));
11696
+ if (links.length > 1) return bad(place, "an error has a cause, an exception or causeParts, not more than one.");
11697
+ const link = links[0];
11698
+ if (link === "cause") {
11699
+ const cause = readTerm(kit, data["cause"], [...place, "cause"]);
11700
+ if (!cause.ok) return cause;
11701
+ error.cause = cause.value;
11702
+ } else if (link !== void 0) {
11703
+ const read = readCause(kit, link, data[link], [...place, link]);
11704
+ if (!read.ok) return read;
11705
+ error.cause = read.value;
11706
+ }
11707
+ return ok(error);
11708
+ }
11709
+ /**
11710
+ * This function reads the JSON form of a cause again: an exception in `exception`, or a container in `causeParts`
11711
+ * (RUN.REPLAY-CAUSES, RUN.REPLAY-HIDDEN, RUN.REPLAY-FIELDS, D87). The walk has the order of `causeJson`, thus a loop
11712
+ * gives the same exception. A list or a record of parts gives a new list or plain record (D82). A share gives the same
11713
+ * list or record as its earlier place (D88). The walk is a loop, thus a long chain does not overflow the stack.
11714
+ */
11715
+ function readCause(kit, kind, data, place) {
11716
+ const chain = [];
11717
+ const held = [];
11718
+ const tasks = [];
11719
+ const open = (at, where) => {
11720
+ if (!isRecord(at) || typeof at["name"] !== "string" || typeof at["message"] !== "string" || !Object.keys(at).every(exceptionField)) return bad(where, "an exception is a record with the texts name and message, and only the fields fields, parts, dropped, hidden, cause, exception, loop and causeParts.");
11721
+ const made = exception(at["name"], at["message"]);
11722
+ const fields = at["fields"];
11723
+ if (fields !== void 0) {
11724
+ if (!isRecord(fields)) return bad([...where, "fields"], "the fields of an exception are a record.");
11725
+ for (const key of Object.keys(fields)) {
11726
+ if (ownField(key)) return bad([
11727
+ ...where,
11728
+ "fields",
11729
+ key
11730
+ ], `the field ${key} of an exception is not in its fields.`);
11731
+ const value = readTerm(kit, fields[key], [
11732
+ ...where,
11733
+ "fields",
11734
+ key
11735
+ ]);
11736
+ if (!value.ok) return value;
11737
+ Object.defineProperty(made, key, {
11738
+ value: value.value,
11739
+ writable: true,
11740
+ enumerable: true,
11741
+ configurable: true
11742
+ });
11743
+ }
11744
+ }
11745
+ const dropped = at["dropped"];
11746
+ if (dropped !== void 0 && !(Array.isArray(dropped) && dropped.every((name) => typeof name === "string"))) return bad([...where, "dropped"], "the list dropped holds texts.");
11747
+ chain.push(made);
11748
+ const children = [];
11749
+ const taken = (key) => isRecord(fields) && Object.hasOwn(fields, key);
11750
+ const parts = at["parts"];
11751
+ if (parts !== void 0) {
11752
+ if (!isRecord(parts)) return bad([...where, "parts"], "the parts of an exception are a record.");
11753
+ for (const key of Object.keys(parts)) {
11754
+ if (ownField(key) || taken(key)) return bad([
11755
+ ...where,
11756
+ "parts",
11757
+ key
11758
+ ], `the field ${key} of an exception is not in its parts.`);
11759
+ const show = (value) => {
11760
+ Object.defineProperty(made, key, {
11761
+ value,
11762
+ writable: true,
11763
+ enumerable: true,
11764
+ configurable: true
11765
+ });
11766
+ };
11767
+ const read = slotTask(parts[key], [
11768
+ ...where,
11769
+ "parts",
11770
+ key
11771
+ ], false, show);
11772
+ if (!read.ok) return read;
11773
+ show(void 0);
11774
+ children.push(read.value);
11775
+ }
11776
+ }
11777
+ const hidden = at["hidden"];
11778
+ if (hidden !== void 0) {
11779
+ if (!isRecord(hidden)) return bad([...where, "hidden"], "the hidden fields of an exception are a record.");
11780
+ for (const key of Object.keys(hidden)) if (!HIDDEN.includes(key) || taken(key) || isRecord(parts) && Object.hasOwn(parts, key)) return bad([
11781
+ ...where,
11782
+ "hidden",
11783
+ key
11784
+ ], `an exception has no hidden field ${key}.`);
11785
+ for (const key of HIDDEN) {
11786
+ if (!Object.hasOwn(hidden, key)) continue;
11787
+ const read = slotTask(hidden[key], [
11788
+ ...where,
11789
+ "hidden",
11790
+ key
11791
+ ], false, (value) => hide(made, key, value));
11792
+ if (!read.ok) return read;
11793
+ children.push(read.value);
11794
+ }
11795
+ }
11796
+ const record = at;
11797
+ const links = LINKS.filter((key) => Object.hasOwn(record, key));
11798
+ if (links.length > 1) return bad(where, "an exception has a cause, an exception, a loop or causeParts, not more than one.");
11799
+ const link = links[0];
11800
+ if (link !== void 0) {
11801
+ const read = linkTask(link, record[link], [...where, link], (value) => hide(made, "cause", value));
11802
+ if (!read.ok) return read;
11803
+ children.push(read.value);
11804
+ }
11805
+ for (let index = children.length - 1; index >= 0; index -= 1) tasks.push(children[index]);
11806
+ return ok(made);
11807
+ };
11808
+ let cause;
11809
+ const root = linkTask(kind, data, place, (value) => {
11810
+ cause = value;
11811
+ });
11812
+ if (!root.ok) return root;
11813
+ tasks.push(root.value);
11814
+ for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {
11815
+ const { kind, data: part, where } = task;
11816
+ if (kind === "dropped") continue;
11817
+ if (kind === "loop") {
11818
+ if (typeof part !== "number" || !Number.isInteger(part) || part < 0 || part >= chain.length) return bad(where, "a loop is the index of an exception of the chain until this one.");
11819
+ task.put(chain[part]);
11820
+ continue;
11821
+ }
11822
+ if (kind === "share") {
11823
+ if (typeof part !== "number" || !Number.isInteger(part) || part < 0 || part >= held.length) return bad(where, "a share is the index of a list or a record of parts of the walk until this one.");
11824
+ task.put(held[part]);
11825
+ continue;
11826
+ }
11827
+ if (kind === "list" || kind === "record") {
11828
+ const items = kind === "list" ? listTasks(part, where, held, task.put) : recordTasks(part, where, held, task.put);
11829
+ if (!items.ok) return items;
11830
+ for (let index = items.value.length - 1; index >= 0; index -= 1) tasks.push(items.value[index]);
11831
+ continue;
11832
+ }
11833
+ const value = kind === "exception" ? open(part, where) : readTerm(kit, part, where);
11834
+ if (!value.ok) return value;
11835
+ task.put(value.value);
11836
+ }
11837
+ return ok(cause);
11838
+ }
11839
+ /**
11840
+ * This function reads the field of a cause: `cause`, `exception`, `loop` or `causeParts`. A value of `causeParts` is a
11841
+ * list of parts, the part `record` or the part `share`, and no other part (D87, D88).
11842
+ */
11843
+ function linkTask(kind, data, where, put) {
11844
+ if (kind !== "causeParts") return ok({
11845
+ kind,
11846
+ data,
11847
+ where,
11848
+ put
11849
+ });
11850
+ if (Array.isArray(data)) return ok({
11851
+ kind: "list",
11852
+ data,
11853
+ where,
11854
+ put
11855
+ });
11856
+ const key = isRecord(data) && Object.keys(data).length === 1 ? Object.keys(data)[0] : void 0;
11857
+ if (isRecord(data) && (key === "record" || key === "share")) return ok({
11858
+ kind: key,
11859
+ data: data[key],
11860
+ where: [...where, key],
11861
+ put
11862
+ });
11863
+ return bad(where, "a cause of parts is a list of parts, the part record or the part share.");
11864
+ }
11865
+ /**
11866
+ * This function reads one value of a field in `parts`, in `hidden` or in a record of parts. A list is a list of parts,
11867
+ * and another value is one part.
11868
+ */
11869
+ function slotTask(data, where, item, put) {
11870
+ return Array.isArray(data) ? ok({
11871
+ kind: "list",
11872
+ data,
11873
+ where,
11874
+ put
11875
+ }) : partTask(data, where, item, put);
11876
+ }
11877
+ /**
11878
+ * This function gives a list of parts its length at once, and it gives the tasks of its items. Thus the mark `dropped`
11879
+ * leaves a hole at its place, and each later item keeps its index (D78). The list goes in `held` for a share (D88).
11880
+ */
11881
+ function listTasks(data, where, held, put) {
11882
+ const items = data;
11883
+ const list = [];
11884
+ list.length = items.length;
11885
+ held.push(list);
11886
+ put(list);
11887
+ const tasks = [];
11888
+ for (let item = 0; item < items.length; item += 1) {
11889
+ const task = slotTask(items[item], [...where, item], true, (value) => {
11890
+ list[item] = value;
11891
+ });
11892
+ if (!task.ok) return task;
11893
+ tasks.push(task.value);
11894
+ }
11895
+ return ok(tasks);
11896
+ }
11897
+ /**
11898
+ * This function gives a record of parts a new plain record (D82). It gives the tasks of its fields in the order of
11899
+ * the keys. Each key gets its place at once, thus the record keeps the order of the keys. The record goes in `held`
11900
+ * for a share (D88).
11901
+ */
11902
+ function recordTasks(data, where, held, put) {
11903
+ if (!isRecord(data)) return bad(where, "a record of parts is a record.");
11904
+ const record = {};
11905
+ held.push(record);
11906
+ put(record);
11907
+ const tasks = [];
11908
+ for (const key of Object.keys(data)) {
11909
+ const show = (value) => {
11910
+ Object.defineProperty(record, key, {
11911
+ value,
11912
+ writable: true,
11913
+ enumerable: true,
11914
+ configurable: true
11915
+ });
11916
+ };
11917
+ const task = slotTask(data[key], [...where, key], false, show);
11918
+ if (!task.ok) return task;
11919
+ show(void 0);
11920
+ tasks.push(task.value);
11921
+ }
11922
+ return ok(tasks);
11923
+ }
11924
+ /**
11925
+ * This function reads one part: a record with only one of the fields `value`, `exception`, `loop`, `record` and
11926
+ * `share`. An item of a list can also be the mark `{ "dropped": true }`.
11927
+ */
11928
+ function partTask(data, where, item, put) {
11929
+ const keys = isRecord(data) ? Object.keys(data) : [];
11930
+ const kind = keys[0];
11931
+ const mark = kind === "dropped" && item && isRecord(data) && data[kind] === true;
11932
+ if (!isRecord(data) || keys.length !== 1 || kind === void 0 || !(PARTS$1.includes(kind) || mark)) return bad(where, "a field of parts is a part or a list of parts. A part has only one of the fields value, exception, loop, record and share, or an item is the mark dropped.");
11933
+ return ok({
11934
+ kind,
11935
+ data: data[kind],
11936
+ where: [...where, kind],
11937
+ put
11938
+ });
11939
+ }
11940
+ /** The fields of the JSON form of an exception that give its cause. */
11941
+ const LINKS = /* @__PURE__ */ Object.freeze([
11942
+ "cause",
11943
+ "exception",
11944
+ "loop",
11945
+ "causeParts"
11946
+ ]);
11947
+ /** The fields of the JSON form of a part of a field in `parts` or `hidden`. */
11948
+ const PARTS$1 = /* @__PURE__ */ Object.freeze([
11949
+ "value",
11950
+ "exception",
11951
+ "loop",
11952
+ "record",
11953
+ "share"
11954
+ ]);
11955
+ /** This function reads the JSON form of one effect again. */
11956
+ function readEntry(kit, data, place) {
11957
+ if (!isRecord(data) || typeof data["address"] !== "string" || typeof data["kind"] !== "string" || typeof data["waited"] !== "boolean" || !Object.hasOwn(data, "payload")) return bad(place, "an effect is a record with the texts address and kind, a payload, and the truth value waited.");
11958
+ for (const key of Object.keys(data)) if (key !== "address" && key !== "kind" && key !== "payload" && key !== "outcome" && key !== "waited") return bad(place, `an effect has no field ${key}.`);
11959
+ const payload = readTerm(kit, data["payload"], [...place, "payload"]);
11960
+ if (!payload.ok) return payload;
11961
+ const head = {
11962
+ address: data["address"],
11963
+ kind: data["kind"],
11964
+ payload: payload.value,
11965
+ waited: data["waited"]
11966
+ };
11967
+ if (!Object.hasOwn(data, "outcome")) return ok(head);
11968
+ const raw = data["outcome"];
11969
+ const at = [...place, "outcome"];
11970
+ if (isRecord(raw) && raw["ok"] === true && Object.hasOwn(raw, "value") && Object.keys(raw).length === 2) {
11971
+ const value = readTerm(kit, raw["value"], [...at, "value"]);
11972
+ return value.ok ? ok({
11973
+ ...head,
11974
+ outcome: ok(value.value)
11975
+ }) : value;
11976
+ }
11977
+ if (isRecord(raw) && raw["ok"] === false && Object.keys(raw).length === 2) {
11978
+ const error = readError(kit, raw["error"], [...at, "error"]);
11979
+ return error.ok ? ok({
11980
+ ...head,
11981
+ outcome: {
11982
+ ok: false,
11983
+ error: error.value
11984
+ }
11985
+ }) : error;
11986
+ }
11987
+ return bad(at, "an outcome is a record with ok true and a value, or with ok false and an error.");
11988
+ }
11989
+ /**
11990
+ * This function reads the JSON form of a log again (RUN.REPLAY-JSON). It reads each term document with the formula kit
11991
+ * and the domains of the machine. A cause in the field `exception` becomes an exception with that name and message.
11992
+ * The exception gets its fields and the chain of its causes again, also a cycle (RUN.REPLAY-CAUSES). A list gets a
11993
+ * hole at the place of the mark `dropped`, thus each later item keeps its index (D78). Each share of a list or a record
11994
+ * gives the same object (RUN.REPLAY-SHARED).
11995
+ *
11996
+ * @param machine - The machine of the run, or only its domains.
11997
+ * @param data - The JSON form, for example from `JSON.parse` of a golden file.
11998
+ * @returns The log for `replayer`, or `#VALUE!` with the place of the first field that it cannot read.
11999
+ */
12000
+ function decodeLog(machine, data) {
12001
+ if (!isRecord(data) || data["version"] !== 1) return bad([], "the form is a record with the version 1.");
12002
+ const list = data["effects"];
12003
+ const order = data["settles"];
12004
+ if (!Array.isArray(list) || !Array.isArray(order) || Object.keys(data).length !== 3) return bad([], "the form has only the version and the lists effects and settles.");
12005
+ const domains = machine.domains;
12006
+ const kit = {
12007
+ ...formulaMachine(),
12008
+ ...domains === void 0 ? {} : { domains }
12009
+ };
12010
+ const effects = [];
12011
+ for (let index = 0; index < list.length; index += 1) {
12012
+ const entry = readEntry(kit, list[index], ["effects", index]);
12013
+ if (!entry.ok) return entry;
12014
+ effects.push(entry.value);
12015
+ }
12016
+ const settles = [];
12017
+ for (let index = 0; index < order.length; index += 1) {
12018
+ const settle = order[index];
12019
+ if (!isRecord(settle) || typeof settle["all"] !== "string" || !Number.isInteger(settle["item"]) || Object.keys(settle).length !== 2) return bad(["settles", index], "a settle is a record with only the text all and the whole number item.");
12020
+ settles.push({
12021
+ all: settle["all"],
12022
+ item: settle["item"]
12023
+ });
12024
+ }
12025
+ return ok({
12026
+ effects,
12027
+ settles
12028
+ });
12029
+ }
12030
+ // src/agree.ts
12031
+ /** The tiers that `agree` compares when its options name none. */
12032
+ const DEFAULT_TIERS = /* @__PURE__ */ Object.freeze([
12033
+ "reference",
12034
+ "traced",
12035
+ "again",
12036
+ "folds",
12037
+ "fixed"
12038
+ ]);
12039
+ /**
12040
+ * This function tells if two values are the same for `agree`. Lists and plain records compare item by item and field
12041
+ * by field, and the order of the fields does not matter. Each other leaf compares with `Object.is`, thus `-0` is not
12042
+ * `0`, and `NaN` is `NaN`. The identity of a list or of a plain record is not compared.
12043
+ *
12044
+ * Two closures of `fn` are the same when they have the same parameters. Two `Held` values are the same when their
12045
+ * errors have the same code and place. Each other object is the same only as itself, unless the rule of the caller
12046
+ * tells otherwise.
12047
+ *
12048
+ * `docEquals` and `sameResult` use the same walk (D20). `docEquals` has no rules for closures, for `Held` values and
12049
+ * for a rule of the caller. `sameResult` is for an early cutoff, thus a closure is the same there only as itself, and
12050
+ * two errors also need the same reason.
12051
+ *
12052
+ * @param a - The first value.
12053
+ * @param b - The second value.
12054
+ * @param equal - The rule of the caller for other values. It answers first, and `undefined` gives the rules above.
12055
+ * @returns `true` when the values are the same.
12056
+ */
12057
+ function sameValue(a, b, equal) {
12058
+ return equalWith(a, b, equal === void 0 ? sameInTiers : (x, y) => equal(x, y) ?? sameInTiers(x, y));
12059
+ }
12060
+ /** The rules of `sameValue` for the values that two tiers make again: closures and held errors. */
12061
+ function sameInTiers(x, y) {
12062
+ if (isClosure(x) || isClosure(y)) return isClosure(x) && isClosure(y) && docEquals(closureParams(x), closureParams(y));
12063
+ if (x instanceof Held || y instanceof Held) return x instanceof Held && y instanceof Held && errorDiffers(x.error, y.error, false) === void 0;
12064
+ }
12065
+ const CLOSURE = /* @__PURE__ */ Symbol.for("coeval.closure");
12066
+ /** This function gives the parameters of a closure of `fn`, or `undefined` for another function. */
12067
+ function closureParams(fn) {
12068
+ return fn[CLOSURE]?.params;
12069
+ }
12070
+ function codeAndPlace(error) {
12071
+ return error.place === void 0 ? error.code : `${error.code} at [${error.place.join(", ")}]`;
9996
12072
  }
9997
12073
  /** This function gives the difference of two errors, or `undefined` when they agree. */
9998
12074
  function errorDiffers(a, b, strict) {
@@ -10221,18 +12297,12 @@ function agree(machine, doc, context = makeContext(), options = {}) {
10221
12297
  function watched(perform) {
10222
12298
  const effects = [];
10223
12299
  const settles = [];
10224
- const inner = perform[JOURNAL];
10225
- const settled = (all, item) => {
12300
+ const journal = relay(perform, (all, item) => {
10226
12301
  settles.push({
10227
12302
  all,
10228
12303
  item
10229
12304
  });
10230
- inner?.settled?.(all, item);
10231
- };
10232
- const journal = inner?.next === void 0 ? { settled } : {
10233
- settled,
10234
- next: (all, waiting) => inner.next?.(all, waiting)
10235
- };
12305
+ });
10236
12306
  const host = (effect) => {
10237
12307
  effects.push(effect);
10238
12308
  return perform(effect);
@@ -10254,6 +12324,82 @@ function settlesDiffer(a, b) {
10254
12324
  if (x?.all !== y?.all || x?.item !== y?.item) return `The wait ${index} settles ${settleText(x)} in the plan, and ${settleText(y)} in the tier.`;
10255
12325
  }
10256
12326
  }
12327
+ /** The roots beside `self` that a value without static reads keeps whole (READS.KEPT). */
12328
+ const KEPT_ROOTS = /* @__PURE__ */ Object.freeze([
12329
+ "names",
12330
+ "world",
12331
+ "event",
12332
+ "caps"
12333
+ ]);
12334
+ /**
12335
+ * This function tells if the plan does not know the reads of a run. A value without static reads keeps each root
12336
+ * (READS.KEPT), thus the list holds a kept read of each whole root.
12337
+ */
12338
+ function readsUnknown(reads) {
12339
+ return KEPT_ROOTS.every((root) => reads.some((read) => read.kept === true && read.path.length === 1 && read.path[0] === root));
12340
+ }
12341
+ /**
12342
+ * This function gives the reads that `agreeRun` compares: the free reads of the resolutions (RUN.AGREES-READS). A
12343
+ * kept read is the bound of the plan for the later reads of a value, and the reference has no such bound.
12344
+ */
12345
+ function resolutions(reads) {
12346
+ return reads.filter((read) => read.free && read.kept !== true);
12347
+ }
12348
+ function pathText(path) {
12349
+ if (path === void 0) return "no read";
12350
+ try {
12351
+ return JSON.stringify(path);
12352
+ } catch {
12353
+ return path.map(String).join(", ");
12354
+ }
12355
+ }
12356
+ /**
12357
+ * This function gives the rule of a comparison of reads. The rule of the caller answers first. Each tier makes its
12358
+ * own nodes of a tree and its own adopted things. Thus two host things are the same when they have the same label,
12359
+ * and they are nodes or have the same JSON object.
12360
+ */
12361
+ function sameThing(equal) {
12362
+ return (a, b) => {
12363
+ const told = equal?.(a, b);
12364
+ if (told !== void 0) return told;
12365
+ if (!isHostThing(a) || !isHostThing(b)) return void 0;
12366
+ if (a.label !== b.label) return false;
12367
+ if (a.label.startsWith("node ")) return true;
12368
+ try {
12369
+ return Object.is(a.toJson(), b.toJson());
12370
+ } catch {
12371
+ return false;
12372
+ }
12373
+ };
12374
+ }
12375
+ /** This function gives the difference of what two reads reached, or `undefined` when they agree. */
12376
+ function reachedDiffers(a, b, equal, strict) {
12377
+ if (a.ok && b.ok) return sameValue(a.value, b.value, equal) ? void 0 : "The read reaches another value in the tier.";
12378
+ if (!a.ok && !b.ok) {
12379
+ if (a.error.code !== b.error.code) return `The read gives ${a.error.code} in the plan, and ${b.error.code} in the tier.`;
12380
+ return strict && a.error.reason !== b.error.reason ? `The read gives ${a.error.code} with another reason in the tier: "${b.error.reason}" for "${a.error.reason}".` : void 0;
12381
+ }
12382
+ if (!b.ok) return `The read reaches a value in the plan, and ${b.error.code} in the tier.`;
12383
+ return `The read gives ${a.error.code} in the plan, and a value in the tier.`;
12384
+ }
12385
+ /**
12386
+ * This function gives the first difference of the reads of the plan and of a tier, or `undefined` when they agree
12387
+ * (RUN.AGREES-READS). Only the free reads of the resolutions compare, in their order. When the plan does not know its
12388
+ * reads, the function compares nothing.
12389
+ */
12390
+ function readsDiffer(plan, tier, options) {
12391
+ if (readsUnknown(plan)) return void 0;
12392
+ const a = resolutions(plan);
12393
+ const b = resolutions(tier);
12394
+ const equal = sameThing(options.equal);
12395
+ for (let index = 0; index < Math.max(a.length, b.length); index += 1) {
12396
+ const x = a[index];
12397
+ const y = b[index];
12398
+ if (x === void 0 || y === void 0 || !sameValue(x.path, y.path, equal)) return `The free read ${index} is ${pathText(x?.path)} in the plan, and ${pathText(y?.path)} in the tier.`;
12399
+ const why = reachedDiffers(x.reached, y.reached, equal, options.strict === true);
12400
+ if (why !== void 0) return `The free read ${index} of ${pathText(x.path)} differs. ${why}`;
12401
+ }
12402
+ }
10257
12403
  /**
10258
12404
  * This function compares the run of a document in a plan with its run in other tiers (RUN.AGREES). First the plan
10259
12405
  * starts the run with a recorder around the host. Then each tier replays the log of that run. These tiers are the
@@ -10262,6 +12408,13 @@ function settlesDiffer(a, b) {
10262
12408
  * The rules of `agree` compare the results and the effects, with their addresses and outcomes. A tier must also
10263
12409
  * settle the waits of each `all` in the order of the plan, thus a replay keeps the order of the waits.
10264
12410
  *
12411
+ * The reference run must also give the free reads of the plan, in their order (RUN.AGREES-READS). Another replay of
12412
+ * the plan records these reads. A kept read does not compare. When the plan keeps each root, its reads are not known,
12413
+ * and no read compares.
12414
+ *
12415
+ * One replayer of the log serves each tier and the replay for the reads (RUN.AGREES-ONE-REPLAYER). The replayer keeps
12416
+ * no state of a run (RUN.REPLAY-RUNS), thus each tier replays the same log as with a replayer of its own.
12417
+ *
10265
12418
  * @param machine - The world, the evaluators and the runners.
10266
12419
  * @param doc - The document.
10267
12420
  * @param context - The names and the capabilities at the root.
@@ -10285,17 +12438,24 @@ async function agreeRun(machine, doc, context = makeContext(), options = {}) {
10285
12438
  const result = await plan.run(context, { perform: first.perform });
10286
12439
  const saw = observe?.();
10287
12440
  const log = recording.log();
12441
+ let planReads;
12442
+ let compared;
12443
+ const replay = replayer(log);
10288
12444
  for (const tier of options.tiers ?? DEFAULT_TIERS) {
10289
12445
  if (tier === "fixed") continue;
10290
- const replay = watched(replayer(log));
10291
- const host = { perform: replay.perform };
12446
+ const tierReplay = watched(replay);
12447
+ const host = { perform: tierReplay.perform };
10292
12448
  let other;
10293
- if (tier === "reference") other = await referenceRun(machine, doc, context, {
10294
- ...declared,
10295
- ...host,
10296
- ...options.definitions === void 0 ? {} : { definitions: options.definitions }
10297
- });
10298
- else if (tier === "traced") other = (await run(machine, doc, context, {
12449
+ let tierReads;
12450
+ if (tier === "reference") {
12451
+ tierReads = [];
12452
+ other = await referenceRun(machine, doc, context, {
12453
+ ...declared,
12454
+ ...host,
12455
+ reads: tierReads,
12456
+ ...options.definitions === void 0 ? {} : { definitions: options.definitions }
12457
+ });
12458
+ } else if (tier === "traced") other = (await run(machine, doc, context, {
10299
12459
  ...declared,
10300
12460
  ...host
10301
12461
  })).result;
@@ -10307,7 +12467,20 @@ async function agreeRun(machine, doc, context = makeContext(), options = {}) {
10307
12467
  const compareCalls = observe !== void 0 && tier !== "folds";
10308
12468
  const calls = observe?.();
10309
12469
  if (overflowed(result) || overflowed(other)) continue;
10310
- const why = resultDiffers(result, other, options) ?? effectsDiffer(first.effects, replay.effects, options) ?? settlesDiffer(first.settles, replay.settles) ?? (compareCalls && !sameValue(saw, calls, options.equal) ? "The host saw other calls in the tier." : void 0);
12470
+ let why = resultDiffers(result, other, options) ?? effectsDiffer(first.effects, tierReplay.effects, options) ?? settlesDiffer(first.settles, tierReplay.settles) ?? (compareCalls && !sameValue(saw, calls, options.equal) ? "The host saw other calls in the tier." : void 0);
12471
+ if (why === void 0 && tierReads !== void 0) {
12472
+ if (planReads === void 0) {
12473
+ const reads = [];
12474
+ await plan.run(context, {
12475
+ perform: replay,
12476
+ reads
12477
+ });
12478
+ observe?.();
12479
+ planReads = reads;
12480
+ }
12481
+ why = readsDiffer(planReads, tierReads, options);
12482
+ if (why === void 0 && !readsUnknown(planReads)) compared = resolutions(planReads);
12483
+ }
10311
12484
  if (why !== void 0) return {
10312
12485
  ok: false,
10313
12486
  tier,
@@ -10316,14 +12489,18 @@ async function agreeRun(machine, doc, context = makeContext(), options = {}) {
10316
12489
  reason: why
10317
12490
  };
10318
12491
  }
10319
- return {
12492
+ return compared === void 0 ? {
10320
12493
  ok: true,
10321
12494
  result,
10322
12495
  effects: first.effects
12496
+ } : {
12497
+ ok: true,
12498
+ result,
12499
+ effects: first.effects,
12500
+ reads: compared
10323
12501
  };
10324
12502
  }
10325
- //#endregion
10326
- //#region src/generate.ts
12503
+ // src/generate.ts
10327
12504
  /**
10328
12505
  * This function makes a source of random numbers with a seed (the algorithm mulberry32). It needs no package.
10329
12506
  *
@@ -10725,8 +12902,7 @@ function generate(world, options) {
10725
12902
  hint: void 0
10726
12903
  });
10727
12904
  }
10728
- //#endregion
10729
- //#region src/conform.ts
12905
+ // src/conform.ts
10730
12906
  /** The order of the obligations in the list of findings. */
10731
12907
  const ORDER = [
10732
12908
  "C1",
@@ -10738,7 +12914,9 @@ const ORDER = [
10738
12914
  "C7",
10739
12915
  "C8",
10740
12916
  "local",
10741
- "agree"
12917
+ "agree",
12918
+ "truth",
12919
+ "cover"
10742
12920
  ];
10743
12921
  /** A function in the results of the probe parts. It gives the count of its arguments. */
10744
12922
  const PROBE_FN = (...args) => args.length;
@@ -11616,14 +13794,58 @@ function examine(env, sample, contract) {
11616
13794
  if (env.runner) for (const scenario of scenariosOf(env, sample, contract, true)) checkShot(env, sample, contract, scenario, shoot(env, code, sample, scenario));
11617
13795
  }
11618
13796
  /**
13797
+ * This function checks the declared truth of a profile (D86). The function `truthy` must give `true` or `false` for
13798
+ * each member of `truthType`, and it must not throw. The members come from the lists `values` of the domains of the
13799
+ * type. A type without such a list gets its members from the results of the palette and from the samples of the
13800
+ * domains (D99).
13801
+ */
13802
+ function checkTruth(env, code, probe) {
13803
+ const truth = declaredTruthOf(code);
13804
+ if (truth === void 0) return;
13805
+ const domains = env.machine.domains;
13806
+ if (typeIssues(truth.truthType, domains).length > 0) return;
13807
+ const samples = env.results.flatMap((result) => result.ok ? [result.value] : []);
13808
+ const of = (value) => `the member ${valueText(value)} of the truth type ${typeText(truth.truthType)}`;
13809
+ for (const value of membersOf(truth.truthType, domains, samples)) {
13810
+ let given;
13811
+ try {
13812
+ given = truth.truthy(value);
13813
+ } catch (error) {
13814
+ report(env, "truth", `The function truthy of the profile throws for ${of(value)}: ${describe(error)}`, () => probe(value));
13815
+ return;
13816
+ }
13817
+ if (typeof given === "boolean") continue;
13818
+ report(env, "truth", `The function truthy of the profile gives ${given === void 0 ? "no truth" : valueText(given)} for ${of(value)}. A truth is true or false.`, () => probe(value));
13819
+ return;
13820
+ }
13821
+ }
13822
+ /**
13823
+ * This function checks the covers of the domains of the machine from samples (D94). Each sample of a covered domain
13824
+ * must be in one domain of each valid cover. The samples of a domain come from its list `values`. A domain without
13825
+ * that list gets its members from the palette and from the samples of the domains, as for the check `truth`.
13826
+ */
13827
+ function checkCovers(env, probe) {
13828
+ const domains = env.machine.domains;
13829
+ if (domains === void 0) return;
13830
+ const palette = env.results.flatMap((result) => result.ok ? [result.value] : []);
13831
+ const samples = {};
13832
+ for (const [name, domain] of Object.entries(domains)) if (domain.covers !== void 0) samples[name] = membersOf(name, domains, palette);
13833
+ const found = falseCovers(domains, samples)[0];
13834
+ if (found === void 0) return;
13835
+ report(env, "cover", `The member ${valueText(found.value)} of the domain ${found.domain} is in no domain of its cover ${found.cover.join(", ")}. The check of types trusts the cover, thus it is unsound for ${found.domain}.`, () => probe(found.value));
13836
+ }
13837
+ /**
11619
13838
  * This function examines one evaluator or runner of a machine against the obligations of host code (K92, D36). It
11620
13839
  * starts the code directly, without the kernel, with probe parts and a probe runtime. It generates probe documents from
11621
13840
  * the contract of each kind that names the code, and it gives the probe parts chosen and random results.
11622
13841
  *
11623
13842
  * The checks follow the obligations C1 to C8 of `docs/SEMANTICS.md`. Two more checks follow the premises of the
11624
13843
  * simulation of the plan. The check `local` finds state that stays from one call to the next. The check `agree` compares
11625
- * compiled code with its definition. The
11626
- * finding of an obligation names the first probe that breaks it. An empty list means that each probe conforms.
13844
+ * compiled code with its definition. The finding of an obligation names the first probe that breaks it. An empty list
13845
+ * means that each probe conforms.
13846
+ *
13847
+ * The check `truth` tests the declared truth of a formula profile (D86). The check `cover` tests the covers of the
13848
+ * domains of the machine from samples (D94).
11627
13849
  *
11628
13850
  * @param machine - The machine with the code and the world of the kinds.
11629
13851
  * @param name - The name of the evaluator or of the runner. A runner wins over an evaluator of the same name.
@@ -11654,18 +13876,39 @@ function conforms(machine, name, options = {}) {
11654
13876
  found: /* @__PURE__ */ new Map()
11655
13877
  };
11656
13878
  const types = options.types ?? typesNaming(machine.world, name, verb);
13879
+ let first;
11657
13880
  if (types.length === 0) throw new Error(`No kind of the world names ${name} for the verb ${verb}. Give the types of the probe documents in the option types.`);
11658
13881
  for (const type of types) {
11659
13882
  const found = lookupKind(machine.world, type);
11660
13883
  if (!found.ok) throw new Error(`The world has no kind for the type ${typeName(type)}.`);
11661
13884
  const contract = contractOf(env, found.kind, found.path, options.caps);
11662
13885
  const extra = own(options.values, typeName(type)) ?? own(options.values, found.path.join(".")) ?? [];
11663
- for (const sample of samplesOf(type, found.path, found.kind, contract, extra)) examine(env, sample, contract);
13886
+ for (const sample of samplesOf(type, found.path, found.kind, contract, extra)) {
13887
+ first ??= sample;
13888
+ examine(env, sample, contract);
13889
+ }
11664
13890
  }
13891
+ const probeWith = (value) => first === void 0 ? {
13892
+ type: typeName(types[0]),
13893
+ doc: {
13894
+ type: types[0],
13895
+ value: null
13896
+ },
13897
+ results: {},
13898
+ waits: [],
13899
+ caps: NO_CAPS,
13900
+ running: runner
13901
+ } : probeOf(first, {
13902
+ results: first.split.parts.map(() => ok(value)),
13903
+ waits: [],
13904
+ caps: NO_CAPS,
13905
+ running: runner
13906
+ });
13907
+ checkTruth(env, code, probeWith);
13908
+ checkCovers(env, probeWith);
11665
13909
  return ORDER.filter((obligation) => env.found.has(obligation)).map((obligation) => env.found.get(obligation));
11666
13910
  }
11667
- //#endregion
11668
- //#region src/same.ts
13911
+ // src/same.ts
11669
13912
  /**
11670
13913
  * This function tells if two results are the same for an early cutoff (RESULT.SAME). A schedule uses it to stop the
11671
13914
  * work when a part that evaluates again gives the same result. A wrong `true` keeps a stale value, but a wrong `false`
@@ -11701,8 +13944,7 @@ function sameError(a, b) {
11701
13944
  if (a.place === void 0 || b.place === void 0) return a.place === b.place;
11702
13945
  return docEquals(a.place, b.place);
11703
13946
  }
11704
- //#endregion
11705
- //#region src/reads.ts
13947
+ // src/reads.ts
11706
13948
  /** One answer serves each list whose reads are all the same. */
11707
13949
  const SAME = /* @__PURE__ */ Object.freeze({ same: true });
11708
13950
  /** This function tells if two lists of hops are the same: the same steps, rungs and things, in order. */
@@ -11793,8 +14035,7 @@ function verifyReads(target, reads, context, options = {}) {
11793
14035
  }
11794
14036
  return SAME;
11795
14037
  }
11796
- //#endregion
11797
- //#region src/durable.ts
14038
+ // src/durable.ts
11798
14039
  /** The most values that a cache of value documents keeps, as in `planner`. */
11799
14040
  const MAX_VALUES = 1e3;
11800
14041
  /** No reads. One frozen list serves each result of a pure document without reads. */
@@ -11934,8 +14175,7 @@ function durable(machine, options = {}) {
11934
14175
  }
11935
14176
  };
11936
14177
  }
11937
- //#endregion
11938
- //#region src/graph.ts
14178
+ // src/graph.ts
11939
14179
  /** This function gives the indexed form of a graph, with the edges that the options keep. */
11940
14180
  function indexed(graph, options) {
11941
14181
  const eager = options.eager === true;
@@ -12265,8 +14505,7 @@ function deepestFirst(from, edgesOf) {
12265
14505
  }
12266
14506
  return out;
12267
14507
  }
12268
- //#endregion
12269
- //#region src/schedule.ts
14508
+ // src/schedule.ts
12270
14509
  /**
12271
14510
  * This function gives the edges of a node from the static facts of its document (SCHED.EDGES). Each read of the root
12272
14511
  * `world` is an edge to the node of its first key. The keys after that key are the field of the edge (SCHED.GRAIN).
@@ -12560,8 +14799,7 @@ function schedule(machine, options = {}) {
12560
14799
  }
12561
14800
  };
12562
14801
  }
12563
- //#endregion
12564
- //#region src/meaning.ts
14802
+ // src/meaning.ts
12565
14803
  /** A list of eight reference types. The generator then gives more references, thus more reads of nodes. */
12566
14804
  function moreRefs() {
12567
14805
  return Array.from({ length: 8 }, () => ["ref"]);
@@ -12960,8 +15198,7 @@ function agreeSchedule(engine, options = {}) {
12960
15198
  counts
12961
15199
  };
12962
15200
  }
12963
- //#endregion
12964
- //#region src/providers.ts
15201
+ // src/providers.ts
12965
15202
  /** The deepest schema that `typeFromSchema` reads. A deeper schema reads as `unknown`. */
12966
15203
  const MAX_SCHEMA_DEPTH = 256;
12967
15204
  /** The keywords that describe a schema and do not test a value. The reading ignores them without an issue. */
@@ -13270,7 +15507,6 @@ function samplesAt(values, closed, depth) {
13270
15507
  function typeFromSamples(values, options = {}) {
13271
15508
  return samplesAt(values, options.closed === true, 0);
13272
15509
  }
13273
- //#endregion
13274
- export { ATTRIBUTE_RUNGS, CAPS_TYPE, CONSTRUCTS, ENVELOPE_KEYS, Failure, Held, JOURNAL, 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, agree, agreeRun, agreeSchedule, ask, attributeTrace, capKeys, check, checkLatent, checkSteps, checkWorld, classify, components, conforms, context, cycles, dataEdges, decodeDomain, decodeValue, derefStep, describe, docEquals, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stored, syntaxFormat, tag, thrown, toJson, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
15510
+ export { ATTRIBUTE_RUNGS, CAPS_TYPE, CONSTRUCTS, ENVELOPE_KEYS, Failure, Held, JOURNAL, 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, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, ask, attributeTrace, capKeys, check, checkLatent, checkSteps, checkWorld, classify, components, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, derefStep, describe, docEquals, 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, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stored, syntaxFormat, tag, thrown, toJson, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
13275
15511
 
13276
15512
  //# sourceMappingURL=index.js.map