@mark1russell7/coeval 0.22.0 → 0.24.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/src/types.ts CHANGED
@@ -87,7 +87,8 @@ export interface Domain {
87
87
  /**
88
88
  * The codec of a domain: it writes a member of the domain as JSON, and it reads the JSON again (D40). Both functions
89
89
  * must be pure. `decode(encode(v))` must equal `v` by `sameValue` (EXT.ROUNDTRIP). The codec must give one JSON
90
- * value for each member, thus the same value has the same document in each language (D12).
90
+ * value for each member, thus the same value has the same document in each language (D12). `codecLaws` examines
91
+ * these laws for the members of the domain (D130).
91
92
  */
92
93
  export interface DomainCodec {
93
94
  /**
package/src/world.ts CHANGED
@@ -89,7 +89,13 @@ export interface ScopeRule {
89
89
  export type CapsRule =
90
90
  | { readonly rule: "same"; readonly in?: readonly (readonly Key[])[] }
91
91
  | { readonly rule: "mask"; readonly in?: readonly (readonly Key[])[] }
92
- | { readonly rule: "only"; readonly caps: readonly Cap[]; readonly in?: readonly (readonly Key[])[] };
92
+ | { readonly rule: "only"; readonly caps: readonly Cap[]; readonly in?: readonly (readonly Key[])[] }
93
+ /**
94
+ * The parts that the rule covers get each capability that the value of the document holds at the path `from`. The
95
+ * code of the kind answers these effects with its own clauses (`RunPart.handled`), thus they do not reach the host.
96
+ * The key `"*"` in `from` steps into each item (CAP.GRANT, D146).
97
+ */
98
+ | { readonly rule: "grant"; readonly from: readonly Key[]; readonly in?: readonly (readonly Key[])[] };
93
99
 
94
100
  /**
95
101
  * A lazy rule of a kind names the parts that an evaluation can skip and still give a value. An example is the
@@ -146,6 +152,8 @@ export interface KindFacts {
146
152
  * whose attributes each declare `circular` gives a fixed point.
147
153
  * - `collect`: the value of a node without an answer of the first four rungs and without a fold. The node combines
148
154
  * the contributions of each node of its subtree (TREE.COLLECT, D122).
155
+ * - `higher`: the value of a node without an answer of the rungs before it. The term gives a document as data. The kit
156
+ * evaluates that document with the node as `self`, thus its root is a new node under the node (TREE.HIGHER, D126).
149
157
  */
150
158
  export interface AttributeDeclaration {
151
159
  readonly copy?: boolean;
@@ -153,6 +161,7 @@ export interface AttributeDeclaration {
153
161
  readonly default?: Json;
154
162
  readonly circular?: CircularDeclaration;
155
163
  readonly collect?: CollectDeclaration;
164
+ readonly higher?: Json;
156
165
  }
157
166
 
158
167
  /**
@@ -189,6 +198,9 @@ export interface CircularDeclaration {
189
198
  readonly limit?: number;
190
199
  }
191
200
 
201
+ /** The most generated documents on the way from a node to the root of its tree (TREE.HIGHER-DEPTH, D126). */
202
+ export const GENERATION_LIMIT = 64;
203
+
192
204
  /** The most rounds of a circular attribute without its own `limit` (TREE.CIRCULAR-LIMIT, D113). */
193
205
  export const CIRCULAR_LIMIT = 100;
194
206
 
@@ -260,6 +272,8 @@ export function collectOf(declared: unknown): CollectRule {
260
272
  * equation sees no names.
261
273
  * - `at`: the attributes with parameters of the node (TREE.AT, D124). Only the step `tree.at` reads them, and the
262
274
  * equation sees each parameter as a name.
275
+ * - `forwards`: the name of an attribute that gives a node. An attribute that no other rung answers comes from that
276
+ * node (TREE.FORWARD, D126).
263
277
  */
264
278
  export interface TreeContract {
265
279
  readonly equations?: Readonly<Record<string, Json>>;
@@ -267,6 +281,7 @@ export interface TreeContract {
267
281
  readonly attributes?: Readonly<Record<string, AttributeDeclaration>>;
268
282
  readonly contributes?: Readonly<Record<string, Json>>;
269
283
  readonly at?: Readonly<Record<string, AtEquation>>;
284
+ readonly forwards?: string;
270
285
  }
271
286
 
272
287
  /**
@@ -334,15 +349,27 @@ export function argsKey(value: unknown): string | undefined {
334
349
  return keyOf(value, new Set());
335
350
  }
336
351
 
337
- function keyOf(value: unknown, open: Set<object>): string | undefined {
352
+ /**
353
+ * This function gives the structural key of a document (TREE.HIGHER-PLAN, D126). The fields of a record keep their
354
+ * order, because the order of the parts decides the order of the JSON and the first error. Thus one key means one
355
+ * document, and the two documents are equal by DOC.EQUALS.
356
+ *
357
+ * @param doc - The document.
358
+ * @returns The JSON text, or `undefined` for a value that is not JSON data.
359
+ */
360
+ export function documentKey(doc: unknown): string | undefined {
361
+ return keyOf(doc, new Set(), false);
362
+ }
363
+
364
+ function keyOf(value: unknown, open: Set<object>, sorted = true): string | undefined {
338
365
  if (value === null || typeof value === "boolean" || typeof value === "string") return JSON.stringify(value);
339
366
  if (typeof value === "number") return !Number.isFinite(value) ? undefined : Object.is(value, -0) ? "-0" : JSON.stringify(value);
340
367
  if (typeof value !== "object" || open.has(value) || (!Array.isArray(value) && !isRecord(value))) return undefined;
341
368
  open.add(value);
342
369
  try {
343
370
  const list = Array.isArray(value);
344
- const names = list ? [] : Object.keys(value).sort();
345
- const items = list ? value.map((item) => keyOf(item, open)) : names.map((name) => keyOf(field(value as JsonRecord, name), open));
371
+ const names = list ? [] : sorted ? Object.keys(value).sort() : Object.keys(value);
372
+ const items = list ? value.map((item) => keyOf(item, open, sorted)) : names.map((name) => keyOf(field(value as JsonRecord, name), open, sorted));
346
373
  if (items.includes(undefined)) return undefined;
347
374
  return list ? `[${items.join(",")}]` : `{${names.map((name, index) => `${JSON.stringify(name)}:${String(items[index])}`).join(",")}}`;
348
375
  } finally {