@mark1russell7/coeval 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.6.0",
4
+ "version": "0.6.2",
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",
@@ -36,6 +36,7 @@
36
36
  "devDependencies": {
37
37
  "@mark1russell7/cue": "github:mark1russell7/cue",
38
38
  "@types/node": "^26.6.4",
39
+ "esbuild": "^0.28.2",
39
40
  "typescript": "^7.0.2",
40
41
  "vitest": "^5.0.3"
41
42
  },
package/src/agree.ts CHANGED
@@ -132,7 +132,7 @@ export function sameValue(a: unknown, b: unknown, equal?: (a: unknown, b: unknow
132
132
  return true;
133
133
  }
134
134
 
135
- const CLOSURE = Symbol.for("coeval.closure");
135
+ const CLOSURE = /* @__PURE__ */ Symbol.for("coeval.closure");
136
136
 
137
137
  function closureParams(fn: object): unknown {
138
138
  return (fn as { readonly [CLOSURE]?: { readonly params: readonly string[] } })[CLOSURE]?.params;
package/src/deref.ts CHANGED
@@ -6,7 +6,7 @@ import type { ErrorCode } from "./errors.ts";
6
6
  * The brand of a host thing: an object of the host that answers the steps of a path itself. The brand is a
7
7
  * global symbol, thus two copies of the kernel in one program know the things of each other.
8
8
  */
9
- export const THING: unique symbol = Symbol.for("coeval.thing") as never;
9
+ export const THING: unique symbol = /* @__PURE__ */ Symbol.for("coeval.thing") as never;
10
10
 
11
11
  /**
12
12
  * A host thing: an object that answers the steps of a path itself, for example a node of a live tree. It is the
@@ -220,7 +220,7 @@ export function isRef(thing: unknown): thing is Envelope & { readonly value: rea
220
220
  return path !== undefined && path.length === 1 && path[0] === "ref";
221
221
  }
222
222
 
223
- const worlds = new WeakMap<World, Json>();
223
+ const worlds = /* @__PURE__ */ new WeakMap<World, Json>();
224
224
 
225
225
  /**
226
226
  * This function makes the thing of the root `world`: the entries of the world as JSON. An alias is a reference
@@ -256,7 +256,7 @@ export function context(parts: Partial<Context> = {}): Context {
256
256
  }
257
257
 
258
258
  const MAX_COLLAPSE = 64;
259
- const NO_HOPS: readonly Hop[] = Object.freeze([]);
259
+ const NO_HOPS: readonly Hop[] = /* @__PURE__ */ Object.freeze([]);
260
260
 
261
261
  /** A value that can be a reference document: a record with the type `ref`. The full check comes after. */
262
262
  function mayBeRef(thing: unknown): boolean {
package/src/evaluate.ts CHANGED
@@ -75,10 +75,10 @@ export function narrow(parent: Context, next: Context): Context {
75
75
  }
76
76
 
77
77
  /** No capabilities. One list serves each masked part. */
78
- const NO_CAPS: readonly Cap[] = Object.freeze([]);
78
+ const NO_CAPS: readonly Cap[] = /* @__PURE__ */ Object.freeze([]);
79
79
 
80
80
  /** No capability rules. One list serves each part that no rule narrows. */
81
- const NO_RULES: readonly CapsRule[] = Object.freeze([]);
81
+ const NO_RULES: readonly CapsRule[] = /* @__PURE__ */ Object.freeze([]);
82
82
 
83
83
  /**
84
84
  * This function gives the capabilities that two lists both permit. An effect is permitted by the result when each
@@ -550,8 +550,8 @@ export interface EvalOptions {
550
550
  }
551
551
 
552
552
  /** The options of a resolution without a record of hops, and with one. One object of each serves each call. */
553
- const WITHOUT_HOPS: ResolveOptions = Object.freeze({ hops: false });
554
- const WITH_HOPS: ResolveOptions = Object.freeze({ hops: true });
553
+ const WITHOUT_HOPS: ResolveOptions = /* @__PURE__ */ Object.freeze({ hops: false });
554
+ const WITH_HOPS: ResolveOptions = /* @__PURE__ */ Object.freeze({ hops: true });
555
555
 
556
556
  /** This class holds the state of one evaluation or run: the machine, the effects, the clock and the trace. */
557
557
  class Session implements Runtime {
@@ -759,7 +759,7 @@ function drive(steps: Steps): Result {
759
759
  return fail("#CALC!", "A part waited, and its parent cannot wait.");
760
760
  }
761
761
 
762
- const ABORTED = Symbol("aborted");
762
+ const ABORTED = /* @__PURE__ */ Symbol("aborted");
763
763
 
764
764
  /** This function drives steps that can wait. The steps before the first wait happen at once, in the call. */
765
765
  async function driveWaiting(steps: Steps, signal: StopSignal | undefined): Promise<Result> {
@@ -916,7 +916,7 @@ function evaluatorOf(world: World, envelope: Envelope | undefined, kind: Kind |
916
916
  }
917
917
 
918
918
  /** The meta of a node of a compilation without a trace. Only a trace reads the meta of a node. */
919
- const NO_META: Meta = Object.freeze({ path: [], doc: { type: "?", value: null }, declared: false, answer: NO_ANSWER, side: "derive" });
919
+ const NO_META: Meta = /* @__PURE__ */ Object.freeze({ path: [], doc: { type: "?", value: null }, declared: false, answer: NO_ANSWER, side: "derive" });
920
920
 
921
921
  function compileNode(c: Compiler, value: unknown, place: readonly Key[], declared: string | undefined, depth: number, address = false): { readonly code: Code; readonly run: RunCode } {
922
922
  const world = c.machine.world;
package/src/formula.ts CHANGED
@@ -48,14 +48,14 @@ export interface FormulaProfile {
48
48
  }
49
49
 
50
50
  /** The mark of a field that the profile leaves out of a record. */
51
- const SKIPPED: unique symbol = Symbol("skipped");
51
+ const SKIPPED: unique symbol = /* @__PURE__ */ Symbol("skipped");
52
52
 
53
53
  /** The value of a name whose binding failed. A reference to the name gives the error. */
54
54
  export class Held {
55
55
  constructor(readonly error: EvalError) {}
56
56
  }
57
57
 
58
- const CLOSURE: unique symbol = Symbol.for("coeval.closure") as never;
58
+ const CLOSURE: unique symbol = /* @__PURE__ */ Symbol.for("coeval.closure") as never;
59
59
 
60
60
  /** A function that the construct `fn` made. It throws a `Failure` when its body fails. */
61
61
  export type Closure = ((...args: readonly unknown[]) => unknown) & { readonly [CLOSURE]: { readonly params: readonly string[] } };
package/src/index.ts CHANGED
@@ -55,7 +55,17 @@ export {
55
55
  looksLikeKind,
56
56
  lookupKind,
57
57
  } from "./world.ts";
58
- export { type MachinePart, type MergeConflict, type MergePath, type WorldPart, MergeError, mergeMachines, mergeWorlds } from "./merge.ts";
58
+ export {
59
+ type MachinePart,
60
+ type MergeConflict,
61
+ type MergePath,
62
+ type WorldPart,
63
+ MergeError,
64
+ mergeMachines,
65
+ mergeWorlds,
66
+ restrictMachine,
67
+ restrictWorld,
68
+ } from "./merge.ts";
59
69
  export {
60
70
  type Answer,
61
71
  type AskOptions,
package/src/merge.ts CHANGED
@@ -55,7 +55,7 @@ export class MergeError extends Error {
55
55
 
56
56
  type Known = NonNullable<Machine["known"]>;
57
57
 
58
- const NONE: ReadonlySet<string> = new Set();
58
+ const NONE: ReadonlySet<string> = /* @__PURE__ */ new Set();
59
59
 
60
60
  function keyOf(path: MergePath): string {
61
61
  return JSON.stringify(path.map(String));
@@ -246,7 +246,7 @@ export function mergeWorlds(...parts: readonly (WorldPart | ((prev: World) => Wo
246
246
  }
247
247
 
248
248
  /** The fields of a machine that merge by their own rules. Each other field is one value, or a conflict. */
249
- const TABLES = new Set(["world", "evaluators", "runners", "derefs", "walkers", "known", "replaces"]);
249
+ const TABLES = /* @__PURE__ */ new Set(["world", "evaluators", "runners", "derefs", "walkers", "known", "replaces"]);
250
250
 
251
251
  interface MachineDraft {
252
252
  readonly world: WorldDraft;
@@ -385,3 +385,102 @@ export function mergeMachines(...parts: readonly (MachinePart | ((prev: Machine)
385
385
  if (m.conflicts.length > 0) throw new MergeError(m.conflicts);
386
386
  return machineOf(draft);
387
387
  }
388
+
389
+ /** This function removes the entry at a path from a table of entries. It gives the same table when no entry is there. */
390
+ function removeEntry(entries: Readonly<Record<string, WorldEntry>>, path: readonly Key[]): Readonly<Record<string, WorldEntry>> {
391
+ const [first, ...rest] = path;
392
+ if (first === undefined) return entries;
393
+ const key = String(first);
394
+ const entry = own(entries, key);
395
+ if (entry === undefined) return entries;
396
+ let next: WorldEntry | undefined;
397
+ if (rest.length > 0) {
398
+ if (!isNamespace(entry)) return entries;
399
+ if (rest.length === 1 && String(rest[0]) === "fallback") {
400
+ if (entry.fallback === undefined) return entries;
401
+ next = { kinds: entry.kinds };
402
+ } else {
403
+ if (String(rest[0]) !== "kinds") return entries;
404
+ const kinds = removeEntry(entry.kinds, rest.slice(1));
405
+ if (kinds === entry.kinds) return entries;
406
+ next = entry.fallback === undefined ? { kinds } : { kinds, fallback: entry.fallback };
407
+ }
408
+ }
409
+ const out: Record<string, WorldEntry> = { ...entries };
410
+ if (next === undefined) delete out[key];
411
+ else setOwn(out, key, next);
412
+ return out;
413
+ }
414
+
415
+ /**
416
+ * This function removes entries from a world, for a language that restricts another language. A path names an entry
417
+ * as `replaces` names it, for example `["kinds", "fn"]`, `["kinds", "ops", "kinds", "mul"]`,
418
+ * `["kinds", "ops", "fallback"]`, `["defaults", "view"]` or `["fallback"]`. A path that names no entry changes
419
+ * nothing. The function does not change the world.
420
+ *
421
+ * A removed kind gives `#KIND?`, also through an alias to it. A namespace without its fallback knows only its own keys.
422
+ * A world without its fallback is closed.
423
+ *
424
+ * @param world - The world.
425
+ * @param paths - The paths of the entries to remove.
426
+ * @returns The world without the entries.
427
+ */
428
+ export function restrictWorld(world: World, paths: readonly MergePath[]): World {
429
+ let kinds = world.kinds;
430
+ const defaults: Record<string, string> = { ...world.defaults };
431
+ let fallback = world.fallback;
432
+ for (const path of paths) {
433
+ const [first, ...rest] = path.map(String);
434
+ if (first === "kinds") kinds = removeEntry(kinds, rest);
435
+ else if (first === "defaults" && rest.length === 1) delete defaults[rest[0] as string];
436
+ else if (first === "fallback" && rest.length === 0) fallback = undefined;
437
+ }
438
+ const out = { kinds: { ...kinds }, defaults };
439
+ return fallback === undefined ? out : { ...out, fallback };
440
+ }
441
+
442
+ /** The tables of the code of a machine, as the paths of a restriction name them. */
443
+ const CODE_TABLES = ["evaluators", "runners", "derefs", "walkers"] as const;
444
+
445
+ /**
446
+ * This function removes entries from a machine, for a language that restricts another language. A path names an
447
+ * entry as `replaces` names it:
448
+ *
449
+ * - A path that starts with `"world"` removes an entry of the world, with the rules of `restrictWorld`.
450
+ * - `["evaluators", name]` or `["runners", name]` removes the code of the name: its evaluator and its runner.
451
+ * - `["derefs", name]` and `["walkers", name]` remove one entry of their tables.
452
+ *
453
+ * A path that names no entry changes nothing. The function does not change the machine. An own entry names an
454
+ * evaluator directly, thus only a machine without the code of a name refuses each document that names it.
455
+ *
456
+ * @param machine - The machine.
457
+ * @param paths - The paths of the entries to remove.
458
+ * @returns The machine without the entries.
459
+ */
460
+ export function restrictMachine(machine: Machine, paths: readonly MergePath[]): Machine {
461
+ const world = paths.filter((path) => String(path[0]) === "world").map((path) => path.slice(1));
462
+ const tables: Record<(typeof CODE_TABLES)[number], Record<string, unknown> | undefined> = {
463
+ evaluators: { ...machine.evaluators },
464
+ runners: machine.runners === undefined ? undefined : { ...machine.runners },
465
+ derefs: machine.derefs === undefined ? undefined : { ...machine.derefs },
466
+ walkers: machine.walkers === undefined ? undefined : { ...machine.walkers },
467
+ };
468
+ for (const path of paths) {
469
+ const [table, name, ...rest] = path.map(String);
470
+ if (name === undefined || rest.length > 0 || !(CODE_TABLES as readonly (string | undefined)[]).includes(table)) continue;
471
+ // The evaluator and the runner of a name are its code, as for a replacement (MACHINE.RUNNER).
472
+ const from = table === "evaluators" || table === "runners" ? ["evaluators", "runners"] : [table as string];
473
+ for (const key of from) {
474
+ const entries = tables[key as (typeof CODE_TABLES)[number]];
475
+ if (entries !== undefined) delete entries[name];
476
+ }
477
+ }
478
+ return {
479
+ ...machine,
480
+ world: world.length === 0 ? machine.world : restrictWorld(machine.world, world),
481
+ evaluators: tables.evaluators as Machine["evaluators"],
482
+ ...(tables.runners === undefined ? {} : { runners: tables.runners as NonNullable<Machine["runners"]> }),
483
+ ...(tables.derefs === undefined ? {} : { derefs: tables.derefs as NonNullable<Machine["derefs"]> }),
484
+ ...(tables.walkers === undefined ? {} : { walkers: tables.walkers as NonNullable<Machine["walkers"]> }),
485
+ };
486
+ }
package/src/parts.ts CHANGED
@@ -50,7 +50,7 @@ function setOwn(target: Record<string, unknown>, key: string, value: unknown): v
50
50
  else target[key] = value;
51
51
  }
52
52
 
53
- const NO_SLOTS: readonly PartSlot[] = Object.freeze([]);
53
+ const NO_SLOTS: readonly PartSlot[] = /* @__PURE__ */ Object.freeze([]);
54
54
 
55
55
  function hasSlots(template: Template): boolean {
56
56
  return template.t !== "data";
package/src/reference.ts CHANGED
@@ -366,7 +366,7 @@ interface RefNode {
366
366
  readonly pending: Set<string>;
367
367
  }
368
368
 
369
- const refNodes = new WeakMap<object, RefNode>();
369
+ const refNodes = /* @__PURE__ */ new WeakMap<object, RefNode>();
370
370
 
371
371
  /** The attributes in evaluation in the reference, in the order of their demands (TREE.CYCLE). */
372
372
  const inEvaluation: { readonly node: RefNode; readonly name: string }[] = [];
@@ -484,7 +484,7 @@ export const STD_DEFINITIONS: Definitions = { evaluators: { "tree.node": treeDef
484
484
 
485
485
  /* The definitions of the formula kit: one function evaluator for each construct, written from docs/SPEC.md. */
486
486
 
487
- const CLOSURE: unique symbol = Symbol.for("coeval.closure") as never;
487
+ const CLOSURE: unique symbol = /* @__PURE__ */ Symbol.for("coeval.closure") as never;
488
488
 
489
489
  /** This function sets an own field, also the field `__proto__` (SHAPE.PROTO). */
490
490
  function setField(target: Record<string, unknown>, key: string, value: unknown): void {
@@ -696,7 +696,7 @@ export function formulaDefinitions(profile: FormulaProfile = {}): Definitions {
696
696
  }
697
697
 
698
698
  /** The mark of a field that the profile leaves out of a record (FORMULA.RECORD). */
699
- const SKIP: unique symbol = Symbol("skip");
699
+ const SKIP: unique symbol = /* @__PURE__ */ Symbol("skip");
700
700
 
701
701
  /** The values of parts in order. The first error stops them, also with `combine` (FORMULA.STEPS, FORMULA.FN). */
702
702
  function valuesOfStrict(parts: readonly Part[]): { readonly values: readonly unknown[] } | Failed {
package/src/static.ts CHANGED
@@ -127,7 +127,7 @@ function scopesOf(rules: readonly ScopeRule[] | undefined, value: unknown, slots
127
127
  }
128
128
 
129
129
  /** The names of a walk without names. A walk does not change a set at any time: it makes a new set to add names. */
130
- const NO_NAMES: ReadonlySet<string> = new Set();
130
+ const NO_NAMES: ReadonlySet<string> = /* @__PURE__ */ new Set();
131
131
 
132
132
  /** This function gives the options of a walk without the names of the host. */
133
133
  function withoutNames(options: WalkOptions): WalkOptions {
package/src/stdlib.ts CHANGED
@@ -122,9 +122,9 @@ function dataOf(type: "number" | "string" | "boolean"): Evaluator {
122
122
 
123
123
  /** The code of the evaluators of the standard world, by name. */
124
124
  export const STD_EVALUATORS: Readonly<Record<string, Evaluator>> = {
125
- "data.number": dataOf("number"),
126
- "data.text": dataOf("string"),
127
- "data.bool": dataOf("boolean"),
125
+ "data.number": /* @__PURE__ */ dataOf("number"),
126
+ "data.text": /* @__PURE__ */ dataOf("string"),
127
+ "data.bool": /* @__PURE__ */ dataOf("boolean"),
128
128
  "math.add": ({ parts }) => {
129
129
  const all = allValues(parts.map((part) => part.evaluate()));
130
130
  if ("error" in all) return all.error;
@@ -164,7 +164,7 @@ export const STD_EVALUATORS: Readonly<Record<string, Evaluator>> = {
164
164
  */
165
165
 
166
166
  /** The brand of a node of the decorated tree. Its value is the state that the kit reads. */
167
- const TREE_NODE: unique symbol = Symbol.for("coeval.tree.node") as never;
167
+ const TREE_NODE: unique symbol = /* @__PURE__ */ Symbol.for("coeval.tree.node") as never;
168
168
 
169
169
  /** One tree in one evaluation. It is open until its root gives the JSON of the tree. */
170
170
  interface TreeBuild {
@@ -189,7 +189,7 @@ interface NodeState {
189
189
  /** The memo cell of one attribute: in evaluation, or done with its result. */
190
190
  type Cell = { readonly busy: true } | { readonly busy: false; readonly result: Result };
191
191
 
192
- const BUSY: Cell = Object.freeze({ busy: true });
192
+ const BUSY: Cell = /* @__PURE__ */ Object.freeze({ busy: true });
193
193
 
194
194
  /** One attribute in evaluation. The text names it in the reason of a cycle. */
195
195
  interface Demand {
@@ -392,7 +392,7 @@ export function nearestWalker(options: NearestOptions = {}): Walker {
392
392
  };
393
393
  }
394
394
 
395
- const nearest: Walker = nearestWalker();
395
+ const nearest: Walker = /* @__PURE__ */ nearestWalker();
396
396
 
397
397
  /** The walkers of the standard world, by name. */
398
398
  export const STD_WALKERS: Readonly<Record<string, Walker>> = { "walk.nearest": nearest };