@calcit/procs 0.13.42 → 0.13.44

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.
Files changed (68) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/RFCs/04-15-match-syntax-rfc.md +14 -8
  3. package/RFCs/04-15-type-directed-optimization-catalog.md +20 -14
  4. package/RFCs/08-05-systematic-nil-reduction-rfc.md +16 -5
  5. package/editing-history/20260823-0401-guard-range-progress.md +9 -0
  6. package/editing-history/20260824-0318-range-backend-consistency.md +13 -0
  7. package/editing-history/20260824-0645-unit-truthiness-review.md +6 -0
  8. package/editing-history/20260824-0655-project-module-merge-review.md +4 -0
  9. package/editing-history/20260824-0705-unit-effect-return-review.md +5 -0
  10. package/editing-history/20260824-1540-scaffold-data-kind-schema.md +6 -0
  11. package/editing-history/20260824-2119-validate-number-call-metadata.md +8 -0
  12. package/editing-history/20260824-2155-stable-js-struct-layout.md +11 -0
  13. package/editing-history/20260824-2224-struct-index-review-followups.md +7 -0
  14. package/editing-history/20260824-2233-indexed-struct-js-regressions.md +5 -0
  15. package/editing-history/20260824-2256-dynamic-method-analysis.md +9 -0
  16. package/editing-history/20260824-2329-dynamic-method-review-followups.md +7 -0
  17. package/editing-history/202608241525-release-01343.md +5 -0
  18. package/editing-history/202608241731-contiguous-executable-calls.md +34 -0
  19. package/editing-history/202608241920-borrowed-syntax-arguments.md +34 -0
  20. package/editing-history/202608241924-unify-editing-history-directory.md +7 -0
  21. package/editing-history/202608242013-typed-native-number-ops.md +34 -0
  22. package/editing-history/20260825-0020-indexed-enum-match.md +34 -0
  23. package/editing-history/20260825-0100-indexed-enum-match-validation.md +7 -0
  24. package/editing-history/20260825-0120-indexed-enum-match-review.md +7 -0
  25. package/editing-history/20260825-1215-typed-literal-paths.md +56 -0
  26. package/editing-history/20260825-1344-typed-literal-path-review.md +17 -0
  27. package/editing-history/20260825-1505-typed-method-native-op.md +23 -0
  28. package/editing-history/20260825-1540-nil-unit-runtime-separation.md +15 -0
  29. package/editing-history/20260825-1725-typed-method-error-stack-review.md +10 -0
  30. package/editing-history/20260825-1733-nil-unit-doc-review.md +5 -0
  31. package/editing-history/20260825-1758-nil-unit-review-followup.md +6 -0
  32. package/editing-history/20260825-1845-release-01344.md +6 -0
  33. package/examples/bench_enum_match.rs +41 -0
  34. package/lib/calcit-data.d.mts +4 -0
  35. package/lib/calcit-data.mjs +59 -9
  36. package/lib/calcit.procs.d.mts +17 -9
  37. package/lib/calcit.procs.mjs +104 -57
  38. package/lib/custom-formatter.mjs +12 -3
  39. package/lib/js-cirru.mjs +6 -5
  40. package/lib/js-impl.mjs +4 -3
  41. package/lib/js-primes.d.mts +1 -1
  42. package/lib/js-primes.mjs +22 -18
  43. package/lib/js-struct-def.mjs +4 -6
  44. package/lib/js-struct-value.d.mts +5 -1
  45. package/lib/js-struct-value.mjs +66 -38
  46. package/lib/package.json +8 -2
  47. package/package.json +8 -2
  48. package/ts-src/calcit-data.mts +54 -9
  49. package/ts-src/calcit.procs.mts +107 -61
  50. package/ts-src/custom-formatter.mts +12 -3
  51. package/ts-src/js-cirru.mts +6 -5
  52. package/ts-src/js-impl.mts +4 -3
  53. package/ts-src/js-primes.mts +5 -1
  54. package/ts-src/js-struct-def.mts +4 -6
  55. package/ts-src/js-struct-value.mts +78 -33
  56. /package/{history → editing-history}/202608191501-release-01326.md +0 -0
  57. /package/{history → editing-history}/202608191628-revert-transparent-union-types.md +0 -0
  58. /package/{history → editing-history}/202608191741-release-01327.md +0 -0
  59. /package/{history → editing-history}/202608212020-release-01328.md +0 -0
  60. /package/{2026082200-release-01330.md → editing-history/2026082200-release-01330.md} +0 -0
  61. /package/{2026082200-same-package-module-meta.md → editing-history/2026082200-same-package-module-meta.md} +0 -0
  62. /package/{2026082200-transitive-module-loading.md → editing-history/2026082200-transitive-module-loading.md} +0 -0
  63. /package/{2026082222-release-01331.md → editing-history/2026082222-release-01331.md} +0 -0
  64. /package/{history → editing-history}/2026082223-release-01332.md +0 -0
  65. /package/{history → editing-history}/2026082223-same-package-namespaces.md +0 -0
  66. /package/{history → editing-history}/2026082300-fix-cross-package-namespace-merge.md +0 -0
  67. /package/{history → editing-history}/2026082300-release-01333.md +0 -0
  68. /package/{history → editing-history}/2026082316-release-01334.md +0 -0
@@ -3,7 +3,7 @@ export const calcit_version = pkg.version;
3
3
  export const calcit_package_json = pkg;
4
4
  import { parse } from "@cirru/parser.ts";
5
5
  import { writeCirruCode } from "@cirru/writer.ts";
6
- import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, getStringName, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
6
+ import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, getStringName, compareTagNames, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
7
7
  import { CalcitRef, atom } from "./js-ref.mjs";
8
8
  import { CalcitStructValue } from "./js-struct-value.mjs";
9
9
  import { CalcitImpl } from "./js-impl.mjs";
@@ -50,9 +50,11 @@ export let type_of = (x) => {
50
50
  if (x instanceof CalcitMap || x instanceof CalcitSliceMap) {
51
51
  return newTag("map");
52
52
  }
53
- if (x == null) {
53
+ if (x === null) {
54
54
  return newTag("nil");
55
55
  }
56
+ if (x === undefined)
57
+ return newTag("unit");
56
58
  if (x instanceof CalcitRef) {
57
59
  return newTag("ref");
58
60
  }
@@ -214,7 +216,7 @@ export let defstruct = (name, ...entries) => {
214
216
  const fieldType = items[1];
215
217
  fields.push({ tag: fieldTag, type: fieldType });
216
218
  }
217
- fields.sort((a, b) => a.tag.idx - b.tag.idx);
219
+ fields.sort((a, b) => compareTagNames(a.tag, b.tag));
218
220
  for (let i = 1; i < fields.length; i++) {
219
221
  if (fields[i - 1].tag.value === fields[i].tag.value) {
220
222
  throw new Error(`defstruct duplicated field: ${fields[i].tag.toString()}`);
@@ -237,7 +239,7 @@ export let defenum = (name, ...variants) => {
237
239
  const payload = new CalcitSliceList(items.slice(1));
238
240
  entries.push({ tag, payload });
239
241
  }
240
- entries.sort((a, b) => a.tag.idx - b.tag.idx);
242
+ entries.sort((a, b) => compareTagNames(a.tag, b.tag));
241
243
  for (let i = 1; i < entries.length; i++) {
242
244
  if (entries[i - 1].tag.value === entries[i].tag.value) {
243
245
  throw new Error(`defenum duplicated variant: ${entries[i].tag.toString()}`);
@@ -280,7 +282,7 @@ export let _$n_impl_$o__$o_new = (name, ...pairs) => {
280
282
  }
281
283
  entries.push({ tag: fieldTag, value });
282
284
  }
283
- entries.sort((a, b) => a.tag.idx - b.tag.idx);
285
+ entries.sort((a, b) => compareTagNames(a.tag, b.tag));
284
286
  for (let i = 1; i < entries.length; i++) {
285
287
  if (entries[i - 1].tag.value === entries[i].tag.value) {
286
288
  throw new Error(`&impl::new duplicated field: ${entries[i].tag.toString()}`);
@@ -345,14 +347,26 @@ export function _$n_struct_$o_field_tag(x, idx) {
345
347
  throw new Error(`&struct:field-tag index ${i} out of bounds (${x.fields.length})`);
346
348
  return x.fields[i];
347
349
  }
348
- export function _$n_struct_$o_nth(x, idx) {
350
+ export function _$n_struct_$o_nth(x, idx, field) {
349
351
  if (!(x instanceof CalcitStructValue))
350
352
  throw new Error(`&struct:nth expected a struct value, got ${x}`);
353
+ if (field !== undefined)
354
+ return x.nthAt(idx, field);
351
355
  const i = idx;
352
356
  if (i < 0 || i >= x.values.length)
353
357
  throw new Error(`&struct:nth index ${i} out of range for struct with ${x.values.length} fields`);
354
358
  return x.values[i];
355
359
  }
360
+ export function _$n_struct_$o_assoc_at(x, idx, field, value) {
361
+ if (!(x instanceof CalcitStructValue))
362
+ throw new Error(`&struct:assoc-at expected a struct value, got ${x}`);
363
+ return x.assocAt(idx, field, value);
364
+ }
365
+ export function _$n_struct_$o_with_at(x, ...triples) {
366
+ if (!(x instanceof CalcitStructValue))
367
+ throw new Error(`&struct:with-at expected a struct value, got ${x}`);
368
+ return x.withAt(...triples);
369
+ }
356
370
  export function _$n_set_$o_count(x) {
357
371
  if (x instanceof CalcitSet)
358
372
  return x.len();
@@ -395,7 +409,7 @@ export let _$n__$s_ = (x, y) => {
395
409
  return x * y;
396
410
  };
397
411
  export let _$n_str = (x) => {
398
- if (x == null) {
412
+ if (x === null) {
399
413
  return "";
400
414
  }
401
415
  if (typeof x === "string") {
@@ -607,7 +621,7 @@ export let _$n_enum_$o_validate = function (enumValue, tag) {
607
621
  if (!(enumValue instanceof CalcitEnumValue))
608
622
  throw new Error("&enum:validate expects an enum value as first argument");
609
623
  if (enumValue.enumPrototype == null) {
610
- return null;
624
+ return;
611
625
  }
612
626
  const proto = assert_enum_tag_args("&enum:validate", enumValue.enumPrototype, tag);
613
627
  const tagValue = tag;
@@ -621,7 +635,7 @@ export let _$n_enum_$o_validate = function (enumValue, tag) {
621
635
  if (expected !== actual) {
622
636
  throw new Error(`enum variant expects ${expected} payload(s), got ${actual} for ${enumValue}`);
623
637
  }
624
- return null;
638
+ return;
625
639
  }
626
640
  throw new Error("Expected variant to be a list");
627
641
  };
@@ -783,7 +797,7 @@ export let reset_$x_ = (a, v) => {
783
797
  a.listeners.forEach((f) => {
784
798
  f(v, prev);
785
799
  });
786
- return null;
800
+ return v;
787
801
  };
788
802
  export let add_watch = (a, k, f) => {
789
803
  if (!(a instanceof CalcitRef)) {
@@ -796,29 +810,52 @@ export let add_watch = (a, k, f) => {
796
810
  throw new Error("Expected watcher function");
797
811
  }
798
812
  a.listeners.set(k, f);
799
- return null;
800
813
  };
801
814
  export let remove_watch = (a, k) => {
802
815
  a.listeners.delete(k);
803
- return null;
804
816
  };
817
+ const MAX_RANGE_LENGTH = 4294967295;
805
818
  export let range = (n, m, step = 1) => {
806
- var result = new CalcitSliceList([]);
807
- if (m != null) {
808
- var idx = n;
809
- while (idx < m) {
810
- result = result.append(idx);
811
- idx = idx + step;
819
+ const base = m == null ? 0 : n;
820
+ const bound = m == null ? n : m;
821
+ if (!Number.isFinite(base) || !Number.isFinite(bound) || !Number.isFinite(step)) {
822
+ throw new TypeError("&list:range expected finite numbers for base, bound, and step");
823
+ }
824
+ if (base === bound) {
825
+ return new CalcitSliceList([]);
826
+ }
827
+ if (step === 0 || (bound > base && step < 0) || (bound < base && step > 0)) {
828
+ throw new Error("&list:range cannot construct list with a step of 0 or invalid step direction");
829
+ }
830
+ // Avoid overflowing `bound - base` when finite endpoints have opposite signs.
831
+ const estimatedLength = (base < 0) !== (bound < 0)
832
+ ? Math.ceil(Math.abs(base) / Math.abs(step) + Math.abs(bound) / Math.abs(step))
833
+ : Math.ceil((bound - base) / step);
834
+ if (!Number.isFinite(estimatedLength) || estimatedLength > MAX_RANGE_LENGTH) {
835
+ throw new Error("&list:range result is too large");
836
+ }
837
+ const result = [];
838
+ if (step > 0) {
839
+ for (let value = base; value < bound;) {
840
+ result.push(value);
841
+ const next = value + step;
842
+ if (next === value) {
843
+ throw new Error("&list:range step does not advance the current value");
844
+ }
845
+ value = next;
812
846
  }
813
847
  }
814
848
  else {
815
- var idx = 0;
816
- while (idx < n) {
817
- result = result.append(idx);
818
- idx = idx + step;
849
+ for (let value = base; value > bound;) {
850
+ result.push(value);
851
+ const next = value + step;
852
+ if (next === value) {
853
+ throw new Error("&list:range step does not advance the current value");
854
+ }
855
+ value = next;
819
856
  }
820
857
  }
821
- return result;
858
+ return new CalcitSliceList(result);
822
859
  };
823
860
  export function _$n_list_$o_empty_$q_(xs) {
824
861
  if (xs instanceof CalcitList || xs instanceof CalcitSliceList)
@@ -896,7 +933,6 @@ export let timeout_call = (duration, f) => {
896
933
  throw new Error("Expected callback in fn");
897
934
  }
898
935
  setTimeout(f, duration);
899
- return null;
900
936
  };
901
937
  export let _$n_list_$o_rest = (xs) => {
902
938
  if (xs instanceof CalcitList || xs instanceof CalcitSliceList) {
@@ -981,10 +1017,9 @@ export let generate_id_$x_ = () => {
981
1017
  };
982
1018
  export let _$n_display_stack = () => {
983
1019
  console.trace();
984
- return null;
985
1020
  };
986
1021
  export let _$n_list_$o_slice = (xs, from, to) => {
987
- if (xs == null) {
1022
+ if (xs === null) {
988
1023
  return null;
989
1024
  }
990
1025
  let size = xs.len();
@@ -1003,7 +1038,7 @@ export let _$n_list_$o_concat = (...lists) => {
1003
1038
  let result = new CalcitSliceList([]);
1004
1039
  for (let idx = 0; idx < lists.length; idx++) {
1005
1040
  let item = lists[idx];
1006
- if (item == null) {
1041
+ if (item === null) {
1007
1042
  continue;
1008
1043
  }
1009
1044
  if (item instanceof CalcitList || item instanceof CalcitSliceList) {
@@ -1021,7 +1056,7 @@ export let _$n_list_$o_concat = (...lists) => {
1021
1056
  return result;
1022
1057
  };
1023
1058
  export let _$n_list_$o_reverse = (xs) => {
1024
- if (xs == null) {
1059
+ if (xs === null) {
1025
1060
  return null;
1026
1061
  }
1027
1062
  return xs.reverse();
@@ -1050,12 +1085,12 @@ export let round_$q_ = (a) => {
1050
1085
  };
1051
1086
  export let _$n_str_$o_concat = (a, b) => {
1052
1087
  // Optimize string concatenation by avoiding unnecessary toString calls
1053
- const aStr = a != null ? toString(a, false) : "";
1054
- const bStr = b != null ? toString(b, false) : "";
1088
+ const aStr = a !== null ? toString(a, false) : "";
1089
+ const bStr = b !== null ? toString(b, false) : "";
1055
1090
  return aStr + bStr;
1056
1091
  };
1057
1092
  export let sort = (xs, f) => {
1058
- if (xs == null) {
1093
+ if (xs === null) {
1059
1094
  return null;
1060
1095
  }
1061
1096
  if (xs instanceof CalcitList || xs instanceof CalcitSliceList) {
@@ -1068,10 +1103,10 @@ export let floor = (n) => {
1068
1103
  return Math.floor(n);
1069
1104
  };
1070
1105
  export let _$n_merge = (a, b) => {
1071
- if (a == null) {
1106
+ if (a === null) {
1072
1107
  return b;
1073
1108
  }
1074
- if (b == null) {
1109
+ if (b === null) {
1075
1110
  return a;
1076
1111
  }
1077
1112
  if (a instanceof CalcitMap || a instanceof CalcitSliceMap) {
@@ -1113,10 +1148,10 @@ export let _$n_merge = (a, b) => {
1113
1148
  throw new Error("Expected map or struct value");
1114
1149
  };
1115
1150
  export let _$n_merge_non_nil = (a, b) => {
1116
- if (a == null) {
1151
+ if (a === null) {
1117
1152
  return b;
1118
1153
  }
1119
- if (b == null) {
1154
+ if (b === null) {
1120
1155
  return a;
1121
1156
  }
1122
1157
  if (!(a instanceof CalcitMap || a instanceof CalcitSliceMap)) {
@@ -1174,7 +1209,7 @@ export let _$n_include = (xs, y) => {
1174
1209
  if (!(xs instanceof CalcitSet)) {
1175
1210
  throw new Error("Expected a set");
1176
1211
  }
1177
- if (y == null) {
1212
+ if (y === null) {
1178
1213
  return xs;
1179
1214
  }
1180
1215
  return xs.include(y);
@@ -1183,7 +1218,7 @@ export let _$n_exclude = (xs, y) => {
1183
1218
  if (!(xs instanceof CalcitSet)) {
1184
1219
  throw new Error("Expected a set");
1185
1220
  }
1186
- if (y == null) {
1221
+ if (y === null) {
1187
1222
  return xs;
1188
1223
  }
1189
1224
  return xs.exclude(y);
@@ -1302,7 +1337,7 @@ export let aget = (x, name) => {
1302
1337
  export let aset = (x, name, v) => {
1303
1338
  return (x[name] = v);
1304
1339
  };
1305
- export let js_get = aget;
1340
+ export let js_get = (x, name) => x[name] ?? null;
1306
1341
  export let js_set = aset;
1307
1342
  /** generates `delete a.b` */
1308
1343
  export let js_delete = (obj, name) => {
@@ -1380,7 +1415,7 @@ export let quit_$x_ = () => {
1380
1415
  }
1381
1416
  };
1382
1417
  export let turn_string = (x) => {
1383
- if (x == null) {
1418
+ if (x === null) {
1384
1419
  return "";
1385
1420
  }
1386
1421
  if (typeof x === "string") {
@@ -1420,7 +1455,7 @@ export let ends_with_$q_ = (xs, y) => {
1420
1455
  return xs.endsWith(y);
1421
1456
  };
1422
1457
  export let blank_$q_ = (x) => {
1423
- if (x == null) {
1458
+ if (x === null) {
1424
1459
  return true;
1425
1460
  }
1426
1461
  if (typeof x === "string") {
@@ -1443,7 +1478,7 @@ export let arrayToList = (xs) => {
1443
1478
  return new CalcitSliceList(xs ?? []);
1444
1479
  };
1445
1480
  export let listToArray = (xs) => {
1446
- if (xs == null) {
1481
+ if (xs === null) {
1447
1482
  return null;
1448
1483
  }
1449
1484
  if (xs instanceof CalcitList || xs instanceof CalcitSliceList) {
@@ -1463,7 +1498,7 @@ export let bool_$q_ = (x) => {
1463
1498
  return typeof x === "boolean";
1464
1499
  };
1465
1500
  export let nil_$q_ = (x) => {
1466
- return x == null;
1501
+ return x === null;
1467
1502
  };
1468
1503
  export let tag_$q_ = (x) => {
1469
1504
  return x instanceof CalcitTag;
@@ -1540,8 +1575,10 @@ export let parse_cirru_edn = (code, options) => {
1540
1575
  }
1541
1576
  };
1542
1577
  const typed_edn_kind = (value) => {
1543
- if (value == null)
1578
+ if (value === null)
1544
1579
  return "nil";
1580
+ if (value === undefined)
1581
+ return "unit";
1545
1582
  if (typeof value === "boolean")
1546
1583
  return "bool";
1547
1584
  if (typeof value === "number")
@@ -1583,10 +1620,14 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
1583
1620
  if (node == null)
1584
1621
  typed_edn_error(path, `invalid data shape node #${nodeId}`);
1585
1622
  switch (node.kind) {
1586
- case "unit":
1587
- if (input == null)
1623
+ case "nil":
1624
+ if (input === null)
1588
1625
  return null;
1589
- return typed_edn_error(path, `expected nil, got ${typed_edn_kind(input)}`);
1626
+ return typed_edn_error(path, `expected Nil, got ${typed_edn_kind(input)}`);
1627
+ case "unit":
1628
+ if (input === undefined)
1629
+ return input;
1630
+ return typed_edn_error(path, `expected Unit, got ${typed_edn_kind(input)}`);
1590
1631
  case "bool":
1591
1632
  if (typeof input === "boolean")
1592
1633
  return input;
@@ -1616,7 +1657,7 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
1616
1657
  return input;
1617
1658
  return typed_edn_error(path, `expected cirru-quote, got ${typed_edn_kind(input)}`);
1618
1659
  case "optional":
1619
- return input == null ? null : decode_typed_edn_node(graph, node.inner, input, path, depth + 1);
1660
+ return input === null ? null : decode_typed_edn_node(graph, node.inner, input, path, depth + 1);
1620
1661
  case "list": {
1621
1662
  if (!(input instanceof CalcitList || input instanceof CalcitSliceList)) {
1622
1663
  return typed_edn_error(path, `expected list, got ${typed_edn_kind(input)}`);
@@ -1681,8 +1722,8 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
1681
1722
  const idx = actualNames.indexOf(name);
1682
1723
  decodedFields.set(name, decode_typed_edn_node(graph, fieldNode, input.values[idx], `${path}.${name}`, depth + 1));
1683
1724
  });
1684
- // Native declarations use lexical field order while the JS runtime keeps
1685
- // its interned-tag order. Re-align values to the nominal JS declaration.
1725
+ // Re-align by name so values produced by older runtimes or external data
1726
+ // still adopt the current nominal declaration's canonical field layout.
1686
1727
  if (decodedFields.size !== node.nominal.fields.length) {
1687
1728
  return typed_edn_error(path, `struct :${node.nominal.name.value} decoder fields do not match its nominal declaration`);
1688
1729
  }
@@ -1723,8 +1764,8 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
1723
1764
  export let parse_cirru_edn_as = (code, graph) => {
1724
1765
  if (typeof code !== "string")
1725
1766
  throw new Error(`parse-cirru-edn-as expected a string, got ${typed_edn_kind(code)}`);
1726
- if (graph.version !== 1)
1727
- throw new Error(`parse-cirru-edn-as expected data shape ABI version 1, got ${graph.version}`);
1767
+ if (graph.version !== 2)
1768
+ throw new Error(`parse-cirru-edn-as expected data shape ABI version 2, got ${graph.version}`);
1728
1769
  if (typeof graph.fingerprint !== "string" || graph.fingerprint.length === 0) {
1729
1770
  throw new Error("parse-cirru-edn-as expected a non-empty data shape fingerprint");
1730
1771
  }
@@ -1842,7 +1883,7 @@ const decode_runtime_map_node = (graph, nodeId, input, path, depth) => {
1842
1883
  return new CalcitSliceMap(entries.flat());
1843
1884
  }
1844
1885
  case "optional":
1845
- return input == null ? null : decode_runtime_map_node(graph, node.inner, input, path, depth + 1);
1886
+ return input === null ? null : decode_runtime_map_node(graph, node.inner, input, path, depth + 1);
1846
1887
  case "ref":
1847
1888
  if (!(input instanceof CalcitRef))
1848
1889
  return map_decode_error(path, `expected atom, got ${typed_edn_kind(input)}`);
@@ -1872,8 +1913,8 @@ const decode_runtime_map_node = (graph, nodeId, input, path, depth) => {
1872
1913
  }
1873
1914
  };
1874
1915
  export let decode_map_as = (value, graph) => {
1875
- if (graph.version !== 1)
1876
- throw new Error(`decode-map-as expected data shape ABI version 1, got ${graph.version}`);
1916
+ if (graph.version !== 2)
1917
+ throw new Error(`decode-map-as expected data shape ABI version 2, got ${graph.version}`);
1877
1918
  if (typeof graph.fingerprint !== "string" || graph.fingerprint.length === 0) {
1878
1919
  throw new Error("decode-map-as expected a non-empty data shape fingerprint");
1879
1920
  }
@@ -1915,7 +1956,7 @@ const cirru_quote_to_json = (value) => {
1915
1956
  throw new Error(`Unsupported cirru quote node: ${value}`);
1916
1957
  };
1917
1958
  const calcit_to_json = (value) => {
1918
- if (value == null)
1959
+ if (value === null)
1919
1960
  return null;
1920
1961
  if (typeof value === "string")
1921
1962
  return value;
@@ -1977,9 +2018,12 @@ export let json_pretty = function (value) {
1977
2018
  return JSON.stringify(calcit_to_json(value), null, 2);
1978
2019
  };
1979
2020
  export let format_to_lisp = (x) => {
1980
- if (x == null) {
2021
+ if (x === null) {
1981
2022
  return "nil";
1982
2023
  }
2024
+ else if (x === undefined) {
2025
+ return "&unit";
2026
+ }
1983
2027
  else if (x instanceof CalcitSymbol) {
1984
2028
  return x.value;
1985
2029
  }
@@ -2007,9 +2051,12 @@ export let format_to_cirru = (x) => {
2007
2051
  return writeCirruCode([xs], { useInline: false });
2008
2052
  };
2009
2053
  export let transform_code_to_cirru = (x) => {
2010
- if (x == null) {
2054
+ if (x === null) {
2011
2055
  return "nil";
2012
2056
  }
2057
+ else if (x === undefined) {
2058
+ return "&unit";
2059
+ }
2013
2060
  else if (x instanceof CalcitSymbol) {
2014
2061
  return x.value;
2015
2062
  }
@@ -10,9 +10,12 @@ import { CalcitSet } from "./js-set.mjs";
10
10
  import { CalcitEnumValue } from "./js-enum-value.mjs";
11
11
  import { CalcitCirruQuote } from "./js-cirru.mjs";
12
12
  let embedObject = (x) => {
13
- if (x == null) {
13
+ if (x === null) {
14
14
  return null;
15
15
  }
16
+ if (x === undefined) {
17
+ return span({ whiteSpace: "pre", color: hsl(240, 70, 50) }, "&unit");
18
+ }
16
19
  if (typeof x === "string") {
17
20
  return span({ whiteSpace: "pre", color: hsl(120, 70, 50), maxWidth: "100vw" }, `|${x}`);
18
21
  }
@@ -61,6 +64,12 @@ let td = (style, ...children) => {
61
64
  };
62
65
  /** handle null value in nested data */
63
66
  let saveString = (v) => {
67
+ if (v === null) {
68
+ return "nil";
69
+ }
70
+ if (v === undefined) {
71
+ return "&unit";
72
+ }
64
73
  if (typeof v === "string") {
65
74
  if (v.match(/[\s\"\n\t\,]/)) {
66
75
  return `"|${v}"`;
@@ -69,11 +78,11 @@ let saveString = (v) => {
69
78
  return `|${v}`;
70
79
  }
71
80
  }
72
- else if (v != null && v.toString) {
81
+ else if (v.toString) {
73
82
  return v.toString();
74
83
  }
75
84
  else {
76
- return "nil";
85
+ return String(v);
77
86
  }
78
87
  };
79
88
  export let load_console_formatter_$x_ = () => {
package/lib/js-cirru.mjs CHANGED
@@ -4,7 +4,7 @@ import { CalcitList, CalcitSliceList } from "./js-list.mjs";
4
4
  import { CalcitStructValue } from "./js-struct-value.mjs";
5
5
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
6
6
  import { CalcitSet } from "./js-set.mjs";
7
- import { CalcitTag, CalcitSymbol, CalcitRecur, newTag } from "./calcit-data.mjs";
7
+ import { CalcitTag, CalcitSymbol, CalcitRecur, newTag, compareTagNames } from "./calcit-data.mjs";
8
8
  import { CalcitEnumValue } from "./js-enum-value.mjs";
9
9
  import { CalcitEnumDef } from "./js-enum-def.mjs";
10
10
  import { CalcitImpl } from "./js-impl.mjs";
@@ -79,9 +79,12 @@ export let format_cirru_one_liner = (data) => {
79
79
  };
80
80
  /** better use string version of Cirru EDN in future */
81
81
  export let to_cirru_edn = (x) => {
82
- if (x == null) {
82
+ if (x === null) {
83
83
  return "nil";
84
84
  }
85
+ if (x === undefined) {
86
+ throw new Error("Cirru EDN cannot encode &unit");
87
+ }
85
88
  if (typeof x === "string") {
86
89
  return `|${x}`;
87
90
  }
@@ -364,9 +367,7 @@ const extract_cirru_edn_inner = (x, options, preserveSourceEntries) => {
364
367
  throw new Error(`Expected field pairs for struct, got: ${pair}`);
365
368
  }
366
369
  });
367
- entries.sort((a, b) => {
368
- return a[0].cmp(b[0]);
369
- });
370
+ entries.sort((a, b) => compareTagNames(a[0], b[0]));
370
371
  let fields = [];
371
372
  let values = [];
372
373
  for (let idx = 0; idx < entries.length; idx++) {
package/lib/js-impl.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { castTag, findInFields, toString } from "./calcit-data.mjs";
1
+ import { canonicalizeTagPairs, castTag, findInFields, toString } from "./calcit-data.mjs";
2
2
  const CALCIT_IMPL_BRAND = Symbol.for("@calcit/procs/CalcitImpl");
3
3
  export class CalcitImpl {
4
4
  static [Symbol.hasInstance](value) {
@@ -29,10 +29,11 @@ export class CalcitImpl {
29
29
  // optimized dependencies. A global, non-enumerable brand keeps impl values
30
30
  // recognizable across those otherwise distinct module instances.
31
31
  Object.defineProperty(this, CALCIT_IMPL_BRAND, { value: true });
32
+ const [canonicalFields, canonicalValues] = canonicalizeTagPairs(fields, values, "CalcitImpl");
32
33
  this.name = name;
33
34
  this.origin = origin;
34
- this.fields = fields;
35
- this.values = values;
35
+ this.fields = canonicalFields;
36
+ this.values = canonicalValues;
36
37
  this.cachedHash = null;
37
38
  }
38
39
  get(k) {
@@ -10,6 +10,6 @@ import { CalcitSet as CalcitSet } from "./js-set.mjs";
10
10
  import { CalcitEnumValue } from "./js-enum-value.mjs";
11
11
  import { CalcitCirruQuote } from "./js-cirru.mjs";
12
12
  import { CalcitTrait } from "./js-trait.mjs";
13
- export type CalcitValue = string | number | boolean | CalcitMap | CalcitSliceMap | CalcitList | CalcitSliceList | CalcitSet | CalcitTag | CalcitSymbol | CalcitRef | CalcitEnumValue | CalcitFn | CalcitRecur | CalcitStructValue | CalcitImpl | CalcitTrait | CalcitStructDef | CalcitEnumDef | CalcitCirruQuote | null;
13
+ export type CalcitValue = string | number | boolean | CalcitMap | CalcitSliceMap | CalcitList | CalcitSliceList | CalcitSet | CalcitTag | CalcitSymbol | CalcitRef | CalcitEnumValue | CalcitFn | CalcitRecur | CalcitStructValue | CalcitImpl | CalcitTrait | CalcitStructDef | CalcitEnumDef | CalcitCirruQuote | undefined | null;
14
14
  export declare let isLiteral: (x: CalcitValue) => boolean;
15
15
  export declare let _$n_compare: (a: CalcitValue, b: CalcitValue) => number;
package/lib/js-primes.mjs CHANGED
@@ -27,28 +27,31 @@ export let isLiteral = (x) => {
27
27
  var PseudoTypeIndex;
28
28
  (function (PseudoTypeIndex) {
29
29
  PseudoTypeIndex[PseudoTypeIndex["nil"] = 0] = "nil";
30
- PseudoTypeIndex[PseudoTypeIndex["bool"] = 1] = "bool";
31
- PseudoTypeIndex[PseudoTypeIndex["number"] = 2] = "number";
32
- PseudoTypeIndex[PseudoTypeIndex["symbol"] = 3] = "symbol";
33
- PseudoTypeIndex[PseudoTypeIndex["tag"] = 4] = "tag";
34
- PseudoTypeIndex[PseudoTypeIndex["string"] = 5] = "string";
35
- PseudoTypeIndex[PseudoTypeIndex["ref"] = 6] = "ref";
36
- PseudoTypeIndex[PseudoTypeIndex["enum_value"] = 7] = "enum_value";
37
- PseudoTypeIndex[PseudoTypeIndex["recur"] = 8] = "recur";
38
- PseudoTypeIndex[PseudoTypeIndex["list"] = 9] = "list";
39
- PseudoTypeIndex[PseudoTypeIndex["set"] = 10] = "set";
40
- PseudoTypeIndex[PseudoTypeIndex["map"] = 11] = "map";
41
- PseudoTypeIndex[PseudoTypeIndex["struct_value"] = 12] = "struct_value";
42
- PseudoTypeIndex[PseudoTypeIndex["impl"] = 13] = "impl";
43
- PseudoTypeIndex[PseudoTypeIndex["struct_def"] = 14] = "struct_def";
44
- PseudoTypeIndex[PseudoTypeIndex["enum_def"] = 15] = "enum_def";
45
- PseudoTypeIndex[PseudoTypeIndex["fn"] = 16] = "fn";
46
- PseudoTypeIndex[PseudoTypeIndex["cirru_quote"] = 17] = "cirru_quote";
30
+ PseudoTypeIndex[PseudoTypeIndex["unit"] = 1] = "unit";
31
+ PseudoTypeIndex[PseudoTypeIndex["bool"] = 2] = "bool";
32
+ PseudoTypeIndex[PseudoTypeIndex["number"] = 3] = "number";
33
+ PseudoTypeIndex[PseudoTypeIndex["symbol"] = 4] = "symbol";
34
+ PseudoTypeIndex[PseudoTypeIndex["tag"] = 5] = "tag";
35
+ PseudoTypeIndex[PseudoTypeIndex["string"] = 6] = "string";
36
+ PseudoTypeIndex[PseudoTypeIndex["ref"] = 7] = "ref";
37
+ PseudoTypeIndex[PseudoTypeIndex["enum_value"] = 8] = "enum_value";
38
+ PseudoTypeIndex[PseudoTypeIndex["recur"] = 9] = "recur";
39
+ PseudoTypeIndex[PseudoTypeIndex["list"] = 10] = "list";
40
+ PseudoTypeIndex[PseudoTypeIndex["set"] = 11] = "set";
41
+ PseudoTypeIndex[PseudoTypeIndex["map"] = 12] = "map";
42
+ PseudoTypeIndex[PseudoTypeIndex["struct_value"] = 13] = "struct_value";
43
+ PseudoTypeIndex[PseudoTypeIndex["impl"] = 14] = "impl";
44
+ PseudoTypeIndex[PseudoTypeIndex["struct_def"] = 15] = "struct_def";
45
+ PseudoTypeIndex[PseudoTypeIndex["enum_def"] = 16] = "enum_def";
46
+ PseudoTypeIndex[PseudoTypeIndex["fn"] = 17] = "fn";
47
+ PseudoTypeIndex[PseudoTypeIndex["cirru_quote"] = 18] = "cirru_quote";
47
48
  })(PseudoTypeIndex || (PseudoTypeIndex = {}));
48
49
  let typeAsInt = (x) => {
49
50
  // based on order used in Ord trait
50
- if (x == null)
51
+ if (x === null)
51
52
  return PseudoTypeIndex.nil;
53
+ if (x === undefined)
54
+ return PseudoTypeIndex.unit;
52
55
  let t = typeof x;
53
56
  if (t === "boolean")
54
57
  return PseudoTypeIndex.bool;
@@ -106,6 +109,7 @@ export let _$n_compare = (a, b) => {
106
109
  if (ta === tb) {
107
110
  switch (ta) {
108
111
  case PseudoTypeIndex.nil:
112
+ case PseudoTypeIndex.unit:
109
113
  return 0;
110
114
  case PseudoTypeIndex.bool:
111
115
  return rawCompare(a, b);
@@ -1,13 +1,11 @@
1
- import { toString } from "./calcit-data.mjs";
1
+ import { canonicalizeTagPairs, toString } from "./calcit-data.mjs";
2
2
  import { CalcitImpl } from "./js-impl.mjs";
3
3
  export class CalcitStructDef {
4
4
  constructor(name, fields, fieldTypes, impls = []) {
5
- if (fields.length !== fieldTypes.length) {
6
- throw new Error("CalcitStructDef: fields and fieldTypes length mismatch");
7
- }
5
+ const [canonicalFields, canonicalTypes] = canonicalizeTagPairs(fields, fieldTypes, "CalcitStructDef");
8
6
  this.name = name;
9
- this.fields = fields;
10
- this.fieldTypes = fieldTypes;
7
+ this.fields = canonicalFields;
8
+ this.fieldTypes = canonicalTypes;
11
9
  this.impls = impls;
12
10
  this.cachedHash = null;
13
11
  }
@@ -14,6 +14,10 @@ export declare class CalcitStructValue {
14
14
  getRequired(k: CalcitValue): CalcitValue;
15
15
  getOrNil(k: CalcitValue): CalcitValue;
16
16
  assoc(k: CalcitValue, v: CalcitValue): CalcitStructValue;
17
+ nthAt(index: CalcitValue, field: CalcitValue): CalcitValue;
18
+ assocAt(index: CalcitValue, field: CalcitValue, value: CalcitValue): CalcitStructValue;
19
+ withAt(...triples: CalcitValue[]): CalcitStructValue;
20
+ private assertFieldAt;
17
21
  /** return -1 for missing */
18
22
  findIndex(k: CalcitValue): number;
19
23
  contains(k: CalcitValue): boolean;
@@ -23,7 +27,7 @@ export declare class CalcitStructValue {
23
27
  export declare let new_struct_value: (name: CalcitValue, ...fields: Array<CalcitValue>) => CalcitValue;
24
28
  export declare let new_impl_struct_value: (impl: CalcitImpl, name: CalcitValue, ...fields: Array<CalcitValue>) => CalcitValue;
25
29
  /** Loose record: `?{} :field1 val1 :field2 val2` – record without a declared struct.
26
- * Fields are sorted by tag index. The record name is "?" (sentinel). */
30
+ * Fields use the same lexical layout as named structs. The record name is "_". */
27
31
  export declare let _$q__$M_: (...xs: Array<CalcitValue>) => CalcitValue;
28
32
  export declare let fieldsEqual: (xs: Array<CalcitTag>, ys: Array<CalcitTag>) => boolean;
29
33
  export declare let _$n__PCT__$M_: (proto: CalcitValue, ...xs: Array<CalcitValue>) => CalcitValue;