@mark1russell7/coeval 0.10.0 → 0.11.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 +1 -1
- package/build/index.d.ts +14 -11
- package/build/index.d.ts.map +1 -1
- package/build/index.js +25 -5
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/evaluate.ts +35 -12
- package/src/formula.ts +4 -3
- package/src/generate.ts +7 -2
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/coeval",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"description": "coeval: the kernel of declarative languages. Documents in envelopes, a ladder that finds the evaluator, kind contracts, compiled plans, a static kit, a formula kit and a run side with capabilities.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./build/index.js",
|
package/src/evaluate.ts
CHANGED
|
@@ -785,17 +785,13 @@ export interface StopSignal {
|
|
|
785
785
|
addEventListener(type: "abort", listener: () => void, options?: { readonly once?: boolean }): void;
|
|
786
786
|
}
|
|
787
787
|
|
|
788
|
-
/**
|
|
789
|
-
|
|
788
|
+
/**
|
|
789
|
+
* The options of `plan.run`. A plan keeps the verb and the declared type of its `prepare`, thus these options do not
|
|
790
|
+
* have them (PLAN.RUN-OPTIONS).
|
|
791
|
+
*/
|
|
792
|
+
export interface PlanRunOptions {
|
|
790
793
|
/** The host code that does each effect. Without it, an effect gives its payload, as in an evaluation. */
|
|
791
794
|
readonly perform?: Perform;
|
|
792
|
-
/** The type of a bare root value. */
|
|
793
|
-
readonly declaredType?: string;
|
|
794
|
-
/**
|
|
795
|
-
* The verb of `run`, for example `format`. The default is `eval` (VERB.PREPARE). A plan keeps the verb of its
|
|
796
|
-
* `prepare`, thus `plan.run` does not read this option.
|
|
797
|
-
*/
|
|
798
|
-
readonly verb?: string;
|
|
799
795
|
/** A signal of the host. When it aborts, the run stops with `#ABORT`. */
|
|
800
796
|
readonly signal?: StopSignal;
|
|
801
797
|
/**
|
|
@@ -805,6 +801,14 @@ export interface RunOptions {
|
|
|
805
801
|
readonly reads?: Read[];
|
|
806
802
|
}
|
|
807
803
|
|
|
804
|
+
/** The options of `run`: the options of `plan.run`, and the type of a bare root value and the verb for `prepare`. */
|
|
805
|
+
export interface RunOptions extends PlanRunOptions {
|
|
806
|
+
/** The type of a bare root value. */
|
|
807
|
+
readonly declaredType?: string;
|
|
808
|
+
/** The verb of `run`, for example `format`. The default is `eval` (VERB.PREPARE). */
|
|
809
|
+
readonly verb?: string;
|
|
810
|
+
}
|
|
811
|
+
|
|
808
812
|
/** The options of an evaluation of a plan. */
|
|
809
813
|
export interface EvalOptions {
|
|
810
814
|
/** A list that gets each effect, in its order. */
|
|
@@ -1303,7 +1307,7 @@ export interface Plan {
|
|
|
1303
1307
|
* @param options - The host code that does the effects, a signal to stop the run and a list that gets the reads.
|
|
1304
1308
|
* @returns The result, when the run ends.
|
|
1305
1309
|
*/
|
|
1306
|
-
run(context?: Context, options?:
|
|
1310
|
+
run(context?: Context, options?: PlanRunOptions): Promise<Result>;
|
|
1307
1311
|
}
|
|
1308
1312
|
|
|
1309
1313
|
interface Compiler {
|
|
@@ -1471,7 +1475,8 @@ function compileNode(c: Compiler, value: unknown, place: readonly Key[], declare
|
|
|
1471
1475
|
} catch (error) {
|
|
1472
1476
|
return failingWith(c, meta, placed(thrown(error, `the evaluator ${name}`), place));
|
|
1473
1477
|
}
|
|
1474
|
-
|
|
1478
|
+
// Code that cannot fail needs no place and no catch, and it does not read the context of its grant (PLAN.TOTAL).
|
|
1479
|
+
const done = finish(c, meta, TOTAL.has(inner) ? inner : placedCode(inner, place, name), undefined);
|
|
1475
1480
|
if (frees === undefined || kind === undefined || !pureCode(c, envelope, kind, typePath, name, quick)) return done;
|
|
1476
1481
|
const free = freeOf(doc, kind, split.parts, frees);
|
|
1477
1482
|
if (free === undefined) return done;
|
|
@@ -1721,6 +1726,24 @@ function copyPlain(value: unknown, memo: Map<object, unknown>): unknown {
|
|
|
1721
1726
|
* the split of the value. Thus a plan with these helpers keeps only its code.
|
|
1722
1727
|
*/
|
|
1723
1728
|
|
|
1729
|
+
/**
|
|
1730
|
+
* The compiled code that cannot fail (PLAN.TOTAL). Such code gives a value and throws nothing. It does not read its
|
|
1731
|
+
* context or its runtime. Only the kits of the kernel mark code, thus the code of a host always gets its grant.
|
|
1732
|
+
*/
|
|
1733
|
+
const TOTAL: WeakSet<Code> = /* @__PURE__ */ new WeakSet();
|
|
1734
|
+
|
|
1735
|
+
/**
|
|
1736
|
+
* This function marks compiled code that cannot fail (PLAN.TOTAL). Then `compileNode` does not wrap the code in
|
|
1737
|
+
* `placedCode`, thus a literal costs one call. The kits of the kernel use it. The package does not export it.
|
|
1738
|
+
*
|
|
1739
|
+
* @param code - The code. It gives a value and throws nothing. It does not read its context or its runtime.
|
|
1740
|
+
* @returns The same code.
|
|
1741
|
+
*/
|
|
1742
|
+
export function totalCode(code: Code): Code {
|
|
1743
|
+
TOTAL.add(code);
|
|
1744
|
+
return code;
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1724
1747
|
/**
|
|
1725
1748
|
* This function gives the code of a document: the code of its evaluator, with the place of each error and of each
|
|
1726
1749
|
* exception. The code gets the context that its grant permits, thus a compiled parent cannot widen it (CAP.NARROW-CODE).
|
|
@@ -1952,7 +1975,7 @@ class CompiledPlan implements Plan {
|
|
|
1952
1975
|
return this.code(ctx, s);
|
|
1953
1976
|
}
|
|
1954
1977
|
|
|
1955
|
-
run(context: Context = makeContext(), runOptions:
|
|
1978
|
+
run(context: Context = makeContext(), runOptions: PlanRunOptions = {}): Promise<Result> {
|
|
1956
1979
|
const machine = this.machine;
|
|
1957
1980
|
const ctx = rootContext(machine, context);
|
|
1958
1981
|
const s = new Session(machine, true, this.traced, runOptions.perform, runOptions.signal, undefined, readingOf(runOptions.reads, ctx));
|
package/src/formula.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type Json, type Key, docEquals, isKey, isRecord } from "./doc.ts";
|
|
|
2
2
|
import type { Kind, KindFacts, LazyRule, WorldEntry } from "./world.ts";
|
|
3
3
|
import { type CompiledPath, type Context, type Resolution, compilePath, valueOfThing } from "./deref.ts";
|
|
4
4
|
import { type EvalError, type Failed, type Result, Failure, fail, ok, thrown } from "./errors.ts";
|
|
5
|
-
import { type Code, type CompileInput, type CompiledEvaluator, type CompiledPart, type Evaluator, type Machine, type Runtime, resolveCompiled } from "./evaluate.ts";
|
|
5
|
+
import { type Code, type CompileInput, type CompiledEvaluator, type CompiledPart, type Evaluator, type Machine, type Runtime, resolveCompiled, totalCode } from "./evaluate.ts";
|
|
6
6
|
import { type MachinePart, mergeMachines } from "./merge.ts";
|
|
7
7
|
import { type Domain, type ValueType, HEADER_KEYS, STD_DOMAINS, callable, fieldOf, fits, fnOf, holdsEnvelope, isPrecise, isUnknown, itemOf, join, member, stepType, typeText } from "./types.ts";
|
|
8
8
|
import type { TypeInput, TypeRule } from "./typing.ts";
|
|
@@ -697,8 +697,9 @@ function formulaCode(profile: FormulaProfile): Readonly<Record<string, CompiledE
|
|
|
697
697
|
|
|
698
698
|
return {
|
|
699
699
|
"formula.lit": compiled(({ doc }) => {
|
|
700
|
+
// A literal cannot fail, thus its code needs no place (PLAN.TOTAL).
|
|
700
701
|
const result = ok(doc.value);
|
|
701
|
-
return () => result;
|
|
702
|
+
return totalCode(() => result);
|
|
702
703
|
}),
|
|
703
704
|
|
|
704
705
|
"formula.ref": compiled(({ doc, parts, fill, address, machine }) => {
|
|
@@ -718,7 +719,7 @@ function formulaCode(profile: FormulaProfile): Readonly<Record<string, CompiledE
|
|
|
718
719
|
// A step document without parts is its own value. A step document with parts gets the result of each part.
|
|
719
720
|
if (parts.length === 0) {
|
|
720
721
|
const same = ok(doc);
|
|
721
|
-
return () => same;
|
|
722
|
+
return totalCode(() => same);
|
|
722
723
|
}
|
|
723
724
|
return (ctx, rt) => {
|
|
724
725
|
const values = valuesOf(parts, ctx, rt);
|
package/src/generate.ts
CHANGED
|
@@ -146,9 +146,11 @@ export function generate(world: World, options: GenerateOptions): unknown {
|
|
|
146
146
|
const keys = options.keys ?? KEYS;
|
|
147
147
|
const steps = options.steps ?? 2;
|
|
148
148
|
const roots: readonly Root[] = options.roots ?? ROOTS;
|
|
149
|
+
// A kind with the verb step walks a step document. With a default of step, each other kind walks one too (GEN.STEPS).
|
|
150
|
+
const defaultStep = Object.hasOwn(world.defaults, "step");
|
|
149
151
|
const stepTypes = types.filter((type) => {
|
|
150
152
|
const found = lookupKind(world, type);
|
|
151
|
-
return found.ok && Object.hasOwn(found.kind.verbs, "step");
|
|
153
|
+
return found.ok && (defaultStep || Object.hasOwn(found.kind.verbs, "step"));
|
|
152
154
|
});
|
|
153
155
|
// A name under each namespace with a fallback that no evaluator knows, for example ["ops", "nope"].
|
|
154
156
|
const unknownNames: readonly (readonly Key[])[] = Object.keys(world.kinds)
|
|
@@ -205,7 +207,10 @@ export function generate(world: World, options: GenerateOptions): unknown {
|
|
|
205
207
|
return out;
|
|
206
208
|
};
|
|
207
209
|
|
|
208
|
-
/**
|
|
210
|
+
/**
|
|
211
|
+
* A path from a root (D10). It uses the names in scope, and sometimes a step document. The kind of a step document
|
|
212
|
+
* has the verb `step`, or the default of the world for `step` serves it.
|
|
213
|
+
*/
|
|
209
214
|
const pathFor = (pos: Position, refKind: Kind | undefined): Json => {
|
|
210
215
|
if (rng.chance(malformed)) return rng.pick<Json>(["names", [], { names: "a" }, ["nowhere", "a"]]);
|
|
211
216
|
const others = roots.filter((name) => name !== "names");
|