@mark1russell7/coeval 0.25.1 → 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 +1 -0
- package/build/index.d.ts +176 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1243 -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 +1 -0
- package/src/stepper.ts +1150 -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.26.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/agree.ts
CHANGED
|
@@ -5,8 +5,9 @@ import { type CheckOptions, typeCheck } from "./static.ts";
|
|
|
5
5
|
import { isPrecise, member, typeText } from "./types.ts";
|
|
6
6
|
import { boundariesOf } from "./typing.ts";
|
|
7
7
|
import { type Effect, type Machine, type Perform, type Read, type TraceNode, JOURNAL, evaluate, makeContext, prepare, run, sharedCopy } from "./evaluate.ts";
|
|
8
|
-
import { Held, isClosure } from "./formula.ts";
|
|
8
|
+
import { type FormulaProfile, Held, isClosure } from "./formula.ts";
|
|
9
9
|
import { type Definitions, reference, referenceRun } from "./reference.ts";
|
|
10
|
+
import { stepper } from "./stepper.ts";
|
|
10
11
|
import { type ReplaySettle, recorder, relay, replayer } from "./replay.ts";
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -21,7 +22,7 @@ import { type ReplaySettle, recorder, relay, replayer } from "./replay.ts";
|
|
|
21
22
|
* each such name, and then with the context of `agree`. `agreeRun` does not have this tier.
|
|
22
23
|
* - `other`: the second tier of a language, from the option `other`.
|
|
23
24
|
*/
|
|
24
|
-
export type Tier = "reference" | "traced" | "again" | "folds" | "fixed" | "other";
|
|
25
|
+
export type Tier = "reference" | "traced" | "again" | "folds" | "fixed" | "stepper" | "other";
|
|
25
26
|
|
|
26
27
|
/** What a second tier gives: its result, and its effects when it records them. */
|
|
27
28
|
export interface TierResult {
|
|
@@ -51,9 +52,11 @@ export interface AgreeOptions {
|
|
|
51
52
|
readonly definitions?: Definitions;
|
|
52
53
|
/**
|
|
53
54
|
* The tiers to compare with the plan. The default is the reference, the traced evaluation, a second evaluation, the
|
|
54
|
-
* plan with the other choice of folds and the plan with fixed names.
|
|
55
|
+
* plan with the other choice of folds and the plan with fixed names. The tier `stepper` is not a default.
|
|
55
56
|
*/
|
|
56
57
|
readonly tiers?: readonly Exclude<Tier, "other">[];
|
|
58
|
+
/** The profile of the formula kit, for the tier `stepper`. */
|
|
59
|
+
readonly profile?: FormulaProfile;
|
|
57
60
|
/**
|
|
58
61
|
* This function gives the result of the second tier of a language, for example a compiler to loops.
|
|
59
62
|
*
|
|
@@ -290,6 +293,8 @@ export function agree(machine: Machine, doc: unknown, context: Context = makeCon
|
|
|
290
293
|
let otherEffects: Effect[] = [];
|
|
291
294
|
if (tier === "reference") {
|
|
292
295
|
other = reference(machine, doc, context, { ...declared, ...mock, effects: otherEffects, ...(options.definitions === undefined ? {} : { definitions: options.definitions }) });
|
|
296
|
+
} else if (tier === "stepper") {
|
|
297
|
+
other = stepper(machine, doc, context, { ...declared, ...mock, effects: otherEffects, ...(options.profile === undefined ? {} : { profile: options.profile }), ...(options.definitions === undefined ? {} : { definitions: options.definitions }) });
|
|
293
298
|
} else if (tier === "traced") {
|
|
294
299
|
const traced = evaluate(machine, doc, context, { ...declared, ...mock });
|
|
295
300
|
other = traced.result;
|
|
@@ -509,8 +514,8 @@ export async function agreeRun(machine: Machine, doc: unknown, context: Context
|
|
|
509
514
|
const replay = replayer(log);
|
|
510
515
|
|
|
511
516
|
for (const tier of options.tiers ?? DEFAULT_TIERS) {
|
|
512
|
-
// A run has no tier with fixed names (PLAN.FIXED).
|
|
513
|
-
if (tier === "fixed") continue;
|
|
517
|
+
// A run has no tier with fixed names (PLAN.FIXED), and the stepper does no runs.
|
|
518
|
+
if (tier === "fixed" || tier === "stepper") continue;
|
|
514
519
|
const tierReplay = watched(replay);
|
|
515
520
|
const host = { perform: tierReplay.perform };
|
|
516
521
|
let other: Result;
|
package/src/facts.ts
CHANGED
|
@@ -185,7 +185,8 @@ export function codeFactsOf(machine: Machine, v: DocVisit, kind: Kind, verb: str
|
|
|
185
185
|
*
|
|
186
186
|
* - `reads`: each free reference, with the root and the keys of its path. A read under a lazy part has the mark
|
|
187
187
|
* `lazy`, for example a read in a branch of `if`. A read after a step document has `exact: false`. A kind that
|
|
188
|
-
* declares `reads` adds a read of each of its roots at each document of the kind.
|
|
188
|
+
* declares `reads` adds a read of each of its roots at each document of the kind. A reference with a step document
|
|
189
|
+
* of the kind also has these reads (FACTS.STEP-READS). The first document of a tree
|
|
189
190
|
* kind also gets the lazy reads of the equations of its kind (FACTS.EQUATIONS). A read from `self` or from a name
|
|
190
191
|
* of a rung is not one of them, because it is not free (READS.EQUATION).
|
|
191
192
|
* - `side` and `effects`: from the contract of each kind, for the verb of the facts.
|
|
@@ -232,6 +233,18 @@ export function factsOf(machine: Machine, doc: unknown, options: FactsOptions =
|
|
|
232
233
|
reads.push(read);
|
|
233
234
|
if (options.volatile?.(read) === true) volatile = true;
|
|
234
235
|
};
|
|
236
|
+
/**
|
|
237
|
+
* This function adds a read of each declared root at the place of a document (FACTS.KIND-READS, FACTS.STEP-READS).
|
|
238
|
+
* It is one function for the facts, thus a visit makes no new function.
|
|
239
|
+
*/
|
|
240
|
+
const declare = (list: readonly Root[] | undefined, node: DocVisit | undefined, lazy: boolean, place: DocVisit): void => {
|
|
241
|
+
if (list === undefined) return;
|
|
242
|
+
for (const root of list) {
|
|
243
|
+
// In an equation, the root self is the node, thus its read is not free (READS.EQUATION).
|
|
244
|
+
if (node !== undefined && root === "self") continue;
|
|
245
|
+
add({ root, keys: NONE, exact: true, lazy, address: false, path: [root], place: tight(place.place), at: tight(place.at) });
|
|
246
|
+
}
|
|
247
|
+
};
|
|
235
248
|
/**
|
|
236
249
|
* This function walks a document. Without `node`, it walks the document of the facts. With `node`, it walks an
|
|
237
250
|
* equation of a tree kind, and each read gets the place of that node: the first document of the kind.
|
|
@@ -265,11 +278,7 @@ export function factsOf(machine: Machine, doc: unknown, options: FactsOptions =
|
|
|
265
278
|
roots = answer?.reads;
|
|
266
279
|
}
|
|
267
280
|
// The code of the kind resolves each of these roots as a whole, at the place of its document (FACTS.KIND-READS).
|
|
268
|
-
|
|
269
|
-
// In an equation, the root self is the node, thus its read is not free (READS.EQUATION).
|
|
270
|
-
if (node !== undefined && root === "self") continue;
|
|
271
|
-
add({ root, keys: NONE, exact: true, lazy, address: false, path: [root], place: tight(place.place), at: tight(place.at) });
|
|
272
|
-
}
|
|
281
|
+
declare(roots, node, lazy, place);
|
|
273
282
|
// check and effectsOf read the declared effects with the same function (D27). The verb of the facts selects the
|
|
274
283
|
// declaration: effects for eval, and the entry of verbEffects for another verb (D49, D111).
|
|
275
284
|
// The answer of the hook for the code of eval wins over the contract, also for an own entry (D118).
|
|
@@ -322,6 +331,8 @@ export function factsOf(machine: Machine, doc: unknown, options: FactsOptions =
|
|
|
322
331
|
const stepAnswer = walker.name === undefined ? undefined : hook?.(found.path, walker.name);
|
|
323
332
|
if (walker.described) note(stepAnswer?.pure ?? found.kind.pure, stepAnswer?.volatile ?? found.kind.volatile);
|
|
324
333
|
else note(stepAnswer?.pure, stepAnswer?.volatile);
|
|
334
|
+
// A walker can resolve a root of its own. The read has the place of the reference (FACTS.STEP-READS).
|
|
335
|
+
declare(stepAnswer?.reads ?? (walker.described ? found.kind.reads : undefined), node, lazy, place);
|
|
325
336
|
}
|
|
326
337
|
const first = path[1];
|
|
327
338
|
// A reference to a name that a kind around it binds reads inside the document: it is not a read. The names of
|
package/src/formula.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Json, type Key, docEquals, isKey, isRecord, typeName } from "./doc.ts";
|
|
2
2
|
import { partsOf as docParts } from "./parts.ts";
|
|
3
3
|
import type { Kind, KindFacts, LazyRule, WorldEntry } from "./world.ts";
|
|
4
|
-
import { type CompiledPath, type Context, type Resolution, compilePath, valueOfThing, walkerOf } from "./deref.ts";
|
|
4
|
+
import { type CompiledPath, type Context, type Resolution, type Root, compilePath, valueOfThing, walkerOf } from "./deref.ts";
|
|
5
5
|
import { type EvalError, type Failed, type Result, Failure, fail, ok, thrown } from "./errors.ts";
|
|
6
6
|
import { type Code, type CompileInput, type CompiledEvaluator, type CompiledPart, type Evaluator, type Machine, type Runtime, resolveCompiled, totalCode } from "./evaluate.ts";
|
|
7
7
|
import { type MachinePart, mergeMachines } from "./merge.ts";
|
|
@@ -51,6 +51,9 @@ export type ExtFn = (data: Json, context: Context, domains?: Readonly<Record<str
|
|
|
51
51
|
* names no operation.
|
|
52
52
|
* - `pureExt`: the pure extensions of `ext`, by their name, for `factsOf` and the folds of a plan (PLAN.FOLD, D47).
|
|
53
53
|
* The default names no extension. A standard extension is pure without a name here.
|
|
54
|
+
* - `extReads`: the roots that an extension of `ext` reads from its context, by its name, for `factsOf`
|
|
55
|
+
* (FACTS.EXT-READS). A read of a root through the context refuses a fold, thus such a pure extension runs at each
|
|
56
|
+
* evaluation.
|
|
54
57
|
* - `volatile`: the operations whose results can change while their arguments stay the same, for example a clock.
|
|
55
58
|
* - `sigs`: the signatures of the operations, by their name, for a check of types (TYPE.SIGNATURE). A list gives
|
|
56
59
|
* overloads. An operation without a signature takes and gives `unknown` (TYPE.GRADUAL).
|
|
@@ -74,6 +77,7 @@ export interface FormulaProfile {
|
|
|
74
77
|
readonly combine?: (errors: readonly EvalError[]) => EvalError;
|
|
75
78
|
readonly pure?: true | readonly string[];
|
|
76
79
|
readonly pureExt?: readonly string[];
|
|
80
|
+
readonly extReads?: Readonly<Record<string, readonly Root[]>>;
|
|
77
81
|
readonly volatile?: readonly string[];
|
|
78
82
|
readonly sigs?: Readonly<Record<string, Signature | readonly Signature[]>> | ((name: string) => Signature | readonly Signature[] | undefined);
|
|
79
83
|
}
|
|
@@ -776,6 +780,7 @@ const PROFILE_KEYS = /* @__PURE__ */ Object.freeze([
|
|
|
776
780
|
"combine",
|
|
777
781
|
"pure",
|
|
778
782
|
"pureExt",
|
|
783
|
+
"extReads",
|
|
779
784
|
"volatile",
|
|
780
785
|
"sigs",
|
|
781
786
|
] as const satisfies readonly (keyof FormulaProfile)[]);
|
|
@@ -1285,7 +1290,11 @@ function makeFacts(profile: FormulaProfile, known: (path: readonly Key[], evalua
|
|
|
1285
1290
|
if (code !== "formula.op" && code !== "formula.ext") return undefined;
|
|
1286
1291
|
const name = path.slice(1).join(".");
|
|
1287
1292
|
if (code === "formula.ext") {
|
|
1288
|
-
if (profile.ext !== undefined && Object.hasOwn(profile.ext, name))
|
|
1293
|
+
if (profile.ext !== undefined && Object.hasOwn(profile.ext, name)) {
|
|
1294
|
+
const facts = pureExt.has(name) ? PURE : NOT_PURE;
|
|
1295
|
+
const reads = profile.extReads !== undefined && Object.hasOwn(profile.extReads, name) ? profile.extReads[name] : undefined;
|
|
1296
|
+
return reads === undefined ? facts : { ...facts, reads };
|
|
1297
|
+
}
|
|
1289
1298
|
return Object.hasOwn(STD_EXT, name) ? PURE : undefined;
|
|
1290
1299
|
}
|
|
1291
1300
|
// An operation that the language does not have gives #NAME?. The kit gives it no facts.
|
package/src/index.ts
CHANGED
|
@@ -293,6 +293,7 @@ export {
|
|
|
293
293
|
print,
|
|
294
294
|
syntaxFormat,
|
|
295
295
|
} from "./syntax.ts";
|
|
296
|
+
export { type Configuration, type Frame, type StepperOptions, stepper, stepperNext, stepperStart } from "./stepper.ts";
|
|
296
297
|
export { type Definitions, type ReferenceOptions, type ReferenceRunOptions, STD_DEFINITIONS, formulaDefinitions, reference, referenceRun } from "./reference.ts";
|
|
297
298
|
export { type AgreeOptions, type AgreeRunOptions, type Agreement, type AgreeTypesOptions, type TypeAgreement, agreeTypes, type Tier, type TierInput, type TierResult, agree, agreeRun, sameValue } from "./agree.ts";
|
|
298
299
|
export { type ConformOptions, type ConformProbe, type Finding, type Obligation, conforms } from "./conform.ts";
|