@mark1russell7/coeval 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -282,7 +282,11 @@ var Failure = class extends Error {
282
282
  * @returns `true` for a stack overflow.
283
283
  */
284
284
  function isStackOverflow(error) {
285
- return error instanceof RangeError && /call stack/i.test(error.message);
285
+ try {
286
+ return error instanceof RangeError && /call stack/i.test(error.message);
287
+ } catch {
288
+ return true;
289
+ }
286
290
  }
287
291
  /**
288
292
  * This function changes an exception into an error value. A `Failure` gives its error value. A stack overflow
@@ -1281,6 +1285,52 @@ function narrow(parent, next) {
1281
1285
  caps
1282
1286
  };
1283
1287
  }
1288
+ /** No capabilities. One list serves each masked part. */
1289
+ const NO_CAPS = Object.freeze([]);
1290
+ /** No capability rules. One list serves each part that no rule narrows. */
1291
+ const NO_RULES = Object.freeze([]);
1292
+ /**
1293
+ * This function gives the capabilities that two lists both permit. An effect is permitted by the result when each
1294
+ * list permits it. When the list `b` permits each capability of `a`, the result is the list `a` itself.
1295
+ *
1296
+ * @param a - The first list, for example the capabilities of a document.
1297
+ * @param b - The second list, for example the list of a rule `only`.
1298
+ * @returns The capabilities that both lists permit.
1299
+ */
1300
+ function intersectCaps(a, b) {
1301
+ if (a.every((cap) => permits(b, cap))) return a;
1302
+ const out = [];
1303
+ for (const cap of b) if (permits(a, cap)) out.push(cap);
1304
+ for (const cap of a) if (permits(b, cap) && !permits(out, cap)) out.push(cap);
1305
+ return out;
1306
+ }
1307
+ /** This function gives the capability rules of a kind that cover a part and change its capabilities. */
1308
+ function rulesFor(rules, path) {
1309
+ if (rules === void 0 || rules.length === 0) return NO_RULES;
1310
+ const out = rules.filter((rule) => rule.rule !== "same" && (rule.in === void 0 || rule.in.some((pattern) => pathMatches(path, pattern))));
1311
+ return out.length === 0 ? NO_RULES : out;
1312
+ }
1313
+ /** This function applies the rules that cover a part to the capabilities of its document. */
1314
+ function capsUnder(rules, caps) {
1315
+ let out = caps;
1316
+ for (const rule of rules) {
1317
+ if (rule.rule === "mask") return NO_CAPS;
1318
+ if (rule.rule === "only") out = intersectCaps(out, rule.caps);
1319
+ }
1320
+ return out;
1321
+ }
1322
+ /**
1323
+ * This function gives the capabilities that a kind gives one of its parts, by the capability rules of its contract.
1324
+ * The kernel and the static kit both use it, thus a run and a check narrow the same way.
1325
+ *
1326
+ * @param rules - The capability rules of the kind (`Kind.caps`).
1327
+ * @param path - The path of the part in the value of the document.
1328
+ * @param caps - The capabilities of the document.
1329
+ * @returns The capabilities of the part: the same list or a smaller one.
1330
+ */
1331
+ function partCaps(rules, path, caps) {
1332
+ return capsUnder(rulesFor(rules, path), caps);
1333
+ }
1284
1334
  function selfLabel(self) {
1285
1335
  try {
1286
1336
  if (isHostThing(self)) return self.label;
@@ -1497,7 +1547,7 @@ function holderNode() {
1497
1547
  };
1498
1548
  }
1499
1549
  /** This function drives steps that cannot wait. */
1500
- function drive(steps) {
1550
+ function drive$1(steps) {
1501
1551
  const step = steps.next();
1502
1552
  if (step.done === true) return step.value;
1503
1553
  step.value.catch(() => void 0);
@@ -1540,7 +1590,10 @@ function isCompiledRunner(runner) {
1540
1590
  return typeof runner === "object" && runner !== null && typeof runner.compileRun === "function";
1541
1591
  }
1542
1592
  function failing(c, meta, place, code, reason) {
1543
- const result = fail(code, reason, { place });
1593
+ return failingWith(c, meta, fail(code, reason, { place }));
1594
+ }
1595
+ /** This function gives the code of a document that fails with one result at each evaluation. */
1596
+ function failingWith(c, meta, result) {
1544
1597
  const plain = () => result;
1545
1598
  return finish(c, meta, plain, function* () {
1546
1599
  return result;
@@ -1676,7 +1729,9 @@ function compileNode(c, value, place, declared, depth, address = false) {
1676
1729
  }
1677
1730
  const parts = split.parts.map((slot) => {
1678
1731
  const item = slot.item;
1679
- const compiled = compileNode(c, item, place.concat(slot.path), slot.of, depth + 1, slot.address === true);
1732
+ const own = compileNode(c, item, place.concat(slot.path), slot.of, depth + 1, slot.address === true);
1733
+ const rules = rulesFor(kind?.caps, slot.path);
1734
+ const compiled = rules.length === 0 ? own : gated(rules, own);
1680
1735
  const header = typeof item?.name === "string" && isEnvelope(item) ? item.name : void 0;
1681
1736
  return header === void 0 ? {
1682
1737
  key: slot.key,
@@ -1704,10 +1759,22 @@ function compileNode(c, value, place, declared, depth, address = false) {
1704
1759
  ...address ? { address: true } : {}
1705
1760
  };
1706
1761
  if (runner !== void 0) {
1707
- const run = placedRun(isCompiledRunner(runner) ? runner.compileRun(input) : interpretRun(runner, input, split.fill), place, name);
1762
+ let inner;
1763
+ try {
1764
+ inner = isCompiledRunner(runner) ? runner.compileRun(input) : interpretRun(runner, input, split.fill);
1765
+ } catch (error) {
1766
+ return failingWith(c, meta, placed(thrown(error, `the runner ${name}`), place));
1767
+ }
1768
+ const run = placedRun(inner, place, name);
1708
1769
  return finish(c, meta, runnerCode(run, place, kindText), run);
1709
1770
  }
1710
- const code = placedCode(isCompiledEvaluator(evaluator) ? evaluator.compile(input) : interpret(evaluator, input, split.fill), place, name);
1771
+ let inner;
1772
+ try {
1773
+ inner = isCompiledEvaluator(evaluator) ? evaluator.compile(input) : interpret(evaluator, input, split.fill);
1774
+ } catch (error) {
1775
+ return failingWith(c, meta, placed(thrown(error, `the evaluator ${name}`), place));
1776
+ }
1777
+ const code = placedCode(inner, place, name);
1711
1778
  return finish(c, meta, code, runOf(code));
1712
1779
  }
1713
1780
  /** This function gives the code of a document: the code of its evaluator, with the place of each error and of each exception. */
@@ -1720,6 +1787,25 @@ function placedCode(inner, place, name) {
1720
1787
  }
1721
1788
  };
1722
1789
  }
1790
+ /**
1791
+ * This function gives the code of a part that capability rules cover. The code narrows the context of the part by
1792
+ * the rules before the part starts.
1793
+ */
1794
+ function gated(rules, part) {
1795
+ const inner = part.code;
1796
+ const steps = part.run;
1797
+ const under = (ctx) => {
1798
+ const caps = capsUnder(rules, ctx.caps);
1799
+ return caps === ctx.caps || caps.length === 0 && ctx.caps.length === 0 ? ctx : {
1800
+ ...ctx,
1801
+ caps
1802
+ };
1803
+ };
1804
+ return {
1805
+ code: (ctx, rt) => inner(under(ctx), rt),
1806
+ run: (ctx, rt) => steps(under(ctx), rt)
1807
+ };
1808
+ }
1723
1809
  /** This function gives the steps of a runner, with the place of each error and of each exception. */
1724
1810
  function placedRun(inner, place, name) {
1725
1811
  return function* (ctx, rt) {
@@ -1730,9 +1816,12 @@ function placedRun(inner, place, name) {
1730
1816
  }
1731
1817
  };
1732
1818
  }
1733
- /** This function gives the code of a runner in an evaluation: its steps, which cannot wait. */
1819
+ /**
1820
+ * This function gives the code of a runner in an evaluation: its steps, which cannot wait. A step that waits gives
1821
+ * `#CALC!` at the place of the runner, where the error started (RUN.WAIT).
1822
+ */
1734
1823
  function runnerCode(run, place, kindText) {
1735
- return (ctx, rt) => rt.running ? fail("#CALC!", `${kindText} waits for effects, and its parent cannot wait. Give the parent a runner.`, { place }) : drive(run(ctx, rt));
1824
+ return (ctx, rt) => rt.running ? fail("#CALC!", `${kindText} waits for effects, and its parent cannot wait. Give the parent a runner.`, { place }) : placed(drive$1(run(ctx, rt)), place);
1736
1825
  }
1737
1826
  /** This function gives the steps of a run of an evaluator. The code runs at the first step, and it does not wait. */
1738
1827
  function runOf(code) {
@@ -1824,7 +1913,7 @@ function prepare(machine, doc, options = {}) {
1824
1913
  try {
1825
1914
  root = compileNode(c, doc, [], options.declaredType, 0);
1826
1915
  } catch (error) {
1827
- const result = thrown(error, "the compilation");
1916
+ const result = placed(thrown(error, "the compilation"), []);
1828
1917
  root = {
1829
1918
  code: () => result,
1830
1919
  run: function* () {
@@ -1885,7 +1974,7 @@ function planner(machine, options = {}) {
1885
1974
  return plan;
1886
1975
  };
1887
1976
  }
1888
- function record(s, result) {
1977
+ function record$1(s, result) {
1889
1978
  const root = s.holder?.children[0];
1890
1979
  if (root === void 0) throw new Error("The evaluation made no trace.");
1891
1980
  return {
@@ -1914,7 +2003,7 @@ function evaluate(machine, doc, context = makeContext(), declaredType) {
1914
2003
  ...declaredType === void 0 ? {} : { declaredType }
1915
2004
  });
1916
2005
  const s = new Session(machine, false, true, void 0, void 0, void 0);
1917
- return record(s, plan.root.code(rootContext(machine, context), s));
2006
+ return record$1(s, plan.root.code(rootContext(machine, context), s));
1918
2007
  }
1919
2008
  /**
1920
2009
  * This function runs a document: an evaluation in which the host does each effect. A runner waits for its
@@ -1933,7 +2022,7 @@ async function run(machine, doc, context = makeContext(), options = {}) {
1933
2022
  ...options.declaredType === void 0 ? {} : { declaredType: options.declaredType }
1934
2023
  });
1935
2024
  const s = new Session(machine, true, true, options.perform, options.signal, void 0);
1936
- return record(s, await driveWaiting(plan.root.run(rootContext(machine, context), s), options.signal));
2025
+ return record$1(s, await driveWaiting(plan.root.run(rootContext(machine, context), s), options.signal));
1937
2026
  }
1938
2027
  /**
1939
2028
  * This function finds a node of a trace by its path.
@@ -2146,6 +2235,7 @@ const STD_WORLD = {
2146
2235
  view: "view.op"
2147
2236
  },
2148
2237
  parts: { shape: "list" },
2238
+ caps: [{ rule: "mask" }],
2149
2239
  summary: "It evaluates its part without capabilities, thus an effect in it fails."
2150
2240
  },
2151
2241
  log: {
@@ -2158,6 +2248,7 @@ const STD_WORLD = {
2158
2248
  of: "text"
2159
2249
  },
2160
2250
  side: "run",
2251
+ effects: ["log"],
2161
2252
  summary: "It writes the result of its part to the log. This is an effect."
2162
2253
  },
2163
2254
  write: {
@@ -2170,6 +2261,7 @@ const STD_WORLD = {
2170
2261
  fields: ["value"]
2171
2262
  },
2172
2263
  side: "run",
2264
+ effects: ["write"],
2173
2265
  summary: "It writes the result of its part to the store, at its key. This is an effect."
2174
2266
  }
2175
2267
  },
@@ -2347,13 +2439,10 @@ const STD_RUNNERS = {
2347
2439
  }
2348
2440
  return ok(last);
2349
2441
  },
2350
- "control.pure": function* ({ parts, context }) {
2442
+ "control.pure": function* ({ parts }) {
2351
2443
  const only = parts[0];
2352
2444
  if (only === void 0) return fail("#VALUE!", "pure needs one part.");
2353
- return yield* only.evaluate({
2354
- ...context,
2355
- caps: []
2356
- });
2445
+ return yield* only.evaluate();
2357
2446
  },
2358
2447
  "control.if": function* ({ parts }) {
2359
2448
  const test = parts.find((part) => part.key === "test");
@@ -2878,9 +2967,10 @@ var Visit = class {
2878
2967
  kind;
2879
2968
  typePath;
2880
2969
  address;
2970
+ caps;
2881
2971
  #place;
2882
2972
  #at;
2883
- constructor(place, at, doc, declared, depth, names, later, slot, parent, kind, typePath, address) {
2973
+ constructor(place, at, doc, declared, depth, names, later, slot, parent, kind, typePath, address, caps) {
2884
2974
  this.doc = doc;
2885
2975
  this.declared = declared;
2886
2976
  this.depth = depth;
@@ -2891,6 +2981,7 @@ var Visit = class {
2891
2981
  this.kind = kind;
2892
2982
  this.typePath = typePath;
2893
2983
  this.address = address;
2984
+ this.caps = caps;
2894
2985
  this.#place = place;
2895
2986
  this.#at = at;
2896
2987
  }
@@ -2903,14 +2994,15 @@ var Visit = class {
2903
2994
  };
2904
2995
  /**
2905
2996
  * This function visits each document of a document: the root and each part at each depth, by the contracts of the
2906
- * kinds. A part of a kind that the world does not have is not visited. The walk uses no stack of the host for the
2997
+ * kinds. A part of a kind that the world does not have is not visited. With capabilities in the options, the walk
2998
+ * narrows them for each part by the rules of its kind, as a run does. The walk uses no stack of the host for the
2907
2999
  * depth, thus a deep document cannot overflow it. The time and the memory of a walk are linear in the size of the
2908
3000
  * document. A visit makes the keys of its place and of its path only when a reader asks for them.
2909
3001
  *
2910
3002
  * @param world - The world of the kinds.
2911
3003
  * @param doc - The document, as JSON.
2912
3004
  * @param visit - The function that gets each document. It gives `"skip"` to not visit the parts of a document.
2913
- * @param options - The type of a bare root value, the names of the host, and a function for the problems.
3005
+ * @param options - The type of a bare root value, the names, the capabilities and a function for the problems.
2914
3006
  */
2915
3007
  function walk(world, doc, visit, options = {}) {
2916
3008
  const stack = [{
@@ -2923,7 +3015,8 @@ function walk(world, doc, visit, options = {}) {
2923
3015
  later: NO_NAMES,
2924
3016
  address: false,
2925
3017
  slot: [],
2926
- parent: void 0
3018
+ parent: void 0,
3019
+ caps: options.caps
2927
3020
  }];
2928
3021
  while (stack.length > 0) {
2929
3022
  const item = stack.pop();
@@ -2943,7 +3036,7 @@ function walk(world, doc, visit, options = {}) {
2943
3036
  };
2944
3037
  const found = lookupKind(world, doc.type);
2945
3038
  const kind = found.ok ? found.kind : void 0;
2946
- const here = new Visit(item.place, item.at, doc, envelope === void 0, item.depth, item.names, item.later, item.slot, item.parent, kind, found.ok ? found.path : void 0, item.address ? true : void 0);
3039
+ const here = new Visit(item.place, item.at, doc, envelope === void 0, item.depth, item.names, item.later, item.slot, item.parent, kind, found.ok ? found.path : void 0, item.address ? true : void 0, item.caps);
2947
3040
  if (visit(here) === "skip" || kind === void 0) continue;
2948
3041
  const split = splitParts(kind.parts, doc.value);
2949
3042
  const base = envelope === void 0 ? item.at : {
@@ -2985,7 +3078,8 @@ function walk(world, doc, visit, options = {}) {
2985
3078
  later: hidden.length === 0 ? item.later : /* @__PURE__ */ new Set([...item.later, ...hidden]),
2986
3079
  address: slot.address === true,
2987
3080
  slot: slot.path,
2988
- parent: here
3081
+ parent: here,
3082
+ caps: item.caps === void 0 || kind.caps === void 0 ? item.caps : partCaps(kind.caps, slot.path, item.caps)
2989
3083
  });
2990
3084
  }
2991
3085
  }
@@ -3073,6 +3167,15 @@ function mapRefs(world, doc, change, options = {}) {
3073
3167
  return out;
3074
3168
  }
3075
3169
  /**
3170
+ * This function gives the reason of a `#CAP!`. When a kind around the document narrowed the capabilities, the
3171
+ * reason names the nearest such kind.
3172
+ */
3173
+ function capReason(v, kind) {
3174
+ const text = kind.join(".");
3175
+ for (let up = v.parent; up !== void 0; up = up.parent) if (up.caps !== void 0 && permits(up.caps, kind)) return `The capabilities do not permit the effect ${text} here. The kind ${typeName(up.doc.type)} around it narrows them for its parts.`;
3176
+ return `The capabilities do not permit the effect ${text}.`;
3177
+ }
3178
+ /**
3076
3179
  * This function checks a document before an evaluation, by the contracts of its kinds. It finds the problems
3077
3180
  * that an evaluation finds when it reaches them:
3078
3181
  *
@@ -3083,7 +3186,7 @@ function mapRefs(world, doc, change, options = {}) {
3083
3186
  * - `#DEPTH!`: too much nesting.
3084
3187
  * - `#REF!` and `#STEP?`: a bad path.
3085
3188
  * - `#NAME?`: a name that nothing binds.
3086
- * - `#CAP!`: an effect that the capabilities do not permit.
3189
+ * - `#CAP!`: an effect that the capabilities of its document do not permit. A kind around the document can narrow them.
3087
3190
  *
3088
3191
  * @param machine - The world and the code of the evaluators.
3089
3192
  * @param doc - The document, as JSON.
@@ -3124,12 +3227,13 @@ function check(machine, doc, options = {}) {
3124
3227
  reason: `No rung gives an evaluator for ${typeName(v.doc.type)}.`,
3125
3228
  at: v.at
3126
3229
  });
3127
- if (options.caps !== void 0 && v.kind?.effects !== void 0) {
3230
+ const caps = v.caps;
3231
+ if (caps !== void 0 && v.kind?.effects !== void 0) {
3128
3232
  const kinds = v.kind.effects === "type" ? [v.typePath ?? []] : v.kind.effects.map((kind) => kind.split("."));
3129
- for (const kind of kinds) if (!permits(options.caps, kind)) issues.push({
3233
+ for (const kind of kinds) if (!permits(caps, kind)) issues.push({
3130
3234
  code: "#CAP!",
3131
3235
  place: v.place,
3132
- reason: `The capabilities do not permit the effect ${kind.join(".")}.`,
3236
+ reason: capReason(v, kind),
3133
3237
  at: v.at
3134
3238
  });
3135
3239
  }
@@ -3187,6 +3291,7 @@ function check(machine, doc, options = {}) {
3187
3291
  }, {
3188
3292
  ...options.declaredType === void 0 ? {} : { declaredType: options.declaredType },
3189
3293
  ...Array.isArray(options.names) ? { names: options.names } : {},
3294
+ ...options.caps === void 0 ? {} : { caps: options.caps },
3190
3295
  problem: (problem) => issues.push({
3191
3296
  code: problem.code,
3192
3297
  place: problem.place,
@@ -3207,7 +3312,7 @@ var Held = class {
3207
3312
  this.error = error;
3208
3313
  }
3209
3314
  };
3210
- const CLOSURE = Symbol.for("coeval.closure");
3315
+ const CLOSURE$2 = Symbol.for("coeval.closure");
3211
3316
  /**
3212
3317
  * This function tells if a value is a function that the construct `fn` made.
3213
3318
  *
@@ -3215,7 +3320,7 @@ const CLOSURE = Symbol.for("coeval.closure");
3215
3320
  * @returns `true` for a closure.
3216
3321
  */
3217
3322
  function isClosure(value) {
3218
- return typeof value === "function" && value[CLOSURE] !== void 0;
3323
+ return typeof value === "function" && value[CLOSURE$2] !== void 0;
3219
3324
  }
3220
3325
  /** The standard extensions: the values that JSON cannot write. */
3221
3326
  const STD_EXT = {
@@ -3448,18 +3553,19 @@ function formulaEvaluators(profile = {}) {
3448
3553
  if (missing !== void 0 && missing(reached)) return fail("#N/A", "The path reaches no value.");
3449
3554
  return ok(reached);
3450
3555
  };
3451
- const computed = parts.length > 0;
3556
+ const held = (ctx) => {
3557
+ if (head === void 0 || !Object.hasOwn(ctx.names, head)) return void 0;
3558
+ const bound = ctx.names[head];
3559
+ return bound instanceof Held ? {
3560
+ ok: false,
3561
+ error: bound.error
3562
+ } : void 0;
3563
+ };
3564
+ if (parts.length === 0) return (ctx, rt) => held(ctx) ?? give(rt.resolve(ctx, path));
3452
3565
  return (ctx, rt) => {
3453
- if (head !== void 0 && Object.hasOwn(ctx.names, head)) {
3454
- const bound = ctx.names[head];
3455
- if (bound instanceof Held) return {
3456
- ok: false,
3457
- error: bound.error
3458
- };
3459
- }
3460
- if (!computed) return give(rt.resolve(ctx, path));
3461
3566
  const steps = valuesOf(parts, ctx, rt);
3462
- return Array.isArray(steps) ? give(rt.resolve(ctx, fill(steps))) : steps;
3567
+ if (!Array.isArray(steps)) return steps;
3568
+ return held(ctx) ?? give(rt.resolve(ctx, fill(steps)));
3463
3569
  };
3464
3570
  }),
3465
3571
  "formula.step": compiled(({ doc, parts, fill }) => {
@@ -3543,7 +3649,7 @@ function formulaEvaluators(profile = {}) {
3543
3649
  if (!result.ok) throw new Failure(result.error);
3544
3650
  return result.value;
3545
3651
  };
3546
- Object.defineProperty(closure, CLOSURE, { value: { params: names } });
3652
+ Object.defineProperty(closure, CLOSURE$2, { value: { params: names } });
3547
3653
  return ok(closure);
3548
3654
  };
3549
3655
  }),
@@ -3712,6 +3818,1054 @@ function formulaMachine(profile = {}, more = {}) {
3712
3818
  };
3713
3819
  }
3714
3820
  //#endregion
3715
- export { CONSTRUCTS, ENVELOPE_KEYS, Failure, Held, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_WALKERS, STD_WORLD, THING, ask, capKeys, check, checkSteps, classify, context, dataEdges, derefStep, describe, docEquals, effectEdges, entriesAsJson, evaluate, fail, failures, field, flatten, formulaEvaluators, formulaKinds, formulaMachine, fromJson, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isTypeRef, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapRefs, narrow, nearestWalker, nodeAt, ok, pathMatches, permits, placed, planner, prepare, ref, refsOf, resolve, run, splitParts, stored, tag, thrown, toJson, typeName, typePath, typed, valueOfThing, walk, worldThing };
3821
+ //#region src/reference.ts
3822
+ function own(table, name) {
3823
+ return table !== void 0 && Object.hasOwn(table, name) ? table[name] : void 0;
3824
+ }
3825
+ /** This function finds the code of an evaluator name. A runner wins over an evaluator of the same name. */
3826
+ function choose(env, name) {
3827
+ const runner = own(env.machine.runners, name);
3828
+ if (runner !== void 0) {
3829
+ const defined = own(env.definitions.runners, name);
3830
+ if (defined !== void 0) return { runner: defined };
3831
+ return typeof runner === "function" ? { runner } : { gap: `The reference has no definition of the compiled runner ${name}.` };
3832
+ }
3833
+ const evaluator = own(env.machine.evaluators, name);
3834
+ if (evaluator === void 0) return void 0;
3835
+ const defined = own(env.definitions.evaluators, name);
3836
+ if (defined !== void 0) return { evaluator: defined };
3837
+ return typeof evaluator === "function" ? { evaluator } : { gap: `The reference has no definition of the compiled evaluator ${name}.` };
3838
+ }
3839
+ /**
3840
+ * This function reads one document by the rules, in their order. First come an envelope or a declared type
3841
+ * (EVAL.ERRORS) and the limit of the depth (PLAN.DEPTH). Then come the ladder (LADDER.*), an evaluator and the shape
3842
+ * of the parts (SHAPE.*).
3843
+ */
3844
+ function examine(env, at) {
3845
+ const { place, declared } = at;
3846
+ const envelope = isEnvelope(at.value) ? at.value : void 0;
3847
+ if (envelope === void 0 && declared === void 0) return fail("#PART?", "The value has no envelope, and its position declares no type.", { place });
3848
+ if (at.depth > env.maxDepth) return fail("#DEPTH!", `The nesting is deeper than ${env.maxDepth} documents.`, { place });
3849
+ const doc = envelope ?? {
3850
+ type: declared,
3851
+ value: at.value
3852
+ };
3853
+ const kindText = typeName(doc.type);
3854
+ const world = env.machine.world;
3855
+ const answer = ask(world, envelope ?? {}, "eval", declared === void 0 ? {} : { declaredType: declared });
3856
+ if (answer.error === "unknown-kind") return fail("#KIND?", `The world has no kind ${kindText}.`, { place });
3857
+ const name = answer.evaluator;
3858
+ const chosen = name === void 0 ? void 0 : choose(env, name);
3859
+ if (name === void 0 || chosen === void 0) return fail("#NOEVAL", `No rung gives an evaluator for ${kindText}.`, { place });
3860
+ const found = lookupKind(world, doc.type);
3861
+ const kind = found.ok ? found.kind : void 0;
3862
+ const split = splitParts(kind?.parts, doc.value);
3863
+ if (!split.ok) {
3864
+ const where = split.at.length === 0 ? "" : ` (at ${split.at.join(".")})`;
3865
+ return fail("#VALUE!", `${split.reason}${where} The kind is ${kindText}.`, { place });
3866
+ }
3867
+ return {
3868
+ doc,
3869
+ kindText,
3870
+ typePath: found.ok ? found.path : [],
3871
+ kind,
3872
+ name,
3873
+ chosen,
3874
+ split
3875
+ };
3876
+ }
3877
+ /** This function gives the capabilities that the rules of a kind give one part (D14, CAP.CONTRACT, CAP.ONLY). */
3878
+ function capsOfPart(rules, path, caps) {
3879
+ let out = caps;
3880
+ for (const rule of rules ?? []) {
3881
+ if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(path, pattern))) continue;
3882
+ if (rule.rule === "mask") return [];
3883
+ if (rule.rule === "only") out = intersectCaps(out, rule.caps);
3884
+ }
3885
+ return out;
3886
+ }
3887
+ /**
3888
+ * This function gives the context of a part. A context that the evaluator gives keeps only the capabilities of the
3889
+ * parent (CAP.NARROW). Then the rules of the kind narrow it (CAP.CONTRACT).
3890
+ */
3891
+ function contextOfPart(seen, slot, parent, given) {
3892
+ const base = given === void 0 || given === parent ? parent : {
3893
+ ...given,
3894
+ caps: given.caps.filter((cap) => permits(parent.caps, cap))
3895
+ };
3896
+ const caps = capsOfPart(seen.kind?.caps, slot.path, base.caps);
3897
+ return caps === base.caps ? base : {
3898
+ ...base,
3899
+ caps
3900
+ };
3901
+ }
3902
+ function headerOf(item) {
3903
+ return isEnvelope(item) && typeof item.name === "string" ? item.name : void 0;
3904
+ }
3905
+ function partAt(seen, at, slot, given) {
3906
+ return {
3907
+ value: slot.item,
3908
+ place: at.place.concat(slot.path),
3909
+ declared: slot.of,
3910
+ depth: at.depth + 1,
3911
+ address: slot.address === true,
3912
+ ctx: contextOfPart(seen, slot, at.ctx, given)
3913
+ };
3914
+ }
3915
+ /** This function resolves a path with the full algorithm of `resolve`, not with its short path (DEREF.QUICK). */
3916
+ function resolveFully(machine, ctx, path, options) {
3917
+ const found = resolve(machine, ctx, path, { hops: true });
3918
+ return options?.hops === true ? found : {
3919
+ ...found,
3920
+ hops: []
3921
+ };
3922
+ }
3923
+ /** This function records an effect when the capabilities permit it (RUN.CAP, CAP.HOOK). */
3924
+ function record(env, ctx, kind, payload, place) {
3925
+ const keys = typeof kind === "string" ? kind.split(".") : kind;
3926
+ const text = keys.join(".");
3927
+ const machine = env.machine;
3928
+ if (!(machine.permits === void 0 ? permits(ctx.caps, keys) : machine.permits(ctx.caps, keys, ctx))) return fail("#CAP!", `The context has no capability for the effect ${text}.`, { place });
3929
+ env.effects.push({
3930
+ index: env.effects.length,
3931
+ kind: text,
3932
+ path: keys,
3933
+ payload,
3934
+ node: -1,
3935
+ at: 0,
3936
+ place,
3937
+ context: ctx
3938
+ });
3939
+ }
3940
+ /** This function evaluates a document. Each error gets the place of the document where it started (K5). */
3941
+ function evaluateAt(env, at) {
3942
+ const seen = examine(env, at);
3943
+ if (!("doc" in seen)) return seen;
3944
+ return evaluateSeen(env, seen, at);
3945
+ }
3946
+ function evaluateSeen(env, seen, at) {
3947
+ const { chosen } = seen;
3948
+ const { place } = at;
3949
+ if ("gap" in chosen) return fail("#NOEVAL", chosen.gap, { place });
3950
+ if ("runner" in chosen) return drive(runSeen(env, seen, at, chosen.runner), place);
3951
+ const input = evalInput(env, seen, at);
3952
+ try {
3953
+ return placed(chosen.evaluator(input), place);
3954
+ } catch (error) {
3955
+ return placed(thrown(error, `the evaluator ${seen.name}`), place);
3956
+ }
3957
+ }
3958
+ /** This function gives the steps of a document for a runner. Nothing happens before the first step. */
3959
+ function* stepsAt(env, at) {
3960
+ const seen = examine(env, at);
3961
+ if (!("doc" in seen)) return seen;
3962
+ if ("runner" in seen.chosen) return yield* runSeen(env, seen, at, seen.chosen.runner);
3963
+ return evaluateSeen(env, seen, at);
3964
+ }
3965
+ function* runSeen(env, seen, at, runner) {
3966
+ try {
3967
+ return placed(yield* runner(runInput(env, seen, at)), at.place);
3968
+ } catch (error) {
3969
+ return placed(thrown(error, `the runner ${seen.name}`), at.place);
3970
+ }
3971
+ }
3972
+ /** This function drives steps that cannot wait. A step that waits gives `#CALC!` at the document (RUN.WAIT). */
3973
+ function drive(steps, place) {
3974
+ const step = steps.next();
3975
+ if (step.done === true) return step.value;
3976
+ step.value.catch(() => void 0);
3977
+ const waited = fail("#CALC!", "A part waited, and its parent cannot wait.", { place });
3978
+ steps.return(waited);
3979
+ return waited;
3980
+ }
3981
+ function evalInput(env, seen, at) {
3982
+ const { split, doc } = seen;
3983
+ const parts = split.parts.map((slot) => {
3984
+ const name = headerOf(slot.item);
3985
+ return {
3986
+ key: slot.key,
3987
+ path: slot.path,
3988
+ ...name === void 0 ? {} : { name },
3989
+ evaluate: (given) => evaluateAt(env, partAt(seen, at, slot, given))
3990
+ };
3991
+ });
3992
+ const fill = (items) => split.parts.length === 0 ? doc.value : split.fill(items);
3993
+ return {
3994
+ kind: seen.kindText,
3995
+ typePath: seen.typePath,
3996
+ doc,
3997
+ value: fill(parts),
3998
+ data: split.data,
3999
+ parts,
4000
+ context: at.ctx,
4001
+ place: at.place,
4002
+ ...at.address ? { address: true } : {},
4003
+ resolve: (path, options) => resolveFully(env.machine, at.ctx, path, options),
4004
+ effect: (kind, payload) => record(env, at.ctx, kind, payload, at.place) ?? ok(payload),
4005
+ fill
4006
+ };
4007
+ }
4008
+ function runInput(env, seen, at) {
4009
+ const { split, doc } = seen;
4010
+ const parts = split.parts.map((slot) => {
4011
+ const name = headerOf(slot.item);
4012
+ return {
4013
+ key: slot.key,
4014
+ path: slot.path,
4015
+ ...name === void 0 ? {} : { name },
4016
+ evaluate: (given) => stepsAt(env, partAt(seen, at, slot, given))
4017
+ };
4018
+ });
4019
+ const fill = (items) => split.parts.length === 0 ? doc.value : split.fill(items);
4020
+ return {
4021
+ kind: seen.kindText,
4022
+ typePath: seen.typePath,
4023
+ doc,
4024
+ value: fill(parts),
4025
+ data: split.data,
4026
+ parts,
4027
+ context: at.ctx,
4028
+ place: at.place,
4029
+ resolve: (path, options) => resolveFully(env.machine, at.ctx, path, options),
4030
+ effect: function* (kind, payload) {
4031
+ return record(env, at.ctx, kind, payload, at.place) ?? ok(payload);
4032
+ },
4033
+ all: (list, options) => together(list, options),
4034
+ fill
4035
+ };
4036
+ }
4037
+ /**
4038
+ * This function evaluates parts for `all` (RUN.ALL). The parts start in their order, up to the limit, and each part
4039
+ * goes on until it ends or waits. In an evaluation, a part that waits does not end, thus it keeps its place in the
4040
+ * limit. With `failFast`, the first failure stops the parts that wait, and the later parts do not start
4041
+ * (RUN.FAIL-FAST). When no part failed and a part waits, the steps wait, and the drive gives `#CALC!`.
4042
+ */
4043
+ function* together(list, options = {}) {
4044
+ const limit = Math.max(1, options.concurrency ?? list.length);
4045
+ const results = list.map(() => void 0);
4046
+ const waiting = [];
4047
+ let failed = false;
4048
+ for (let index = 0; index < list.length && !failed && waiting.length < limit; index += 1) {
4049
+ let result;
4050
+ try {
4051
+ const steps = list[index].evaluate();
4052
+ const step = steps.next();
4053
+ if (step.done === true) result = step.value;
4054
+ else waiting.push({
4055
+ steps,
4056
+ promise: step.value
4057
+ });
4058
+ } catch (error) {
4059
+ result = thrown(error, "a part");
4060
+ }
4061
+ results[index] = result;
4062
+ if (result !== void 0 && options.failFast === true && !result.ok) failed = true;
4063
+ }
4064
+ if (failed) {
4065
+ const stopped = fail("#ABORT", "The part stopped: a part before it failed, and the parts run with failFast.");
4066
+ for (const item of waiting) try {
4067
+ item.steps.return(stopped);
4068
+ } catch {}
4069
+ return results.map((result) => result ?? stopped);
4070
+ }
4071
+ if (waiting.length > 0) yield Promise.race(waiting.map((item) => item.promise));
4072
+ return results;
4073
+ }
4074
+ /**
4075
+ * This function evaluates a document by the rules, without a compilation. It is the reference of the plans: a plan,
4076
+ * a traced plan and the second tier of a language must give its results. It covers evaluations, not runs: an effect
4077
+ * gives its payload, and a part that waits gives `#CALC!`.
4078
+ *
4079
+ * @param machine - The world and the code of the evaluators.
4080
+ * @param doc - The document.
4081
+ * @param context - The names and the capabilities at the root.
4082
+ * @param options - The type of a bare root value, the definitions of compiled code, and a list for the effects.
4083
+ * @returns The result.
4084
+ */
4085
+ function reference(machine, doc, context = makeContext(), options = {}) {
4086
+ const env = {
4087
+ machine,
4088
+ definitions: options.definitions ?? {},
4089
+ effects: options.effects ?? [],
4090
+ maxDepth: machine.maxDepth ?? 1e3
4091
+ };
4092
+ const ctx = context.world === null ? {
4093
+ ...context,
4094
+ world: worldThing(machine.world)
4095
+ } : context;
4096
+ try {
4097
+ return evaluateAt(env, {
4098
+ value: doc,
4099
+ place: [],
4100
+ declared: options.declaredType,
4101
+ depth: 0,
4102
+ address: false,
4103
+ ctx
4104
+ });
4105
+ } catch (error) {
4106
+ return placed(thrown(error, "the reference"), []);
4107
+ }
4108
+ }
4109
+ const CLOSURE$1 = Symbol.for("coeval.closure");
4110
+ /** This function sets an own field, also the field `__proto__` (SHAPE.PROTO). */
4111
+ function setField(target, key, value) {
4112
+ Object.defineProperty(target, key, {
4113
+ value,
4114
+ enumerable: true,
4115
+ writable: true,
4116
+ configurable: true
4117
+ });
4118
+ }
4119
+ function partNamed(parts, key) {
4120
+ return parts.find((part) => part.path.length === 1 && part.path[0] === key);
4121
+ }
4122
+ function partsUnder(parts, key) {
4123
+ return parts.filter((part) => part.path.length === 2 && part.path[0] === key);
4124
+ }
4125
+ /**
4126
+ * This function gives the definitions of the formula kit for one profile. Each construct is a function evaluator in
4127
+ * the most direct style. It shares no code with the compilers of `formulaEvaluators`, thus the two readings of the
4128
+ * rules can disagree, and a test finds it.
4129
+ *
4130
+ * @param profile - The operations and the rules of the language.
4131
+ * @returns The definitions, by evaluator name.
4132
+ */
4133
+ function formulaDefinitions(profile = {}) {
4134
+ const truthy = profile.truthy ?? ((value) => typeof value === "boolean" ? value : void 0);
4135
+ const opOf = (name) => typeof profile.ops === "function" ? profile.ops(name) : own(profile.ops, name);
4136
+ const noTruth = (what) => fail("#VALUE!", `The ${what} must give a truth value.`);
4137
+ /** FORMULA.LIST, FORMULA.OPS and FORMULA.COMBINE: the values of parts in order, or the error. */
4138
+ const valuesOf = (parts, skip) => {
4139
+ const values = [];
4140
+ const errors = [];
4141
+ for (const part of parts) {
4142
+ const result = part.evaluate();
4143
+ if (result.ok) values.push(result.value);
4144
+ else if (skip?.(result.error) === true) values.push(SKIP);
4145
+ else if (profile.combine === void 0) return result;
4146
+ else errors.push(result.error);
4147
+ }
4148
+ if (errors.length === 0 || profile.combine === void 0) return { values };
4149
+ return {
4150
+ ok: false,
4151
+ error: errors.length === 1 ? errors[0] : profile.combine(errors)
4152
+ };
4153
+ };
4154
+ const lit = ({ doc }) => ok(doc.value);
4155
+ const ref = ({ doc, parts, fill, address, context, resolve: walk }) => {
4156
+ const path = doc.value;
4157
+ if (!Array.isArray(path) || path.length === 0) return fail("#VALUE!", "The value of ref is a path: a list that starts with a root, for example [\"names\", \"a\"].");
4158
+ let steps = path;
4159
+ if (parts.length > 0) {
4160
+ const all = valuesOfStrict(parts);
4161
+ if (!("values" in all)) return all;
4162
+ steps = fill(all.values);
4163
+ }
4164
+ const head = path[0] === "names" && typeof path[1] === "string" ? path[1] : void 0;
4165
+ const bound = head === void 0 ? void 0 : own(context.names, head);
4166
+ if (bound instanceof Held) return {
4167
+ ok: false,
4168
+ error: bound.error
4169
+ };
4170
+ const found = walk(steps);
4171
+ if (!found.ok) return fail(found.code, found.reason);
4172
+ if (address === true) return ok(found.thing);
4173
+ const reached = valueOfThing(found.thing);
4174
+ if (reached instanceof Held) return {
4175
+ ok: false,
4176
+ error: reached.error
4177
+ };
4178
+ if (profile.missing?.(reached) === true) return fail("#N/A", "The path reaches no value.");
4179
+ return ok(reached);
4180
+ };
4181
+ const step = ({ doc, parts, fill }) => {
4182
+ if (parts.length === 0) return ok(doc);
4183
+ const all = valuesOfStrict(parts);
4184
+ return "values" in all ? ok({
4185
+ ...doc,
4186
+ value: fill(all.values)
4187
+ }) : all;
4188
+ };
4189
+ const record = ({ parts }) => {
4190
+ const all = valuesOf(parts, profile.omit);
4191
+ if (!("values" in all)) return all;
4192
+ const out = {};
4193
+ parts.forEach((part, index) => {
4194
+ const value = all.values[index];
4195
+ if (value !== SKIP) setField(out, String(part.path[0]), value);
4196
+ });
4197
+ return ok(out);
4198
+ };
4199
+ const list = ({ parts }) => {
4200
+ const all = valuesOf(parts);
4201
+ return "values" in all ? ok([...all.values]) : all;
4202
+ };
4203
+ const letIn = ({ parts, context }) => {
4204
+ const names = {};
4205
+ for (const key of Object.keys(context.names)) setField(names, key, context.names[key]);
4206
+ for (const binding of partsUnder(parts, "bind")) {
4207
+ const result = binding.evaluate();
4208
+ setField(names, String(binding.path[1]), result.ok ? result.value : new Held(result.error));
4209
+ }
4210
+ return partNamed(parts, "body").evaluate({
4211
+ ...context,
4212
+ names
4213
+ });
4214
+ };
4215
+ const fn = ({ data, parts, context }) => {
4216
+ const params = isRecord(data) ? data["params"] : void 0;
4217
+ if (!Array.isArray(params) || !params.every((param) => typeof param === "string") || new Set(params).size !== params.length) return fail("#VALUE!", "The params of fn are a list of different texts.");
4218
+ const names = params;
4219
+ const body = partNamed(parts, "body");
4220
+ const closure = (...args) => {
4221
+ const scope = {};
4222
+ for (const key of Object.keys(context.names)) setField(scope, key, context.names[key]);
4223
+ names.forEach((name, index) => setField(scope, name, args[index]));
4224
+ const result = body.evaluate({
4225
+ ...context,
4226
+ names: scope
4227
+ });
4228
+ if (!result.ok) throw new Failure(result.error);
4229
+ return result.value;
4230
+ };
4231
+ Object.defineProperty(closure, CLOSURE$1, { value: { params: names } });
4232
+ return ok(closure);
4233
+ };
4234
+ const call = ({ parts }) => {
4235
+ const target = partNamed(parts, "fn").evaluate();
4236
+ if (!target.ok) return target;
4237
+ if (typeof target.value !== "function") return fail("#VALUE!", "The fn of call must give a function.");
4238
+ const all = valuesOfStrict(partsUnder(parts, "args"));
4239
+ if (!("values" in all)) return all;
4240
+ try {
4241
+ return ok(target.value(...all.values));
4242
+ } catch (error) {
4243
+ return thrown(error, "the function of call");
4244
+ }
4245
+ };
4246
+ const choice = ({ parts }) => {
4247
+ const test = partNamed(parts, "test").evaluate();
4248
+ if (!test.ok) return test;
4249
+ const truth = truthy(test.value);
4250
+ if (truth === void 0) return noTruth("test of if");
4251
+ if (truth) return partNamed(parts, "then").evaluate();
4252
+ const other = partNamed(parts, "else");
4253
+ if (other !== void 0) return other.evaluate();
4254
+ return ok(Object.hasOwn(profile, "otherwise") ? profile.otherwise : null);
4255
+ };
4256
+ /** FORMULA.LOGIC: `and` stops at the first false term, and `or` at the first true term. */
4257
+ const logic = (stopAt, what) => ({ parts }) => {
4258
+ let last = ok(!stopAt);
4259
+ for (const part of parts) {
4260
+ last = part.evaluate();
4261
+ if (!last.ok) return last;
4262
+ const truth = truthy(last.value);
4263
+ if (truth === void 0) return noTruth(what);
4264
+ if (truth === stopAt) return profile.logic === "value" ? last : ok(stopAt);
4265
+ }
4266
+ return profile.logic === "value" ? last : ok(!stopAt);
4267
+ };
4268
+ const op = ({ typePath, parts }) => {
4269
+ const name = typePath.slice(1).join(".");
4270
+ const lazy = own(profile.lazy, name);
4271
+ if (lazy !== void 0) try {
4272
+ return lazy(parts.map((part) => () => part.evaluate()));
4273
+ } catch (error) {
4274
+ return thrown(error, `the operation ${name}`);
4275
+ }
4276
+ const apply = opOf(name);
4277
+ if (apply === void 0) return fail("#NAME?", `The language has no operation ${name}.`);
4278
+ const all = valuesOf(parts);
4279
+ if (!("values" in all)) return all;
4280
+ try {
4281
+ const out = apply(...all.values);
4282
+ return profile.check?.(out, name) ?? ok(out);
4283
+ } catch (error) {
4284
+ return thrown(error, `the operation ${name}`);
4285
+ }
4286
+ };
4287
+ const ext = ({ typePath, doc, context }) => {
4288
+ const name = typePath.slice(1).join(".");
4289
+ const handler = own(profile.ext, name) ?? own(STD_EXT, name);
4290
+ if (handler === void 0) return fail("#NAME?", `The language has no extension ${name}.`);
4291
+ try {
4292
+ return handler(doc.value, context);
4293
+ } catch (error) {
4294
+ return thrown(error, `the extension ${name}`);
4295
+ }
4296
+ };
4297
+ return { evaluators: {
4298
+ "formula.lit": lit,
4299
+ "formula.ref": ref,
4300
+ "formula.step": step,
4301
+ "formula.record": record,
4302
+ "formula.list": list,
4303
+ "formula.let": letIn,
4304
+ "formula.fn": fn,
4305
+ "formula.call": call,
4306
+ "formula.if": choice,
4307
+ "formula.and": logic(false, "term of and"),
4308
+ "formula.or": logic(true, "term of or"),
4309
+ "formula.op": op,
4310
+ "formula.ext": ext
4311
+ } };
4312
+ }
4313
+ /** The mark of a field that the profile leaves out of a record (FORMULA.RECORD). */
4314
+ const SKIP = Symbol("skip");
4315
+ /** The values of parts in order. The first error stops them, also with `combine` (FORMULA.STEPS, FORMULA.FN). */
4316
+ function valuesOfStrict(parts) {
4317
+ const values = [];
4318
+ for (const part of parts) {
4319
+ const result = part.evaluate();
4320
+ if (!result.ok) return result;
4321
+ values.push(result.value);
4322
+ }
4323
+ return { values };
4324
+ }
4325
+ //#endregion
4326
+ //#region src/agree.ts
4327
+ /**
4328
+ * This function tells if two values are the same for `agree`. Lists and plain records compare item by item and field
4329
+ * by field, and the order of the fields does not matter. Each other leaf compares with `Object.is`, thus `-0` is not
4330
+ * `0`, and `NaN` is `NaN`. Two closures of `fn` are the same when they have the same parameters. Two `Held` values
4331
+ * are the same when their errors have the same code and place. Identity is not compared.
4332
+ *
4333
+ * @param a - The first value.
4334
+ * @param b - The second value.
4335
+ * @param equal - The rule of the caller for other values. It answers first, and `undefined` gives the rules above.
4336
+ * @returns `true` when the values are the same.
4337
+ */
4338
+ function sameValue(a, b, equal) {
4339
+ const stack = [[a, b]];
4340
+ const seen = /* @__PURE__ */ new Map();
4341
+ while (stack.length > 0) {
4342
+ const [x, y] = stack.pop();
4343
+ if (Object.is(x, y)) continue;
4344
+ const told = equal?.(x, y);
4345
+ if (told !== void 0) {
4346
+ if (told) continue;
4347
+ return false;
4348
+ }
4349
+ if (typeof x !== "object" && typeof x !== "function") return false;
4350
+ if (typeof y !== "object" && typeof y !== "function") return false;
4351
+ if (x === null || y === null) return false;
4352
+ const pairs = seen.get(x) ?? /* @__PURE__ */ new Set();
4353
+ if (pairs.has(y)) continue;
4354
+ pairs.add(y);
4355
+ seen.set(x, pairs);
4356
+ if (isClosure(x) || isClosure(y)) {
4357
+ if (!(isClosure(x) && isClosure(y))) return false;
4358
+ stack.push([closureParams(x), closureParams(y)]);
4359
+ continue;
4360
+ }
4361
+ if (x instanceof Held || y instanceof Held) {
4362
+ if (!(x instanceof Held && y instanceof Held) || errorDiffers(x.error, y.error, false) !== void 0) return false;
4363
+ continue;
4364
+ }
4365
+ if (Array.isArray(x) || Array.isArray(y)) {
4366
+ if (!Array.isArray(x) || !Array.isArray(y) || x.length !== y.length) return false;
4367
+ for (let index = 0; index < x.length; index += 1) stack.push([x[index], y[index]]);
4368
+ continue;
4369
+ }
4370
+ if (!isRecord(x) || !isRecord(y)) return false;
4371
+ const keys = Object.keys(x);
4372
+ if (keys.length !== Object.keys(y).length) return false;
4373
+ for (const key of keys) {
4374
+ if (!Object.hasOwn(y, key)) return false;
4375
+ stack.push([x[key], y[key]]);
4376
+ }
4377
+ }
4378
+ return true;
4379
+ }
4380
+ const CLOSURE = Symbol.for("coeval.closure");
4381
+ function closureParams(fn) {
4382
+ return fn[CLOSURE]?.params;
4383
+ }
4384
+ function codeAndPlace(error) {
4385
+ return error.place === void 0 ? error.code : `${error.code} at [${error.place.join(", ")}]`;
4386
+ }
4387
+ /** This function gives the difference of two errors, or `undefined` when they agree. */
4388
+ function errorDiffers(a, b, strict) {
4389
+ if (a.code !== b.code) return `The plan gives ${codeAndPlace(a)}, and the tier gives ${codeAndPlace(b)}.`;
4390
+ if (strict && (a.place === void 0 || b.place === void 0)) return `An error ${a.code} has no place.`;
4391
+ if (a.place !== void 0 && b.place !== void 0 && !docEquals(a.place, b.place)) return `The error ${a.code} has the place [${a.place.join(", ")}] in the plan, and [${b.place.join(", ")}] in the tier.`;
4392
+ if (strict && a.reason !== b.reason) return `The error ${a.code} has another reason in the tier: "${b.reason}" for "${a.reason}".`;
4393
+ }
4394
+ /** A host stack overflow is the one permitted difference (VALUE.DEPTH): the tiers use different numbers of frames. */
4395
+ function overflowed(result) {
4396
+ return !result.ok && result.error.code === "#DEPTH!" && isStackOverflow(result.error.cause);
4397
+ }
4398
+ /** This function gives the difference of two results, or `undefined` when they agree. */
4399
+ function resultDiffers(a, b, options) {
4400
+ if (a.ok && b.ok) return sameValue(a.value, b.value, options.equal) ? void 0 : "The plan and the tier give different values.";
4401
+ if (!a.ok && !b.ok) return errorDiffers(a.error, b.error, options.strict === true);
4402
+ return a.ok ? `The plan gives a value, and the tier gives ${codeAndPlace(b.error)}.` : `The plan gives ${codeAndPlace(a.error)}, and the tier gives a value.`;
4403
+ }
4404
+ /** This function gives the difference of two lists of effects, or `undefined` when they agree (EFFECT.ORDER). */
4405
+ function effectsDiffer(a, b, options) {
4406
+ if (a.length !== b.length) return `The plan causes ${a.length} effects, and the tier causes ${b.length}.`;
4407
+ for (let index = 0; index < a.length; index += 1) {
4408
+ const x = a[index];
4409
+ const y = b[index];
4410
+ if (x.kind !== y.kind || !docEquals(x.place, y.place) || !sameValue(x.payload, y.payload, options.equal)) return `The effect ${index} differs: ${x.kind} at [${x.place.join(", ")}] in the plan, and ${y.kind} at [${y.place.join(", ")}] in the tier.`;
4411
+ }
4412
+ }
4413
+ /**
4414
+ * This function evaluates a document with a plan and with other tiers, and compares the results (PLAN.AGREES). Two
4415
+ * results agree when they have the same value by `sameValue`, or errors with the same code, and the same place when
4416
+ * both have one. The effects must have the same kinds, places and payloads, in the same order. A language gives its
4417
+ * own tier with the option `other`.
4418
+ *
4419
+ * @param machine - The world and the code of the evaluators.
4420
+ * @param doc - The document.
4421
+ * @param context - The names and the capabilities at the root.
4422
+ * @param options - The tiers, the definitions for the reference, the rules of the comparison and the second tier.
4423
+ * @returns The result of the plan, or the first tier that disagrees and the reason.
4424
+ */
4425
+ function agree(machine, doc, context = makeContext(), options = {}) {
4426
+ const declared = options.declaredType === void 0 ? {} : { declaredType: options.declaredType };
4427
+ const observe = options.observe;
4428
+ observe?.();
4429
+ const plan = prepare(machine, doc, declared);
4430
+ const effects = [];
4431
+ const result = plan.evaluate(context, { effects });
4432
+ const saw = observe?.();
4433
+ const differs = (other, otherEffects) => {
4434
+ if (overflowed(result) || overflowed(other)) return void 0;
4435
+ const why = resultDiffers(result, other, options) ?? (otherEffects === void 0 ? void 0 : effectsDiffer(effects, otherEffects, options));
4436
+ if (why !== void 0 || observe === void 0) return why;
4437
+ return sameValue(saw, observe(), options.equal) ? void 0 : "The host saw other calls in the tier.";
4438
+ };
4439
+ for (const tier of options.tiers ?? [
4440
+ "reference",
4441
+ "traced",
4442
+ "again"
4443
+ ]) {
4444
+ let other;
4445
+ let otherEffects = [];
4446
+ if (tier === "reference") other = reference(machine, doc, context, {
4447
+ ...declared,
4448
+ effects: otherEffects,
4449
+ ...options.definitions === void 0 ? {} : { definitions: options.definitions }
4450
+ });
4451
+ else if (tier === "traced") {
4452
+ const traced = evaluate(machine, doc, context, options.declaredType);
4453
+ other = traced.result;
4454
+ otherEffects = [...traced.effects];
4455
+ } else other = plan.evaluate(context, { effects: otherEffects });
4456
+ const why = differs(other, otherEffects);
4457
+ if (why !== void 0) return {
4458
+ ok: false,
4459
+ tier,
4460
+ plan: result,
4461
+ other,
4462
+ reason: why
4463
+ };
4464
+ }
4465
+ if (options.other !== void 0) {
4466
+ let given;
4467
+ try {
4468
+ given = options.other(doc, context);
4469
+ } catch (error) {
4470
+ given = thrown(error, "the tier");
4471
+ }
4472
+ const other = "result" in given ? given.result : given;
4473
+ const why = differs(other, "result" in given ? given.effects : void 0);
4474
+ if (why !== void 0) return {
4475
+ ok: false,
4476
+ tier: "other",
4477
+ plan: result,
4478
+ other,
4479
+ reason: why
4480
+ };
4481
+ }
4482
+ return {
4483
+ ok: true,
4484
+ result,
4485
+ effects
4486
+ };
4487
+ }
4488
+ //#endregion
4489
+ //#region src/generate.ts
4490
+ /**
4491
+ * This function makes a source of random numbers with a seed (the algorithm mulberry32). It needs no package.
4492
+ *
4493
+ * @param seed - The seed: a whole number.
4494
+ * @returns The source.
4495
+ */
4496
+ function random(seed) {
4497
+ let state = seed >>> 0;
4498
+ const next = () => {
4499
+ state = state + 1831565813 >>> 0;
4500
+ let t = state;
4501
+ t = Math.imul(t ^ t >>> 15, t | 1);
4502
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
4503
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
4504
+ };
4505
+ const int = (below) => Math.floor(next() * below);
4506
+ return {
4507
+ next,
4508
+ int,
4509
+ chance: (p) => next() < p,
4510
+ pick: (items) => items[int(items.length)]
4511
+ };
4512
+ }
4513
+ /**
4514
+ * This function lists the types of a world: each kind and each alias, also in a namespace. A namespace with a
4515
+ * fallback gives no types, because each key names a kind.
4516
+ *
4517
+ * @param world - The world.
4518
+ * @returns The keys of each type.
4519
+ */
4520
+ function typesOf(world) {
4521
+ const out = [];
4522
+ const visit = (entries, prefix) => {
4523
+ for (const key of Object.keys(entries)) {
4524
+ const entry = entries[key];
4525
+ if (isKind(entry) || isAlias(entry)) out.push([...prefix, key]);
4526
+ else if (isNamespace(entry)) visit(entry.kinds, [...prefix, key]);
4527
+ }
4528
+ };
4529
+ visit(world.kinds, []);
4530
+ return out;
4531
+ }
4532
+ const NAMES = [
4533
+ "a",
4534
+ "b",
4535
+ "x",
4536
+ "n",
4537
+ "last",
4538
+ "__proto__"
4539
+ ];
4540
+ const FIELDS = [
4541
+ "a",
4542
+ "b",
4543
+ "c",
4544
+ "1",
4545
+ "__proto__"
4546
+ ];
4547
+ const KEYS = [
4548
+ "a",
4549
+ "b",
4550
+ "x",
4551
+ 0,
4552
+ 1,
4553
+ "0",
4554
+ "length",
4555
+ "type",
4556
+ "value",
4557
+ "parent"
4558
+ ];
4559
+ /** This function tells if a kind can be a leaf: it needs no part. */
4560
+ function leafKind(kind) {
4561
+ const shape = kind?.parts;
4562
+ return shape === void 0 || shape.shape === "none" || shape.shape === "list" || shape.shape === "map" || shape.shape === "text" || shape.shape === "number" || shape.shape === "one";
4563
+ }
4564
+ /**
4565
+ * This function builds a random document for a world from the contracts of its kinds. It reads the shapes of the
4566
+ * parts, the declared types, the permitted kinds and the names that the scope rules bind. Some choices are malformed
4567
+ * on purpose. Examples are an unknown kind, a value without its shape, a bare value without a type and a name that
4568
+ * nothing binds. The depth and the size have limits.
4569
+ *
4570
+ * @param world - The world.
4571
+ * @param options - The seed, the types, the limits and the data of the leaves.
4572
+ * @returns The document, as JSON.
4573
+ */
4574
+ function generate(world, options) {
4575
+ const rng = random(options.seed);
4576
+ const types = options.types ?? typesOf(world);
4577
+ const maxDepth = options.maxDepth ?? 4;
4578
+ const maxSize = options.maxSize ?? 24;
4579
+ const malformed = options.malformed ?? .05;
4580
+ const keys = options.keys ?? KEYS;
4581
+ const stepTypes = types.filter((type) => {
4582
+ const found = lookupKind(world, type);
4583
+ return found.ok && Object.hasOwn(found.kind.verbs, "step");
4584
+ });
4585
+ let size = 0;
4586
+ const kindOf = (type) => {
4587
+ const found = lookupKind(world, type);
4588
+ return found.ok ? found.kind : void 0;
4589
+ };
4590
+ const anyJson = (depth = 0) => {
4591
+ const roll = rng.int(depth > 1 ? 6 : 8);
4592
+ if (roll === 0) return null;
4593
+ if (roll === 1) return rng.chance(.5);
4594
+ if (roll === 2) return rng.pick([
4595
+ 0,
4596
+ 1,
4597
+ 2,
4598
+ -1,
4599
+ .5,
4600
+ 1e21
4601
+ ]);
4602
+ if (roll === 3) return rng.pick([
4603
+ "",
4604
+ "a",
4605
+ "text",
4606
+ "0"
4607
+ ]);
4608
+ if (roll === 4) return rng.int(10);
4609
+ if (roll === 5) return rng.pick(NAMES);
4610
+ if (roll === 6) return Array.from({ length: rng.int(3) }, () => anyJson(depth + 1));
4611
+ const out = {};
4612
+ for (let index = rng.int(3); index > 0; index -= 1) Object.defineProperty(out, rng.pick(FIELDS), {
4613
+ value: anyJson(depth + 1),
4614
+ enumerable: true,
4615
+ writable: true,
4616
+ configurable: true
4617
+ });
4618
+ return out;
4619
+ };
4620
+ const dataOf = (type) => options.data?.(type, rng) ?? anyJson();
4621
+ const renderType = (type) => {
4622
+ const roll = rng.next();
4623
+ if (roll < .06) return {
4624
+ type: "ref",
4625
+ value: ["world", ...type]
4626
+ };
4627
+ if (type.length === 1 && roll < .8) return type[0];
4628
+ return [...type];
4629
+ };
4630
+ const permitted = (type, kinds) => kinds === void 0 || kinds.some((kind) => kind.length <= type.length && kind.every((key, index) => String(key) === String(type[index])));
4631
+ const pickName = (names) => names.length === 0 || rng.chance(malformed) ? rng.pick(["unbound", "zz"]) : rng.pick(names);
4632
+ const someNames = () => {
4633
+ const out = /* @__PURE__ */ new Set();
4634
+ for (let index = 1 + rng.int(2); index > 0; index -= 1) out.add(rng.pick(NAMES));
4635
+ return [...out];
4636
+ };
4637
+ const envelope = (type, value, header) => {
4638
+ const out = {
4639
+ type: renderType(type),
4640
+ value
4641
+ };
4642
+ if (header !== void 0) out["name"] = header;
4643
+ if (options.own !== void 0 && options.own.length > 0 && rng.chance(.03)) out["own"] = { eval: rng.pick(options.own) };
4644
+ return out;
4645
+ };
4646
+ /** A path from a root (D10). It uses the names in scope, and sometimes a step document. */
4647
+ const pathFor = (pos, refKind) => {
4648
+ if (rng.chance(malformed)) return rng.pick([
4649
+ "names",
4650
+ [],
4651
+ { names: "a" },
4652
+ ["nowhere", "a"]
4653
+ ]);
4654
+ const root = pos.names.length > 0 && rng.chance(.75) ? "names" : rng.pick(ROOTS.filter((name) => name !== "names"));
4655
+ const path = [root];
4656
+ if (root === "names") path.push(pickName(pos.names));
4657
+ if (root === "world") path.push(String(rng.pick(types)[0]));
4658
+ for (let index = rng.int(3); index > 0; index -= 1) if (stepTypes.length > 0 && rng.chance(.2)) {
4659
+ const type = rng.pick(stepTypes);
4660
+ const kind = kindOf(type);
4661
+ const value = refKind?.parts?.shape === "deep" && kind?.parts !== void 0 ? valueOf(kind.parts, [], {
4662
+ ...pos,
4663
+ depth: pos.depth + 1
4664
+ }, emptyScope()) : dataOf(type);
4665
+ path.push({
4666
+ type: renderType(type),
4667
+ value
4668
+ });
4669
+ } else path.push(rng.pick(keys));
4670
+ return path;
4671
+ };
4672
+ const emptyScope = () => ({
4673
+ rules: [],
4674
+ names: [],
4675
+ covered: [],
4676
+ sources: /* @__PURE__ */ new Map()
4677
+ });
4678
+ /** This function decides the names of the scope rules before the parts, so that each part knows what it sees. */
4679
+ const scopeOf = (kind) => {
4680
+ const rules = kind.scope ?? [];
4681
+ const scope = {
4682
+ rules,
4683
+ names: [],
4684
+ covered: rules.map(() => 0),
4685
+ sources: /* @__PURE__ */ new Map()
4686
+ };
4687
+ for (const rule of rules) {
4688
+ const source = rule.names;
4689
+ let names = [];
4690
+ if ("fixed" in source) names = [...source.fixed];
4691
+ else if ("keysAt" in source) {
4692
+ names = someNames();
4693
+ scope.sources.set(source.keysAt.join("."), { keys: names });
4694
+ } else if ("listAt" in source) {
4695
+ names = someNames();
4696
+ scope.sources.set(source.listAt.join("."), { list: rng.chance(malformed) ? [...names, ...names] : names });
4697
+ } else if ("textAt" in source) {
4698
+ names = [rng.pick(NAMES)];
4699
+ scope.sources.set(source.textAt.join("."), { text: names[0] });
4700
+ }
4701
+ scope.names.push(names);
4702
+ }
4703
+ return scope;
4704
+ };
4705
+ /** The names that a part sees from the scope rules of its parent. A rule `sequential` shows only earlier names. */
4706
+ const seenBy = (scope, path) => {
4707
+ const names = [];
4708
+ let headers = false;
4709
+ scope.rules.forEach((rule, index) => {
4710
+ if (!rule.in.some((pattern) => pathMatches(path, pattern))) return;
4711
+ const ruleNames = scope.names[index] ?? [];
4712
+ if ("headers" in rule.names) headers = true;
4713
+ if (rule.sequential !== true || "headers" in rule.names || (scope.covered[index] ?? 0) > 0) names.push(...ruleNames);
4714
+ });
4715
+ return {
4716
+ names,
4717
+ headers
4718
+ };
4719
+ };
4720
+ /** This function records the part at a path, and the header name that it got, for the rules that cover it. */
4721
+ const saw = (scope, path, part) => {
4722
+ const header = isEnvelope(part) && typeof part.name === "string" ? part.name : void 0;
4723
+ scope.rules.forEach((rule, index) => {
4724
+ if (!rule.in.some((pattern) => pathMatches(path, pattern))) return;
4725
+ scope.covered[index] = (scope.covered[index] ?? 0) + 1;
4726
+ if ("headers" in rule.names && header !== void 0) scope.names[index]?.push(header);
4727
+ });
4728
+ };
4729
+ const partAt = (pos, scope, path, spec, parentType) => {
4730
+ const seen = seenBy(scope, path);
4731
+ const header = seen.headers && rng.chance(.5) ? rng.pick(NAMES) : void 0;
4732
+ const part = docAt({
4733
+ declared: spec.of,
4734
+ kinds: "kinds" in spec ? spec.kinds : void 0,
4735
+ names: seen.names.length === 0 ? pos.names : [...pos.names, ...seen.names],
4736
+ depth: pos.depth + 1,
4737
+ hint: parentType === void 0 ? void 0 : options.hints?.(parentType, path)
4738
+ }, header);
4739
+ saw(scope, path, part);
4740
+ return part;
4741
+ };
4742
+ /** This function builds a value of a shape (SHAPE.*). A part is a document at the next depth. */
4743
+ const valueOf = (shape, path, pos, scope, type) => {
4744
+ const source = scope.sources.get(path.join("."));
4745
+ if (source !== void 0 && "list" in source) return [...source.list];
4746
+ if (source !== void 0 && "text" in source) return source.text;
4747
+ const term = (of) => of === void 0 ? { shape: "term" } : {
4748
+ shape: "term",
4749
+ of
4750
+ };
4751
+ const small = () => pos.depth >= maxDepth ? 0 : size >= maxSize ? rng.int(2) : rng.int(4);
4752
+ if (shape === void 0 || shape.shape === "none") return path.length === 0 && type !== void 0 ? dataOf(type) : anyJson();
4753
+ switch (shape.shape) {
4754
+ case "term": return partAt(pos, scope, path, shape, type);
4755
+ case "list": {
4756
+ const items = Array.from({ length: small() }, (_, index) => valueOf(shape.item ?? term(shape.of), [...path, index], pos, scope, type));
4757
+ if (shape.distinct !== true || rng.chance(malformed)) return items;
4758
+ return items.filter((item, index) => !items.slice(0, index).some((before) => docEquals(before, item)));
4759
+ }
4760
+ case "map": {
4761
+ const out = {};
4762
+ const names = source !== void 0 && "keys" in source ? source.keys : Array.from({ length: small() }, () => rng.pick(FIELDS));
4763
+ for (const key of names) Object.defineProperty(out, key, {
4764
+ value: valueOf(shape.item ?? term(shape.of), [...path, key], pos, scope, type),
4765
+ enumerable: true,
4766
+ writable: true,
4767
+ configurable: true
4768
+ });
4769
+ return out;
4770
+ }
4771
+ case "record": {
4772
+ const named = Array.isArray(shape.fields) ? Object.fromEntries(shape.fields.map((name) => [name, term(shape.of)])) : shape.fields;
4773
+ const fieldKeys = /* @__PURE__ */ new Set([...shape.required ?? [], ...Object.keys(named).filter(() => rng.chance(.75))]);
4774
+ if (shape.closed !== true && shape.rest === void 0 && rng.chance(.15)) fieldKeys.add("extra");
4775
+ const ordered = rng.chance(.2) ? [...fieldKeys].reverse() : [...fieldKeys];
4776
+ const out = {};
4777
+ for (const key of ordered) {
4778
+ if (rng.chance(malformed / 2) && (shape.required ?? []).includes(key)) continue;
4779
+ const fieldShape = Object.hasOwn(named, key) ? named[key] : shape.rest;
4780
+ Object.defineProperty(out, key, {
4781
+ value: valueOf(fieldShape, [...path, key], pos, scope, type),
4782
+ enumerable: true,
4783
+ writable: true,
4784
+ configurable: true
4785
+ });
4786
+ }
4787
+ if (shape.closed === true && rng.chance(malformed)) out["stray"] = 1;
4788
+ return out;
4789
+ }
4790
+ case "deep": return rng.chance(.5) ? [partAt(pos, scope, [...path, 0], term(shape.of), type), anyJson()] : {
4791
+ at: partAt(pos, scope, [...path, "at"], term(shape.of), type),
4792
+ data: anyJson()
4793
+ };
4794
+ case "text": return rng.chance(malformed) ? 1 : rng.pick([
4795
+ "",
4796
+ "a",
4797
+ "label"
4798
+ ]);
4799
+ case "number": {
4800
+ if (rng.chance(malformed)) return "1";
4801
+ const value = (shape.min ?? -2) + rng.int(5) + (shape.whole === true ? 0 : rng.pick([0, .5]));
4802
+ return shape.max !== void 0 && value > shape.max ? shape.max : value;
4803
+ }
4804
+ case "one": return rng.chance(malformed) ? "other" : rng.pick(shape.values);
4805
+ }
4806
+ };
4807
+ /** A malformed document: an unknown kind, a bad shape, a bare value without a type, or a bad reference. */
4808
+ const brokenAt = (pos) => {
4809
+ const roll = rng.int(5);
4810
+ if (roll === 0) return {
4811
+ type: rng.pick(["nothing", ["no", "such"]]),
4812
+ value: 1
4813
+ };
4814
+ if (roll === 1) return pos.declared === void 0 ? rng.pick([
4815
+ 7,
4816
+ "bare",
4817
+ [1]
4818
+ ]) : {
4819
+ type: "ref",
4820
+ value: ["names", "unbound"]
4821
+ };
4822
+ if (roll === 2) {
4823
+ const shaped = types.filter((type) => kindOf(type)?.parts !== void 0);
4824
+ if (shaped.length > 0) return envelope(rng.pick(shaped), rng.pick([
4825
+ 7,
4826
+ "x",
4827
+ null
4828
+ ]));
4829
+ }
4830
+ if (roll === 3) return {
4831
+ type: "ref",
4832
+ value: rng.pick([
4833
+ ["names", "unbound"],
4834
+ ["nowhere"],
4835
+ "names"
4836
+ ])
4837
+ };
4838
+ return {
4839
+ type: rng.pick(types),
4840
+ value: anyJson()
4841
+ };
4842
+ };
4843
+ const docAt = (pos, header) => {
4844
+ size += 1;
4845
+ const leaf = pos.depth >= maxDepth || size >= maxSize;
4846
+ if (rng.chance(malformed)) return brokenAt(pos);
4847
+ if (pos.declared !== void 0 && rng.chance(leaf ? .7 : .3)) return dataOf([pos.declared]);
4848
+ let candidates = types.filter((type) => permitted(type, pos.kinds) && (!leaf || leafKind(kindOf(type))));
4849
+ if (pos.hint !== void 0 && rng.chance(.6)) {
4850
+ const hinted = candidates.filter((type) => pos.hint?.some((hint) => hint.length === type.length && hint.every((key, index) => key === type[index])));
4851
+ if (hinted.length > 0) candidates = hinted;
4852
+ }
4853
+ if (candidates.length === 0) candidates = [...types];
4854
+ const type = rng.pick(candidates);
4855
+ const kind = kindOf(type);
4856
+ if (type.length === 1 && type[0] === "ref") return envelope(type, pathFor(pos, kind), header);
4857
+ const value = kind === void 0 ? dataOf(type) : valueOf(kind.parts, [], pos, scopeOf(kind), type);
4858
+ return envelope(type, value, header);
4859
+ };
4860
+ return docAt({
4861
+ declared: options.declaredType,
4862
+ kinds: void 0,
4863
+ names: options.names ?? [],
4864
+ depth: 0,
4865
+ hint: void 0
4866
+ });
4867
+ }
4868
+ //#endregion
4869
+ export { CONSTRUCTS, ENVELOPE_KEYS, Failure, Held, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_WALKERS, STD_WORLD, THING, agree, ask, capKeys, check, checkSteps, classify, context, dataEdges, derefStep, describe, docEquals, effectEdges, entriesAsJson, evaluate, fail, failures, field, flatten, formulaDefinitions, formulaEvaluators, formulaKinds, formulaMachine, fromJson, generate, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isTypeRef, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapRefs, narrow, nearestWalker, nodeAt, ok, partCaps, pathMatches, permits, placed, planner, prepare, random, ref, reference, refsOf, resolve, run, sameValue, splitParts, stored, tag, thrown, toJson, typeName, typePath, typed, typesOf, valueOfThing, walk, worldThing };
3716
4870
 
3717
4871
  //# sourceMappingURL=index.js.map