@calcit/procs 0.11.0-a8 → 0.11.0-a9

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.
Binary file
@@ -3,6 +3,7 @@ import { overwriteComparator } from "@calcit/ternary-tree";
3
3
  import { overwriteMapComparator } from "./js-map.mjs";
4
4
  import { disableListStructureCheck } from "@calcit/ternary-tree";
5
5
  import { CalcitRecord, fieldsEqual } from "./js-record.mjs";
6
+ import { CalcitImpl } from "./js-impl.mjs";
6
7
  import { CalcitStruct } from "./js-struct.mjs";
7
8
  import { CalcitEnum } from "./js-enum.mjs";
8
9
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
@@ -66,6 +67,9 @@ export let isNestedCalcitData = (x) => {
66
67
  if (x instanceof CalcitRecord) {
67
68
  return x.fields.length > 0;
68
69
  }
70
+ if (x instanceof CalcitImpl) {
71
+ return x.fields.length > 0;
72
+ }
69
73
  if (x instanceof CalcitSet) {
70
74
  return false;
71
75
  }
@@ -81,6 +85,9 @@ export let tipNestedCalcitData = (x) => {
81
85
  if (x instanceof CalcitRecord) {
82
86
  return "'%{}...";
83
87
  }
88
+ if (x instanceof CalcitImpl) {
89
+ return "'%impl...";
90
+ }
84
91
  if (x instanceof CalcitSet) {
85
92
  return "'#{}...";
86
93
  }
@@ -156,6 +163,7 @@ let defaultHash_set = valueHash("set:");
156
163
  let defaultHash_list = valueHash("list:");
157
164
  let defaultHash_map = valueHash("map:");
158
165
  let defaultHash_record = valueHash("record:");
166
+ let defaultHash_impl = valueHash("impl:");
159
167
  let defaultHash_struct = valueHash("struct:");
160
168
  let defaultHash_enum = valueHash("enum:");
161
169
  let defaultHash_cirru_quote = valueHash("cirru-quote:");
@@ -280,6 +288,16 @@ export let hashFunction = (x) => {
280
288
  x.cachedHash = base;
281
289
  return base;
282
290
  }
291
+ if (x instanceof CalcitImpl) {
292
+ let base = defaultHash_impl;
293
+ base = mergeValueHash(base, hashFunction(x.name));
294
+ for (let idx = 0; idx < x.fields.length; idx++) {
295
+ base = mergeValueHash(base, hashFunction(x.fields[idx]));
296
+ base = mergeValueHash(base, hashFunction(x.values[idx]));
297
+ }
298
+ x.cachedHash = base;
299
+ return base;
300
+ }
283
301
  if (x instanceof CalcitStruct) {
284
302
  let base = defaultHash_struct;
285
303
  base = mergeValueHash(base, hashFunction(x.name));
@@ -376,6 +394,9 @@ export let toString = (x, escaped, disableJsDataWarning = false) => {
376
394
  if (x instanceof CalcitRecord) {
377
395
  return x.toString(disableJsDataWarning);
378
396
  }
397
+ if (x instanceof CalcitImpl) {
398
+ return x.toString(disableJsDataWarning);
399
+ }
379
400
  if (x instanceof CalcitStruct) {
380
401
  return x.toString(disableJsDataWarning);
381
402
  }
@@ -644,6 +665,26 @@ export let _$n__$e_ = (x, y) => {
644
665
  }
645
666
  return false;
646
667
  }
668
+ if (x instanceof CalcitImpl) {
669
+ if (y instanceof CalcitImpl) {
670
+ if (x.name !== y.name) {
671
+ return false;
672
+ }
673
+ if (!fieldsEqual(x.fields, y.fields)) {
674
+ return false;
675
+ }
676
+ if (x.values.length !== y.values.length) {
677
+ return false;
678
+ }
679
+ for (let idx = 0; idx < x.fields.length; idx++) {
680
+ if (!_$n__$e_(x.values[idx], y.values[idx])) {
681
+ return false;
682
+ }
683
+ }
684
+ return true;
685
+ }
686
+ return false;
687
+ }
647
688
  if (x instanceof CalcitStruct) {
648
689
  if (y instanceof CalcitStruct) {
649
690
  return x.name === y.name && fieldsEqual(x.fields, y.fields);
@@ -6,11 +6,13 @@ import { writeCirruCode } from "@cirru/writer.ts";
6
6
  import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, getStringName, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
7
7
  import { CalcitRef } from "./js-ref.mjs";
8
8
  import { CalcitRecord } from "./js-record.mjs";
9
+ import { CalcitImpl } from "./js-impl.mjs";
9
10
  import { CalcitStruct } from "./js-struct.mjs";
10
11
  import { CalcitEnum } from "./js-enum.mjs";
11
12
  import { CalcitTrait } from "./js-trait.mjs";
12
13
  export * from "./calcit-data.mjs";
13
14
  export * from "./js-record.mjs";
15
+ export * from "./js-impl.mjs";
14
16
  export * from "./js-struct.mjs";
15
17
  export * from "./js-enum.mjs";
16
18
  export * from "./js-map.mjs";
@@ -62,6 +64,9 @@ export let type_of = (x) => {
62
64
  if (x instanceof CalcitRecord) {
63
65
  return newTag("record");
64
66
  }
67
+ if (x instanceof CalcitImpl) {
68
+ return newTag("impl");
69
+ }
65
70
  if (x instanceof CalcitStruct) {
66
71
  return newTag("struct");
67
72
  }
@@ -195,6 +200,45 @@ export let defenum = (name, ...variants) => {
195
200
  const prototype = new CalcitRecord(enumName, tags, values, null);
196
201
  return new CalcitEnum(prototype, null);
197
202
  };
203
+ export let _$n_impl_$o__$o_new = (name, ...pairs) => {
204
+ if (name === undefined)
205
+ throw new Error("&impl::new expected arguments");
206
+ const implName = castTag(name);
207
+ if (pairs.length === 0) {
208
+ return new CalcitImpl(implName, [], []);
209
+ }
210
+ const entries = [];
211
+ for (let idx = 0; idx < pairs.length; idx++) {
212
+ const pairValue = pairs[idx];
213
+ let fieldTag;
214
+ let value;
215
+ if (pairValue instanceof CalcitTuple) {
216
+ if (pairValue.extra.length !== 1) {
217
+ throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
218
+ }
219
+ fieldTag = castTag(pairValue.tag);
220
+ value = pairValue.extra[0];
221
+ }
222
+ else {
223
+ const pair = list_items(pairValue);
224
+ if (pair.length !== 2) {
225
+ throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
226
+ }
227
+ fieldTag = castTag(pair[0]);
228
+ value = pair[1];
229
+ }
230
+ entries.push({ tag: fieldTag, value });
231
+ }
232
+ entries.sort((a, b) => a.tag.idx - b.tag.idx);
233
+ for (let i = 1; i < entries.length; i++) {
234
+ if (entries[i - 1].tag.value === entries[i].tag.value) {
235
+ throw new Error(`&impl::new duplicated field: ${entries[i].tag.toString()}`);
236
+ }
237
+ }
238
+ const fields = entries.map((entry) => entry.tag);
239
+ const values = entries.map((entry) => entry.value);
240
+ return new CalcitImpl(implName, fields, values);
241
+ };
198
242
  export let _$n_struct_$o__$o_new = (name, ...entries) => {
199
243
  return defstruct(name, ...entries);
200
244
  };
@@ -385,6 +429,12 @@ export let _$n_tuple_$o_count = function (xs) {
385
429
  return xs.count();
386
430
  throw new Error("Does not support `count` on this type");
387
431
  };
432
+ const coerce_impl = (value, procName) => {
433
+ if (value instanceof CalcitImpl) {
434
+ return value;
435
+ }
436
+ throw new Error(`${procName} expects trait impls as impls`);
437
+ };
388
438
  export let _$n_tuple_$o_impls = function (x) {
389
439
  if (arguments.length !== 1)
390
440
  throw new Error("&tuple:impls takes 1 argument");
@@ -400,21 +450,16 @@ export let _$n_tuple_$o_with_impls = function (x, y) {
400
450
  throw new Error("&tuple:with-impls takes 2 arguments");
401
451
  if (!(x instanceof CalcitTuple))
402
452
  throw new Error("&tuple:with-impls expects a tuple");
403
- if (!(y instanceof CalcitRecord))
404
- throw new Error("&tuple:with-impls expects second argument in record");
405
- return new CalcitTuple(x.tag, x.extra, [y], x.enumPrototype);
453
+ const impl = coerce_impl(y, "&tuple:with-impls");
454
+ return new CalcitTuple(x.tag, x.extra, [impl], x.enumPrototype);
406
455
  };
407
456
  export let _$n_tuple_$o_impl_traits = function (x, ...traits) {
408
457
  if (traits.length < 1)
409
458
  throw new Error("&tuple:impl-traits takes 2+ arguments");
410
459
  if (!(x instanceof CalcitTuple))
411
460
  throw new Error("&tuple:impl-traits expects a tuple");
412
- for (let idx = 0; idx < traits.length; idx++) {
413
- if (!(traits[idx] instanceof CalcitRecord)) {
414
- throw new Error("&tuple:impl-traits expects trait impls as records");
415
- }
416
- }
417
- return new CalcitTuple(x.tag, x.extra, x.impls.concat(traits), x.enumPrototype);
461
+ const impls = traits.map((trait) => coerce_impl(trait, "&tuple:impl-traits"));
462
+ return new CalcitTuple(x.tag, x.extra, x.impls.concat(impls), x.enumPrototype);
418
463
  };
419
464
  export let _$n_tuple_$o_enum = function (x) {
420
465
  if (arguments.length !== 1)
@@ -547,40 +592,28 @@ export let _$n_record_$o_impl_traits = function (xs, ...traits) {
547
592
  throw new Error("&record:impl-traits takes 2+ arguments");
548
593
  if (!(xs instanceof CalcitRecord))
549
594
  throw new Error("&record:impl-traits expected a record");
550
- for (let idx = 0; idx < traits.length; idx++) {
551
- if (!(traits[idx] instanceof CalcitRecord)) {
552
- throw new Error("&record:impl-traits expects trait impls as records");
553
- }
554
- }
555
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(traits));
595
+ const impls = traits.map((trait) => coerce_impl(trait, "&record:impl-traits"));
596
+ return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(impls));
556
597
  };
557
598
  export let _$n_struct_$o_impl_traits = function (xs, ...traits) {
558
599
  if (traits.length < 1)
559
600
  throw new Error("&struct:impl-traits takes 2+ arguments");
560
601
  if (!(xs instanceof CalcitStruct))
561
602
  throw new Error("&struct:impl-traits expected a struct");
562
- for (let idx = 0; idx < traits.length; idx++) {
563
- if (!(traits[idx] instanceof CalcitRecord)) {
564
- throw new Error("&struct:impl-traits expects trait impls as records");
565
- }
566
- }
567
- const impls = xs.impls ?? [];
568
- return new CalcitStruct(xs.name, xs.fields, xs.fieldTypes, impls.concat(traits));
603
+ const addedImpls = traits.map((trait) => coerce_impl(trait, "&struct:impl-traits"));
604
+ const baseImpls = xs.impls ?? [];
605
+ return new CalcitStruct(xs.name, xs.fields, xs.fieldTypes, baseImpls.concat(addedImpls));
569
606
  };
570
607
  export let _$n_enum_$o_impl_traits = function (xs, ...traits) {
571
608
  if (traits.length < 1)
572
609
  throw new Error("&enum:impl-traits takes 2+ arguments");
573
- for (let idx = 0; idx < traits.length; idx++) {
574
- if (!(traits[idx] instanceof CalcitRecord)) {
575
- throw new Error("&enum:impl-traits expects trait impls as records");
576
- }
577
- }
610
+ const addedImpls = traits.map((trait) => coerce_impl(trait, "&enum:impl-traits"));
578
611
  if (xs instanceof CalcitEnum) {
579
- const impls = xs.impls ?? [];
580
- return new CalcitEnum(xs.prototype, impls.concat(traits));
612
+ const baseImpls = xs.impls ?? [];
613
+ return new CalcitEnum(xs.prototype, baseImpls.concat(addedImpls));
581
614
  }
582
615
  if (xs instanceof CalcitRecord) {
583
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(traits));
616
+ return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(addedImpls));
584
617
  }
585
618
  throw new Error("&enum:impl-traits expected an enum or enum record");
586
619
  };
@@ -1493,7 +1526,8 @@ export let _PCT__PCT__$o__$o_ = (impl, enumPrototype, tag, ...extra) => {
1493
1526
  throw new Error(`Expected variant definition to be a list, got ${variantDefinition}`);
1494
1527
  }
1495
1528
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1496
- return new CalcitTuple(tag, extra, [impl], tupleEnumPrototype);
1529
+ const implValue = coerce_impl(impl, "%:: with impl");
1530
+ return new CalcitTuple(tag, extra, [implValue], tupleEnumPrototype);
1497
1531
  };
1498
1532
  let calcit_builtin_impls = {
1499
1533
  number: null,
@@ -1516,10 +1550,14 @@ export function invoke_method_closure(p) {
1516
1550
  function normalize_builtin_impls(entry) {
1517
1551
  if (entry == null)
1518
1552
  return null;
1519
- if (entry instanceof CalcitRecord)
1553
+ if (entry instanceof CalcitImpl)
1520
1554
  return [entry];
1521
1555
  if (entry instanceof CalcitList || entry instanceof CalcitSliceList) {
1522
- return list_items(entry);
1556
+ return list_items(entry).map((item) => {
1557
+ if (item instanceof CalcitImpl)
1558
+ return item;
1559
+ throw new Error(`invoke-method expects impls in list, but received: ${toString(item, true)}`);
1560
+ });
1523
1561
  }
1524
1562
  return null;
1525
1563
  }
@@ -1641,7 +1679,7 @@ export function _$n_inspect_methods(obj, note) {
1641
1679
  implsInOrder.push(impl);
1642
1680
  idx += reverse ? -1 : 1;
1643
1681
  }
1644
- console.log(`Impl records (high → low precedence): ${implsInOrder.length}`);
1682
+ console.log(`Impls (high → low precedence): ${implsInOrder.length}`);
1645
1683
  for (let i = 0; i < implsInOrder.length; i++) {
1646
1684
  let impl = implsInOrder[i];
1647
1685
  let names = [];
@@ -1689,7 +1727,7 @@ export function _$n_trait_call(traitDef, method, obj, ...args) {
1689
1727
  }
1690
1728
  idx += reverse ? -1 : 1;
1691
1729
  }
1692
- throw new Error(`&trait-call: cannot find impl for trait ${traitDef.name.toString()} on ${toString(obj, true)}. Hint: use defimpl to create impl records tagged by trait.`);
1730
+ throw new Error(`&trait-call: cannot find impl for trait ${traitDef.name.toString()} on ${toString(obj, true)}. Hint: use defimpl to create impls tagged by trait.`);
1693
1731
  }
1694
1732
  export let _$n_map_$o_to_list = (m) => {
1695
1733
  if (m instanceof CalcitMap || m instanceof CalcitSliceMap) {
package/lib/js-cirru.mjs CHANGED
@@ -7,6 +7,7 @@ import { CalcitSet } from "./js-set.mjs";
7
7
  import { CalcitTag, CalcitSymbol, CalcitRecur, newTag } from "./calcit-data.mjs";
8
8
  import { CalcitTuple } from "./js-tuple.mjs";
9
9
  import { CalcitEnum } from "./js-enum.mjs";
10
+ import { CalcitImpl } from "./js-impl.mjs";
10
11
  import { CalcitRef } from "./js-ref.mjs";
11
12
  import { deepEqual } from "@calcit/ternary-tree/lib/utils.mjs";
12
13
  import { atom } from "./js-ref.mjs";
@@ -182,6 +183,9 @@ export let to_cirru_edn = (x) => {
182
183
  else if (x.tag instanceof CalcitRecord) {
183
184
  return ["%::", enumTag, x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
184
185
  }
186
+ else if (x.tag instanceof CalcitImpl) {
187
+ return ["%::", enumTag, x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
188
+ }
185
189
  else {
186
190
  throw new Error(`Unsupported tag for EDN: ${x.tag}`);
187
191
  }
@@ -192,6 +196,9 @@ export let to_cirru_edn = (x) => {
192
196
  else if (x.tag instanceof CalcitRecord) {
193
197
  return ["::", x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
194
198
  }
199
+ else if (x.tag instanceof CalcitImpl) {
200
+ return ["::", x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
201
+ }
195
202
  else {
196
203
  throw new Error(`Unsupported tag for EDN: ${x.tag}`);
197
204
  }
package/lib/js-enum.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { CalcitRecord } from "./js-record.mjs";
1
+ import { CalcitImpl } from "./js-impl.mjs";
2
2
  export class CalcitEnum {
3
3
  constructor(prototype, impls = []) {
4
4
  this.prototype = prototype;
@@ -9,13 +9,13 @@ export class CalcitEnum {
9
9
  return this.prototype.name.value;
10
10
  }
11
11
  withImpls(impls) {
12
- if (impls instanceof CalcitRecord) {
12
+ if (impls instanceof CalcitImpl) {
13
13
  return new CalcitEnum(this.prototype, [impls]);
14
14
  }
15
15
  else if (Array.isArray(impls)) {
16
16
  return new CalcitEnum(this.prototype, impls);
17
17
  }
18
- throw new Error("Expected a record as implementation");
18
+ throw new Error("Expected an impl as implementation");
19
19
  }
20
20
  toString() {
21
21
  return `(%enum :${this.prototype.name.value})`;
@@ -0,0 +1,33 @@
1
+ import { castTag, findInFields, toString } from "./calcit-data.mjs";
2
+ export class CalcitImpl {
3
+ constructor(name, fields, values) {
4
+ this.name = name;
5
+ this.fields = fields;
6
+ this.values = values;
7
+ this.cachedHash = null;
8
+ }
9
+ get(k) {
10
+ let field = castTag(k);
11
+ let idx = findInFields(this.fields, field);
12
+ if (idx >= 0) {
13
+ return this.values[idx];
14
+ }
15
+ throw new Error(`Cannot find :${field} among (${this.fields.join(",")})`);
16
+ }
17
+ getOrNil(k) {
18
+ let field = castTag(k);
19
+ let idx = findInFields(this.fields, field);
20
+ if (idx >= 0) {
21
+ return this.values[idx];
22
+ }
23
+ return undefined;
24
+ }
25
+ toString(disableJsDataWarning = false) {
26
+ const parts = ["(%impl ", this.name.toString()];
27
+ for (let idx = 0; idx < this.fields.length; idx++) {
28
+ parts.push(" (", this.fields[idx].toString(), " ", toString(this.values[idx], true, disableJsDataWarning), ")");
29
+ }
30
+ parts.push(")");
31
+ return parts.join("");
32
+ }
33
+ }
package/lib/js-primes.mjs CHANGED
@@ -2,6 +2,7 @@ import { CalcitTag, CalcitSymbol, CalcitRecur } from "./calcit-data.mjs";
2
2
  import { CalcitRef } from "./js-ref.mjs";
3
3
  import { CalcitList, CalcitSliceList } from "./js-list.mjs";
4
4
  import { CalcitRecord } from "./js-record.mjs";
5
+ import { CalcitImpl } from "./js-impl.mjs";
5
6
  import { CalcitStruct } from "./js-struct.mjs";
6
7
  import { CalcitEnum } from "./js-enum.mjs";
7
8
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
@@ -38,10 +39,11 @@ var PseudoTypeIndex;
38
39
  PseudoTypeIndex[PseudoTypeIndex["set"] = 10] = "set";
39
40
  PseudoTypeIndex[PseudoTypeIndex["map"] = 11] = "map";
40
41
  PseudoTypeIndex[PseudoTypeIndex["record"] = 12] = "record";
41
- PseudoTypeIndex[PseudoTypeIndex["struct"] = 13] = "struct";
42
- PseudoTypeIndex[PseudoTypeIndex["enum_type"] = 14] = "enum_type";
43
- PseudoTypeIndex[PseudoTypeIndex["fn"] = 15] = "fn";
44
- PseudoTypeIndex[PseudoTypeIndex["cirru_quote"] = 16] = "cirru_quote";
42
+ PseudoTypeIndex[PseudoTypeIndex["impl"] = 13] = "impl";
43
+ PseudoTypeIndex[PseudoTypeIndex["struct"] = 14] = "struct";
44
+ PseudoTypeIndex[PseudoTypeIndex["enum_type"] = 15] = "enum_type";
45
+ PseudoTypeIndex[PseudoTypeIndex["fn"] = 16] = "fn";
46
+ PseudoTypeIndex[PseudoTypeIndex["cirru_quote"] = 17] = "cirru_quote";
45
47
  })(PseudoTypeIndex || (PseudoTypeIndex = {}));
46
48
  let typeAsInt = (x) => {
47
49
  // based on order used in Ord trait
@@ -72,6 +74,8 @@ let typeAsInt = (x) => {
72
74
  return PseudoTypeIndex.map;
73
75
  if (x instanceof CalcitRecord)
74
76
  return PseudoTypeIndex.record;
77
+ if (x instanceof CalcitImpl)
78
+ return PseudoTypeIndex.impl;
75
79
  if (x instanceof CalcitStruct)
76
80
  return PseudoTypeIndex.struct;
77
81
  if (x instanceof CalcitEnum)
package/lib/js-record.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { CalcitImpl } from "./js-impl.mjs";
1
2
  import { castTag, toString, findInFields } from "./calcit-data.mjs";
2
3
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
3
4
  export class CalcitRecord {
@@ -70,11 +71,11 @@ export class CalcitRecord {
70
71
  return parts.join("");
71
72
  }
72
73
  withImpls(impl) {
73
- if (impl instanceof CalcitRecord) {
74
+ if (impl instanceof CalcitImpl) {
74
75
  return new CalcitRecord(this.name, this.fields, this.values, [impl]);
75
76
  }
76
77
  else {
77
- throw new Error("Expected a record");
78
+ throw new Error("Expected an impl");
78
79
  }
79
80
  }
80
81
  }
package/lib/js-struct.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { toString } from "./calcit-data.mjs";
2
- import { CalcitRecord } from "./js-record.mjs";
2
+ import { CalcitImpl } from "./js-impl.mjs";
3
3
  export class CalcitStruct {
4
4
  constructor(name, fields, fieldTypes, impls = []) {
5
5
  if (fields.length !== fieldTypes.length) {
@@ -12,13 +12,13 @@ export class CalcitStruct {
12
12
  this.cachedHash = null;
13
13
  }
14
14
  withImpls(impls) {
15
- if (impls instanceof CalcitRecord) {
15
+ if (impls instanceof CalcitImpl) {
16
16
  return new CalcitStruct(this.name, this.fields, this.fieldTypes, [impls]);
17
17
  }
18
18
  else if (Array.isArray(impls)) {
19
19
  return new CalcitStruct(this.name, this.fields, this.fieldTypes, impls);
20
20
  }
21
- throw new Error("Expected a record as implementation");
21
+ throw new Error("Expected an impl as implementation");
22
22
  }
23
23
  toString(disableJsDataWarning = false) {
24
24
  if (this.fields.length !== this.fieldTypes.length) {
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.11.0-a8",
3
+ "version": "0.11.0-a9",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.0.9",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.11.0-a8",
3
+ "version": "0.11.0-a9",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.0.9",
@@ -4,6 +4,7 @@ import { overwriteMapComparator } from "./js-map.mjs";
4
4
  import { disableListStructureCheck } from "@calcit/ternary-tree";
5
5
 
6
6
  import { CalcitRecord, fieldsEqual } from "./js-record.mjs";
7
+ import { CalcitImpl } from "./js-impl.mjs";
7
8
  import { CalcitStruct } from "./js-struct.mjs";
8
9
  import { CalcitEnum } from "./js-enum.mjs";
9
10
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
@@ -82,6 +83,9 @@ export let isNestedCalcitData = (x: CalcitValue): boolean => {
82
83
  if (x instanceof CalcitRecord) {
83
84
  return x.fields.length > 0;
84
85
  }
86
+ if (x instanceof CalcitImpl) {
87
+ return x.fields.length > 0;
88
+ }
85
89
  if (x instanceof CalcitSet) {
86
90
  return false;
87
91
  }
@@ -98,6 +102,9 @@ export let tipNestedCalcitData = (x: CalcitValue): string => {
98
102
  if (x instanceof CalcitRecord) {
99
103
  return "'%{}...";
100
104
  }
105
+ if (x instanceof CalcitImpl) {
106
+ return "'%impl...";
107
+ }
101
108
  if (x instanceof CalcitSet) {
102
109
  return "'#{}...";
103
110
  }
@@ -180,6 +187,7 @@ let defaultHash_set = valueHash("set:");
180
187
  let defaultHash_list = valueHash("list:");
181
188
  let defaultHash_map = valueHash("map:");
182
189
  let defaultHash_record = valueHash("record:");
190
+ let defaultHash_impl = valueHash("impl:");
183
191
  let defaultHash_struct = valueHash("struct:");
184
192
  let defaultHash_enum = valueHash("enum:");
185
193
  let defaultHash_cirru_quote = valueHash("cirru-quote:");
@@ -309,6 +317,16 @@ export let hashFunction = (x: CalcitValue): Hash => {
309
317
  x.cachedHash = base;
310
318
  return base;
311
319
  }
320
+ if (x instanceof CalcitImpl) {
321
+ let base = defaultHash_impl;
322
+ base = mergeValueHash(base, hashFunction(x.name));
323
+ for (let idx = 0; idx < x.fields.length; idx++) {
324
+ base = mergeValueHash(base, hashFunction(x.fields[idx]));
325
+ base = mergeValueHash(base, hashFunction(x.values[idx]));
326
+ }
327
+ x.cachedHash = base;
328
+ return base;
329
+ }
312
330
  if (x instanceof CalcitStruct) {
313
331
  let base = defaultHash_struct;
314
332
  base = mergeValueHash(base, hashFunction(x.name));
@@ -405,6 +423,9 @@ export let toString = (x: CalcitValue, escaped: boolean, disableJsDataWarning: b
405
423
  if (x instanceof CalcitRecord) {
406
424
  return x.toString(disableJsDataWarning);
407
425
  }
426
+ if (x instanceof CalcitImpl) {
427
+ return x.toString(disableJsDataWarning);
428
+ }
408
429
  if (x instanceof CalcitStruct) {
409
430
  return x.toString(disableJsDataWarning);
410
431
  }
@@ -682,6 +703,26 @@ export let _$n__$e_ = (x: CalcitValue, y: CalcitValue): boolean => {
682
703
  }
683
704
  return false;
684
705
  }
706
+ if (x instanceof CalcitImpl) {
707
+ if (y instanceof CalcitImpl) {
708
+ if (x.name !== y.name) {
709
+ return false;
710
+ }
711
+ if (!fieldsEqual(x.fields, y.fields)) {
712
+ return false;
713
+ }
714
+ if (x.values.length !== y.values.length) {
715
+ return false;
716
+ }
717
+ for (let idx = 0; idx < x.fields.length; idx++) {
718
+ if (!_$n__$e_(x.values[idx], y.values[idx])) {
719
+ return false;
720
+ }
721
+ }
722
+ return true;
723
+ }
724
+ return false;
725
+ }
685
726
  if (x instanceof CalcitStruct) {
686
727
  if (y instanceof CalcitStruct) {
687
728
  return x.name === y.name && fieldsEqual(x.fields, y.fields);
@@ -23,12 +23,14 @@ import {
23
23
 
24
24
  import { CalcitRef } from "./js-ref.mjs";
25
25
  import { fieldsEqual, CalcitRecord } from "./js-record.mjs";
26
+ import { CalcitImpl } from "./js-impl.mjs";
26
27
  import { CalcitStruct } from "./js-struct.mjs";
27
28
  import { CalcitEnum } from "./js-enum.mjs";
28
29
  import { CalcitTrait } from "./js-trait.mjs";
29
30
 
30
31
  export * from "./calcit-data.mjs";
31
32
  export * from "./js-record.mjs";
33
+ export * from "./js-impl.mjs";
32
34
  export * from "./js-struct.mjs";
33
35
  export * from "./js-enum.mjs";
34
36
  export * from "./js-map.mjs";
@@ -83,6 +85,9 @@ export let type_of = (x: any): CalcitTag => {
83
85
  if (x instanceof CalcitRecord) {
84
86
  return newTag("record");
85
87
  }
88
+ if (x instanceof CalcitImpl) {
89
+ return newTag("impl");
90
+ }
86
91
  if (x instanceof CalcitStruct) {
87
92
  return newTag("struct");
88
93
  }
@@ -228,6 +233,44 @@ export let defenum = (name: CalcitValue, ...variants: CalcitValue[]): CalcitEnum
228
233
  return new CalcitEnum(prototype, null);
229
234
  };
230
235
 
236
+ export let _$n_impl_$o__$o_new = (name: CalcitValue, ...pairs: CalcitValue[]): CalcitImpl => {
237
+ if (name === undefined) throw new Error("&impl::new expected arguments");
238
+ const implName = castTag(name);
239
+ if (pairs.length === 0) {
240
+ return new CalcitImpl(implName, [], []);
241
+ }
242
+ const entries: Array<{ tag: CalcitTag; value: CalcitValue }> = [];
243
+ for (let idx = 0; idx < pairs.length; idx++) {
244
+ const pairValue = pairs[idx];
245
+ let fieldTag: CalcitTag;
246
+ let value: CalcitValue;
247
+ if (pairValue instanceof CalcitTuple) {
248
+ if (pairValue.extra.length !== 1) {
249
+ throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
250
+ }
251
+ fieldTag = castTag(pairValue.tag);
252
+ value = pairValue.extra[0];
253
+ } else {
254
+ const pair = list_items(pairValue);
255
+ if (pair.length !== 2) {
256
+ throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
257
+ }
258
+ fieldTag = castTag(pair[0]);
259
+ value = pair[1];
260
+ }
261
+ entries.push({ tag: fieldTag, value });
262
+ }
263
+ entries.sort((a, b) => a.tag.idx - b.tag.idx);
264
+ for (let i = 1; i < entries.length; i++) {
265
+ if (entries[i - 1].tag.value === entries[i].tag.value) {
266
+ throw new Error(`&impl::new duplicated field: ${entries[i].tag.toString()}`);
267
+ }
268
+ }
269
+ const fields = entries.map((entry) => entry.tag);
270
+ const values = entries.map((entry) => entry.value);
271
+ return new CalcitImpl(implName, fields, values);
272
+ };
273
+
231
274
  export let _$n_struct_$o__$o_new = (name: CalcitValue, ...entries: CalcitValue[]): CalcitStruct => {
232
275
  return defstruct(name, ...entries);
233
276
  };
@@ -444,6 +487,13 @@ export let _$n_tuple_$o_count = function (xs: CalcitValue) {
444
487
  throw new Error("Does not support `count` on this type");
445
488
  };
446
489
 
490
+ const coerce_impl = (value: CalcitValue, procName: string): CalcitImpl => {
491
+ if (value instanceof CalcitImpl) {
492
+ return value;
493
+ }
494
+ throw new Error(`${procName} expects trait impls as impls`);
495
+ };
496
+
447
497
  export let _$n_tuple_$o_impls = function (x: CalcitTuple) {
448
498
  if (arguments.length !== 1) throw new Error("&tuple:impls takes 1 argument");
449
499
  return new CalcitSliceList(x.impls);
@@ -454,22 +504,18 @@ export let _$n_tuple_$o_params = function (x: CalcitTuple) {
454
504
  return new CalcitSliceList(x.extra);
455
505
  };
456
506
 
457
- export let _$n_tuple_$o_with_impls = function (x: CalcitTuple, y: CalcitRecord) {
507
+ export let _$n_tuple_$o_with_impls = function (x: CalcitTuple, y: CalcitValue) {
458
508
  if (arguments.length !== 2) throw new Error("&tuple:with-impls takes 2 arguments");
459
509
  if (!(x instanceof CalcitTuple)) throw new Error("&tuple:with-impls expects a tuple");
460
- if (!(y instanceof CalcitRecord)) throw new Error("&tuple:with-impls expects second argument in record");
461
- return new CalcitTuple(x.tag, x.extra, [y], x.enumPrototype);
510
+ const impl = coerce_impl(y, "&tuple:with-impls");
511
+ return new CalcitTuple(x.tag, x.extra, [impl], x.enumPrototype);
462
512
  };
463
513
 
464
514
  export let _$n_tuple_$o_impl_traits = function (x: CalcitValue, ...traits: CalcitValue[]) {
465
515
  if (traits.length < 1) throw new Error("&tuple:impl-traits takes 2+ arguments");
466
516
  if (!(x instanceof CalcitTuple)) throw new Error("&tuple:impl-traits expects a tuple");
467
- for (let idx = 0; idx < traits.length; idx++) {
468
- if (!(traits[idx] instanceof CalcitRecord)) {
469
- throw new Error("&tuple:impl-traits expects trait impls as records");
470
- }
471
- }
472
- return new CalcitTuple(x.tag, x.extra, x.impls.concat(traits as CalcitRecord[]), x.enumPrototype);
517
+ const impls = traits.map((trait) => coerce_impl(trait, "&tuple:impl-traits"));
518
+ return new CalcitTuple(x.tag, x.extra, x.impls.concat(impls), x.enumPrototype);
473
519
  };
474
520
 
475
521
  export let _$n_tuple_$o_enum = function (x: CalcitTuple) {
@@ -610,39 +656,27 @@ export let _$n_record_$o_impls = function (xs: CalcitValue) {
610
656
  export let _$n_record_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
611
657
  if (traits.length < 1) throw new Error("&record:impl-traits takes 2+ arguments");
612
658
  if (!(xs instanceof CalcitRecord)) throw new Error("&record:impl-traits expected a record");
613
- for (let idx = 0; idx < traits.length; idx++) {
614
- if (!(traits[idx] instanceof CalcitRecord)) {
615
- throw new Error("&record:impl-traits expects trait impls as records");
616
- }
617
- }
618
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(traits as CalcitRecord[]));
659
+ const impls = traits.map((trait) => coerce_impl(trait, "&record:impl-traits"));
660
+ return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(impls));
619
661
  };
620
662
 
621
663
  export let _$n_struct_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
622
664
  if (traits.length < 1) throw new Error("&struct:impl-traits takes 2+ arguments");
623
665
  if (!(xs instanceof CalcitStruct)) throw new Error("&struct:impl-traits expected a struct");
624
- for (let idx = 0; idx < traits.length; idx++) {
625
- if (!(traits[idx] instanceof CalcitRecord)) {
626
- throw new Error("&struct:impl-traits expects trait impls as records");
627
- }
628
- }
629
- const impls = xs.impls ?? [];
630
- return new CalcitStruct(xs.name, xs.fields, xs.fieldTypes, impls.concat(traits as CalcitRecord[]));
666
+ const addedImpls = traits.map((trait) => coerce_impl(trait, "&struct:impl-traits"));
667
+ const baseImpls = xs.impls ?? [];
668
+ return new CalcitStruct(xs.name, xs.fields, xs.fieldTypes, baseImpls.concat(addedImpls));
631
669
  };
632
670
 
633
671
  export let _$n_enum_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
634
672
  if (traits.length < 1) throw new Error("&enum:impl-traits takes 2+ arguments");
635
- for (let idx = 0; idx < traits.length; idx++) {
636
- if (!(traits[idx] instanceof CalcitRecord)) {
637
- throw new Error("&enum:impl-traits expects trait impls as records");
638
- }
639
- }
673
+ const addedImpls = traits.map((trait) => coerce_impl(trait, "&enum:impl-traits"));
640
674
  if (xs instanceof CalcitEnum) {
641
- const impls = xs.impls ?? [];
642
- return new CalcitEnum(xs.prototype, impls.concat(traits as CalcitRecord[]));
675
+ const baseImpls = xs.impls ?? [];
676
+ return new CalcitEnum(xs.prototype, baseImpls.concat(addedImpls));
643
677
  }
644
678
  if (xs instanceof CalcitRecord) {
645
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(traits as CalcitRecord[]));
679
+ return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(addedImpls));
646
680
  }
647
681
  throw new Error("&enum:impl-traits expected an enum or enum record");
648
682
  };
@@ -1593,7 +1627,7 @@ export let _PCT__$o__$o_ = (enumPrototype: CalcitValue, tag: CalcitValue, ...ext
1593
1627
  return new CalcitTuple(tag, extra, [], tupleEnumPrototype);
1594
1628
  };
1595
1629
 
1596
- export let _PCT__PCT__$o__$o_ = (impl: CalcitRecord, enumPrototype: CalcitValue, tag: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
1630
+ export let _PCT__PCT__$o__$o_ = (impl: CalcitValue, enumPrototype: CalcitValue, tag: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
1597
1631
  // Runtime validation: check if tag exists in enum and arity matches
1598
1632
  const proto = assert_enum_tag_args("%%::", enumPrototype, tag as CalcitTag);
1599
1633
  const tagValue = tag as CalcitTag;
@@ -1614,11 +1648,12 @@ export let _PCT__PCT__$o__$o_ = (impl: CalcitRecord, enumPrototype: CalcitValue,
1614
1648
  }
1615
1649
 
1616
1650
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1617
- return new CalcitTuple(tag, extra, [impl], tupleEnumPrototype);
1651
+ const implValue = coerce_impl(impl, "%:: with impl");
1652
+ return new CalcitTuple(tag, extra, [implValue], tupleEnumPrototype);
1618
1653
  };
1619
1654
 
1620
1655
  // mutable place for core to register
1621
- type CalcitImplEntry = CalcitRecord | CalcitList | CalcitSliceList | null;
1656
+ type CalcitImplEntry = CalcitImpl | CalcitList | CalcitSliceList | null;
1622
1657
 
1623
1658
  let calcit_builtin_impls = {
1624
1659
  number: null as CalcitImplEntry,
@@ -1641,17 +1676,20 @@ export function invoke_method_closure(p: string) {
1641
1676
  };
1642
1677
  }
1643
1678
 
1644
- function normalize_builtin_impls(entry: CalcitImplEntry): CalcitRecord[] | null {
1679
+ function normalize_builtin_impls(entry: CalcitImplEntry): CalcitImpl[] | null {
1645
1680
  if (entry == null) return null;
1646
- if (entry instanceof CalcitRecord) return [entry];
1681
+ if (entry instanceof CalcitImpl) return [entry];
1647
1682
  if (entry instanceof CalcitList || entry instanceof CalcitSliceList) {
1648
- return list_items(entry) as CalcitRecord[];
1683
+ return list_items(entry).map((item) => {
1684
+ if (item instanceof CalcitImpl) return item;
1685
+ throw new Error(`invoke-method expects impls in list, but received: ${toString(item, true)}`);
1686
+ }) as CalcitImpl[];
1649
1687
  }
1650
1688
  return null;
1651
1689
  }
1652
1690
 
1653
- function lookup_impls(obj: CalcitValue): [CalcitRecord[], string] {
1654
- let impls: CalcitRecord[];
1691
+ function lookup_impls(obj: CalcitValue): [CalcitImpl[], string] {
1692
+ let impls: CalcitImpl[];
1655
1693
  let tag: string;
1656
1694
  if (obj instanceof CalcitList || obj instanceof CalcitSliceList) {
1657
1695
  tag = "&core-list-methods";
@@ -1755,7 +1793,7 @@ export function _$n_inspect_methods(obj: CalcitValue, note: CalcitValue): Calcit
1755
1793
  console.log("Method call syntax: `.method self p1 p2`");
1756
1794
  console.log(" - dot is part of the method name, first arg is the receiver\n");
1757
1795
 
1758
- let implsInOrder: CalcitRecord[] = [];
1796
+ let implsInOrder: CalcitImpl[] = [];
1759
1797
  let idx = reverse ? impls.length - 1 : 0;
1760
1798
  while (reverse ? idx >= 0 : idx < impls.length) {
1761
1799
  let impl = impls[idx];
@@ -1763,7 +1801,7 @@ export function _$n_inspect_methods(obj: CalcitValue, note: CalcitValue): Calcit
1763
1801
  idx += reverse ? -1 : 1;
1764
1802
  }
1765
1803
 
1766
- console.log(`Impl records (high → low precedence): ${implsInOrder.length}`);
1804
+ console.log(`Impls (high → low precedence): ${implsInOrder.length}`);
1767
1805
  for (let i = 0; i < implsInOrder.length; i++) {
1768
1806
  let impl = implsInOrder[i];
1769
1807
  let names: string[] = [];
@@ -1815,7 +1853,7 @@ export function _$n_trait_call(traitDef: CalcitValue, method: CalcitValue, obj:
1815
1853
  idx += reverse ? -1 : 1;
1816
1854
  }
1817
1855
  throw new Error(
1818
- `&trait-call: cannot find impl for trait ${traitDef.name.toString()} on ${toString(obj, true)}. Hint: use defimpl to create impl records tagged by trait.`
1856
+ `&trait-call: cannot find impl for trait ${traitDef.name.toString()} on ${toString(obj, true)}. Hint: use defimpl to create impls tagged by trait.`
1819
1857
  );
1820
1858
  }
1821
1859
 
@@ -9,6 +9,7 @@ import { CalcitSet } from "./js-set.mjs";
9
9
  import { CalcitTag, CalcitSymbol, CalcitRecur, newTag } from "./calcit-data.mjs";
10
10
  import { CalcitTuple } from "./js-tuple.mjs";
11
11
  import { CalcitEnum } from "./js-enum.mjs";
12
+ import { CalcitImpl } from "./js-impl.mjs";
12
13
  import { CalcitRef } from "./js-ref.mjs";
13
14
  import { deepEqual } from "@calcit/ternary-tree/lib/utils.mjs";
14
15
  import { atom } from "./js-ref.mjs";
@@ -182,6 +183,8 @@ export let to_cirru_edn = (x: CalcitValue): CirruEdnFormat => {
182
183
  return ["%::", enumTag, x.tag.toString(), ...x.extra.map(to_cirru_edn)];
183
184
  } else if (x.tag instanceof CalcitRecord) {
184
185
  return ["%::", enumTag, x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
186
+ } else if (x.tag instanceof CalcitImpl) {
187
+ return ["%::", enumTag, x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
185
188
  } else {
186
189
  throw new Error(`Unsupported tag for EDN: ${x.tag}`);
187
190
  }
@@ -189,6 +192,8 @@ export let to_cirru_edn = (x: CalcitValue): CirruEdnFormat => {
189
192
  return ["::", x.tag.toString(), ...x.extra.map(to_cirru_edn)];
190
193
  } else if (x.tag instanceof CalcitRecord) {
191
194
  return ["::", x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
195
+ } else if (x.tag instanceof CalcitImpl) {
196
+ return ["::", x.tag.name.toString(), ...x.extra.map(to_cirru_edn)];
192
197
  } else {
193
198
  throw new Error(`Unsupported tag for EDN: ${x.tag}`);
194
199
  }
@@ -1,11 +1,12 @@
1
1
  import { CalcitRecord } from "./js-record.mjs";
2
+ import { CalcitImpl } from "./js-impl.mjs";
2
3
 
3
4
  export class CalcitEnum {
4
5
  prototype: CalcitRecord;
5
- impls: CalcitRecord[];
6
+ impls: CalcitImpl[];
6
7
  cachedHash: number;
7
8
 
8
- constructor(prototype: CalcitRecord, impls: CalcitRecord[] = []) {
9
+ constructor(prototype: CalcitRecord, impls: CalcitImpl[] = []) {
9
10
  this.prototype = prototype;
10
11
  this.impls = impls;
11
12
  this.cachedHash = null;
@@ -15,13 +16,13 @@ export class CalcitEnum {
15
16
  return this.prototype.name.value;
16
17
  }
17
18
 
18
- withImpls(impls: CalcitRecord | CalcitRecord[]): CalcitEnum {
19
- if (impls instanceof CalcitRecord) {
19
+ withImpls(impls: CalcitImpl | CalcitImpl[]): CalcitEnum {
20
+ if (impls instanceof CalcitImpl) {
20
21
  return new CalcitEnum(this.prototype, [impls]);
21
22
  } else if (Array.isArray(impls)) {
22
23
  return new CalcitEnum(this.prototype, impls);
23
24
  }
24
- throw new Error("Expected a record as implementation");
25
+ throw new Error("Expected an impl as implementation");
25
26
  }
26
27
 
27
28
  toString(): string {
@@ -0,0 +1,44 @@
1
+ import { Hash } from "@calcit/ternary-tree";
2
+ import { CalcitValue } from "./js-primes.mjs";
3
+ import { CalcitTag, castTag, findInFields, toString } from "./calcit-data.mjs";
4
+
5
+ export class CalcitImpl {
6
+ name: CalcitTag;
7
+ fields: Array<CalcitTag>;
8
+ values: Array<CalcitValue>;
9
+ cachedHash: Hash;
10
+
11
+ constructor(name: CalcitTag, fields: Array<CalcitTag>, values: Array<CalcitValue>) {
12
+ this.name = name;
13
+ this.fields = fields;
14
+ this.values = values;
15
+ this.cachedHash = null;
16
+ }
17
+
18
+ get(k: CalcitValue) {
19
+ let field = castTag(k);
20
+ let idx = findInFields(this.fields, field);
21
+ if (idx >= 0) {
22
+ return this.values[idx];
23
+ }
24
+ throw new Error(`Cannot find :${field} among (${this.fields.join(",")})`);
25
+ }
26
+
27
+ getOrNil(k: CalcitValue) {
28
+ let field = castTag(k);
29
+ let idx = findInFields(this.fields, field);
30
+ if (idx >= 0) {
31
+ return this.values[idx];
32
+ }
33
+ return undefined;
34
+ }
35
+
36
+ toString(disableJsDataWarning: boolean = false): string {
37
+ const parts = ["(%impl ", this.name.toString()];
38
+ for (let idx = 0; idx < this.fields.length; idx++) {
39
+ parts.push(" (", this.fields[idx].toString(), " ", toString(this.values[idx], true, disableJsDataWarning), ")");
40
+ }
41
+ parts.push(")");
42
+ return parts.join("");
43
+ }
44
+ }
@@ -2,6 +2,7 @@ import { CalcitTag, CalcitSymbol, CalcitFn, CalcitRecur } from "./calcit-data.mj
2
2
  import { CalcitRef } from "./js-ref.mjs";
3
3
  import { CalcitList, CalcitSliceList } from "./js-list.mjs";
4
4
  import { CalcitRecord } from "./js-record.mjs";
5
+ import { CalcitImpl } from "./js-impl.mjs";
5
6
  import { CalcitStruct } from "./js-struct.mjs";
6
7
  import { CalcitEnum } from "./js-enum.mjs";
7
8
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
@@ -25,6 +26,7 @@ export type CalcitValue =
25
26
  | CalcitFn
26
27
  | CalcitRecur // should not be exposed to function
27
28
  | CalcitRecord
29
+ | CalcitImpl
28
30
  | CalcitStruct
29
31
  | CalcitEnum
30
32
  | CalcitCirruQuote
@@ -54,6 +56,7 @@ enum PseudoTypeIndex {
54
56
  set,
55
57
  map,
56
58
  record,
59
+ impl,
57
60
  struct,
58
61
  enum_type,
59
62
  fn,
@@ -76,6 +79,7 @@ let typeAsInt = (x: CalcitValue): number => {
76
79
  if (x instanceof CalcitSet) return PseudoTypeIndex.set;
77
80
  if (x instanceof CalcitMap || x instanceof CalcitSliceMap) return PseudoTypeIndex.map;
78
81
  if (x instanceof CalcitRecord) return PseudoTypeIndex.record;
82
+ if (x instanceof CalcitImpl) return PseudoTypeIndex.impl;
79
83
  if (x instanceof CalcitStruct) return PseudoTypeIndex.struct;
80
84
  if (x instanceof CalcitEnum) return PseudoTypeIndex.enum_type;
81
85
  if (x instanceof CalcitCirruQuote) return PseudoTypeIndex.cirru_quote;
@@ -1,5 +1,6 @@
1
1
  import { initTernaryTreeMap, Hash, insert } from "@calcit/ternary-tree";
2
2
  import { CalcitValue } from "./js-primes.mjs";
3
+ import { CalcitImpl } from "./js-impl.mjs";
3
4
  import { newTag, castTag, toString, CalcitTag, getStringName, findInFields } from "./calcit-data.mjs";
4
5
 
5
6
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
@@ -8,9 +9,9 @@ export class CalcitRecord {
8
9
  name: CalcitTag;
9
10
  fields: Array<CalcitTag>;
10
11
  values: Array<CalcitValue>;
11
- impls: Array<CalcitRecord>;
12
+ impls: Array<CalcitImpl>;
12
13
  cachedHash: Hash;
13
- constructor(name: CalcitTag, fields: Array<CalcitTag>, values?: Array<CalcitValue>, impls?: Array<CalcitRecord>) {
14
+ constructor(name: CalcitTag, fields: Array<CalcitTag>, values?: Array<CalcitValue>, impls?: Array<CalcitImpl>) {
14
15
  this.name = name;
15
16
  let fieldNames = fields.map(castTag);
16
17
  this.fields = fields;
@@ -75,10 +76,10 @@ export class CalcitRecord {
75
76
  return parts.join("");
76
77
  }
77
78
  withImpls(impl: CalcitValue): CalcitRecord {
78
- if (impl instanceof CalcitRecord) {
79
+ if (impl instanceof CalcitImpl) {
79
80
  return new CalcitRecord(this.name, this.fields, this.values, [impl]);
80
81
  } else {
81
- throw new Error("Expected a record");
82
+ throw new Error("Expected an impl");
82
83
  }
83
84
  }
84
85
  }
@@ -96,7 +97,7 @@ export let new_record = (name: CalcitValue, ...fields: Array<CalcitValue>): Calc
96
97
  return new CalcitRecord(castTag(name), fieldNames);
97
98
  };
98
99
 
99
- export let new_impl_record = (impl: CalcitRecord, name: CalcitValue, ...fields: Array<CalcitValue>): CalcitValue => {
100
+ export let new_impl_record = (impl: CalcitImpl, name: CalcitValue, ...fields: Array<CalcitValue>): CalcitValue => {
100
101
  let fieldNames = fields.map(castTag).sort((x, y) => {
101
102
  if (x.idx < y.idx) {
102
103
  return -1;
@@ -1,15 +1,15 @@
1
1
  import { CalcitTag, toString } from "./calcit-data.mjs";
2
2
  import { CalcitValue } from "./js-primes.mjs";
3
- import { CalcitRecord } from "./js-record.mjs";
3
+ import { CalcitImpl } from "./js-impl.mjs";
4
4
 
5
5
  export class CalcitStruct {
6
6
  name: CalcitTag;
7
7
  fields: CalcitTag[];
8
8
  fieldTypes: CalcitValue[];
9
- impls: CalcitRecord[];
9
+ impls: CalcitImpl[];
10
10
  cachedHash: number;
11
11
 
12
- constructor(name: CalcitTag, fields: CalcitTag[], fieldTypes: CalcitValue[], impls: CalcitRecord[] = []) {
12
+ constructor(name: CalcitTag, fields: CalcitTag[], fieldTypes: CalcitValue[], impls: CalcitImpl[] = []) {
13
13
  if (fields.length !== fieldTypes.length) {
14
14
  throw new Error("CalcitStruct: fields and fieldTypes length mismatch");
15
15
  }
@@ -20,13 +20,13 @@ export class CalcitStruct {
20
20
  this.cachedHash = null;
21
21
  }
22
22
 
23
- withImpls(impls: CalcitRecord | CalcitRecord[]): CalcitStruct {
24
- if (impls instanceof CalcitRecord) {
23
+ withImpls(impls: CalcitImpl | CalcitImpl[]): CalcitStruct {
24
+ if (impls instanceof CalcitImpl) {
25
25
  return new CalcitStruct(this.name, this.fields, this.fieldTypes, [impls]);
26
26
  } else if (Array.isArray(impls)) {
27
27
  return new CalcitStruct(this.name, this.fields, this.fieldTypes, impls);
28
28
  }
29
- throw new Error("Expected a record as implementation");
29
+ throw new Error("Expected an impl as implementation");
30
30
  }
31
31
 
32
32
  toString(disableJsDataWarning: boolean = false): string {
@@ -2,16 +2,17 @@ import { Hash } from "@calcit/ternary-tree";
2
2
 
3
3
  import { CalcitValue } from "./js-primes.mjs";
4
4
  import { _$n__$e_, newTag, toString } from "./calcit-data.mjs";
5
+ import { CalcitImpl } from "./js-impl.mjs";
5
6
  import { CalcitRecord } from "./js-record.mjs";
6
7
  import { CalcitEnum } from "./js-enum.mjs";
7
8
 
8
9
  export class CalcitTuple {
9
10
  tag: CalcitValue;
10
11
  extra: CalcitValue[];
11
- impls: CalcitRecord[];
12
+ impls: CalcitImpl[];
12
13
  enumPrototype: CalcitRecord | CalcitEnum;
13
14
  cachedHash: Hash;
14
- constructor(tagName: CalcitValue, extra: CalcitValue[], impls: CalcitRecord[] = [], enumPrototype: CalcitRecord | CalcitEnum = null) {
15
+ constructor(tagName: CalcitValue, extra: CalcitValue[], impls: CalcitImpl[] = [], enumPrototype: CalcitRecord | CalcitEnum = null) {
15
16
  this.tag = tagName;
16
17
  this.extra = extra;
17
18
  this.impls = impls;