@mark1russell7/coeval 0.21.0 → 0.22.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/build/index.js CHANGED
@@ -428,6 +428,92 @@ function collectOf(declared) {
428
428
  };
429
429
  }
430
430
  /**
431
+ * This function reads an entry of the table `tree.at` (D124). The tree kit, the reference, `check` and the graph of
432
+ * attribute instances read it with this one function.
433
+ *
434
+ * @param declared - The entry.
435
+ * @returns The rule, or the reason when the entry has no correct form.
436
+ */
437
+ function atRuleOf(declared) {
438
+ const params = isRecord(declared) ? field(declared, "params") : void 0;
439
+ if (!(Array.isArray(params) && params.every((name, index) => typeof name === "string" && params.indexOf(name) === index)) || !Object.hasOwn(declared, "equation")) return {
440
+ ok: false,
441
+ reason: "An entry of tree.at needs a list params of different texts and the field equation."
442
+ };
443
+ return {
444
+ ok: true,
445
+ params,
446
+ equation: field(declared, "equation")
447
+ };
448
+ }
449
+ /**
450
+ * This function examines the arguments of a step `tree.at` (D124). The step gives an argument for each parameter, and
451
+ * no other argument. Each argument is JSON data. The key is the text of `argsKey`, thus two equal arguments give one key.
452
+ *
453
+ * @param params - The parameters of the attribute.
454
+ * @param args - The field `args` of the step.
455
+ * @returns The names of the equation and the key, or the reason.
456
+ */
457
+ function atArgsOf(params, args) {
458
+ if (!isRecord(args)) return {
459
+ ok: false,
460
+ reason: "The arguments are a record."
461
+ };
462
+ const extra = Object.keys(args).find((name) => !params.includes(name));
463
+ if (extra !== void 0) return {
464
+ ok: false,
465
+ reason: `The attribute has no parameter ${extra}.`
466
+ };
467
+ const names = {};
468
+ for (const name of params) {
469
+ if (!Object.hasOwn(args, name)) return {
470
+ ok: false,
471
+ reason: `The step gives no argument ${name}.`
472
+ };
473
+ const value = field(args, name);
474
+ if (argsKey(value) === void 0) return {
475
+ ok: false,
476
+ reason: `The argument ${name} is not JSON data.`
477
+ };
478
+ Object.defineProperty(names, name, {
479
+ value,
480
+ enumerable: true,
481
+ writable: true,
482
+ configurable: true
483
+ });
484
+ }
485
+ return {
486
+ ok: true,
487
+ names,
488
+ key: argsKey(names)
489
+ };
490
+ }
491
+ /**
492
+ * This function gives the key of a JSON value (D124). The fields of a record are in the order of their names. Two
493
+ * values have the same key only when they are equal by DOC.EQUALS, thus `-0` and `0` have different keys.
494
+ *
495
+ * @param value - The value.
496
+ * @returns The JSON text, or `undefined` for a value that is not JSON data: a number that is not finite, a host value or a cycle.
497
+ */
498
+ function argsKey(value) {
499
+ return keyOf$1(value, /* @__PURE__ */ new Set());
500
+ }
501
+ function keyOf$1(value, open) {
502
+ if (value === null || typeof value === "boolean" || typeof value === "string") return JSON.stringify(value);
503
+ if (typeof value === "number") return !Number.isFinite(value) ? void 0 : Object.is(value, -0) ? "-0" : JSON.stringify(value);
504
+ if (typeof value !== "object" || open.has(value) || !Array.isArray(value) && !isRecord(value)) return void 0;
505
+ open.add(value);
506
+ try {
507
+ const list = Array.isArray(value);
508
+ const names = list ? [] : Object.keys(value).sort();
509
+ const items = list ? value.map((item) => keyOf$1(item, open)) : names.map((name) => keyOf$1(field(value, name), open));
510
+ if (items.includes(void 0)) return void 0;
511
+ return list ? `[${items.join(",")}]` : `{${names.map((name, index) => `${JSON.stringify(name)}:${String(items[index])}`).join(",")}}`;
512
+ } finally {
513
+ open.delete(value);
514
+ }
515
+ }
516
+ /**
431
517
  * This function gives the type of a bare equation of a kind (D42). It is the type `of` of the shape of its parts, or
432
518
  * else the type `of` of the shape `rest` of a record. The plan, the reference and `check` read it with this one function.
433
519
  *
@@ -5484,14 +5570,24 @@ const STD_WORLD = {
5484
5570
  pure: true,
5485
5571
  summary: "A step of a path: it follows a key again and again, until it reaches a node of a type."
5486
5572
  },
5487
- tree: { kinds: { named: {
5488
- verbs: {
5489
- step: "walk.named",
5490
- view: "view.card"
5573
+ tree: { kinds: {
5574
+ named: {
5575
+ verbs: {
5576
+ step: "walk.named",
5577
+ view: "view.card"
5578
+ },
5579
+ pure: true,
5580
+ summary: "A step of a path: it goes up to the nearest registry of names, and it gives the node with the name (TREE.NAMED)."
5491
5581
  },
5492
- pure: true,
5493
- summary: "A step of a path: it goes up to the nearest registry of names, and it gives the node with the name (TREE.NAMED)."
5494
- } } },
5582
+ at: {
5583
+ verbs: {
5584
+ step: "walk.tree.at",
5585
+ view: "view.card"
5586
+ },
5587
+ pure: true,
5588
+ summary: "A step of a path: it reads an attribute with parameters of the node before it, with the arguments of the step (TREE.AT)."
5589
+ }
5590
+ } },
5495
5591
  panel: {
5496
5592
  verbs: {
5497
5593
  eval: "tree.node",
@@ -5737,6 +5833,12 @@ const WORLD_SYNTAX = /* @__PURE__ */ Object.freeze({
5737
5833
  args: "named",
5738
5834
  fields: ["name", "in"]
5739
5835
  },
5836
+ {
5837
+ name: "tree.at",
5838
+ kind: "tree.at",
5839
+ args: "named",
5840
+ fields: ["attr", "args"]
5841
+ },
5740
5842
  {
5741
5843
  name: "add",
5742
5844
  kind: "add"
@@ -6328,6 +6430,80 @@ function collected(root, key, declared) {
6328
6430
  return acc;
6329
6431
  }
6330
6432
  /**
6433
+ * The host things that answer the step `tree.at` with their own function (D124). A node of the reference is in it, and
6434
+ * its fields do not change. The walker reads the state of a node of the kit.
6435
+ */
6436
+ const AT_READERS = /* @__PURE__ */ new WeakMap();
6437
+ /** The memo of the instances of the attributes with parameters of each node, without the cells of a host (TREE.AT). */
6438
+ const atMemos = /* @__PURE__ */ new WeakMap();
6439
+ /** The second key of each key of a node, for the cells of the attributes with parameters (TREE.AT-CELL). */
6440
+ const atPlaces = /* @__PURE__ */ new WeakMap();
6441
+ /**
6442
+ * This function gives an instance of an attribute with parameters of a node (TREE.AT, D124). The equation in
6443
+ * `tree.at` of the kind of the node evaluates with the arguments as names. The memo keeps one result for each key of
6444
+ * the arguments, and a demand of an instance in evaluation gives `#CYCLE!`. The function is outside the code of
6445
+ * `read`, thus a node without such attributes does no new work.
6446
+ */
6447
+ function atRead(n, attr, args) {
6448
+ const declared = entryOf(n.tree?.at, attr);
6449
+ if (declared === void 0) return void 0;
6450
+ const rule = atRuleOf(declared);
6451
+ if (!rule.ok) return fail("#VALUE!", `The attribute ${attributeText(attr, n.type, n.place)} has a bad entry tree.at. ${rule.reason}`);
6452
+ const given = atArgsOf(rule.params, args);
6453
+ if (!given.ok) return fail("#VALUE!", `The step tree.at of ${attributeText(attr, n.type, n.place)} has bad arguments. ${given.reason}`);
6454
+ const host = openPoint === void 0 ? n.host : void 0;
6455
+ const place = n.host === void 0 ? n.place : keptAt(atPlaces, n.place, () => Object.freeze([...n.place]));
6456
+ let marks = n.host === void 0 ? atMemos.get(n) : keptAt(marksByPlace, place, () => /* @__PURE__ */ new Map());
6457
+ if (marks === void 0) {
6458
+ marks = /* @__PURE__ */ new Map();
6459
+ atMemos.set(n, marks);
6460
+ }
6461
+ const key = `[${JSON.stringify(attr)},${given.key}]`;
6462
+ const text = attributeText(`${attr} with ${given.key}`, n.type, n.place);
6463
+ const cell = marks.get(key);
6464
+ if (cell !== void 0) return cell.busy ? cycleAt(marks, key, text) : cell.result;
6465
+ const demand = {
6466
+ cells: marks,
6467
+ key,
6468
+ text
6469
+ };
6470
+ const loop = openPoint;
6471
+ const compute = () => ({
6472
+ result: n.equation(rule.equation, given.names),
6473
+ by: "kind"
6474
+ });
6475
+ marks.set(key, BUSY);
6476
+ demands.push(demand);
6477
+ let thrown = NOT_THROWN;
6478
+ let answer;
6479
+ try {
6480
+ answer = host === void 0 ? compute() : host(place, key, () => {
6481
+ try {
6482
+ return compute();
6483
+ } catch (error) {
6484
+ thrown = error;
6485
+ throw error;
6486
+ }
6487
+ });
6488
+ } catch (error) {
6489
+ marks.delete(key);
6490
+ if (host === void 0 || error === thrown) throw error;
6491
+ answer = {
6492
+ result: fail("#CYCLE!", `The cells of the host found a cycle in the demands: ${demands.map((item) => item.text).join(" -> ")}.`, { cause: error }),
6493
+ by: void 0
6494
+ };
6495
+ } finally {
6496
+ demands.pop();
6497
+ }
6498
+ if (n.host !== void 0 || loop?.tentative.has(demand) === true) marks.delete(key);
6499
+ else marks.set(key, {
6500
+ busy: false,
6501
+ result: answer.result,
6502
+ by: answer.by
6503
+ });
6504
+ return answer.result;
6505
+ }
6506
+ /**
6331
6507
  * This function makes a node of the decorated tree. A step `parent` gives the self of the context of the node, and a
6332
6508
  * step `type` gives its type. Another step reads an attribute through its ladder (TREE.LADDER). The rungs are a part of
6333
6509
  * the node, an equation of its kind and an equation `down` of the kind of its parent. A copy from the parent, then a
@@ -6702,10 +6878,40 @@ const named$2 = ({ data, here, deref }) => {
6702
6878
  reason: `No registry ${registry} is on the way.`
6703
6879
  };
6704
6880
  };
6881
+ /**
6882
+ * The walker of the step `tree.at` (TREE.AT, D124). The field `attr` names an attribute with parameters, and the
6883
+ * field `args` gives the arguments. The thing before the step is a node. A failed instance throws its own error.
6884
+ */
6885
+ const at = ({ data, here }) => {
6886
+ const attr = isRecord(data) ? field(data, "attr") : void 0;
6887
+ if (typeof attr !== "string") return {
6888
+ ok: false,
6889
+ code: "#VALUE!",
6890
+ reason: "The step tree.at needs a text attr."
6891
+ };
6892
+ const args = isRecord(data) && Object.hasOwn(data, "args") ? field(data, "args") : {};
6893
+ const state = stateOf(here);
6894
+ const reader = state === void 0 && typeof here === "object" && here !== null ? AT_READERS.get(here) : void 0;
6895
+ if (state === void 0 && reader === void 0) return {
6896
+ ok: false,
6897
+ reason: `The step tree.at reads ${attr} of a thing that is not a node of a tree.`
6898
+ };
6899
+ const result = state === void 0 ? reader(attr, args) : atRead(state, attr, args);
6900
+ if (result === void 0) return {
6901
+ ok: false,
6902
+ reason: `No rung gives the attribute ${attr} with parameters.`
6903
+ };
6904
+ if (!result.ok) throw new Failure(result.error);
6905
+ return {
6906
+ ok: true,
6907
+ thing: result.value
6908
+ };
6909
+ };
6705
6910
  /** The walkers of the standard world, by name. */
6706
6911
  const STD_WALKERS = {
6707
6912
  "walk.nearest": nearest,
6708
- "walk.named": named$2
6913
+ "walk.named": named$2,
6914
+ "walk.tree.at": at
6709
6915
  };
6710
6916
  /** This function evaluates parts one after the other, and stops at the first error. */
6711
6917
  function* inOrder(parts) {
@@ -8163,6 +8369,25 @@ function vertexOf(b, node, attribute) {
8163
8369
  }
8164
8370
  return id;
8165
8371
  }
8372
+ /**
8373
+ * This function gives the vertex of an instance of an attribute with parameters (TREE.AT-CHECK, D124). Its name is the
8374
+ * name of a plain vertex with the key of the arguments after the name of the attribute.
8375
+ */
8376
+ function atVertexOf(b, node, at) {
8377
+ const id = `${attributeVertexId(node.visit.place, at.attr).slice(0, -1)},${at.key}]`;
8378
+ if (!b.vertices.has(id)) {
8379
+ b.vertices.set(id, {
8380
+ id,
8381
+ place: node.visit.place,
8382
+ attribute: at.attr,
8383
+ type: node.text,
8384
+ args: at.names
8385
+ });
8386
+ b.nodes.set(id, node);
8387
+ b.work.push(id);
8388
+ }
8389
+ return id;
8390
+ }
8166
8391
  function edge(b, from, r, lazy = false) {
8167
8392
  b.edges.push({
8168
8393
  from,
@@ -8252,6 +8477,14 @@ function follow(b, start, path, from, r) {
8252
8477
  }
8253
8478
  continue;
8254
8479
  }
8480
+ if (isAtStep(b.machine, step)) {
8481
+ const at = atStepOf(node.kind, node.text, step.value);
8482
+ if (at.kind === "unknown") edge(b, void 0, r);
8483
+ if (at.kind !== "exact") return;
8484
+ edge(b, atVertexOf(b, node, at), r);
8485
+ here = "unknown";
8486
+ continue;
8487
+ }
8255
8488
  if (walkerOf(b.machine, step) !== STD_WALKERS["walk.nearest"]) {
8256
8489
  edge(b, void 0, r);
8257
8490
  return;
@@ -8327,7 +8560,10 @@ function termReads(b, refs, self, names, r) {
8327
8560
  const name = String(ref.path[1]);
8328
8561
  let start;
8329
8562
  if (ref.bound.has(name)) start = "unknown";
8330
- else if (names?.child !== void 0 && name === "child") start = { node: names.child };
8563
+ else if (names?.params !== void 0) {
8564
+ if (!names.params.includes(name)) continue;
8565
+ start = "data";
8566
+ } else if (names?.child !== void 0 && name === "child") start = { node: names.child };
8331
8567
  else if (names?.prev !== void 0 && name === "prev") start = names.prev;
8332
8568
  else if (name === "index") start = "data";
8333
8569
  else if (name === "acc" || name === "item") start = "unknown";
@@ -8351,7 +8587,8 @@ function prevOf(parent, child) {
8351
8587
  */
8352
8588
  function rungReads(b, id) {
8353
8589
  const node = b.nodes.get(id);
8354
- const key = b.vertices.get(id).attribute;
8590
+ const vertex = b.vertices.get(id);
8591
+ const key = vertex.attribute;
8355
8592
  const tree = node.kind.tree;
8356
8593
  const r = {
8357
8594
  to: id,
@@ -8359,6 +8596,14 @@ function rungReads(b, id) {
8359
8596
  place: node.visit.place,
8360
8597
  at: node.visit.at
8361
8598
  };
8599
+ if (vertex.args !== void 0) {
8600
+ const at = atStepOf(node.kind, node.text, {
8601
+ attr: key,
8602
+ args: vertex.args
8603
+ });
8604
+ if (at.kind === "exact") termReads(b, termRefs(b, node.kind, `tree.at.${key}`, at.equation), node, { params: at.params }, r);
8605
+ return;
8606
+ }
8362
8607
  const equation = hasOwnEntry(tree?.equations, key) ? tree?.equations?.[key] : void 0;
8363
8608
  if (equation !== void 0) {
8364
8609
  termReads(b, termRefs(b, node.kind, `tree.equations.${key}`, equation), node, void 0, r);
@@ -8622,7 +8867,7 @@ function allCircular(b, ids) {
8622
8867
  return ids.every((id) => b.vertices.get(id)?.circular === true);
8623
8868
  }
8624
8869
  function vertexText(vertex) {
8625
- return `${vertex.attribute} of ${vertex.type} at [${vertex.place.join(", ")}]`;
8870
+ return `${vertex.args === void 0 ? vertex.attribute : `${vertex.attribute} with ${String(argsKey(vertex.args))}`} of ${vertex.type} at [${vertex.place.join(", ")}]`;
8626
8871
  }
8627
8872
  /**
8628
8873
  * This function finds each certain cycle of the attributes of a document before a run (TREE.GRAPH-CYCLE, D107). A run
@@ -9228,6 +9473,17 @@ function equationsOf(kind) {
9228
9473
  down: false,
9229
9474
  contributes: true
9230
9475
  });
9476
+ for (const [name, declared] of Object.entries(tree.at ?? {})) {
9477
+ const rule = atRuleOf(declared);
9478
+ if (rule.ok) out.push({
9479
+ label: `tree.at.${name}`,
9480
+ term: rule.equation,
9481
+ names: rule.params,
9482
+ attribute: name,
9483
+ down: false,
9484
+ at: true
9485
+ });
9486
+ }
9231
9487
  return out;
9232
9488
  }
9233
9489
  /**
@@ -9373,7 +9629,7 @@ function equationIssues(machine, kind, kindText, options, state) {
9373
9629
  own: void 0,
9374
9630
  parent: void 0
9375
9631
  };
9376
- for (const { label, term, names, attribute, down, contributes } of equationsOf(kind)) {
9632
+ for (const { label, term, names, attribute, down, contributes, at } of equationsOf(kind)) {
9377
9633
  const inner = {
9378
9634
  names,
9379
9635
  ...of === void 0 ? {} : { declaredType: of },
@@ -9383,7 +9639,7 @@ function equationIssues(machine, kind, kindText, options, state) {
9383
9639
  needs.push({
9384
9640
  name,
9385
9641
  why: `the equation ${label} reads it`,
9386
- hidden: down || contributes === true ? void 0 : attribute
9642
+ hidden: down || contributes === true || at === true ? void 0 : attribute
9387
9643
  });
9388
9644
  };
9389
9645
  for (const issue of checkAll(machine, term, inner, void 0, state, {
@@ -9401,7 +9657,7 @@ function equationIssues(machine, kind, kindText, options, state) {
9401
9657
  * This function finds the issues of the contract of a tree kind (TREE.CHECK-RESERVED). An attribute with the name of a
9402
9658
  * structural step gets no read. A tree kind of the run side contradicts the evaluation on demand of its attributes. A
9403
9659
  * declaration `circular` without a start value or with a bad limit gives `#VALUE!` (TREE.CIRCULAR-CHECK). A declaration
9404
- * `collect` without its form gives `#VALUE!` too (TREE.COLLECT).
9660
+ * `collect` without its form gives `#VALUE!` too (TREE.COLLECT). So does an entry of `at` without its form (TREE.AT-CHECK).
9405
9661
  */
9406
9662
  function contractIssues(kind, kindText) {
9407
9663
  const out = [];
@@ -9410,7 +9666,8 @@ function contractIssues(kind, kindText) {
9410
9666
  "equations",
9411
9667
  "down",
9412
9668
  "attributes",
9413
- "contributes"
9669
+ "contributes",
9670
+ "at"
9414
9671
  ]) for (const name of Object.keys(tree?.[table] ?? {})) {
9415
9672
  const why = Object.hasOwn(STRUCTURAL, name) ? STRUCTURAL[name] : void 0;
9416
9673
  if (why !== void 0) out.push({
@@ -9433,6 +9690,14 @@ function contractIssues(kind, kindText) {
9433
9690
  reason: `The kind ${kindText} has a bad declaration tree.attributes.${name}.collect. ${collect.reason}`
9434
9691
  });
9435
9692
  }
9693
+ for (const [name, declared] of Object.entries(tree?.at ?? {})) {
9694
+ const rule = atRuleOf(declared);
9695
+ if (!rule.ok) out.push({
9696
+ code: "#VALUE!",
9697
+ place: [],
9698
+ reason: `The kind ${kindText} has a bad entry tree.at.${name}. ${rule.reason}`
9699
+ });
9700
+ }
9436
9701
  if (kind.side === "run") out.push({
9437
9702
  code: "#CALC!",
9438
9703
  place: [],
@@ -9478,7 +9743,7 @@ function nodeIssues(machine, node, state, v) {
9478
9743
  * This function examines a reference from the root `self` (TREE.CHECK-UNKNOWN). The steps `parent` go up the known
9479
9744
  * nodes. The first other key names an attribute of the node that they reach. When no rung answers the attribute, the
9480
9745
  * function gives the index of the step and the reason. In an equation, a read of the node of the equation goes to the
9481
- * needs of its kind.
9746
+ * needs of its kind. A step `tree.at` with literal arguments gets the checks of TREE.AT-CHECK.
9482
9747
  */
9483
9748
  function readIssue(machine, self, path, rootSelf) {
9484
9749
  let node = self;
@@ -9488,6 +9753,14 @@ function readIssue(machine, self, path, rootSelf) {
9488
9753
  index += 1;
9489
9754
  }
9490
9755
  const step = path[index];
9756
+ if (node !== void 0 && isAtStep(machine, step)) {
9757
+ const at = atStepOf(node.kind, node.text, step.value);
9758
+ return at.kind === "issue" ? {
9759
+ index,
9760
+ reason: at.reason,
9761
+ code: at.code
9762
+ } : void 0;
9763
+ }
9491
9764
  if (node === void 0 || !isKey(step) || Object.hasOwn(STRUCTURAL, String(step))) return void 0;
9492
9765
  const name = String(step);
9493
9766
  if (node.own === void 0) {
@@ -9499,6 +9772,52 @@ function readIssue(machine, self, path, rootSelf) {
9499
9772
  reason: `No rung gives the attribute ${name} of the kind ${node.text}.`
9500
9773
  };
9501
9774
  }
9775
+ /** This function tells if a step of a path is a step `tree.at` of the standard walker (TREE.AT, D124). */
9776
+ function isAtStep(machine, step) {
9777
+ return isEnvelope(step) && walkerOf(machine, step) === STD_WALKERS["walk.tree.at"];
9778
+ }
9779
+ /**
9780
+ * This function examines the data of a step `tree.at` on a node of a known kind (TREE.AT-CHECK, D124). `check` and the
9781
+ * graph of attribute instances read the step with this one function.
9782
+ */
9783
+ function atStepOf(kind, kindText, data) {
9784
+ if (holdsDocument(data)) return { kind: "unknown" };
9785
+ const attr = isRecord(data) ? field(data, "attr") : void 0;
9786
+ if (typeof attr !== "string") return {
9787
+ kind: "issue",
9788
+ code: "#VALUE!",
9789
+ reason: "The step tree.at needs a text attr."
9790
+ };
9791
+ const table = kind.tree?.at;
9792
+ const declared = table !== void 0 && Object.hasOwn(table, attr) ? table[attr] : void 0;
9793
+ if (declared === void 0) return {
9794
+ kind: "issue",
9795
+ code: "#N/A",
9796
+ reason: `No rung gives the attribute ${attr} with parameters of the kind ${kindText}.`
9797
+ };
9798
+ const rule = atRuleOf(declared);
9799
+ if (!rule.ok) return { kind: "unknown" };
9800
+ const given = atArgsOf(rule.params, isRecord(data) && Object.hasOwn(data, "args") ? field(data, "args") : {});
9801
+ if (!given.ok) return {
9802
+ kind: "issue",
9803
+ code: "#VALUE!",
9804
+ reason: `The step tree.at of ${attr} of the kind ${kindText} has bad arguments. ${given.reason}`
9805
+ };
9806
+ return {
9807
+ kind: "exact",
9808
+ attr,
9809
+ key: given.key,
9810
+ equation: rule.equation,
9811
+ params: rule.params,
9812
+ names: given.names
9813
+ };
9814
+ }
9815
+ /** This function tells if a value holds a document. A document in the data of a step can be a part, thus only the run knows its value. */
9816
+ function holdsDocument(value) {
9817
+ if (isEnvelope(value)) return true;
9818
+ if (Array.isArray(value)) return value.some(holdsDocument);
9819
+ return isRecord(value) && Object.values(value).some(holdsDocument);
9820
+ }
9502
9821
  /**
9503
9822
  * This function finds the issues of `check`. With a list of nodes, it also records each document that it visits for
9504
9823
  * the pass of types. It marks each document with an issue. The state holds the kinds whose equations the check
@@ -9685,7 +10004,7 @@ function checkAll(machine, doc, options, nodes, state = {
9685
10004
  if (attributes && root === "self" && v.address !== true && name === "ref.resolve") {
9686
10005
  const issue = readIssue(machine, self, path, rootSelf);
9687
10006
  if (issue !== void 0) push({
9688
- code: "#N/A",
10007
+ code: issue.code ?? "#N/A",
9689
10008
  place: v.place,
9690
10009
  reason: issue.reason,
9691
10010
  at: stepAt(issue.index)
@@ -10928,17 +11247,26 @@ function formulaCode(profile) {
10928
11247
  }
10929
11248
  return known;
10930
11249
  };
11250
+ const limit = Math.ceil((machine.maxDepth ?? 1e3) / 4);
10931
11251
  return (ctx, rt) => {
10932
11252
  rt.keepsContext?.(ctx, reads);
11253
+ const clock = rt;
10933
11254
  const closure = (...args) => {
10934
- const scope = { ...ctx.names };
10935
- names.forEach((name, index) => setOwn$2(scope, name, args[index]));
10936
- const result = body.code({
10937
- ...ctx,
10938
- names: scope
10939
- }, rt);
10940
- if (!result.ok) throw new Failure(result.error);
10941
- return result.value;
11255
+ const level = (clock.applying ?? 0) + 1;
11256
+ if (level > limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
11257
+ clock.applying = level;
11258
+ try {
11259
+ const scope = { ...ctx.names };
11260
+ names.forEach((name, index) => setOwn$2(scope, name, args[index]));
11261
+ const result = body.code({
11262
+ ...ctx,
11263
+ names: scope
11264
+ }, rt);
11265
+ if (!result.ok) throw new Failure(result.error);
11266
+ return result.value;
11267
+ } finally {
11268
+ clock.applying = level - 1;
11269
+ }
10942
11270
  };
10943
11271
  Object.defineProperty(closure, CLOSURE$2, { value: { params: names } });
10944
11272
  return ok(closure);
@@ -12825,6 +13153,7 @@ function envOf(machine, options, running, root, outer) {
12825
13153
  alls: 0
12826
13154
  },
12827
13155
  held: 0,
13156
+ applying: 0,
12828
13157
  reading: outer ?? (options.reads === void 0 ? void 0 : {
12829
13158
  list: options.reads,
12830
13159
  root
@@ -13175,6 +13504,51 @@ function attributeOf(node, name) {
13175
13504
  if (!entry.tentative && result !== void 0) node.values.set(name, result);
13176
13505
  return result;
13177
13506
  }
13507
+ /** TREE.AT: the instances of each node of the reference. Two arguments are the same instance by DOC.EQUALS. */
13508
+ const refInstances = /* @__PURE__ */ new WeakMap();
13509
+ /**
13510
+ * TREE.AT: the instance of an attribute with parameters, or `undefined` when the kind has no entry in `tree.at`. The
13511
+ * equation sees the arguments as names. A demand of an instance in evaluation gives `#CYCLE!`, also in a fixed point.
13512
+ */
13513
+ function instanceOf$1(node, attr, args) {
13514
+ const declared = termIn(node.contract?.at, attr);
13515
+ if (declared === void 0) return void 0;
13516
+ const rule = atRuleOf(declared);
13517
+ if (!rule.ok) return fail("#VALUE!", `The attribute ${nameOfAttribute(node, attr)} has a bad entry tree.at. ${rule.reason}`);
13518
+ const given = atArgsOf(rule.params, args);
13519
+ if (!given.ok) return fail("#VALUE!", `The step tree.at of ${nameOfAttribute(node, attr)} has bad arguments. ${given.reason}`);
13520
+ const name = `${attr} with ${given.key}`;
13521
+ const list = refInstances.get(node) ?? [];
13522
+ refInstances.set(node, list);
13523
+ const found = list.find((item) => item.attr === attr && docEquals(item.names, given.names));
13524
+ if (found?.result !== void 0) return found.result;
13525
+ if (found !== void 0) {
13526
+ const from = inEvaluation.findIndex((entry) => entry.node === node && entry.name === name);
13527
+ return fail("#CYCLE!", `The attributes form a cycle: ${[...inEvaluation.slice(from).map((entry) => nameOfAttribute(entry.node, entry.name)), nameOfAttribute(node, name)].join(" -> ")}.`);
13528
+ }
13529
+ const item = {
13530
+ attr,
13531
+ names: given.names,
13532
+ result: void 0
13533
+ };
13534
+ list.push(item);
13535
+ const entry = {
13536
+ node,
13537
+ name,
13538
+ circular: false,
13539
+ tentative: false
13540
+ };
13541
+ inEvaluation.push(entry);
13542
+ let result;
13543
+ try {
13544
+ result = equationOf(node, rule.equation, given.names);
13545
+ } finally {
13546
+ inEvaluation.pop();
13547
+ if (result === void 0 || entry.tentative) list.splice(list.indexOf(item), 1);
13548
+ else item.result = result;
13549
+ }
13550
+ return result;
13551
+ }
13178
13552
  /** TREE.RESULT: the JSON of a node. `open` holds the nodes and the containers whose JSON is in progress. */
13179
13553
  function jsonOfNode(node, self, open) {
13180
13554
  const record = {};
@@ -13261,6 +13635,7 @@ const treeDefinition = ({ parts, context, kind, place, machine, typePath, resolv
13261
13635
  };
13262
13636
  node.thing = self;
13263
13637
  refNodes.set(self, node);
13638
+ AT_READERS.set(self, (attr, args) => instanceOf$1(node, attr, args));
13264
13639
  if (nested) return ok(self);
13265
13640
  try {
13266
13641
  return jsonOfNode(node, self, []);
@@ -13387,16 +13762,27 @@ function formulaDefinitions(profile = {}) {
13387
13762
  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.");
13388
13763
  const names = params;
13389
13764
  const body = partNamed(parts, "body");
13765
+ const clock = activeEnvs[activeEnvs.length - 1] ?? {
13766
+ applying: 0,
13767
+ maxDepth: 1e3
13768
+ };
13769
+ const limit = Math.ceil(clock.maxDepth / 4);
13390
13770
  const closure = (...args) => {
13391
- const scope = {};
13392
- for (const key of Object.keys(context.names)) setField$1(scope, key, context.names[key]);
13393
- names.forEach((name, index) => setField$1(scope, name, args[index]));
13394
- const result = body.evaluate({
13395
- ...context,
13396
- names: scope
13397
- });
13398
- if (!result.ok) throw new Failure(result.error);
13399
- return result.value;
13771
+ if (clock.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
13772
+ clock.applying += 1;
13773
+ try {
13774
+ const scope = {};
13775
+ for (const key of Object.keys(context.names)) setField$1(scope, key, context.names[key]);
13776
+ names.forEach((name, index) => setField$1(scope, name, args[index]));
13777
+ const result = body.evaluate({
13778
+ ...context,
13779
+ names: scope
13780
+ });
13781
+ if (!result.ok) throw new Failure(result.error);
13782
+ return result.value;
13783
+ } finally {
13784
+ clock.applying -= 1;
13785
+ }
13400
13786
  };
13401
13787
  Object.defineProperty(closure, CLOSURE$1, { value: { params: names } });
13402
13788
  return ok(closure);
@@ -18002,6 +18388,6 @@ function samplesAt(values, closed, depth) {
18002
18388
  function typeFromSamples(values, options = {}) {
18003
18389
  return samplesAt(values, options.closed === true, 0);
18004
18390
  }
18005
- export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, Held, JOURNAL, 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, ask, attributeGraph, attributeTrace, attributeVertexId, capKeys, check, checkLatent, checkStep, checkSteps, checkWorld, circularOf, classify, collectOf, components, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, derefStep, describe, docEquals, 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, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, 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 };
18391
+ export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, Held, JOURNAL, 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, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, capKeys, check, checkLatent, checkStep, checkSteps, checkWorld, circularOf, classify, collectOf, components, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, derefStep, describe, docEquals, 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, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, 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 };
18006
18392
 
18007
18393
  //# sourceMappingURL=index.js.map