@mark1russell7/coeval 0.25.0 → 0.26.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/README.md +2 -0
- package/build/index.d.ts +228 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1373 -100
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/agree.ts +10 -5
- package/src/facts.ts +17 -6
- package/src/formula.ts +11 -2
- package/src/index.ts +2 -0
- package/src/language.ts +147 -0
- package/src/stepper.ts +1150 -0
package/build/index.js
CHANGED
|
@@ -567,7 +567,7 @@ function effectsOfVerb(kind, verb) {
|
|
|
567
567
|
return table !== void 0 && Object.hasOwn(table, verb) ? table[verb] : void 0;
|
|
568
568
|
}
|
|
569
569
|
/** The most aliases that one lookup follows (WORLD.ALIAS-LIMIT). */
|
|
570
|
-
const MAX_ALIASES = 32;
|
|
570
|
+
const MAX_ALIASES$1 = 32;
|
|
571
571
|
/** This function tells if two paths of a lookup have the same keys. */
|
|
572
572
|
function samePath(a, b) {
|
|
573
573
|
if (a.length !== b.length) return false;
|
|
@@ -695,7 +695,7 @@ function lookupKind(world, type) {
|
|
|
695
695
|
}
|
|
696
696
|
if (isAlias(entry)) {
|
|
697
697
|
aliases += 1;
|
|
698
|
-
if (aliases > MAX_ALIASES) return {
|
|
698
|
+
if (aliases > MAX_ALIASES$1) return {
|
|
699
699
|
ok: false,
|
|
700
700
|
reason: "too-long",
|
|
701
701
|
path
|
|
@@ -1689,7 +1689,7 @@ function itemOf(type, domains) {
|
|
|
1689
1689
|
return form.t === "list" ? form.item : void 0;
|
|
1690
1690
|
}
|
|
1691
1691
|
/** This function gives the type of a field of a record type, or `undefined` when the type is not a record with the field. */
|
|
1692
|
-
function fieldOf(type, key, domains) {
|
|
1692
|
+
function fieldOf$1(type, key, domains) {
|
|
1693
1693
|
const form = formOf(type, domains);
|
|
1694
1694
|
return form.t === "record" && Object.hasOwn(form.fields, key) ? form.fields[key] : void 0;
|
|
1695
1695
|
}
|
|
@@ -1956,7 +1956,7 @@ function setOwn$5(target, key, value) {
|
|
|
1956
1956
|
});
|
|
1957
1957
|
else target[key] = value;
|
|
1958
1958
|
}
|
|
1959
|
-
function own$
|
|
1959
|
+
function own$3(table, key) {
|
|
1960
1960
|
return table !== void 0 && Object.hasOwn(table, key) ? table[key] : void 0;
|
|
1961
1961
|
}
|
|
1962
1962
|
/** This function gives a copy of a JSON value without the fields whose value is `undefined`, as JSON writes it. */
|
|
@@ -2010,7 +2010,7 @@ function sameDomain(a, b) {
|
|
|
2010
2010
|
*/
|
|
2011
2011
|
function extendDomain(name, more) {
|
|
2012
2012
|
return (prev) => {
|
|
2013
|
-
const found = own$
|
|
2013
|
+
const found = own$3(prev.domains, name) ?? own$3(STD_DOMAINS, name);
|
|
2014
2014
|
if (typeof found !== "object" || found === null || typeof found.is !== "function") return {};
|
|
2015
2015
|
const under = [...found.under ?? []];
|
|
2016
2016
|
for (const parent of more.under ?? []) if (parent !== name && !under.includes(parent)) under.push(parent);
|
|
@@ -2081,7 +2081,7 @@ var Merger = class {
|
|
|
2081
2081
|
*/
|
|
2082
2082
|
function mergeLeaf(m, table, key, later, path, part, replaces, equal, reason) {
|
|
2083
2083
|
if (later === void 0) return;
|
|
2084
|
-
const earlier = own$
|
|
2084
|
+
const earlier = own$3(table, key);
|
|
2085
2085
|
if (earlier === void 0) {
|
|
2086
2086
|
setOwn$5(table, key, later);
|
|
2087
2087
|
m.give(path, part);
|
|
@@ -2105,7 +2105,7 @@ function mergeEntries(m, into, from, path, part, replaces) {
|
|
|
2105
2105
|
const later = from[key];
|
|
2106
2106
|
if (later === void 0) continue;
|
|
2107
2107
|
const at = [...path, key];
|
|
2108
|
-
const earlier = own$
|
|
2108
|
+
const earlier = own$3(into, key);
|
|
2109
2109
|
if (earlier === void 0) {
|
|
2110
2110
|
setOwn$5(into, key, later);
|
|
2111
2111
|
m.give(at, part);
|
|
@@ -2152,7 +2152,7 @@ function changeKind(table, path, change) {
|
|
|
2152
2152
|
fallback: change(table.fallback)
|
|
2153
2153
|
};
|
|
2154
2154
|
if (String(first) !== "kinds" || key === void 0) return void 0;
|
|
2155
|
-
const entry = own$
|
|
2155
|
+
const entry = own$3(table.kinds, String(key));
|
|
2156
2156
|
const next = rest.length === 0 ? isKind(entry) ? change(entry) : void 0 : isNamespace(entry) ? changeKind(entry, rest, change) : void 0;
|
|
2157
2157
|
if (next === void 0) return void 0;
|
|
2158
2158
|
const kinds = { ...table.kinds };
|
|
@@ -2178,7 +2178,7 @@ function addVerbs(draft, m) {
|
|
|
2178
2178
|
}
|
|
2179
2179
|
const next = changeKind(table, entry.kind, (kind) => {
|
|
2180
2180
|
const verbs = { ...kind.verbs };
|
|
2181
|
-
const earlier = own$
|
|
2181
|
+
const earlier = own$3(verbs, entry.verb);
|
|
2182
2182
|
if (earlier === void 0) m?.give(entry.path, entry.part);
|
|
2183
2183
|
else if (entry.replaced) m?.replace(entry.path, entry.part);
|
|
2184
2184
|
else if (earlier !== entry.code) m?.clash(entry.path, entry.part, "Two parts give two different evaluators for this verb of this kind.");
|
|
@@ -2363,8 +2363,8 @@ function mergeCode(m, draft, part, index, replaces) {
|
|
|
2363
2363
|
if (part.runners !== void 0) draft.runners ??= {};
|
|
2364
2364
|
const names = /* @__PURE__ */ new Set([...Object.keys(part.evaluators ?? {}), ...Object.keys(part.runners ?? {})]);
|
|
2365
2365
|
for (const name of names) {
|
|
2366
|
-
const evaluator = own$
|
|
2367
|
-
const runner = own$
|
|
2366
|
+
const evaluator = own$3(part.evaluators, name);
|
|
2367
|
+
const runner = own$3(part.runners, name);
|
|
2368
2368
|
if (evaluator === void 0 && runner === void 0) continue;
|
|
2369
2369
|
const evaluatorPath = ["evaluators", name];
|
|
2370
2370
|
const runnerPath = ["runners", name];
|
|
@@ -2387,9 +2387,9 @@ function checkHidden(m, draft) {
|
|
|
2387
2387
|
const runners = draft.runners ?? {};
|
|
2388
2388
|
for (const name of Object.keys(runners)) {
|
|
2389
2389
|
const runner = runners[name];
|
|
2390
|
-
const evaluator = own$
|
|
2390
|
+
const evaluator = own$3(draft.evaluators, name);
|
|
2391
2391
|
if (runner === void 0 || evaluator === void 0) continue;
|
|
2392
|
-
if (draft.parts.some((part) => own$
|
|
2392
|
+
if (draft.parts.some((part) => own$3(part.evaluators, name) === evaluator && own$3(part.runners, name) === runner)) continue;
|
|
2393
2393
|
const a = m.sourceOf(["evaluators", name]);
|
|
2394
2394
|
const b = m.sourceOf(["runners", name]);
|
|
2395
2395
|
m.conflicts.push({
|
|
@@ -2472,7 +2472,7 @@ function removeEntry(entries, path) {
|
|
|
2472
2472
|
const [first, ...rest] = path;
|
|
2473
2473
|
if (first === void 0) return entries;
|
|
2474
2474
|
const key = String(first);
|
|
2475
|
-
const entry = own$
|
|
2475
|
+
const entry = own$3(entries, key);
|
|
2476
2476
|
if (entry === void 0) return entries;
|
|
2477
2477
|
let next;
|
|
2478
2478
|
if (rest.length > 0) {
|
|
@@ -2578,6 +2578,136 @@ function restrictMachine(machine, paths) {
|
|
|
2578
2578
|
...tables.domains === void 0 ? {} : { domains: tables.domains }
|
|
2579
2579
|
};
|
|
2580
2580
|
}
|
|
2581
|
+
// src/language.ts
|
|
2582
|
+
const VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
2583
|
+
function numbers$1(version) {
|
|
2584
|
+
const found = VERSION.exec(version);
|
|
2585
|
+
if (found === null) throw new TypeError(`A language version has the form MAJOR.MINOR.PATCH. The text ${JSON.stringify(version)} does not.`);
|
|
2586
|
+
return [
|
|
2587
|
+
Number(found[1]),
|
|
2588
|
+
Number(found[2]),
|
|
2589
|
+
Number(found[3])
|
|
2590
|
+
];
|
|
2591
|
+
}
|
|
2592
|
+
/**
|
|
2593
|
+
* This function tells if a version satisfies a lowest version, by the rules of a caret range of SemVer. The first
|
|
2594
|
+
* number that is not zero stays the same, and the version is not lower.
|
|
2595
|
+
*/
|
|
2596
|
+
function compatible(version, lowest) {
|
|
2597
|
+
const have = numbers$1(version);
|
|
2598
|
+
const want = numbers$1(lowest);
|
|
2599
|
+
const stable = want.findIndex((part) => part !== 0);
|
|
2600
|
+
const fixed = stable < 0 ? 3 : stable + 1;
|
|
2601
|
+
for (let index = 0; index < 3; index += 1) {
|
|
2602
|
+
const [a, b] = [have[index], want[index]];
|
|
2603
|
+
if (a !== b) return index >= fixed && a > b;
|
|
2604
|
+
}
|
|
2605
|
+
return true;
|
|
2606
|
+
}
|
|
2607
|
+
/** This function gives the JSON text of a value with its keys in order. A value that is not JSON is an error. */
|
|
2608
|
+
function canonical(value, path) {
|
|
2609
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
2610
|
+
if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value);
|
|
2611
|
+
if (Array.isArray(value)) return `[${value.map((item, index) => canonical(item, [...path, index])).join(",")}]`;
|
|
2612
|
+
if (!isRecord(value)) throw new TypeError(`The data half of a language is JSON. The value at ${JSON.stringify(path)} is not.`);
|
|
2613
|
+
return `{${Object.keys(value).filter((key) => value[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key], [...path, key])}`).join(",")}}`;
|
|
2614
|
+
}
|
|
2615
|
+
function frozen(value) {
|
|
2616
|
+
if (typeof value !== "object" || value === null) return value;
|
|
2617
|
+
for (const item of Object.values(value)) frozen(item);
|
|
2618
|
+
return Object.freeze(value);
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* This function makes one value of a language. The data half is JSON, thus a host can store it and compare it. The
|
|
2622
|
+
* code half binds the evaluator names of the world.
|
|
2623
|
+
*
|
|
2624
|
+
* The language keeps a frozen copy of its data half, thus a later change to the input changes nothing.
|
|
2625
|
+
*
|
|
2626
|
+
* @param definition - The name, the version, the world, the needed languages and the code.
|
|
2627
|
+
* @returns The language.
|
|
2628
|
+
* @throws {TypeError} A version in the definition is not `MAJOR.MINOR.PATCH`, the name is empty, or the
|
|
2629
|
+
* data half is not JSON.
|
|
2630
|
+
*/
|
|
2631
|
+
function defineLanguage(definition) {
|
|
2632
|
+
if (definition.name === "") throw new TypeError("A language has a name.");
|
|
2633
|
+
numbers$1(definition.version);
|
|
2634
|
+
const requires = definition.requires ?? {};
|
|
2635
|
+
for (const name of Object.keys(requires)) numbers$1(requires[name]);
|
|
2636
|
+
const data = canonical({
|
|
2637
|
+
requires,
|
|
2638
|
+
world: definition.world ?? {}
|
|
2639
|
+
}, []);
|
|
2640
|
+
const copy = frozen(JSON.parse(data));
|
|
2641
|
+
const language = {
|
|
2642
|
+
name: definition.name,
|
|
2643
|
+
version: definition.version,
|
|
2644
|
+
world: copy.world,
|
|
2645
|
+
requires: copy.requires,
|
|
2646
|
+
data
|
|
2647
|
+
};
|
|
2648
|
+
return Object.freeze(definition.code === void 0 ? language : {
|
|
2649
|
+
...language,
|
|
2650
|
+
code: definition.code
|
|
2651
|
+
});
|
|
2652
|
+
}
|
|
2653
|
+
function partOf(language) {
|
|
2654
|
+
const { code, world } = language;
|
|
2655
|
+
return typeof code === "function" ? (prev) => ({
|
|
2656
|
+
...code(prev),
|
|
2657
|
+
world
|
|
2658
|
+
}) : {
|
|
2659
|
+
...code,
|
|
2660
|
+
world
|
|
2661
|
+
};
|
|
2662
|
+
}
|
|
2663
|
+
/**
|
|
2664
|
+
* This function merges languages into one machine, in the order of the arguments, with `mergeMachines`.
|
|
2665
|
+
*
|
|
2666
|
+
* - A language comes after each language that it names in `requires`, at a compatible version (LANG.REQUIRES).
|
|
2667
|
+
* - One language that comes twice counts once. Thus two languages can share a base.
|
|
2668
|
+
* - Two versions of one name, or two data halves under one name and one version, are conflicts (LANG.COMPOSE).
|
|
2669
|
+
*
|
|
2670
|
+
* @param languages - The languages.
|
|
2671
|
+
* @returns The machine.
|
|
2672
|
+
* @throws {MergeError} The languages do not fit, or their merge has a conflict. The error lists each conflict.
|
|
2673
|
+
*/
|
|
2674
|
+
function compose(...languages) {
|
|
2675
|
+
const conflicts = [];
|
|
2676
|
+
const parts = [];
|
|
2677
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2678
|
+
languages.forEach((language, index) => {
|
|
2679
|
+
const earlier = seen.get(language.name);
|
|
2680
|
+
const conflict = (name, other, reason) => {
|
|
2681
|
+
conflicts.push({
|
|
2682
|
+
path: ["languages", name],
|
|
2683
|
+
parts: [Math.min(other, index), Math.max(other, index)],
|
|
2684
|
+
reason
|
|
2685
|
+
});
|
|
2686
|
+
};
|
|
2687
|
+
if (earlier !== void 0) {
|
|
2688
|
+
if (earlier.language.version !== language.version) conflict(language.name, earlier.index, "Two versions of one language.");
|
|
2689
|
+
else if (earlier.language.data !== language.data) conflict(language.name, earlier.index, "Two languages with one name and one version differ.");
|
|
2690
|
+
else if (earlier.language.code !== language.code) parts.push(partOf(language));
|
|
2691
|
+
return;
|
|
2692
|
+
}
|
|
2693
|
+
for (const name of Object.keys(language.requires)) {
|
|
2694
|
+
const needed = language.requires[name];
|
|
2695
|
+
const found = seen.get(name);
|
|
2696
|
+
if (found === void 0) {
|
|
2697
|
+
const later = languages.findIndex((other) => other.name === name);
|
|
2698
|
+
if (later < 0) conflict(name, index, `A language requires ${name}, and the composition does not have it.`);
|
|
2699
|
+
else conflict(name, later, `A language requires ${name}, and ${name} comes after it.`);
|
|
2700
|
+
} else if (!compatible(found.language.version, needed)) conflict(name, found.index, `A language requires ${name} ${needed}, and the composition has ${found.language.version}.`);
|
|
2701
|
+
}
|
|
2702
|
+
seen.set(language.name, {
|
|
2703
|
+
language,
|
|
2704
|
+
index
|
|
2705
|
+
});
|
|
2706
|
+
parts.push(partOf(language));
|
|
2707
|
+
});
|
|
2708
|
+
if (conflicts.length > 0) throw new MergeError(conflicts);
|
|
2709
|
+
return mergeMachines(...parts);
|
|
2710
|
+
}
|
|
2581
2711
|
// src/ladder.ts
|
|
2582
2712
|
/** The rungs of the ladder, in the order that a question visits them. */
|
|
2583
2713
|
const RUNGS = [
|
|
@@ -3087,7 +3217,7 @@ function context(parts = {}) {
|
|
|
3087
3217
|
caps: parts.caps ?? []
|
|
3088
3218
|
};
|
|
3089
3219
|
}
|
|
3090
|
-
const MAX_COLLAPSE = 64;
|
|
3220
|
+
const MAX_COLLAPSE$1 = 64;
|
|
3091
3221
|
/** The reason of a resolution that reaches the bound of collapses without a cycle that it found (DEREF.CHAIN-REASON). It is a plain string, thus a bundle drops it (PKG.PURE). */
|
|
3092
3222
|
const CHAIN_REASON = "The path follows more than 64 references. One resolution follows at most 64.";
|
|
3093
3223
|
const NO_HOPS$1 = /* @__PURE__ */ Object.freeze([]);
|
|
@@ -3318,7 +3448,7 @@ function resolveFully$1(nav, ctx, path, hops, known) {
|
|
|
3318
3448
|
while (isRef(here)) {
|
|
3319
3449
|
if (open?.includes(here) === true) return failed("#CYCLE!", "The references form a cycle.");
|
|
3320
3450
|
collapses += 1;
|
|
3321
|
-
if (collapses > MAX_COLLAPSE) return failed("#CYCLE!", CHAIN_REASON);
|
|
3451
|
+
if (collapses > MAX_COLLAPSE$1) return failed("#CYCLE!", CHAIN_REASON);
|
|
3322
3452
|
open ??= [];
|
|
3323
3453
|
open.push(here);
|
|
3324
3454
|
const inner = walk(here.value, void 0);
|
|
@@ -3469,7 +3599,7 @@ function tag(value, kind) {
|
|
|
3469
3599
|
return typed(kind, value);
|
|
3470
3600
|
}
|
|
3471
3601
|
// src/parts.ts
|
|
3472
|
-
var Bad = class {
|
|
3602
|
+
var Bad$1 = class {
|
|
3473
3603
|
reason;
|
|
3474
3604
|
at;
|
|
3475
3605
|
constructor(reason, at) {
|
|
@@ -3517,7 +3647,7 @@ function kindFault(kinds, item, of, path) {
|
|
|
3517
3647
|
const type = isEnvelope(item) ? typePath(item.type) : of === void 0 ? void 0 : [of];
|
|
3518
3648
|
if (type !== void 0 && kinds.some((kind) => kind.length <= type.length && kind.every((key, index) => String(key) === String(type[index])))) return;
|
|
3519
3649
|
const names = kinds.map((kind) => kind.join(".")).join(", ");
|
|
3520
|
-
throw new Bad(`${isEnvelope(item) ? `The kind ${typeName(item.type)} is not permitted here.` : "A value without an envelope is not permitted here."} The permitted kinds are ${names}.`, path);
|
|
3650
|
+
throw new Bad$1(`${isEnvelope(item) ? `The kind ${typeName(item.type)} is not permitted here.` : "A value without an envelope is not permitted here."} The permitted kinds are ${names}.`, path);
|
|
3521
3651
|
}
|
|
3522
3652
|
/**
|
|
3523
3653
|
* This function splits a value into its parts, by the shape that its kind declares. The evaluator, the view and
|
|
@@ -3583,7 +3713,7 @@ function splitParts(shape, value) {
|
|
|
3583
3713
|
};
|
|
3584
3714
|
if (spec.shape === "text" || spec.shape === "number" || spec.shape === "one") {
|
|
3585
3715
|
const reason = dataFault(spec, item);
|
|
3586
|
-
if (reason !== void 0) throw new Bad(reason, path);
|
|
3716
|
+
if (reason !== void 0) throw new Bad$1(reason, path);
|
|
3587
3717
|
return {
|
|
3588
3718
|
t: "data",
|
|
3589
3719
|
value: item
|
|
@@ -3595,11 +3725,11 @@ function splitParts(shape, value) {
|
|
|
3595
3725
|
}
|
|
3596
3726
|
if (spec.shape === "deep") return deep(item, path, spec.of, spec.expect);
|
|
3597
3727
|
if (spec.shape === "list") {
|
|
3598
|
-
if (!Array.isArray(item)) throw new Bad("The value must be a list.", path);
|
|
3728
|
+
if (!Array.isArray(item)) throw new Bad$1("The value must be a list.", path);
|
|
3599
3729
|
const list = item;
|
|
3600
3730
|
if (spec.distinct === true) {
|
|
3601
3731
|
const twice = list.findIndex((child, index) => list.slice(0, index).some((before) => docEquals(before, child)));
|
|
3602
|
-
if (twice !== -1) throw new Bad("The items of the list must be different.", [...path, twice]);
|
|
3732
|
+
if (twice !== -1) throw new Bad$1("The items of the list must be different.", [...path, twice]);
|
|
3603
3733
|
}
|
|
3604
3734
|
const each = spec.item ?? termOf$1(spec.of, spec.expect);
|
|
3605
3735
|
const items = list.map((child, index) => walk(each, child, [...path, index]));
|
|
@@ -3611,7 +3741,7 @@ function splitParts(shape, value) {
|
|
|
3611
3741
|
items
|
|
3612
3742
|
};
|
|
3613
3743
|
}
|
|
3614
|
-
if (!isRecord(item)) throw new Bad("The value must be a record.", path);
|
|
3744
|
+
if (!isRecord(item)) throw new Bad$1("The value must be a record.", path);
|
|
3615
3745
|
if (spec.shape === "map") {
|
|
3616
3746
|
const each = spec.item ?? termOf$1(spec.of, spec.expect);
|
|
3617
3747
|
return {
|
|
@@ -3619,11 +3749,11 @@ function splitParts(shape, value) {
|
|
|
3619
3749
|
fields: Object.keys(item).map((key) => [key, walk(each, item[key], [...path, key])])
|
|
3620
3750
|
};
|
|
3621
3751
|
}
|
|
3622
|
-
for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad(`The field ${name} is missing.`, path);
|
|
3752
|
+
for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad$1(`The field ${name} is missing.`, path);
|
|
3623
3753
|
const named = Array.isArray(spec.fields) ? Object.fromEntries(spec.fields.map((name) => [name, termOf$1(spec.of, spec.expect)])) : spec.fields;
|
|
3624
3754
|
const fields = [];
|
|
3625
3755
|
for (const key of Object.keys(item)) {
|
|
3626
|
-
if (spec.closed === true && !Object.hasOwn(named, key)) throw new Bad(`The field ${key} is not a field of this kind.`, [...path, key]);
|
|
3756
|
+
if (spec.closed === true && !Object.hasOwn(named, key)) throw new Bad$1(`The field ${key} is not a field of this kind.`, [...path, key]);
|
|
3627
3757
|
const fieldShape = Object.hasOwn(named, key) ? named[key] : spec.rest;
|
|
3628
3758
|
fields.push([key, walk(fieldShape, item[key], [...path, key])]);
|
|
3629
3759
|
}
|
|
@@ -3636,7 +3766,7 @@ function splitParts(shape, value) {
|
|
|
3636
3766
|
try {
|
|
3637
3767
|
template = walk(shape, value, []);
|
|
3638
3768
|
} catch (error) {
|
|
3639
|
-
if (error instanceof Bad) return {
|
|
3769
|
+
if (error instanceof Bad$1) return {
|
|
3640
3770
|
ok: false,
|
|
3641
3771
|
reason: error.reason,
|
|
3642
3772
|
at: error.at
|
|
@@ -4557,7 +4687,7 @@ var Session = class {
|
|
|
4557
4687
|
if (this.running) return fail("#CALC!", `The effect ${text} needs a runner: in a run, the host does each effect.`, { place });
|
|
4558
4688
|
const frame = frameOf(ctx);
|
|
4559
4689
|
const clause = frame === void 0 ? void 0 : this.clauseOf(ctx, frame, kind, place);
|
|
4560
|
-
if (clause !== void 0) return "ok" in clause ? clause : drive$
|
|
4690
|
+
if (clause !== void 0) return "ok" in clause ? clause : drive$3(clause.answer(payload), text);
|
|
4561
4691
|
const made = this.record(ctx, kind, payload, place);
|
|
4562
4692
|
return "ok" in made ? made : this.answer(made, place);
|
|
4563
4693
|
}
|
|
@@ -4768,7 +4898,7 @@ function heldReason(kind) {
|
|
|
4768
4898
|
/** The wait of an effect that a run does not give to the host. A drive without a wait stops at it (RUN.HELD). */
|
|
4769
4899
|
const HELD = /* @__PURE__ */ Promise.resolve(void 0);
|
|
4770
4900
|
/** This function drives steps that cannot wait. A step that waits stops the steps, and gives `#CALC!`. */
|
|
4771
|
-
function drive$
|
|
4901
|
+
function drive$3(steps, kindText) {
|
|
4772
4902
|
const step = steps.next();
|
|
4773
4903
|
if (step.done === true) return step.value;
|
|
4774
4904
|
step.value.catch(() => void 0);
|
|
@@ -4817,13 +4947,13 @@ function failing(c, meta, place, code, reason) {
|
|
|
4817
4947
|
/** This function gives the code of a document that fails with one result at each evaluation. */
|
|
4818
4948
|
function failingWith(c, meta, result) {
|
|
4819
4949
|
const plain = () => result;
|
|
4820
|
-
return finish$
|
|
4950
|
+
return finish$2(c, meta, plain, void 0);
|
|
4821
4951
|
}
|
|
4822
4952
|
/**
|
|
4823
4953
|
* This function gives the code of a document in a trace. Each node records the context that its grant permits
|
|
4824
4954
|
* (CAP.NARROW-CODE), as the code of the document gets it.
|
|
4825
4955
|
*/
|
|
4826
|
-
function finish$
|
|
4956
|
+
function finish$2(c, meta, code, steps) {
|
|
4827
4957
|
if (!c.traced) return {
|
|
4828
4958
|
code,
|
|
4829
4959
|
run: steps
|
|
@@ -4981,7 +5111,7 @@ function compileNode(c, value, place, declared, depth, address = false) {
|
|
|
4981
5111
|
}
|
|
4982
5112
|
const guard = guardOf(c, place);
|
|
4983
5113
|
const run = placedRun(guard === void 0 ? inner : guardRun(inner, guard, c.machine.domains), place, name);
|
|
4984
|
-
return finish$
|
|
5114
|
+
return finish$2(c, meta, runnerCode(run, place, kindText), run);
|
|
4985
5115
|
}
|
|
4986
5116
|
let inner;
|
|
4987
5117
|
try {
|
|
@@ -4990,7 +5120,7 @@ function compileNode(c, value, place, declared, depth, address = false) {
|
|
|
4990
5120
|
return failingWith(c, meta, placed(thrown(error, `the evaluator ${name}`), place));
|
|
4991
5121
|
}
|
|
4992
5122
|
const guard = guardOf(c, place);
|
|
4993
|
-
const done = finish$
|
|
5123
|
+
const done = finish$2(c, meta, guard !== void 0 ? placedCode(guardCode(inner, guard, c.machine.domains), place, name) : TOTAL.has(inner) ? inner : placedCode(inner, place, name), void 0);
|
|
4994
5124
|
if (frees === void 0 || kind === void 0 || !pureCode(c, envelope, kind, typePath, name, quick)) return done;
|
|
4995
5125
|
const free = freeOf(doc, kind, split.parts, frees);
|
|
4996
5126
|
if (free === void 0) return done;
|
|
@@ -5426,10 +5556,10 @@ function placedRun(inner, place, name) {
|
|
|
5426
5556
|
*/
|
|
5427
5557
|
function runnerCode(run, place, kindText) {
|
|
5428
5558
|
return (ctx, rt) => {
|
|
5429
|
-
if (!rt.running || !(rt instanceof Session)) return placed(drive$
|
|
5559
|
+
if (!rt.running || !(rt instanceof Session)) return placed(drive$3(run(ctx, rt), kindText), place);
|
|
5430
5560
|
rt.held += 1;
|
|
5431
5561
|
try {
|
|
5432
|
-
return placed(drive$
|
|
5562
|
+
return placed(drive$3(run(ctx, rt), kindText), place);
|
|
5433
5563
|
} finally {
|
|
5434
5564
|
rt.held -= 1;
|
|
5435
5565
|
}
|
|
@@ -8500,7 +8630,8 @@ function codeFactsOf(machine, v, kind, verb) {
|
|
|
8500
8630
|
*
|
|
8501
8631
|
* - `reads`: each free reference, with the root and the keys of its path. A read under a lazy part has the mark
|
|
8502
8632
|
* `lazy`, for example a read in a branch of `if`. A read after a step document has `exact: false`. A kind that
|
|
8503
|
-
* declares `reads` adds a read of each of its roots at each document of the kind.
|
|
8633
|
+
* declares `reads` adds a read of each of its roots at each document of the kind. A reference with a step document
|
|
8634
|
+
* of the kind also has these reads (FACTS.STEP-READS). The first document of a tree
|
|
8504
8635
|
* kind also gets the lazy reads of the equations of its kind (FACTS.EQUATIONS). A read from `self` or from a name
|
|
8505
8636
|
* of a rung is not one of them, because it is not free (READS.EQUATION).
|
|
8506
8637
|
* - `side` and `effects`: from the contract of each kind, for the verb of the facts.
|
|
@@ -8547,6 +8678,26 @@ function factsOf(machine, doc, options = {}) {
|
|
|
8547
8678
|
if (options.volatile?.(read) === true) volatile = true;
|
|
8548
8679
|
};
|
|
8549
8680
|
/**
|
|
8681
|
+
* This function adds a read of each declared root at the place of a document (FACTS.KIND-READS, FACTS.STEP-READS).
|
|
8682
|
+
* It is one function for the facts, thus a visit makes no new function.
|
|
8683
|
+
*/
|
|
8684
|
+
const declare = (list, node, lazy, place) => {
|
|
8685
|
+
if (list === void 0) return;
|
|
8686
|
+
for (const root of list) {
|
|
8687
|
+
if (node !== void 0 && root === "self") continue;
|
|
8688
|
+
add({
|
|
8689
|
+
root,
|
|
8690
|
+
keys: NONE,
|
|
8691
|
+
exact: true,
|
|
8692
|
+
lazy,
|
|
8693
|
+
address: false,
|
|
8694
|
+
path: [root],
|
|
8695
|
+
place: tight(place.place),
|
|
8696
|
+
at: tight(place.at)
|
|
8697
|
+
});
|
|
8698
|
+
}
|
|
8699
|
+
};
|
|
8700
|
+
/**
|
|
8550
8701
|
* This function walks a document. Without `node`, it walks the document of the facts. With `node`, it walks an
|
|
8551
8702
|
* equation of a tree kind, and each read gets the place of that node: the first document of the kind.
|
|
8552
8703
|
*/
|
|
@@ -8578,19 +8729,7 @@ function factsOf(machine, doc, options = {}) {
|
|
|
8578
8729
|
note(answer?.pure, answer?.volatile);
|
|
8579
8730
|
roots = answer?.reads;
|
|
8580
8731
|
}
|
|
8581
|
-
|
|
8582
|
-
if (node !== void 0 && root === "self") continue;
|
|
8583
|
-
add({
|
|
8584
|
-
root,
|
|
8585
|
-
keys: NONE,
|
|
8586
|
-
exact: true,
|
|
8587
|
-
lazy,
|
|
8588
|
-
address: false,
|
|
8589
|
-
path: [root],
|
|
8590
|
-
place: tight(place.place),
|
|
8591
|
-
at: tight(place.at)
|
|
8592
|
-
});
|
|
8593
|
-
}
|
|
8732
|
+
declare(roots, node, lazy, place);
|
|
8594
8733
|
const declared = verb === "eval" && answer?.effects !== void 0 ? effectKeys(v, answer.effects) : declaredEffects(v, verb);
|
|
8595
8734
|
if (verb === "eval" ? kind.side === "run" : declared.length > 0) {
|
|
8596
8735
|
if (node === void 0) side = "run";
|
|
@@ -8635,6 +8774,7 @@ function factsOf(machine, doc, options = {}) {
|
|
|
8635
8774
|
const stepAnswer = walker.name === void 0 ? void 0 : hook?.(found.path, walker.name);
|
|
8636
8775
|
if (walker.described) note(stepAnswer?.pure ?? found.kind.pure, stepAnswer?.volatile ?? found.kind.volatile);
|
|
8637
8776
|
else note(stepAnswer?.pure, stepAnswer?.volatile);
|
|
8777
|
+
declare(stepAnswer?.reads ?? (walker.described ? found.kind.reads : void 0), node, lazy, place);
|
|
8638
8778
|
}
|
|
8639
8779
|
const first = path[1];
|
|
8640
8780
|
if (root === "names" && isKey(first) && v.names.has(String(first))) return void 0;
|
|
@@ -9667,7 +9807,7 @@ function withoutNames(options) {
|
|
|
9667
9807
|
return rest;
|
|
9668
9808
|
}
|
|
9669
9809
|
/** This function gives the keys of a trail, from its start. It keeps the result in the trail. */
|
|
9670
|
-
function keysOf(trail) {
|
|
9810
|
+
function keysOf$1(trail) {
|
|
9671
9811
|
if (trail === void 0) return [];
|
|
9672
9812
|
if (trail.full !== void 0) return trail.full;
|
|
9673
9813
|
const steps = [];
|
|
@@ -9726,10 +9866,10 @@ var Visit = class {
|
|
|
9726
9866
|
return this.#expect;
|
|
9727
9867
|
}
|
|
9728
9868
|
get place() {
|
|
9729
|
-
return keysOf(this.#place);
|
|
9869
|
+
return keysOf$1(this.#place);
|
|
9730
9870
|
}
|
|
9731
9871
|
get at() {
|
|
9732
|
-
return keysOf(this.#at);
|
|
9872
|
+
return keysOf$1(this.#at);
|
|
9733
9873
|
}
|
|
9734
9874
|
};
|
|
9735
9875
|
/**
|
|
@@ -9766,8 +9906,8 @@ function walk(world, doc, visit, options = {}) {
|
|
|
9766
9906
|
const read = partsOf(world, item.value, item.declared);
|
|
9767
9907
|
if (!read.ok) {
|
|
9768
9908
|
options.problem?.({
|
|
9769
|
-
place: keysOf(item.place),
|
|
9770
|
-
at: keysOf(item.at),
|
|
9909
|
+
place: keysOf$1(item.place),
|
|
9910
|
+
at: keysOf$1(item.at),
|
|
9771
9911
|
code: read.code,
|
|
9772
9912
|
reason: read.reason
|
|
9773
9913
|
});
|
|
@@ -9782,8 +9922,8 @@ function walk(world, doc, visit, options = {}) {
|
|
|
9782
9922
|
};
|
|
9783
9923
|
if (!split.ok) {
|
|
9784
9924
|
options.problem?.({
|
|
9785
|
-
place: keysOf(item.place),
|
|
9786
|
-
at: keysOf({
|
|
9925
|
+
place: keysOf$1(item.place),
|
|
9926
|
+
at: keysOf$1({
|
|
9787
9927
|
up: base,
|
|
9788
9928
|
keys: split.at
|
|
9789
9929
|
}),
|
|
@@ -11094,7 +11234,7 @@ var Held = class {
|
|
|
11094
11234
|
this.error = error;
|
|
11095
11235
|
}
|
|
11096
11236
|
};
|
|
11097
|
-
const CLOSURE$
|
|
11237
|
+
const CLOSURE$3 = /* @__PURE__ */ Symbol.for("coeval.closure");
|
|
11098
11238
|
/**
|
|
11099
11239
|
* This function tells if a value is a function that the construct `fn` made.
|
|
11100
11240
|
*
|
|
@@ -11102,7 +11242,7 @@ const CLOSURE$2 = /* @__PURE__ */ Symbol.for("coeval.closure");
|
|
|
11102
11242
|
* @returns `true` for a closure.
|
|
11103
11243
|
*/
|
|
11104
11244
|
function isClosure(value) {
|
|
11105
|
-
return typeof value === "function" && value[CLOSURE$
|
|
11245
|
+
return typeof value === "function" && value[CLOSURE$3] !== void 0;
|
|
11106
11246
|
}
|
|
11107
11247
|
/**
|
|
11108
11248
|
* The standard extensions: the values that JSON cannot write. `ext.domain` reads a member of a domain through the
|
|
@@ -11575,7 +11715,7 @@ function formulaTypes(profile) {
|
|
|
11575
11715
|
},
|
|
11576
11716
|
"formula.record": {
|
|
11577
11717
|
part: (input, path) => {
|
|
11578
|
-
const want = fieldOf(input.expected, String(path[0]), input.machine.domains);
|
|
11718
|
+
const want = fieldOf$1(input.expected, String(path[0]), input.machine.domains);
|
|
11579
11719
|
return want === void 0 ? {} : {
|
|
11580
11720
|
expect: want,
|
|
11581
11721
|
what: `field ${String(path[0])} of the record`
|
|
@@ -11896,6 +12036,7 @@ const PROFILE_KEYS = /* @__PURE__ */ Object.freeze([
|
|
|
11896
12036
|
"combine",
|
|
11897
12037
|
"pure",
|
|
11898
12038
|
"pureExt",
|
|
12039
|
+
"extReads",
|
|
11899
12040
|
"volatile",
|
|
11900
12041
|
"sigs"
|
|
11901
12042
|
]);
|
|
@@ -12150,7 +12291,7 @@ function formulaCode(profile) {
|
|
|
12150
12291
|
clock.applying = level - 1;
|
|
12151
12292
|
}
|
|
12152
12293
|
};
|
|
12153
|
-
Object.defineProperty(closure, CLOSURE$
|
|
12294
|
+
Object.defineProperty(closure, CLOSURE$3, { value: { params: names } });
|
|
12154
12295
|
return ok(closure);
|
|
12155
12296
|
};
|
|
12156
12297
|
}),
|
|
@@ -12365,7 +12506,14 @@ function makeFacts(profile, known) {
|
|
|
12365
12506
|
if (code !== "formula.op" && code !== "formula.ext") return void 0;
|
|
12366
12507
|
const name = path.slice(1).join(".");
|
|
12367
12508
|
if (code === "formula.ext") {
|
|
12368
|
-
if (profile.ext !== void 0 && Object.hasOwn(profile.ext, name))
|
|
12509
|
+
if (profile.ext !== void 0 && Object.hasOwn(profile.ext, name)) {
|
|
12510
|
+
const facts = pureExt.has(name) ? PURE : NOT_PURE;
|
|
12511
|
+
const reads = profile.extReads !== void 0 && Object.hasOwn(profile.extReads, name) ? profile.extReads[name] : void 0;
|
|
12512
|
+
return reads === void 0 ? facts : {
|
|
12513
|
+
...facts,
|
|
12514
|
+
reads
|
|
12515
|
+
};
|
|
12516
|
+
}
|
|
12369
12517
|
return Object.hasOwn(STD_EXT, name) ? PURE : void 0;
|
|
12370
12518
|
}
|
|
12371
12519
|
if (known(path, code) !== true) return void 0;
|
|
@@ -12411,7 +12559,7 @@ function formulaMachine(profile = {}, more = {}) {
|
|
|
12411
12559
|
}, more);
|
|
12412
12560
|
}
|
|
12413
12561
|
// src/reference.ts
|
|
12414
|
-
function own$
|
|
12562
|
+
function own$2(table, name) {
|
|
12415
12563
|
return table !== void 0 && Object.hasOwn(table, name) ? table[name] : void 0;
|
|
12416
12564
|
}
|
|
12417
12565
|
/**
|
|
@@ -12419,16 +12567,16 @@ function own$1(table, name) {
|
|
|
12419
12567
|
* evaluator gets the definition of the reference, unless the options give another definition (REF.TREE).
|
|
12420
12568
|
*/
|
|
12421
12569
|
function choose(env, name) {
|
|
12422
|
-
const runner = own$
|
|
12570
|
+
const runner = own$2(env.machine.runners, name);
|
|
12423
12571
|
if (runner !== void 0) {
|
|
12424
|
-
const defined = own$
|
|
12572
|
+
const defined = own$2(env.definitions.runners, name);
|
|
12425
12573
|
if (defined !== void 0) return { runner: defined };
|
|
12426
12574
|
return typeof runner === "function" ? { runner } : { gap: `The reference has no definition of the compiled runner ${name}.` };
|
|
12427
12575
|
}
|
|
12428
|
-
const evaluator = own$
|
|
12576
|
+
const evaluator = own$2(env.machine.evaluators, name);
|
|
12429
12577
|
if (evaluator === void 0) return void 0;
|
|
12430
|
-
const standard = evaluator === own$
|
|
12431
|
-
const defined = own$
|
|
12578
|
+
const standard = evaluator === own$2(STD_EVALUATORS, name) ? own$2(STD_DEFINITIONS.evaluators, name) : void 0;
|
|
12579
|
+
const defined = own$2(env.definitions.evaluators, name) ?? standard;
|
|
12432
12580
|
if (defined !== void 0) return { evaluator: defined };
|
|
12433
12581
|
return typeof evaluator === "function" ? { evaluator } : { gap: `The reference has no definition of the compiled evaluator ${name}.` };
|
|
12434
12582
|
}
|
|
@@ -12592,10 +12740,10 @@ function clauseAt(env, ctx, kind, place) {
|
|
|
12592
12740
|
* address (RUN.ADDRESS) and its outcome (RUN.OUTCOME). The mock answers the effect at once (RUN.MOCK). Without a
|
|
12593
12741
|
* mock, the effect gives its payload (RUN.EVAL).
|
|
12594
12742
|
*/
|
|
12595
|
-
function cause(env, ctx, kind, payload, place) {
|
|
12743
|
+
function cause$1(env, ctx, kind, payload, place) {
|
|
12596
12744
|
const effect = recordEffect(env, ctx, kind, payload, place);
|
|
12597
12745
|
if ("ok" in effect) return effect;
|
|
12598
|
-
effect.outcome = answer(env.perform, effect, place);
|
|
12746
|
+
effect.outcome = answer$1(env.perform, effect, place);
|
|
12599
12747
|
return effect.outcome;
|
|
12600
12748
|
}
|
|
12601
12749
|
/**
|
|
@@ -12606,8 +12754,8 @@ function causeFromEvaluator(env, ctx, kind, payload, place) {
|
|
|
12606
12754
|
const text = typeof kind === "string" ? kind : kind.join(".");
|
|
12607
12755
|
if (env.running) return fail("#CALC!", `The effect ${text} needs a runner: in a run, the host does each effect.`, { place });
|
|
12608
12756
|
const clause = clauseAt(env, ctx, kind, place);
|
|
12609
|
-
if (clause !== void 0) return "ok" in clause ? clause : drive$
|
|
12610
|
-
return cause(env, ctx, kind, payload, place);
|
|
12757
|
+
if (clause !== void 0) return "ok" in clause ? clause : drive$2(clause.answer(payload), place, text);
|
|
12758
|
+
return cause$1(env, ctx, kind, payload, place);
|
|
12611
12759
|
}
|
|
12612
12760
|
/**
|
|
12613
12761
|
* This function causes the effect of a runner. In an evaluation, the mock answers it at once. In a run, the host does
|
|
@@ -12617,7 +12765,7 @@ function causeFromEvaluator(env, ctx, kind, payload, place) {
|
|
|
12617
12765
|
function* causeAndWait(env, ctx, kind, payload, place) {
|
|
12618
12766
|
const clause = clauseAt(env, ctx, kind, place);
|
|
12619
12767
|
if (clause !== void 0) return "ok" in clause ? clause : yield* clause.answer(payload);
|
|
12620
|
-
if (!env.running) return cause(env, ctx, kind, payload, place);
|
|
12768
|
+
if (!env.running) return cause$1(env, ctx, kind, payload, place);
|
|
12621
12769
|
const effect = recordEffect(env, ctx, kind, payload, place);
|
|
12622
12770
|
if ("ok" in effect) return effect;
|
|
12623
12771
|
const perform = env.perform;
|
|
@@ -12674,7 +12822,7 @@ function hostError(effect, place, error) {
|
|
|
12674
12822
|
* This function gives the answer of the mock to an effect. A throw gives `#CALC!` with the cause, and a `Failure`
|
|
12675
12823
|
* gives its own error value. A promise gives `#CALC!`, because an evaluation does not wait.
|
|
12676
12824
|
*/
|
|
12677
|
-
function answer(perform, effect, place) {
|
|
12825
|
+
function answer$1(perform, effect, place) {
|
|
12678
12826
|
if (perform === void 0) return ok(effect.payload);
|
|
12679
12827
|
let given;
|
|
12680
12828
|
try {
|
|
@@ -12697,10 +12845,10 @@ function evaluateSeen(env, seen, at) {
|
|
|
12697
12845
|
const { place } = at;
|
|
12698
12846
|
if ("gap" in chosen) return fail("#NOEVAL", chosen.gap, { place });
|
|
12699
12847
|
if ("runner" in chosen) {
|
|
12700
|
-
if (!env.running) return drive$
|
|
12848
|
+
if (!env.running) return drive$2(runSeen(env, seen, at, chosen.runner), place, seen.kindText);
|
|
12701
12849
|
env.held += 1;
|
|
12702
12850
|
try {
|
|
12703
|
-
return drive$
|
|
12851
|
+
return drive$2(runSeen(env, seen, at, chosen.runner), place, seen.kindText);
|
|
12704
12852
|
} finally {
|
|
12705
12853
|
env.held -= 1;
|
|
12706
12854
|
}
|
|
@@ -12727,7 +12875,7 @@ function* runSeen(env, seen, at, runner) {
|
|
|
12727
12875
|
}
|
|
12728
12876
|
}
|
|
12729
12877
|
/** This function drives steps that cannot wait. A step that waits gives `#CALC!` at the document (RUN.WAIT). */
|
|
12730
|
-
function drive$
|
|
12878
|
+
function drive$2(steps, place, kindText) {
|
|
12731
12879
|
const step = steps.next();
|
|
12732
12880
|
if (step.done === true) return step.value;
|
|
12733
12881
|
step.value.catch(() => void 0);
|
|
@@ -13439,7 +13587,7 @@ function jsonOfNode(node, self, open) {
|
|
|
13439
13587
|
if (!result.ok) return result;
|
|
13440
13588
|
const value = plainValue(result.value, [...open, self]);
|
|
13441
13589
|
if (!value.ok) return value;
|
|
13442
|
-
setField$
|
|
13590
|
+
setField$2(record, part.key, value.value);
|
|
13443
13591
|
}
|
|
13444
13592
|
return ok(record);
|
|
13445
13593
|
}
|
|
@@ -13465,7 +13613,7 @@ function plainValue(value, open) {
|
|
|
13465
13613
|
for (const key of Object.keys(value)) {
|
|
13466
13614
|
const plain = plainValue(value[key], [...open, value]);
|
|
13467
13615
|
if (!plain.ok) return plain;
|
|
13468
|
-
setField$
|
|
13616
|
+
setField$2(copy, key, plain.value);
|
|
13469
13617
|
}
|
|
13470
13618
|
return ok(copy);
|
|
13471
13619
|
}
|
|
@@ -13543,9 +13691,9 @@ const STD_DEFINITIONS = { evaluators: {
|
|
|
13543
13691
|
"tree.node": treeDefinition,
|
|
13544
13692
|
"ref.resolve": refDefinition
|
|
13545
13693
|
} };
|
|
13546
|
-
const CLOSURE$
|
|
13694
|
+
const CLOSURE$2 = /* @__PURE__ */ Symbol.for("coeval.closure");
|
|
13547
13695
|
/** This function sets an own field, also the field `__proto__` (SHAPE.PROTO). */
|
|
13548
|
-
function setField$
|
|
13696
|
+
function setField$2(target, key, value) {
|
|
13549
13697
|
Object.defineProperty(target, key, {
|
|
13550
13698
|
value,
|
|
13551
13699
|
enumerable: true,
|
|
@@ -13553,10 +13701,10 @@ function setField$1(target, key, value) {
|
|
|
13553
13701
|
configurable: true
|
|
13554
13702
|
});
|
|
13555
13703
|
}
|
|
13556
|
-
function partNamed(parts, key) {
|
|
13704
|
+
function partNamed$1(parts, key) {
|
|
13557
13705
|
return parts.find((part) => part.path.length === 1 && part.path[0] === key);
|
|
13558
13706
|
}
|
|
13559
|
-
function partsUnder(parts, key) {
|
|
13707
|
+
function partsUnder$1(parts, key) {
|
|
13560
13708
|
return parts.filter((part) => part.path.length === 2 && part.path[0] === key);
|
|
13561
13709
|
}
|
|
13562
13710
|
/**
|
|
@@ -13569,7 +13717,7 @@ function partsUnder(parts, key) {
|
|
|
13569
13717
|
*/
|
|
13570
13718
|
function formulaDefinitions(profile = {}) {
|
|
13571
13719
|
const truthy = profile.truthy ?? ((value) => typeof value === "boolean" ? value : void 0);
|
|
13572
|
-
const opOf = (name) => typeof profile.ops === "function" ? profile.ops(name) : own$
|
|
13720
|
+
const opOf = (name) => typeof profile.ops === "function" ? profile.ops(name) : own$2(profile.ops, name);
|
|
13573
13721
|
const noTruth = (what) => fail("#VALUE!", `The ${what} must give a truth value.`);
|
|
13574
13722
|
/** FORMULA.LIST, FORMULA.OPS and FORMULA.COMBINE: the values of parts in order, or the error. */
|
|
13575
13723
|
const valuesOf = (parts, skip) => {
|
|
@@ -13599,7 +13747,7 @@ function formulaDefinitions(profile = {}) {
|
|
|
13599
13747
|
steps = fill(all.values);
|
|
13600
13748
|
}
|
|
13601
13749
|
const head = path[0] === "names" && typeof path[1] === "string" ? path[1] : void 0;
|
|
13602
|
-
const bound = head === void 0 ? void 0 : own$
|
|
13750
|
+
const bound = head === void 0 ? void 0 : own$2(context.names, head);
|
|
13603
13751
|
if (bound instanceof Held) {
|
|
13604
13752
|
walk(["names", head]);
|
|
13605
13753
|
return {
|
|
@@ -13632,7 +13780,7 @@ function formulaDefinitions(profile = {}) {
|
|
|
13632
13780
|
const out = {};
|
|
13633
13781
|
parts.forEach((part, index) => {
|
|
13634
13782
|
const value = all.values[index];
|
|
13635
|
-
if (value !== SKIP) setField$
|
|
13783
|
+
if (value !== SKIP) setField$2(out, String(part.path[0]), value);
|
|
13636
13784
|
});
|
|
13637
13785
|
return ok(out);
|
|
13638
13786
|
};
|
|
@@ -13642,12 +13790,12 @@ function formulaDefinitions(profile = {}) {
|
|
|
13642
13790
|
};
|
|
13643
13791
|
const letIn = ({ parts, context }) => {
|
|
13644
13792
|
const names = {};
|
|
13645
|
-
for (const key of Object.keys(context.names)) setField$
|
|
13646
|
-
for (const binding of partsUnder(parts, "bind")) {
|
|
13793
|
+
for (const key of Object.keys(context.names)) setField$2(names, key, context.names[key]);
|
|
13794
|
+
for (const binding of partsUnder$1(parts, "bind")) {
|
|
13647
13795
|
const result = binding.evaluate();
|
|
13648
|
-
setField$
|
|
13796
|
+
setField$2(names, String(binding.path[1]), result.ok ? result.value : new Held(result.error));
|
|
13649
13797
|
}
|
|
13650
|
-
return partNamed(parts, "body").evaluate({
|
|
13798
|
+
return partNamed$1(parts, "body").evaluate({
|
|
13651
13799
|
...context,
|
|
13652
13800
|
names
|
|
13653
13801
|
});
|
|
@@ -13656,7 +13804,7 @@ function formulaDefinitions(profile = {}) {
|
|
|
13656
13804
|
const params = isRecord(data) ? data["params"] : void 0;
|
|
13657
13805
|
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.");
|
|
13658
13806
|
const names = params;
|
|
13659
|
-
const body = partNamed(parts, "body");
|
|
13807
|
+
const body = partNamed$1(parts, "body");
|
|
13660
13808
|
const clock = activeEnvs[activeEnvs.length - 1] ?? {
|
|
13661
13809
|
applying: 0,
|
|
13662
13810
|
maxDepth: 1e3
|
|
@@ -13667,8 +13815,8 @@ function formulaDefinitions(profile = {}) {
|
|
|
13667
13815
|
clock.applying += 1;
|
|
13668
13816
|
try {
|
|
13669
13817
|
const scope = {};
|
|
13670
|
-
for (const key of Object.keys(context.names)) setField$
|
|
13671
|
-
names.forEach((name, index) => setField$
|
|
13818
|
+
for (const key of Object.keys(context.names)) setField$2(scope, key, context.names[key]);
|
|
13819
|
+
names.forEach((name, index) => setField$2(scope, name, args[index]));
|
|
13672
13820
|
const result = body.evaluate({
|
|
13673
13821
|
...context,
|
|
13674
13822
|
names: scope
|
|
@@ -13679,14 +13827,14 @@ function formulaDefinitions(profile = {}) {
|
|
|
13679
13827
|
clock.applying -= 1;
|
|
13680
13828
|
}
|
|
13681
13829
|
};
|
|
13682
|
-
Object.defineProperty(closure, CLOSURE$
|
|
13830
|
+
Object.defineProperty(closure, CLOSURE$2, { value: { params: names } });
|
|
13683
13831
|
return ok(closure);
|
|
13684
13832
|
};
|
|
13685
13833
|
const call = ({ parts }) => {
|
|
13686
|
-
const target = partNamed(parts, "fn").evaluate();
|
|
13834
|
+
const target = partNamed$1(parts, "fn").evaluate();
|
|
13687
13835
|
if (!target.ok) return target;
|
|
13688
13836
|
if (typeof target.value !== "function") return fail("#VALUE!", "The fn of call must give a function.");
|
|
13689
|
-
const all = valuesOfStrict(partsUnder(parts, "args"));
|
|
13837
|
+
const all = valuesOfStrict(partsUnder$1(parts, "args"));
|
|
13690
13838
|
if (!("values" in all)) return all;
|
|
13691
13839
|
try {
|
|
13692
13840
|
return ok(target.value(...all.values));
|
|
@@ -13695,12 +13843,12 @@ function formulaDefinitions(profile = {}) {
|
|
|
13695
13843
|
}
|
|
13696
13844
|
};
|
|
13697
13845
|
const choice = ({ parts }) => {
|
|
13698
|
-
const test = partNamed(parts, "test").evaluate();
|
|
13846
|
+
const test = partNamed$1(parts, "test").evaluate();
|
|
13699
13847
|
if (!test.ok) return test;
|
|
13700
13848
|
const truth = truthy(test.value);
|
|
13701
13849
|
if (truth === void 0) return noTruth("test of if");
|
|
13702
|
-
if (truth) return partNamed(parts, "then").evaluate();
|
|
13703
|
-
const other = partNamed(parts, "else");
|
|
13850
|
+
if (truth) return partNamed$1(parts, "then").evaluate();
|
|
13851
|
+
const other = partNamed$1(parts, "else");
|
|
13704
13852
|
if (other !== void 0) return other.evaluate();
|
|
13705
13853
|
return ok(Object.hasOwn(profile, "otherwise") ? profile.otherwise : null);
|
|
13706
13854
|
};
|
|
@@ -13718,7 +13866,7 @@ function formulaDefinitions(profile = {}) {
|
|
|
13718
13866
|
};
|
|
13719
13867
|
const op = ({ typePath, parts }) => {
|
|
13720
13868
|
const name = typePath.slice(1).join(".");
|
|
13721
|
-
const lazy = own$
|
|
13869
|
+
const lazy = own$2(profile.lazy, name);
|
|
13722
13870
|
if (lazy !== void 0) try {
|
|
13723
13871
|
return lazy(parts.map((part) => () => part.evaluate()));
|
|
13724
13872
|
} catch (error) {
|
|
@@ -13737,7 +13885,7 @@ function formulaDefinitions(profile = {}) {
|
|
|
13737
13885
|
};
|
|
13738
13886
|
const ext = ({ typePath, doc, context, machine }) => {
|
|
13739
13887
|
const name = typePath.slice(1).join(".");
|
|
13740
|
-
const handler = own$
|
|
13888
|
+
const handler = own$2(profile.ext, name) ?? own$2(STD_EXT, name);
|
|
13741
13889
|
if (handler === void 0) return fail("#NAME?", `The language has no extension ${name}.`);
|
|
13742
13890
|
try {
|
|
13743
13891
|
return handler(doc.value, context, machine?.domains);
|
|
@@ -13773,6 +13921,1124 @@ function valuesOfStrict(parts) {
|
|
|
13773
13921
|
}
|
|
13774
13922
|
return { values };
|
|
13775
13923
|
}
|
|
13924
|
+
// src/stepper.ts
|
|
13925
|
+
const CLOSURE_MARK = "coeval.closure";
|
|
13926
|
+
const HELD_MARK = "coeval.held";
|
|
13927
|
+
const CLOSURE$1 = /* @__PURE__ */ Symbol.for("coeval.closure");
|
|
13928
|
+
const MAX_ALIASES = 32;
|
|
13929
|
+
const MAX_COLLAPSE = 64;
|
|
13930
|
+
const ROOTS$1 = /* @__PURE__ */ Object.freeze([
|
|
13931
|
+
"self",
|
|
13932
|
+
"names",
|
|
13933
|
+
"world",
|
|
13934
|
+
"event",
|
|
13935
|
+
"caps"
|
|
13936
|
+
]);
|
|
13937
|
+
const NO_KEYS$1 = /* @__PURE__ */ Object.freeze([]);
|
|
13938
|
+
function own$1(table, name) {
|
|
13939
|
+
return table !== void 0 && Object.hasOwn(table, name) ? table[name] : void 0;
|
|
13940
|
+
}
|
|
13941
|
+
function setField$1(target, key, value) {
|
|
13942
|
+
Object.defineProperty(target, key, {
|
|
13943
|
+
value,
|
|
13944
|
+
enumerable: true,
|
|
13945
|
+
writable: true,
|
|
13946
|
+
configurable: true
|
|
13947
|
+
});
|
|
13948
|
+
}
|
|
13949
|
+
function closureOf(value) {
|
|
13950
|
+
return isRecord(value) && Object.hasOwn(value, CLOSURE_MARK) ? value[CLOSURE_MARK] : void 0;
|
|
13951
|
+
}
|
|
13952
|
+
function heldOf(value) {
|
|
13953
|
+
if (value instanceof Held) return value.error;
|
|
13954
|
+
return isRecord(value) && Object.hasOwn(value, HELD_MARK) ? value[HELD_MARK] : void 0;
|
|
13955
|
+
}
|
|
13956
|
+
/** The judgment 2: K-START and K-COMPUTED. */
|
|
13957
|
+
function keysOf(type) {
|
|
13958
|
+
if (typeof type === "string") return [type];
|
|
13959
|
+
if (Array.isArray(type)) return type;
|
|
13960
|
+
const steps = type.value.slice(1);
|
|
13961
|
+
return steps.every(isKey$1) ? steps : void 0;
|
|
13962
|
+
}
|
|
13963
|
+
/** A key is a text, or a whole number from 0. */
|
|
13964
|
+
function isKey$1(step) {
|
|
13965
|
+
return typeof step === "string" || typeof step === "number" && Number.isInteger(step) && step >= 0;
|
|
13966
|
+
}
|
|
13967
|
+
/** The judgment 2: the lookup of a kind, with the rules K-FALLBACK to K-NOT-A-KIND. */
|
|
13968
|
+
function lookup(world, type) {
|
|
13969
|
+
const start = keysOf(type);
|
|
13970
|
+
if (start === void 0) return void 0;
|
|
13971
|
+
let keys = start;
|
|
13972
|
+
let aliases = 0;
|
|
13973
|
+
for (;;) {
|
|
13974
|
+
let entries = world.kinds;
|
|
13975
|
+
let fallback = world.fallback;
|
|
13976
|
+
let followed = false;
|
|
13977
|
+
if (keys.length === 0) return void 0;
|
|
13978
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
13979
|
+
const key = String(keys[index]);
|
|
13980
|
+
const entry = own$1(entries, key);
|
|
13981
|
+
if (entry === void 0) return fallback === void 0 ? void 0 : {
|
|
13982
|
+
kind: fallback,
|
|
13983
|
+
path: keys
|
|
13984
|
+
};
|
|
13985
|
+
if (isAlias(entry)) {
|
|
13986
|
+
aliases += 1;
|
|
13987
|
+
const target = entry.value.slice(1);
|
|
13988
|
+
if (aliases > MAX_ALIASES || entry.value[0] !== "world" || !target.every(isKey$1)) return void 0;
|
|
13989
|
+
keys = [...target, ...keys.slice(index + 1)];
|
|
13990
|
+
followed = true;
|
|
13991
|
+
break;
|
|
13992
|
+
}
|
|
13993
|
+
if (index === keys.length - 1) return isKind(entry) ? {
|
|
13994
|
+
kind: entry,
|
|
13995
|
+
path: keys
|
|
13996
|
+
} : void 0;
|
|
13997
|
+
if (!isNamespace(entry)) return void 0;
|
|
13998
|
+
entries = entry.kinds;
|
|
13999
|
+
fallback = entry.fallback;
|
|
14000
|
+
}
|
|
14001
|
+
if (!followed) return void 0;
|
|
14002
|
+
}
|
|
14003
|
+
}
|
|
14004
|
+
/** The result of the ladder for each rung: a name, `null` for L-STOP, or `undefined` for L-NONE. */
|
|
14005
|
+
function ladder(world, entries, kind, known, verb, has) {
|
|
14006
|
+
const mine = isRecord(entries) ? own$1(entries, verb) : void 0;
|
|
14007
|
+
if (mine !== void 0 && has(mine)) return mine;
|
|
14008
|
+
if (!known) return null;
|
|
14009
|
+
const named = own$1(kind?.verbs, verb);
|
|
14010
|
+
if (named !== void 0 && has(named)) return named;
|
|
14011
|
+
const fallback = own$1(world.defaults, verb);
|
|
14012
|
+
return fallback !== void 0 && has(fallback) ? fallback : void 0;
|
|
14013
|
+
}
|
|
14014
|
+
var Bad = class {
|
|
14015
|
+
reason;
|
|
14016
|
+
at;
|
|
14017
|
+
constructor(reason, at) {
|
|
14018
|
+
this.reason = reason;
|
|
14019
|
+
this.at = at;
|
|
14020
|
+
}
|
|
14021
|
+
};
|
|
14022
|
+
/** The result of the walk for a part: the field is absent from the data (SPLIT-FILL). */
|
|
14023
|
+
const PART = /* @__PURE__ */ Symbol("part");
|
|
14024
|
+
function isDataShape(shape) {
|
|
14025
|
+
return shape.shape === "none" || shape.shape === "text" || shape.shape === "number" || shape.shape === "one";
|
|
14026
|
+
}
|
|
14027
|
+
/** SPLIT-DATA: the reason why a value is not a member of a data shape. */
|
|
14028
|
+
function notMember(shape, value) {
|
|
14029
|
+
if (shape.shape === "text") return typeof value === "string" ? void 0 : "The value must be a text.";
|
|
14030
|
+
if (shape.shape === "one") return shape.values.some((item) => docEquals(item, value)) ? void 0 : `The value must be one of ${JSON.stringify(shape.values)}.`;
|
|
14031
|
+
if (typeof value !== "number") return "The value must be a number.";
|
|
14032
|
+
if (shape.whole === true && !Number.isInteger(value)) return "The value must be a whole number.";
|
|
14033
|
+
if (shape.min !== void 0 && !(value >= shape.min)) return `The value must be ${String(shape.min)} or more.`;
|
|
14034
|
+
if (shape.max !== void 0 && !(value <= shape.max)) return `The value must be ${String(shape.max)} or less.`;
|
|
14035
|
+
}
|
|
14036
|
+
function checkKinds(kinds, item, of, path) {
|
|
14037
|
+
const type = isEnvelope(item) ? keysOf(item.type) : of === void 0 ? void 0 : [of];
|
|
14038
|
+
if (type !== void 0 && kinds.some((kind) => kind.length <= type.length && kind.every((key, index) => String(key) === String(type[index])))) return;
|
|
14039
|
+
throw new Bad(`${isEnvelope(item) ? `The kind ${typeName(item.type)} is not permitted here.` : "A value without an envelope is not permitted here."} The permitted kinds are ${kinds.map((kind) => kind.join(".")).join(", ")}.`, path);
|
|
14040
|
+
}
|
|
14041
|
+
/** The judgment 1: the rules SPLIT-NONE to SPLIT-DEEP. The result holds the parts and the data of SPLIT-FILL. */
|
|
14042
|
+
function split(shape, value) {
|
|
14043
|
+
const slots = [];
|
|
14044
|
+
const slot = (item, path, of, address) => {
|
|
14045
|
+
slots.push({
|
|
14046
|
+
path,
|
|
14047
|
+
key: path.join("."),
|
|
14048
|
+
item,
|
|
14049
|
+
...of === void 0 ? {} : { of },
|
|
14050
|
+
...address ? { address: true } : {}
|
|
14051
|
+
});
|
|
14052
|
+
return PART;
|
|
14053
|
+
};
|
|
14054
|
+
const term = (of) => of === void 0 ? { shape: "term" } : {
|
|
14055
|
+
shape: "term",
|
|
14056
|
+
of
|
|
14057
|
+
};
|
|
14058
|
+
const listData = (items) => items.every((item) => item === PART) ? null : items.map((item) => item === PART ? null : item);
|
|
14059
|
+
const deep = (item, path, of) => {
|
|
14060
|
+
if (isEnvelope(item)) return slot(item, path, of, false);
|
|
14061
|
+
const before = slots.length;
|
|
14062
|
+
if (Array.isArray(item)) {
|
|
14063
|
+
const items = item.map((child, index) => deep(child, [...path, index], of));
|
|
14064
|
+
return slots.length === before ? item : listData(items);
|
|
14065
|
+
}
|
|
14066
|
+
if (!isRecord(item)) return item;
|
|
14067
|
+
const out = {};
|
|
14068
|
+
for (const key of Object.keys(item)) {
|
|
14069
|
+
const kept = deep(item[key], [...path, key], of);
|
|
14070
|
+
if (kept !== PART) setField$1(out, key, kept);
|
|
14071
|
+
}
|
|
14072
|
+
return slots.length === before ? item : out;
|
|
14073
|
+
};
|
|
14074
|
+
const walk = (spec, item, path) => {
|
|
14075
|
+
if (spec === void 0 || spec.shape === "none") return item;
|
|
14076
|
+
if (spec.shape === "text" || spec.shape === "number" || spec.shape === "one") {
|
|
14077
|
+
const reason = notMember(spec, item);
|
|
14078
|
+
if (reason !== void 0) throw new Bad(reason, path);
|
|
14079
|
+
return item;
|
|
14080
|
+
}
|
|
14081
|
+
if (spec.shape === "term") {
|
|
14082
|
+
if (spec.kinds !== void 0) checkKinds(spec.kinds, item, spec.of, path);
|
|
14083
|
+
return slot(item, path, spec.of, spec.address === true);
|
|
14084
|
+
}
|
|
14085
|
+
if (spec.shape === "deep") return deep(item, path, spec.of);
|
|
14086
|
+
if (spec.shape === "list") {
|
|
14087
|
+
if (!Array.isArray(item)) throw new Bad("The value must be a list.", path);
|
|
14088
|
+
const list = item;
|
|
14089
|
+
if (spec.distinct === true) {
|
|
14090
|
+
const twice = list.findIndex((child, index) => list.slice(0, index).some((before) => docEquals(before, child)));
|
|
14091
|
+
if (twice !== -1) throw new Bad("The items of the list must be different.", [...path, twice]);
|
|
14092
|
+
}
|
|
14093
|
+
const each = spec.item ?? term(spec.of);
|
|
14094
|
+
const items = list.map((child, index) => walk(each, child, [...path, index]));
|
|
14095
|
+
return isDataShape(each) ? item : listData(items);
|
|
14096
|
+
}
|
|
14097
|
+
if (!isRecord(item)) throw new Bad("The value must be a record.", path);
|
|
14098
|
+
const out = {};
|
|
14099
|
+
const keep = (key, kept) => {
|
|
14100
|
+
if (kept !== PART) setField$1(out, key, kept);
|
|
14101
|
+
};
|
|
14102
|
+
if (spec.shape === "map") {
|
|
14103
|
+
for (const key of Object.keys(item)) keep(key, walk(spec.item ?? term(spec.of), item[key], [...path, key]));
|
|
14104
|
+
return out;
|
|
14105
|
+
}
|
|
14106
|
+
for (const name of spec.required ?? []) if (!Object.hasOwn(item, name)) throw new Bad(`The field ${name} is missing.`, path);
|
|
14107
|
+
for (const key of Object.keys(item)) {
|
|
14108
|
+
const named = Array.isArray(spec.fields) ? spec.fields.includes(key) : Object.hasOwn(spec.fields, key);
|
|
14109
|
+
if (spec.closed === true && !named) throw new Bad(`The field ${key} is not a field of this kind.`, [...path, key]);
|
|
14110
|
+
const fieldShape = !named ? spec.rest : Array.isArray(spec.fields) ? term(spec.of) : spec.fields[key];
|
|
14111
|
+
keep(key, walk(fieldShape, item[key], [...path, key]));
|
|
14112
|
+
}
|
|
14113
|
+
return out;
|
|
14114
|
+
};
|
|
14115
|
+
try {
|
|
14116
|
+
const data = walk(shape, value, []);
|
|
14117
|
+
return {
|
|
14118
|
+
slots,
|
|
14119
|
+
data: data === PART ? null : data
|
|
14120
|
+
};
|
|
14121
|
+
} catch (error) {
|
|
14122
|
+
if (error instanceof Bad) return error;
|
|
14123
|
+
throw error;
|
|
14124
|
+
}
|
|
14125
|
+
}
|
|
14126
|
+
function copyOf(container) {
|
|
14127
|
+
if (Array.isArray(container)) return [...container];
|
|
14128
|
+
const out = {};
|
|
14129
|
+
for (const key of Object.keys(container)) setField$1(out, key, container[key]);
|
|
14130
|
+
return out;
|
|
14131
|
+
}
|
|
14132
|
+
/** SPLIT-FILL: the value with the item `i` at the path of the slot `i`. The containers on the way are new. */
|
|
14133
|
+
function fillIn(value, slots, items) {
|
|
14134
|
+
const first = slots[0];
|
|
14135
|
+
if (first === void 0) return value;
|
|
14136
|
+
if (first.path.length === 0) return items[0];
|
|
14137
|
+
const root = copyOf(value);
|
|
14138
|
+
const fresh = /* @__PURE__ */ new Set([root]);
|
|
14139
|
+
slots.forEach((part, index) => {
|
|
14140
|
+
let here = root;
|
|
14141
|
+
for (let step = 0; step < part.path.length - 1; step += 1) {
|
|
14142
|
+
const key = part.path[step];
|
|
14143
|
+
let next = here[key];
|
|
14144
|
+
if (!fresh.has(next)) {
|
|
14145
|
+
next = copyOf(next);
|
|
14146
|
+
fresh.add(next);
|
|
14147
|
+
setField$1(here, String(key), next);
|
|
14148
|
+
}
|
|
14149
|
+
here = next;
|
|
14150
|
+
}
|
|
14151
|
+
setField$1(here, String(part.path[part.path.length - 1]), items[index]);
|
|
14152
|
+
});
|
|
14153
|
+
return root;
|
|
14154
|
+
}
|
|
14155
|
+
/** H-CONTEXT: the capabilities of a rule list for one part. */
|
|
14156
|
+
function capsOf(rules, path, caps) {
|
|
14157
|
+
let out = caps;
|
|
14158
|
+
for (const rule of rules ?? []) {
|
|
14159
|
+
if (rule.in !== void 0 && !rule.in.some((pattern) => pathMatches(path, pattern))) continue;
|
|
14160
|
+
if (rule.rule === "mask") return [];
|
|
14161
|
+
if (rule.rule === "only") out = intersectCaps(out, rule.caps);
|
|
14162
|
+
}
|
|
14163
|
+
return out;
|
|
14164
|
+
}
|
|
14165
|
+
/** H-CONTEXT: the context of a part. */
|
|
14166
|
+
function contextOf(site, slot, given) {
|
|
14167
|
+
const parent = site.ctx;
|
|
14168
|
+
const narrow = (context) => context.caps.every((cap) => permits(parent.caps, cap)) ? context : {
|
|
14169
|
+
...context,
|
|
14170
|
+
caps: intersectCaps(parent.caps, context.caps)
|
|
14171
|
+
};
|
|
14172
|
+
const base = given === void 0 || given === parent ? parent : narrow(given);
|
|
14173
|
+
const caps = capsOf(site.rules, slot.path, base.caps);
|
|
14174
|
+
return caps === base.caps ? base : {
|
|
14175
|
+
...base,
|
|
14176
|
+
caps
|
|
14177
|
+
};
|
|
14178
|
+
}
|
|
14179
|
+
/** H-PLACE: the place of the document on top of the stack. */
|
|
14180
|
+
function placeOf$1(stack) {
|
|
14181
|
+
const pieces = [];
|
|
14182
|
+
let base = NO_KEYS$1;
|
|
14183
|
+
for (let index = stack.length - 1; index >= 0; index -= 1) {
|
|
14184
|
+
const frame = stack[index];
|
|
14185
|
+
if (frame.f === "base" || frame.f === "return") {
|
|
14186
|
+
base = frame.place;
|
|
14187
|
+
break;
|
|
14188
|
+
}
|
|
14189
|
+
pieces.push(frame.at);
|
|
14190
|
+
}
|
|
14191
|
+
const out = [...base];
|
|
14192
|
+
for (let index = pieces.length - 1; index >= 0; index -= 1) out.push(...pieces[index]);
|
|
14193
|
+
return out;
|
|
14194
|
+
}
|
|
14195
|
+
function back(c, result) {
|
|
14196
|
+
return {
|
|
14197
|
+
mode: "resume",
|
|
14198
|
+
result: result.ok || result.error.place !== void 0 ? result : placed(result, placeOf$1(c.stack)),
|
|
14199
|
+
stack: c.stack,
|
|
14200
|
+
applying: c.applying,
|
|
14201
|
+
marked: c.marked
|
|
14202
|
+
};
|
|
14203
|
+
}
|
|
14204
|
+
function pushed(c, frame) {
|
|
14205
|
+
c.stack.push(frame);
|
|
14206
|
+
}
|
|
14207
|
+
function popped(c) {
|
|
14208
|
+
c.stack.pop();
|
|
14209
|
+
}
|
|
14210
|
+
/** H-SEAL: the evaluation of a part, with the frame that waits for it on top of the stack. */
|
|
14211
|
+
function enter(c, frame, site, slot, given, marked = c.marked) {
|
|
14212
|
+
frame.at = slot.path;
|
|
14213
|
+
return {
|
|
14214
|
+
mode: "evaluate",
|
|
14215
|
+
value: slot.item,
|
|
14216
|
+
declared: slot.of,
|
|
14217
|
+
depth: site.depth + 1,
|
|
14218
|
+
address: slot.address === true,
|
|
14219
|
+
ctx: contextOf(site, slot, given),
|
|
14220
|
+
stack: c.stack,
|
|
14221
|
+
applying: c.applying,
|
|
14222
|
+
marked
|
|
14223
|
+
};
|
|
14224
|
+
}
|
|
14225
|
+
function partNamed(slots, key) {
|
|
14226
|
+
return slots.find((slot) => slot.path.length === 1 && slot.path[0] === key);
|
|
14227
|
+
}
|
|
14228
|
+
function partsUnder(slots, key) {
|
|
14229
|
+
return slots.filter((slot) => slot.path.length === 2 && slot.path[0] === key);
|
|
14230
|
+
}
|
|
14231
|
+
function truthOf(p, c, value) {
|
|
14232
|
+
const given = forHost(p, c, value);
|
|
14233
|
+
return p.profile.truthy === void 0 ? typeof given === "boolean" ? given : void 0 : p.profile.truthy(given);
|
|
14234
|
+
}
|
|
14235
|
+
function opOf(p, name) {
|
|
14236
|
+
const { ops } = p.profile;
|
|
14237
|
+
return typeof ops === "function" ? ops(name) : own$1(ops, name);
|
|
14238
|
+
}
|
|
14239
|
+
function startValues(p, c, site, then, slots, strict, more = {}) {
|
|
14240
|
+
const frame = {
|
|
14241
|
+
f: "values",
|
|
14242
|
+
at: NO_KEYS$1,
|
|
14243
|
+
site,
|
|
14244
|
+
then,
|
|
14245
|
+
slots,
|
|
14246
|
+
strict,
|
|
14247
|
+
next: 1,
|
|
14248
|
+
values: [],
|
|
14249
|
+
errors: [],
|
|
14250
|
+
skipped: [],
|
|
14251
|
+
...more
|
|
14252
|
+
};
|
|
14253
|
+
const first = slots[0];
|
|
14254
|
+
if (first === void 0) return finish$1(p, c, frame);
|
|
14255
|
+
pushed(c, frame);
|
|
14256
|
+
return enter(c, frame, site, first);
|
|
14257
|
+
}
|
|
14258
|
+
/** F-REF, after the values of the steps. */
|
|
14259
|
+
function finishRef(p, c, doc, steps, site, address) {
|
|
14260
|
+
const path = doc.value;
|
|
14261
|
+
const head = path[0] === "names" && typeof path[1] === "string" ? path[1] : void 0;
|
|
14262
|
+
const bound = head === void 0 ? void 0 : heldOf(own$1(site.ctx.names, head));
|
|
14263
|
+
if (bound !== void 0) return back(c, {
|
|
14264
|
+
ok: false,
|
|
14265
|
+
error: bound
|
|
14266
|
+
});
|
|
14267
|
+
const found = walkPath(p, site.ctx, steps);
|
|
14268
|
+
if (!found.ok) return back(c, fail(found.code, found.reason));
|
|
14269
|
+
if (address) return back(c, ok(found.thing));
|
|
14270
|
+
const reached = isHostThing(found.thing) ? found.thing.toJson() : found.thing;
|
|
14271
|
+
const held = heldOf(reached);
|
|
14272
|
+
if (held !== void 0) return back(c, {
|
|
14273
|
+
ok: false,
|
|
14274
|
+
error: held
|
|
14275
|
+
});
|
|
14276
|
+
if (p.profile.missing?.(forHost(p, c, reached)) === true) return back(c, fail("#N/A", "The path reaches no value."));
|
|
14277
|
+
return back(c, ok(reached));
|
|
14278
|
+
}
|
|
14279
|
+
/** The work of a construct after the values of its parts. */
|
|
14280
|
+
function finish$1(p, c, frame) {
|
|
14281
|
+
const { values, slots } = frame;
|
|
14282
|
+
switch (frame.then) {
|
|
14283
|
+
case "list": return back(c, ok(values));
|
|
14284
|
+
case "record": {
|
|
14285
|
+
const out = {};
|
|
14286
|
+
slots.forEach((slot, index) => {
|
|
14287
|
+
if (!frame.skipped.includes(index)) setField$1(out, String(slot.path[0]), values[index]);
|
|
14288
|
+
});
|
|
14289
|
+
return back(c, ok(out));
|
|
14290
|
+
}
|
|
14291
|
+
case "op": {
|
|
14292
|
+
const name = frame.name;
|
|
14293
|
+
try {
|
|
14294
|
+
const out = opOf(p, name)(...forHost(p, c, values));
|
|
14295
|
+
return back(c, p.profile.check?.(out, name) ?? ok(out));
|
|
14296
|
+
} catch (error) {
|
|
14297
|
+
return back(c, thrown(error, `the operation ${name}`));
|
|
14298
|
+
}
|
|
14299
|
+
}
|
|
14300
|
+
case "step": {
|
|
14301
|
+
const doc = frame.doc;
|
|
14302
|
+
return back(c, ok(slots.length === 0 ? doc : {
|
|
14303
|
+
...doc,
|
|
14304
|
+
value: fillIn(doc.value, slots, values)
|
|
14305
|
+
}));
|
|
14306
|
+
}
|
|
14307
|
+
case "ref": {
|
|
14308
|
+
const doc = frame.doc;
|
|
14309
|
+
return finishRef(p, c, doc, fillIn(doc.value, slots, values), frame.site, frame.address === true);
|
|
14310
|
+
}
|
|
14311
|
+
case "args": return apply(p, c, frame.target, values);
|
|
14312
|
+
}
|
|
14313
|
+
}
|
|
14314
|
+
/** F-CALL and F-FN: an application of a function. */
|
|
14315
|
+
function apply(p, c, target, args) {
|
|
14316
|
+
const closure = closureOf(target);
|
|
14317
|
+
if (closure === void 0) try {
|
|
14318
|
+
return back(c, ok(target(...forHost(p, c, args))));
|
|
14319
|
+
} catch (error) {
|
|
14320
|
+
return back(c, thrown(error, "the function of call"));
|
|
14321
|
+
}
|
|
14322
|
+
const limit = Math.ceil(p.maxDepth / 4);
|
|
14323
|
+
if (c.applying >= limit) return back(c, fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`));
|
|
14324
|
+
pushed(c, {
|
|
14325
|
+
f: "return",
|
|
14326
|
+
place: closure.place.concat(closure.body.path)
|
|
14327
|
+
});
|
|
14328
|
+
return {
|
|
14329
|
+
...enter(c, { at: NO_KEYS$1 }, closure.site, closure.body, scopeOf(closure, args)),
|
|
14330
|
+
applying: c.applying + 1
|
|
14331
|
+
};
|
|
14332
|
+
}
|
|
14333
|
+
function scopeOf(closure, args) {
|
|
14334
|
+
const { ctx } = closure.site;
|
|
14335
|
+
const scope = {};
|
|
14336
|
+
for (const key of Object.keys(ctx.names)) setField$1(scope, key, ctx.names[key]);
|
|
14337
|
+
closure.params.forEach((name, index) => setField$1(scope, name, args[index]));
|
|
14338
|
+
return {
|
|
14339
|
+
...ctx,
|
|
14340
|
+
names: scope
|
|
14341
|
+
};
|
|
14342
|
+
}
|
|
14343
|
+
/** This function makes the host function of a closure. A host calls it, thus it runs a nested stepper. */
|
|
14344
|
+
function hostClosure(p, value, closure) {
|
|
14345
|
+
const known = p.hosts.get(value);
|
|
14346
|
+
if (known !== void 0) return known;
|
|
14347
|
+
const fn = (...args) => {
|
|
14348
|
+
const limit = Math.ceil(p.maxDepth / 4);
|
|
14349
|
+
if (p.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
|
|
14350
|
+
p.applying += 1;
|
|
14351
|
+
try {
|
|
14352
|
+
const place = closure.place.concat(closure.body.path);
|
|
14353
|
+
const end = drive$1(p, enter({
|
|
14354
|
+
mode: "resume",
|
|
14355
|
+
result: ok(null),
|
|
14356
|
+
stack: [{
|
|
14357
|
+
f: "base",
|
|
14358
|
+
place
|
|
14359
|
+
}],
|
|
14360
|
+
applying: p.applying,
|
|
14361
|
+
marked: true
|
|
14362
|
+
}, { at: NO_KEYS$1 }, closure.site, closure.body, scopeOf(closure, args)));
|
|
14363
|
+
if (!end.result.ok) throw new Failure(end.result.error);
|
|
14364
|
+
return forHost(p, end, end.result.value);
|
|
14365
|
+
} finally {
|
|
14366
|
+
p.applying -= 1;
|
|
14367
|
+
}
|
|
14368
|
+
};
|
|
14369
|
+
Object.defineProperty(fn, CLOSURE$1, { value: { params: closure.params } });
|
|
14370
|
+
p.hosts.set(value, fn);
|
|
14371
|
+
return fn;
|
|
14372
|
+
}
|
|
14373
|
+
/** This function gives a value to host code: a closure is a function, and a held error is a `Held`. */
|
|
14374
|
+
function forHost(p, c, value) {
|
|
14375
|
+
p.applying = c.applying;
|
|
14376
|
+
return c.marked ? hostValue(p, value) : value;
|
|
14377
|
+
}
|
|
14378
|
+
function hostValue(p, value) {
|
|
14379
|
+
if (Array.isArray(value)) {
|
|
14380
|
+
const items = value.map((item) => hostValue(p, item));
|
|
14381
|
+
return items.some((item, index) => item !== value[index]) ? items : value;
|
|
14382
|
+
}
|
|
14383
|
+
if (!isRecord(value)) return value;
|
|
14384
|
+
const closure = closureOf(value);
|
|
14385
|
+
if (closure !== void 0) return hostClosure(p, value, closure);
|
|
14386
|
+
const held = heldOf(value);
|
|
14387
|
+
if (held !== void 0) return new Held(held);
|
|
14388
|
+
let out;
|
|
14389
|
+
for (const key of Object.keys(value)) {
|
|
14390
|
+
const item = hostValue(p, value[key]);
|
|
14391
|
+
if (item !== value[key]) {
|
|
14392
|
+
out ??= copyOf(value);
|
|
14393
|
+
setField$1(out, key, item);
|
|
14394
|
+
}
|
|
14395
|
+
}
|
|
14396
|
+
return out ?? value;
|
|
14397
|
+
}
|
|
14398
|
+
function hostContext(p, c, ctx) {
|
|
14399
|
+
const names = forHost(p, c, ctx.names);
|
|
14400
|
+
return names === ctx.names ? ctx : {
|
|
14401
|
+
...ctx,
|
|
14402
|
+
names
|
|
14403
|
+
};
|
|
14404
|
+
}
|
|
14405
|
+
/** The judgment 3: the steps of a path, with R-NO-ROOT to C-DONE. A failure holds a code and a reason. */
|
|
14406
|
+
function walkPath(p, ctx, path) {
|
|
14407
|
+
const { machine } = p;
|
|
14408
|
+
const adopt = machine.adopt ?? ((value) => value);
|
|
14409
|
+
const failed = (code, reason) => ({
|
|
14410
|
+
ok: false,
|
|
14411
|
+
code,
|
|
14412
|
+
reason,
|
|
14413
|
+
hops: []
|
|
14414
|
+
});
|
|
14415
|
+
const open = [];
|
|
14416
|
+
let collapses = 0;
|
|
14417
|
+
const collapse = (thing) => {
|
|
14418
|
+
let here = thing;
|
|
14419
|
+
if (machine.plain === true) return {
|
|
14420
|
+
ok: true,
|
|
14421
|
+
thing: here,
|
|
14422
|
+
hops: []
|
|
14423
|
+
};
|
|
14424
|
+
while (isReference(here)) {
|
|
14425
|
+
if (open.includes(here)) return failed("#CYCLE!", "The references form a cycle.");
|
|
14426
|
+
collapses += 1;
|
|
14427
|
+
if (collapses > MAX_COLLAPSE) return failed("#CYCLE!", "The path follows more than 64 references. One resolution follows at most 64.");
|
|
14428
|
+
open.push(here);
|
|
14429
|
+
const inner = walk(here.value);
|
|
14430
|
+
open.pop();
|
|
14431
|
+
if (!inner.ok) return inner;
|
|
14432
|
+
here = adopt(inner.thing);
|
|
14433
|
+
}
|
|
14434
|
+
return {
|
|
14435
|
+
ok: true,
|
|
14436
|
+
thing: here,
|
|
14437
|
+
hops: []
|
|
14438
|
+
};
|
|
14439
|
+
};
|
|
14440
|
+
const walk = (steps) => {
|
|
14441
|
+
const root = steps[0];
|
|
14442
|
+
if (typeof root !== "string" || !ROOTS$1.includes(root)) return failed("#REF!", `A path starts with a root: ${ROOTS$1.join(", ")}.`);
|
|
14443
|
+
if (machine.roots !== void 0 && !machine.roots.includes(root)) return failed("#REF!", `The root ${root} is not open here. The open roots are ${machine.roots.join(", ")}.`);
|
|
14444
|
+
const first = collapse(adopt(ctx[root]));
|
|
14445
|
+
if (!first.ok) return first;
|
|
14446
|
+
let here = first.thing;
|
|
14447
|
+
for (let index = 1; index < steps.length; index += 1) {
|
|
14448
|
+
const step = steps[index];
|
|
14449
|
+
const rest = steps.slice(index);
|
|
14450
|
+
if (isHostThing(here) && here.resolve !== void 0 && rest.every(isKey$1)) {
|
|
14451
|
+
const reached = here.resolve(rest);
|
|
14452
|
+
if (reached === void 0) return failed("#N/A", `The path ${rest.join(".")} reaches nothing.`);
|
|
14453
|
+
return collapse(adopt(reached.thing));
|
|
14454
|
+
}
|
|
14455
|
+
const hop = isKey$1(step) ? keyStep(p, here, step) : void 0;
|
|
14456
|
+
if (isKey$1(step)) {
|
|
14457
|
+
if (hop === void 0) {
|
|
14458
|
+
if (root === "names" && index === 1) return failed("#NAME?", `The context has no name ${String(step)}.`);
|
|
14459
|
+
return failed("#N/A", `The step ${String(step)} reaches nothing.`);
|
|
14460
|
+
}
|
|
14461
|
+
here = adopt(hop.thing);
|
|
14462
|
+
} else {
|
|
14463
|
+
const walker = walkerFor(p, step);
|
|
14464
|
+
if (walker === void 0) return failed("#STEP?", "A step is a key, or a document of a kind with the verb step.");
|
|
14465
|
+
const deref = (thing, key) => {
|
|
14466
|
+
const reached = keyStep(p, thing, key);
|
|
14467
|
+
return reached === void 0 ? void 0 : adopt(reached.thing);
|
|
14468
|
+
};
|
|
14469
|
+
const has = (thing, key) => keyStep(p, thing, key) !== void 0;
|
|
14470
|
+
const result = walker({
|
|
14471
|
+
data: step.value,
|
|
14472
|
+
here,
|
|
14473
|
+
context: ctx,
|
|
14474
|
+
deref,
|
|
14475
|
+
has
|
|
14476
|
+
});
|
|
14477
|
+
if (!result.ok) return failed(result.code ?? "#N/A", result.reason);
|
|
14478
|
+
here = adopt(result.thing);
|
|
14479
|
+
}
|
|
14480
|
+
const next = collapse(here);
|
|
14481
|
+
if (!next.ok) return next;
|
|
14482
|
+
here = next.thing;
|
|
14483
|
+
}
|
|
14484
|
+
return {
|
|
14485
|
+
ok: true,
|
|
14486
|
+
thing: here,
|
|
14487
|
+
hops: []
|
|
14488
|
+
};
|
|
14489
|
+
};
|
|
14490
|
+
return path.length === 0 ? failed("#REF!", "A path has at least one step: its root.") : walk(path);
|
|
14491
|
+
}
|
|
14492
|
+
function isReference(thing) {
|
|
14493
|
+
if (!isEnvelope(thing) || !Array.isArray(thing.value)) return false;
|
|
14494
|
+
const keys = keysOf(thing.type);
|
|
14495
|
+
return keys !== void 0 && keys.length === 1 && keys[0] === "ref";
|
|
14496
|
+
}
|
|
14497
|
+
/** R-WALKER: the code of a step document. */
|
|
14498
|
+
function walkerFor(p, step) {
|
|
14499
|
+
const { walkers, world } = p.machine;
|
|
14500
|
+
if (walkers === void 0 || !isEnvelope(step)) return void 0;
|
|
14501
|
+
const found = lookup(world, step.type);
|
|
14502
|
+
const name = ladder(world, field(step, "own"), found?.kind, found !== void 0, "step", (item) => own$1(walkers, item) !== void 0);
|
|
14503
|
+
return typeof name === "string" ? own$1(walkers, name) : void 0;
|
|
14504
|
+
}
|
|
14505
|
+
/** FIELD: the rule of a step in a value. */
|
|
14506
|
+
function fieldOf(value, key) {
|
|
14507
|
+
if (Array.isArray(value)) {
|
|
14508
|
+
if (key === "length") return { thing: value.length };
|
|
14509
|
+
const index = typeof key === "number" ? key : /^\d+$/.test(key) ? Number(key) : -1;
|
|
14510
|
+
return index >= 0 && index < value.length ? { thing: value[index] } : void 0;
|
|
14511
|
+
}
|
|
14512
|
+
if (typeof value !== "object" || value === null || !Object.hasOwn(value, String(key))) return void 0;
|
|
14513
|
+
return { thing: value[String(key)] };
|
|
14514
|
+
}
|
|
14515
|
+
/** The rules S-HOST to S-FIELD: a step with a key. The result is `undefined` for `miss`. */
|
|
14516
|
+
function keyStep(p, thing, key) {
|
|
14517
|
+
const { machine } = p;
|
|
14518
|
+
if (isHostThing(thing)) {
|
|
14519
|
+
const reached = thing.deref(key);
|
|
14520
|
+
return reached !== void 0 || thing.has?.(key) === true ? { thing: reached } : void 0;
|
|
14521
|
+
}
|
|
14522
|
+
if (machine.plain === true || !isEnvelope(thing)) return fieldOf(thing, key);
|
|
14523
|
+
const { derefs, world } = machine;
|
|
14524
|
+
const found = lookup(world, thing.type);
|
|
14525
|
+
const name = derefs === void 0 ? void 0 : ladder(world, field(thing, "own"), found?.kind, found !== void 0, "deref", (item) => own$1(derefs, item) !== void 0);
|
|
14526
|
+
const code = typeof name === "string" ? own$1(derefs, name) : void 0;
|
|
14527
|
+
if (code === void 0) return fieldOf(thing.value, key);
|
|
14528
|
+
const reached = code(thing, key);
|
|
14529
|
+
return reached !== void 0 || code.has?.(thing, key) === true ? { thing: reached } : void 0;
|
|
14530
|
+
}
|
|
14531
|
+
/** A construct of the formula kit, with its compiled evaluator in the machine. */
|
|
14532
|
+
const CONSTRUCTS$2 = {
|
|
14533
|
+
"formula.lit": true,
|
|
14534
|
+
"formula.ref": true,
|
|
14535
|
+
"formula.step": true,
|
|
14536
|
+
"formula.record": true,
|
|
14537
|
+
"formula.list": true,
|
|
14538
|
+
"formula.let": true,
|
|
14539
|
+
"formula.fn": true,
|
|
14540
|
+
"formula.call": true,
|
|
14541
|
+
"formula.if": true,
|
|
14542
|
+
"formula.and": true,
|
|
14543
|
+
"formula.or": true,
|
|
14544
|
+
"formula.op": true,
|
|
14545
|
+
"formula.ext": true
|
|
14546
|
+
};
|
|
14547
|
+
/** The rules F-LIT to F-EXT: the start of a construct. */
|
|
14548
|
+
function construct(p, c, name, doc, keys, slots, site) {
|
|
14549
|
+
const { profile, machine } = p;
|
|
14550
|
+
switch (name) {
|
|
14551
|
+
case "formula.lit": return back(c, ok(doc.value));
|
|
14552
|
+
case "formula.ref": {
|
|
14553
|
+
const path = doc.value;
|
|
14554
|
+
if (!Array.isArray(path) || path.length === 0) return back(c, fail("#VALUE!", "The value of ref is a path: a list that starts with a root, for example [\"names\", \"a\"]."));
|
|
14555
|
+
if (slots.length === 0) return finishRef(p, c, doc, path, site, c.address);
|
|
14556
|
+
return startValues(p, c, site, "ref", slots, true, {
|
|
14557
|
+
doc,
|
|
14558
|
+
address: c.address
|
|
14559
|
+
});
|
|
14560
|
+
}
|
|
14561
|
+
case "formula.step": return startValues(p, c, site, "step", slots, true, { doc });
|
|
14562
|
+
case "formula.record": return startValues(p, c, site, "record", slots, false);
|
|
14563
|
+
case "formula.list": return startValues(p, c, site, "list", slots, false);
|
|
14564
|
+
case "formula.let": {
|
|
14565
|
+
const bindings = partsUnder(slots, "bind");
|
|
14566
|
+
const body = partNamed(slots, "body");
|
|
14567
|
+
const names = {};
|
|
14568
|
+
for (const key of Object.keys(site.ctx.names)) setField$1(names, key, site.ctx.names[key]);
|
|
14569
|
+
const first = bindings[0];
|
|
14570
|
+
if (first === void 0) {
|
|
14571
|
+
const tail = {
|
|
14572
|
+
f: "tail",
|
|
14573
|
+
at: NO_KEYS$1
|
|
14574
|
+
};
|
|
14575
|
+
pushed(c, tail);
|
|
14576
|
+
return enter(c, tail, site, body, {
|
|
14577
|
+
...site.ctx,
|
|
14578
|
+
names
|
|
14579
|
+
});
|
|
14580
|
+
}
|
|
14581
|
+
const frame = {
|
|
14582
|
+
f: "let",
|
|
14583
|
+
at: NO_KEYS$1,
|
|
14584
|
+
site,
|
|
14585
|
+
slots: bindings,
|
|
14586
|
+
body,
|
|
14587
|
+
next: 1,
|
|
14588
|
+
names
|
|
14589
|
+
};
|
|
14590
|
+
pushed(c, frame);
|
|
14591
|
+
return enter(c, frame, site, first);
|
|
14592
|
+
}
|
|
14593
|
+
case "formula.fn": {
|
|
14594
|
+
const params = isRecord(doc.value) ? doc.value["params"] : void 0;
|
|
14595
|
+
if (!Array.isArray(params) || !params.every((item) => typeof item === "string") || new Set(params).size !== params.length) return back(c, fail("#VALUE!", "The params of fn are a list of different texts."));
|
|
14596
|
+
const closure = {
|
|
14597
|
+
params,
|
|
14598
|
+
body: partNamed(slots, "body"),
|
|
14599
|
+
site,
|
|
14600
|
+
place: placeOf$1(c.stack)
|
|
14601
|
+
};
|
|
14602
|
+
return back({
|
|
14603
|
+
...c,
|
|
14604
|
+
marked: true
|
|
14605
|
+
}, ok({ [CLOSURE_MARK]: closure }));
|
|
14606
|
+
}
|
|
14607
|
+
case "formula.call": {
|
|
14608
|
+
const frame = {
|
|
14609
|
+
f: "call",
|
|
14610
|
+
at: NO_KEYS$1,
|
|
14611
|
+
site,
|
|
14612
|
+
args: partsUnder(slots, "args")
|
|
14613
|
+
};
|
|
14614
|
+
pushed(c, frame);
|
|
14615
|
+
return enter(c, frame, site, partNamed(slots, "fn"));
|
|
14616
|
+
}
|
|
14617
|
+
case "formula.if": {
|
|
14618
|
+
const no = partNamed(slots, "else");
|
|
14619
|
+
const frame = {
|
|
14620
|
+
f: "if",
|
|
14621
|
+
at: NO_KEYS$1,
|
|
14622
|
+
site,
|
|
14623
|
+
yes: partNamed(slots, "then"),
|
|
14624
|
+
...no === void 0 ? {} : { no }
|
|
14625
|
+
};
|
|
14626
|
+
pushed(c, frame);
|
|
14627
|
+
return enter(c, frame, site, partNamed(slots, "test"));
|
|
14628
|
+
}
|
|
14629
|
+
case "formula.and":
|
|
14630
|
+
case "formula.or": {
|
|
14631
|
+
const stop = name === "formula.or";
|
|
14632
|
+
const first = slots[0];
|
|
14633
|
+
if (first === void 0) return back(c, ok(!stop));
|
|
14634
|
+
const frame = {
|
|
14635
|
+
f: "logic",
|
|
14636
|
+
at: NO_KEYS$1,
|
|
14637
|
+
site,
|
|
14638
|
+
stop,
|
|
14639
|
+
what: stop ? "term of or" : "term of and",
|
|
14640
|
+
slots,
|
|
14641
|
+
next: 1
|
|
14642
|
+
};
|
|
14643
|
+
pushed(c, frame);
|
|
14644
|
+
return enter(c, frame, site, first);
|
|
14645
|
+
}
|
|
14646
|
+
case "formula.op": {
|
|
14647
|
+
const op = keys.slice(1).join(".");
|
|
14648
|
+
const lazy = own$1(profile.lazy, op);
|
|
14649
|
+
if (lazy !== void 0) {
|
|
14650
|
+
p.applying = c.applying;
|
|
14651
|
+
try {
|
|
14652
|
+
return back(c, lazy(slots.map((slot) => () => nested(p, c, site, slot))));
|
|
14653
|
+
} catch (error) {
|
|
14654
|
+
return back(c, thrown(error, `the operation ${op}`));
|
|
14655
|
+
}
|
|
14656
|
+
}
|
|
14657
|
+
if (opOf(p, op) === void 0) return back(c, fail("#NAME?", `The language has no operation ${op}.`));
|
|
14658
|
+
return startValues(p, c, site, "op", slots, false, { name: op });
|
|
14659
|
+
}
|
|
14660
|
+
default: {
|
|
14661
|
+
const ext = keys.slice(1).join(".");
|
|
14662
|
+
const handler = own$1(profile.ext, ext) ?? own$1(STD_EXT, ext);
|
|
14663
|
+
if (handler === void 0) return back(c, fail("#NAME?", `The language has no extension ${ext}.`));
|
|
14664
|
+
try {
|
|
14665
|
+
return back(c, handler(doc.value, hostContext(p, c, site.ctx), machine.domains));
|
|
14666
|
+
} catch (error) {
|
|
14667
|
+
return back(c, thrown(error, `the extension ${ext}`));
|
|
14668
|
+
}
|
|
14669
|
+
}
|
|
14670
|
+
}
|
|
14671
|
+
}
|
|
14672
|
+
/** H-SEAL for host code: a handle starts a nested stepper, on the stack of the host. */
|
|
14673
|
+
function nested(p, c, site, slot, given) {
|
|
14674
|
+
const stack = [{
|
|
14675
|
+
f: "base",
|
|
14676
|
+
place: placeOf$1(c.stack).concat(slot.path)
|
|
14677
|
+
}];
|
|
14678
|
+
const end = drive$1(p, enter({
|
|
14679
|
+
mode: "resume",
|
|
14680
|
+
result: ok(null),
|
|
14681
|
+
stack,
|
|
14682
|
+
applying: p.applying,
|
|
14683
|
+
marked: c.marked
|
|
14684
|
+
}, { at: NO_KEYS$1 }, site, slot, given));
|
|
14685
|
+
return end.result.ok ? ok(forHost(p, end, end.result.value)) : end.result;
|
|
14686
|
+
}
|
|
14687
|
+
/** RUN.EVAL: an effect of a host evaluator, with RUN.CAP, RUN.ADDRESS and RUN.MOCK. */
|
|
14688
|
+
function cause(p, ctx, kind, payload, place) {
|
|
14689
|
+
const keys = typeof kind === "string" ? kind.split(".") : kind;
|
|
14690
|
+
const text = keys.join(".");
|
|
14691
|
+
const { machine, perform, counts, effects } = p;
|
|
14692
|
+
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 });
|
|
14693
|
+
const at = placeText(place);
|
|
14694
|
+
const count = counts.get(at) ?? 0;
|
|
14695
|
+
counts.set(at, count + 1);
|
|
14696
|
+
const effect = {
|
|
14697
|
+
index: effects.length,
|
|
14698
|
+
kind: text,
|
|
14699
|
+
path: keys,
|
|
14700
|
+
payload,
|
|
14701
|
+
node: -1,
|
|
14702
|
+
at: 0,
|
|
14703
|
+
place,
|
|
14704
|
+
context: ctx,
|
|
14705
|
+
address: `${at}#${count}`
|
|
14706
|
+
};
|
|
14707
|
+
effects.push(effect);
|
|
14708
|
+
effect.outcome = answer(perform, effect, place);
|
|
14709
|
+
return effect.outcome;
|
|
14710
|
+
}
|
|
14711
|
+
function answer(perform, effect, place) {
|
|
14712
|
+
if (perform === void 0) return ok(effect.payload);
|
|
14713
|
+
let given;
|
|
14714
|
+
try {
|
|
14715
|
+
given = perform(effect);
|
|
14716
|
+
} catch (error) {
|
|
14717
|
+
if (error instanceof Failure) return placed({
|
|
14718
|
+
ok: false,
|
|
14719
|
+
error: error.error
|
|
14720
|
+
}, place);
|
|
14721
|
+
return fail("#CALC!", `The host failed the effect ${effect.kind}: ${describe(error)}`, {
|
|
14722
|
+
place,
|
|
14723
|
+
cause: error
|
|
14724
|
+
});
|
|
14725
|
+
}
|
|
14726
|
+
if (!(given instanceof Promise)) return ok(given);
|
|
14727
|
+
given.catch(() => void 0);
|
|
14728
|
+
return fail("#CALC!", `The mock gave a promise for the effect ${effect.kind}, and an evaluation does not wait.`, { place });
|
|
14729
|
+
}
|
|
14730
|
+
/** E-APPLY for host code: one step of the stepper starts the evaluator. */
|
|
14731
|
+
function hostEvaluator(p, c, name, evaluator, doc, keys, data, slots, site) {
|
|
14732
|
+
const place = placeOf$1(c.stack);
|
|
14733
|
+
const parts = slots.map((slot) => {
|
|
14734
|
+
const header = isEnvelope(slot.item) ? field(slot.item, "name") : void 0;
|
|
14735
|
+
return {
|
|
14736
|
+
key: slot.key,
|
|
14737
|
+
path: slot.path,
|
|
14738
|
+
...typeof header === "string" ? { name: header } : {},
|
|
14739
|
+
evaluate: (given) => nested(p, c, site, slot, given)
|
|
14740
|
+
};
|
|
14741
|
+
});
|
|
14742
|
+
const fill = (items) => fillIn(doc.value, slots, items);
|
|
14743
|
+
p.applying = c.applying;
|
|
14744
|
+
const input = {
|
|
14745
|
+
kind: typeName(doc.type),
|
|
14746
|
+
typePath: keys,
|
|
14747
|
+
doc,
|
|
14748
|
+
value: fill(parts),
|
|
14749
|
+
data,
|
|
14750
|
+
parts,
|
|
14751
|
+
context: hostContext(p, c, site.ctx),
|
|
14752
|
+
place,
|
|
14753
|
+
machine: p.machine,
|
|
14754
|
+
...c.address ? { address: true } : {},
|
|
14755
|
+
resolve: (path, _options) => walkPath(p, site.ctx, path),
|
|
14756
|
+
effect: (kind, payload) => cause(p, site.ctx, kind, payload, place),
|
|
14757
|
+
fill
|
|
14758
|
+
};
|
|
14759
|
+
try {
|
|
14760
|
+
return back(c, evaluator(input));
|
|
14761
|
+
} catch (error) {
|
|
14762
|
+
return back(c, thrown(error, `the evaluator ${name}`));
|
|
14763
|
+
}
|
|
14764
|
+
}
|
|
14765
|
+
/** The judgment 4: the rules E-PART to E-APPLY for one document, in their order. */
|
|
14766
|
+
function evaluateDoc(p, c) {
|
|
14767
|
+
const { value, declared, depth } = c;
|
|
14768
|
+
const { machine, verb } = p;
|
|
14769
|
+
const { world } = machine;
|
|
14770
|
+
const envelope = isEnvelope(value) ? value : void 0;
|
|
14771
|
+
if (envelope === void 0 && declared === void 0) return back(c, fail("#PART?", "The value has no envelope, and its position declares no type."));
|
|
14772
|
+
const doc = envelope ?? {
|
|
14773
|
+
type: declared,
|
|
14774
|
+
value
|
|
14775
|
+
};
|
|
14776
|
+
const found = lookup(world, doc.type);
|
|
14777
|
+
if (depth > p.maxDepth) return back(c, fail("#DEPTH!", `The nesting is deeper than ${p.maxDepth} documents.`));
|
|
14778
|
+
const kindText = typeName(doc.type);
|
|
14779
|
+
const name = ladder(world, envelope === void 0 ? void 0 : field(envelope, "own"), found?.kind, found !== void 0, verb, () => true);
|
|
14780
|
+
if (name === null) return back(c, fail("#KIND?", `The world has no kind ${kindText}.`));
|
|
14781
|
+
const code = typeof name === "string" ? own$1(machine.runners, name) ?? own$1(machine.evaluators, name) : void 0;
|
|
14782
|
+
if (name === void 0 || code === void 0) return back(c, fail("#NOEVAL", `No rung gives an evaluator for ${kindText}.`));
|
|
14783
|
+
const read = split(found?.kind.parts, doc.value);
|
|
14784
|
+
if (read instanceof Bad) {
|
|
14785
|
+
const where = read.at.length === 0 ? "" : ` (at ${read.at.join(".")})`;
|
|
14786
|
+
return back(c, fail("#VALUE!", `${read.reason}${where} The kind is ${kindText}.`));
|
|
14787
|
+
}
|
|
14788
|
+
if (own$1(machine.runners, name) !== void 0) return back(c, fail("#NOEVAL", `The stepper has no runner ${name}.`));
|
|
14789
|
+
const rules = found?.kind.caps;
|
|
14790
|
+
const site = {
|
|
14791
|
+
name,
|
|
14792
|
+
depth,
|
|
14793
|
+
ctx: c.ctx,
|
|
14794
|
+
...rules === void 0 ? {} : { rules }
|
|
14795
|
+
};
|
|
14796
|
+
const keys = found?.path ?? [];
|
|
14797
|
+
if (typeof code === "function") return hostEvaluator(p, c, name, code, doc, keys, read.data, read.slots, site);
|
|
14798
|
+
if (own$1(CONSTRUCTS$2, name) === true) try {
|
|
14799
|
+
return construct(p, c, name, doc, keys, read.slots, site);
|
|
14800
|
+
} catch (error) {
|
|
14801
|
+
return back(c, thrown(error, `the evaluator ${name}`));
|
|
14802
|
+
}
|
|
14803
|
+
const defined = own$1(p.definitions.evaluators, name);
|
|
14804
|
+
if (defined !== void 0) return hostEvaluator(p, c, name, defined, doc, keys, read.data, read.slots, site);
|
|
14805
|
+
return back(c, fail("#NOEVAL", `The stepper has no definition of the compiled evaluator ${name}.`));
|
|
14806
|
+
}
|
|
14807
|
+
/** The next part of a frame with a list of parts. */
|
|
14808
|
+
function nextOf(frame) {
|
|
14809
|
+
const slot = frame.slots[frame.next];
|
|
14810
|
+
if (slot !== void 0) frame.next += 1;
|
|
14811
|
+
return slot;
|
|
14812
|
+
}
|
|
14813
|
+
function resumeValues(p, c, frame) {
|
|
14814
|
+
const { result } = c;
|
|
14815
|
+
const { combine, omit } = p.profile;
|
|
14816
|
+
if (result.ok) frame.values.push(result.value);
|
|
14817
|
+
else if (frame.then === "record" && omit?.(result.error) === true) {
|
|
14818
|
+
frame.skipped.push(frame.values.length);
|
|
14819
|
+
frame.values.push(null);
|
|
14820
|
+
} else if (frame.strict || combine === void 0) {
|
|
14821
|
+
popped(c);
|
|
14822
|
+
return c;
|
|
14823
|
+
} else frame.errors.push(result.error);
|
|
14824
|
+
const slot = nextOf(frame);
|
|
14825
|
+
if (slot !== void 0) return enter(c, frame, frame.site, slot);
|
|
14826
|
+
popped(c);
|
|
14827
|
+
const first = frame.errors[0];
|
|
14828
|
+
if (first === void 0) return finish$1(p, c, frame);
|
|
14829
|
+
return back(c, {
|
|
14830
|
+
ok: false,
|
|
14831
|
+
error: frame.errors.length === 1 ? first : combine(frame.errors)
|
|
14832
|
+
});
|
|
14833
|
+
}
|
|
14834
|
+
/** The rule `resume(k, r)`: the top frame takes a result. An exception of a rule of the profile ends its document. */
|
|
14835
|
+
function resume(p, c) {
|
|
14836
|
+
const stack = c.stack;
|
|
14837
|
+
const frame = stack[stack.length - 1];
|
|
14838
|
+
if (frame === void 0) return {
|
|
14839
|
+
mode: "done",
|
|
14840
|
+
result: c.result,
|
|
14841
|
+
stack,
|
|
14842
|
+
applying: c.applying,
|
|
14843
|
+
marked: c.marked
|
|
14844
|
+
};
|
|
14845
|
+
try {
|
|
14846
|
+
return take(p, c, frame);
|
|
14847
|
+
} catch (error) {
|
|
14848
|
+
if (stack[stack.length - 1] === frame) popped(c);
|
|
14849
|
+
return back(c, thrown(error, `the evaluator ${"site" in frame ? frame.site.name : "of the part"}`));
|
|
14850
|
+
}
|
|
14851
|
+
}
|
|
14852
|
+
function take(p, c, frame) {
|
|
14853
|
+
const stack = c.stack;
|
|
14854
|
+
const { result } = c;
|
|
14855
|
+
switch (frame.f) {
|
|
14856
|
+
case "base":
|
|
14857
|
+
popped(c);
|
|
14858
|
+
return {
|
|
14859
|
+
mode: "done",
|
|
14860
|
+
result,
|
|
14861
|
+
stack,
|
|
14862
|
+
applying: c.applying,
|
|
14863
|
+
marked: c.marked
|
|
14864
|
+
};
|
|
14865
|
+
case "tail":
|
|
14866
|
+
popped(c);
|
|
14867
|
+
return c;
|
|
14868
|
+
case "return":
|
|
14869
|
+
popped(c);
|
|
14870
|
+
return {
|
|
14871
|
+
...c,
|
|
14872
|
+
applying: c.applying - 1
|
|
14873
|
+
};
|
|
14874
|
+
case "values": return resumeValues(p, c, frame);
|
|
14875
|
+
case "let": {
|
|
14876
|
+
const key = String(frame.slots[frame.next - 1].path[1]);
|
|
14877
|
+
setField$1(frame.names, key, result.ok ? result.value : { [HELD_MARK]: result.error });
|
|
14878
|
+
const marked = c.marked || !result.ok;
|
|
14879
|
+
const slot = nextOf(frame);
|
|
14880
|
+
if (slot !== void 0) return enter(c, frame, frame.site, slot, void 0, marked);
|
|
14881
|
+
const tail = {
|
|
14882
|
+
f: "tail",
|
|
14883
|
+
at: NO_KEYS$1
|
|
14884
|
+
};
|
|
14885
|
+
stack[stack.length - 1] = tail;
|
|
14886
|
+
return enter(c, tail, frame.site, frame.body, {
|
|
14887
|
+
...frame.site.ctx,
|
|
14888
|
+
names: frame.names
|
|
14889
|
+
}, marked);
|
|
14890
|
+
}
|
|
14891
|
+
case "call":
|
|
14892
|
+
popped(c);
|
|
14893
|
+
if (!result.ok) return c;
|
|
14894
|
+
if (closureOf(result.value) === void 0 && typeof result.value !== "function") return back(c, fail("#VALUE!", "The fn of call must give a function."));
|
|
14895
|
+
return startValues(p, c, frame.site, "args", frame.args, true, { target: result.value });
|
|
14896
|
+
case "if": {
|
|
14897
|
+
if (!result.ok) {
|
|
14898
|
+
popped(c);
|
|
14899
|
+
return c;
|
|
14900
|
+
}
|
|
14901
|
+
const truth = truthOf(p, c, result.value);
|
|
14902
|
+
if (truth === void 0) {
|
|
14903
|
+
popped(c);
|
|
14904
|
+
return back(c, fail("#VALUE!", "The test of if must give a truth value."));
|
|
14905
|
+
}
|
|
14906
|
+
const branch = truth ? frame.yes : frame.no;
|
|
14907
|
+
if (branch === void 0) {
|
|
14908
|
+
popped(c);
|
|
14909
|
+
return back(c, ok(Object.hasOwn(p.profile, "otherwise") ? p.profile.otherwise : null));
|
|
14910
|
+
}
|
|
14911
|
+
const tail = {
|
|
14912
|
+
f: "tail",
|
|
14913
|
+
at: NO_KEYS$1
|
|
14914
|
+
};
|
|
14915
|
+
stack[stack.length - 1] = tail;
|
|
14916
|
+
return enter(c, tail, frame.site, branch);
|
|
14917
|
+
}
|
|
14918
|
+
case "logic": {
|
|
14919
|
+
if (!result.ok) {
|
|
14920
|
+
popped(c);
|
|
14921
|
+
return c;
|
|
14922
|
+
}
|
|
14923
|
+
const truth = truthOf(p, c, result.value);
|
|
14924
|
+
const value = p.profile.logic === "value";
|
|
14925
|
+
if (truth === void 0) {
|
|
14926
|
+
popped(c);
|
|
14927
|
+
return back(c, fail("#VALUE!", `The ${frame.what} must give a truth value.`));
|
|
14928
|
+
}
|
|
14929
|
+
if (truth === frame.stop) {
|
|
14930
|
+
popped(c);
|
|
14931
|
+
return back(c, value ? result : ok(frame.stop));
|
|
14932
|
+
}
|
|
14933
|
+
const slot = nextOf(frame);
|
|
14934
|
+
if (slot !== void 0) return enter(c, frame, frame.site, slot);
|
|
14935
|
+
popped(c);
|
|
14936
|
+
return back(c, value ? result : ok(!frame.stop));
|
|
14937
|
+
}
|
|
14938
|
+
}
|
|
14939
|
+
}
|
|
14940
|
+
function advance(p, c) {
|
|
14941
|
+
if (c.mode === "evaluate") return evaluateDoc(p, c);
|
|
14942
|
+
return c.mode === "resume" ? resume(p, c) : c;
|
|
14943
|
+
}
|
|
14944
|
+
function drive$1(p, start) {
|
|
14945
|
+
let now = start;
|
|
14946
|
+
while (now.mode !== "done") now = advance(p, now);
|
|
14947
|
+
return now;
|
|
14948
|
+
}
|
|
14949
|
+
function programOf(machine, options) {
|
|
14950
|
+
return {
|
|
14951
|
+
machine,
|
|
14952
|
+
profile: options.profile ?? {},
|
|
14953
|
+
definitions: options.definitions ?? {},
|
|
14954
|
+
verb: options.verb ?? "eval",
|
|
14955
|
+
maxDepth: machine.maxDepth ?? 1e3,
|
|
14956
|
+
hosts: /* @__PURE__ */ new WeakMap(),
|
|
14957
|
+
effects: options.effects ?? [],
|
|
14958
|
+
perform: options.perform,
|
|
14959
|
+
counts: /* @__PURE__ */ new Map(),
|
|
14960
|
+
applying: 0
|
|
14961
|
+
};
|
|
14962
|
+
}
|
|
14963
|
+
/**
|
|
14964
|
+
* This function gives the first configuration of a document: `evaluate(d, Γ, [], [])`.
|
|
14965
|
+
*
|
|
14966
|
+
* @param machine - The world, the evaluators and the other code.
|
|
14967
|
+
* @param doc - The document.
|
|
14968
|
+
* @param context - The names and the capabilities at the root. A context without a world gets the world of the machine.
|
|
14969
|
+
* @param options - The type of a bare root value.
|
|
14970
|
+
* @returns The configuration.
|
|
14971
|
+
*/
|
|
14972
|
+
function stepperStart(machine, doc, context = makeContext(), options = {}) {
|
|
14973
|
+
const ctx = context.world === null ? {
|
|
14974
|
+
...context,
|
|
14975
|
+
world: worldThing(machine.world)
|
|
14976
|
+
} : context;
|
|
14977
|
+
return {
|
|
14978
|
+
mode: "evaluate",
|
|
14979
|
+
value: doc,
|
|
14980
|
+
declared: options.declaredType,
|
|
14981
|
+
depth: 0,
|
|
14982
|
+
address: false,
|
|
14983
|
+
ctx,
|
|
14984
|
+
stack: [],
|
|
14985
|
+
applying: 0,
|
|
14986
|
+
marked: false
|
|
14987
|
+
};
|
|
14988
|
+
}
|
|
14989
|
+
/**
|
|
14990
|
+
* This function does one step. It is pure: the configuration stays as it is, and a host can keep it, store it as JSON and
|
|
14991
|
+
* step it again (STEPPER.DATA). The result of `done` holds a closure as data. The function `stepper` gives a host
|
|
14992
|
+
* function.
|
|
14993
|
+
*
|
|
14994
|
+
* @param machine - The machine of the configuration.
|
|
14995
|
+
* @param configuration - The configuration.
|
|
14996
|
+
* @param options - The profile and the verb of the configuration.
|
|
14997
|
+
* @returns The next configuration, or the same configuration at `done`.
|
|
14998
|
+
*/
|
|
14999
|
+
function stepperNext(machine, configuration, options = {}) {
|
|
15000
|
+
const stack = [...configuration.stack];
|
|
15001
|
+
const top = stack[stack.length - 1];
|
|
15002
|
+
if (top !== void 0) {
|
|
15003
|
+
const { f } = top;
|
|
15004
|
+
if (f === "values") stack[stack.length - 1] = {
|
|
15005
|
+
...top,
|
|
15006
|
+
values: [...top.values],
|
|
15007
|
+
errors: [...top.errors],
|
|
15008
|
+
skipped: [...top.skipped]
|
|
15009
|
+
};
|
|
15010
|
+
else if (f === "let") stack[stack.length - 1] = {
|
|
15011
|
+
...top,
|
|
15012
|
+
names: { ...top.names }
|
|
15013
|
+
};
|
|
15014
|
+
else stack[stack.length - 1] = { ...top };
|
|
15015
|
+
}
|
|
15016
|
+
return advance(programOf(machine, options), {
|
|
15017
|
+
...configuration,
|
|
15018
|
+
stack
|
|
15019
|
+
});
|
|
15020
|
+
}
|
|
15021
|
+
/**
|
|
15022
|
+
* This function evaluates a document with an explicit stack (K95, D158). It gives the result of `reference` for each
|
|
15023
|
+
* document of the kernel and the formula kit (AGREE.STEPPER). The nesting of a document does not use the stack of the
|
|
15024
|
+
* host (STEPPER.DEEP). A host evaluator is opaque: one step starts it, and each of its handles starts a nested
|
|
15025
|
+
* stepper. The stepper does no effects and no runs.
|
|
15026
|
+
*
|
|
15027
|
+
* @param machine - The world, the evaluators and the other code.
|
|
15028
|
+
* @param doc - The document.
|
|
15029
|
+
* @param context - The names and the capabilities at the root.
|
|
15030
|
+
* @param options - The profile of the formula kit, the verb and the type of a bare root value.
|
|
15031
|
+
* @returns The result.
|
|
15032
|
+
*/
|
|
15033
|
+
function stepper(machine, doc, context = makeContext(), options = {}) {
|
|
15034
|
+
const p = programOf(machine, options);
|
|
15035
|
+
try {
|
|
15036
|
+
const end = drive$1(p, stepperStart(machine, doc, context, options));
|
|
15037
|
+
return end.result.ok ? ok(forHost(p, end, end.result.value)) : end.result;
|
|
15038
|
+
} catch (error) {
|
|
15039
|
+
return placed(thrown(error, "the stepper"), []);
|
|
15040
|
+
}
|
|
15041
|
+
}
|
|
13776
15042
|
// src/replay.ts
|
|
13777
15043
|
/**
|
|
13778
15044
|
* This function makes a recorder (RUN.RECORD). The recorder gives each effect to the function `perform` of the host.
|
|
@@ -15002,6 +16268,13 @@ function agree(machine, doc, context = makeContext(), options = {}) {
|
|
|
15002
16268
|
effects: otherEffects,
|
|
15003
16269
|
...options.definitions === void 0 ? {} : { definitions: options.definitions }
|
|
15004
16270
|
});
|
|
16271
|
+
else if (tier === "stepper") other = stepper(machine, doc, context, {
|
|
16272
|
+
...declared,
|
|
16273
|
+
...mock,
|
|
16274
|
+
effects: otherEffects,
|
|
16275
|
+
...options.profile === void 0 ? {} : { profile: options.profile },
|
|
16276
|
+
...options.definitions === void 0 ? {} : { definitions: options.definitions }
|
|
16277
|
+
});
|
|
15005
16278
|
else if (tier === "traced") {
|
|
15006
16279
|
const traced = evaluate(machine, doc, context, {
|
|
15007
16280
|
...declared,
|
|
@@ -15239,7 +16512,7 @@ async function agreeRun(machine, doc, context = makeContext(), options = {}) {
|
|
|
15239
16512
|
let compared;
|
|
15240
16513
|
const replay = replayer(log);
|
|
15241
16514
|
for (const tier of options.tiers ?? DEFAULT_TIERS) {
|
|
15242
|
-
if (tier === "fixed") continue;
|
|
16515
|
+
if (tier === "fixed" || tier === "stepper") continue;
|
|
15243
16516
|
const tierReplay = watched(replay);
|
|
15244
16517
|
const host = { perform: tierReplay.perform };
|
|
15245
16518
|
let other;
|
|
@@ -21166,6 +22439,6 @@ function samplesAt(values, closed, depth) {
|
|
|
21166
22439
|
function typeFromSamples(values, options = {}) {
|
|
21167
22440
|
return samplesAt(values, options.closed === true, 0);
|
|
21168
22441
|
}
|
|
21169
|
-
export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, GENERATION_LIMIT, Held, JOURNAL, MAX_SYNTAX_ISSUES, MergeError, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_DEFINITIONS, STD_DOMAINS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_SYNTAX, STD_WALKERS, STD_WORLD, THING, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, agreeTypes, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, boundariesOf, capKeys, check, checkCycles, checkLatent, checkStep, checkSteps, checkSyntax, checkWorld, circularOf, classify, codecLaws, collectOf, compilePath, components, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, derefStep, describe, docEquals, documentKey, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeLog, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, ifRunner, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapDocs, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partGrants, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, resolveCompiled, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stepLadder, stepOf, stepRank, stored, syntaxFormat, tag, thrown, toJson, treeNodeEvaluator, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
|
|
22442
|
+
export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, GENERATION_LIMIT, Held, JOURNAL, MAX_SYNTAX_ISSUES, MergeError, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_DEFINITIONS, STD_DOMAINS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_SYNTAX, STD_WALKERS, STD_WORLD, THING, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, agreeTypes, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, boundariesOf, capKeys, check, checkCycles, checkLatent, checkStep, checkSteps, checkSyntax, checkWorld, circularOf, classify, codecLaws, collectOf, compilePath, components, compose, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, defineLanguage, derefStep, describe, docEquals, documentKey, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeLog, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, ifRunner, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapDocs, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partGrants, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, resolveCompiled, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stepLadder, stepOf, stepRank, stepper, stepperNext, stepperStart, stored, syntaxFormat, tag, thrown, toJson, treeNodeEvaluator, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
|
|
21170
22443
|
|
|
21171
22444
|
//# sourceMappingURL=index.js.map
|