@calcit/procs 0.11.0-a9 → 0.11.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.
Binary file
package/build.rs ADDED
@@ -0,0 +1,74 @@
1
+ use cirru_edn::{Edn, from_edn};
2
+ use cirru_parser::Cirru;
3
+ use serde::{Deserialize, Serialize};
4
+ use std::collections::HashMap;
5
+ use std::env;
6
+ use std::fs;
7
+ use std::path::Path;
8
+
9
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10
+ pub struct SnapshotConfigs {
11
+ #[serde(rename = "init-fn")]
12
+ pub init_fn: String,
13
+ #[serde(rename = "reload-fn")]
14
+ pub reload_fn: String,
15
+ #[serde(default)]
16
+ pub modules: Vec<String>,
17
+ #[serde(default)]
18
+ pub version: String,
19
+ }
20
+
21
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22
+ pub struct CodeEntry {
23
+ pub doc: String,
24
+ #[serde(default)]
25
+ pub examples: Vec<Cirru>,
26
+ pub code: Cirru,
27
+ }
28
+
29
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30
+ pub struct FileInSnapShot {
31
+ pub ns: CodeEntry,
32
+ pub defs: HashMap<String, CodeEntry>,
33
+ }
34
+
35
+ #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36
+ pub struct Snapshot {
37
+ pub package: String,
38
+ pub about: Option<String>,
39
+ pub configs: SnapshotConfigs,
40
+ pub entries: HashMap<String, SnapshotConfigs>,
41
+ pub files: HashMap<String, FileInSnapShot>,
42
+ }
43
+
44
+ fn main() {
45
+ println!("cargo:rerun-if-changed=src/cirru/calcit-core.cirru");
46
+
47
+ let out_dir = env::var_os("OUT_DIR").unwrap();
48
+ let dest_path = Path::new(&out_dir).join("calcit-core.rmp");
49
+
50
+ let core_content = fs::read_to_string("src/cirru/calcit-core.cirru").expect("read core");
51
+ let core_data = cirru_edn::parse(&core_content).expect("parse core");
52
+
53
+ // Minimal logic to convert Edn to Snapshot as in src/snapshot.rs
54
+ let data = core_data.view_map().expect("map");
55
+ let pkg: String = from_edn(data.get_or_nil("package")).expect("pkg");
56
+ let about = match data.get_or_nil("about") {
57
+ Edn::Nil => None,
58
+ value => Some(from_edn::<String>(value).expect("about")),
59
+ };
60
+
61
+ let files: HashMap<String, FileInSnapShot> = from_edn(data.get_or_nil("files")).expect("files");
62
+
63
+ let snapshot = Snapshot {
64
+ package: pkg,
65
+ about,
66
+ configs: from_edn(data.get_or_nil("configs")).expect("configs"),
67
+ entries: from_edn(data.get_or_nil("entries")).expect("entries"),
68
+ files,
69
+ };
70
+
71
+ let mut buf = Vec::new();
72
+ snapshot.serialize(&mut rmp_serde::Serializer::new(&mut buf)).expect("serialize");
73
+ fs::write(dest_path, buf).expect("write");
74
+ }
@@ -291,6 +291,9 @@ export let hashFunction = (x) => {
291
291
  if (x instanceof CalcitImpl) {
292
292
  let base = defaultHash_impl;
293
293
  base = mergeValueHash(base, hashFunction(x.name));
294
+ if (x.origin != null) {
295
+ base = mergeValueHash(base, hashFunction(x.origin));
296
+ }
294
297
  for (let idx = 0; idx < x.fields.length; idx++) {
295
298
  base = mergeValueHash(base, hashFunction(x.fields[idx]));
296
299
  base = mergeValueHash(base, hashFunction(x.values[idx]));
@@ -670,6 +673,12 @@ export let _$n__$e_ = (x, y) => {
670
673
  if (x.name !== y.name) {
671
674
  return false;
672
675
  }
676
+ if ((x.origin == null) !== (y.origin == null)) {
677
+ return false;
678
+ }
679
+ if (x.origin != null && y.origin != null && x.origin.name.value !== y.origin.name.value) {
680
+ return false;
681
+ }
673
682
  if (!fieldsEqual(x.fields, y.fields)) {
674
683
  return false;
675
684
  }
@@ -198,14 +198,15 @@ export let defenum = (name, ...variants) => {
198
198
  const tags = entries.map((entry) => entry.tag);
199
199
  const values = entries.map((entry) => entry.payload);
200
200
  const prototype = new CalcitRecord(enumName, tags, values, null);
201
- return new CalcitEnum(prototype, null);
201
+ return new CalcitEnum(prototype);
202
202
  };
203
203
  export let _$n_impl_$o__$o_new = (name, ...pairs) => {
204
204
  if (name === undefined)
205
205
  throw new Error("&impl::new expected arguments");
206
- const implName = castTag(name);
206
+ const origin = name instanceof CalcitTrait ? name : null;
207
+ const implName = origin ? origin.name : castTag(name);
207
208
  if (pairs.length === 0) {
208
- return new CalcitImpl(implName, [], []);
209
+ return new CalcitImpl(implName, [], [], origin);
209
210
  }
210
211
  const entries = [];
211
212
  for (let idx = 0; idx < pairs.length; idx++) {
@@ -237,7 +238,7 @@ export let _$n_impl_$o__$o_new = (name, ...pairs) => {
237
238
  }
238
239
  const fields = entries.map((entry) => entry.tag);
239
240
  const values = entries.map((entry) => entry.value);
240
- return new CalcitImpl(implName, fields, values);
241
+ return new CalcitImpl(implName, fields, values, origin);
241
242
  };
242
243
  export let _$n_struct_$o__$o_new = (name, ...entries) => {
243
244
  return defstruct(name, ...entries);
@@ -451,7 +452,11 @@ export let _$n_tuple_$o_with_impls = function (x, y) {
451
452
  if (!(x instanceof CalcitTuple))
452
453
  throw new Error("&tuple:with-impls expects a tuple");
453
454
  const impl = coerce_impl(y, "&tuple:with-impls");
454
- return new CalcitTuple(x.tag, x.extra, [impl], x.enumPrototype);
455
+ let proto = x.enumPrototype;
456
+ if (proto == null) {
457
+ proto = new CalcitEnum(new CalcitRecord(newTag("anonymous-tuple"), [], [], new CalcitStruct(newTag("anonymous-tuple"), [], [])));
458
+ }
459
+ return new CalcitTuple(x.tag, x.extra, proto.withImpls(impl));
455
460
  };
456
461
  export let _$n_tuple_$o_impl_traits = function (x, ...traits) {
457
462
  if (traits.length < 1)
@@ -459,7 +464,13 @@ export let _$n_tuple_$o_impl_traits = function (x, ...traits) {
459
464
  if (!(x instanceof CalcitTuple))
460
465
  throw new Error("&tuple:impl-traits expects a tuple");
461
466
  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);
467
+ let proto = x.enumPrototype;
468
+ if (proto == null) {
469
+ const tagName = x.tag instanceof CalcitTag ? x.tag : newTag("tag");
470
+ const anyTypes = new CalcitSliceList(new Array(x.extra.length).fill(newTag("any")));
471
+ proto = new CalcitEnum(new CalcitRecord(newTag("anonymous-tuple"), [tagName], [anyTypes], new CalcitStruct(newTag("anonymous-tuple"), [tagName], [anyTypes])));
472
+ }
473
+ return new CalcitTuple(x.tag, x.extra, proto.withImpls(impls));
463
474
  };
464
475
  export let _$n_tuple_$o_enum = function (x) {
465
476
  if (arguments.length !== 1)
@@ -472,7 +483,7 @@ export let _$n_tuple_$o_enum = function (x) {
472
483
  if (x.enumPrototype instanceof CalcitEnum) {
473
484
  return x.enumPrototype;
474
485
  }
475
- return new CalcitEnum(x.enumPrototype, null);
486
+ return new CalcitEnum(x.enumPrototype);
476
487
  };
477
488
  const unwrap_enum_prototype = (enumPrototype, procName) => {
478
489
  if (enumPrototype instanceof CalcitEnum) {
@@ -584,7 +595,7 @@ export let _$n_record_$o_impls = function (xs) {
584
595
  if (arguments.length !== 1)
585
596
  throw new Error("&record:impls takes 1 argument");
586
597
  if (xs instanceof CalcitRecord)
587
- return new CalcitSliceList(xs.impls);
598
+ return new CalcitSliceList(xs.structRef.impls);
588
599
  throw new Error("&record:impls expected a record");
589
600
  };
590
601
  export let _$n_record_$o_impl_traits = function (xs, ...traits) {
@@ -593,7 +604,8 @@ export let _$n_record_$o_impl_traits = function (xs, ...traits) {
593
604
  if (!(xs instanceof CalcitRecord))
594
605
  throw new Error("&record:impl-traits expected a record");
595
606
  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));
607
+ const nextStruct = new CalcitStruct(xs.name, xs.fields, xs.structRef.fieldTypes, xs.structRef.impls.concat(impls));
608
+ return new CalcitRecord(xs.name, xs.fields, xs.values, nextStruct);
597
609
  };
598
610
  export let _$n_struct_$o_impl_traits = function (xs, ...traits) {
599
611
  if (traits.length < 1)
@@ -609,14 +621,22 @@ export let _$n_enum_$o_impl_traits = function (xs, ...traits) {
609
621
  throw new Error("&enum:impl-traits takes 2+ arguments");
610
622
  const addedImpls = traits.map((trait) => coerce_impl(trait, "&enum:impl-traits"));
611
623
  if (xs instanceof CalcitEnum) {
612
- const baseImpls = xs.impls ?? [];
613
- return new CalcitEnum(xs.prototype, baseImpls.concat(addedImpls));
624
+ return xs.withImpls(addedImpls);
614
625
  }
615
626
  if (xs instanceof CalcitRecord) {
616
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(addedImpls));
627
+ const nextStruct = new CalcitStruct(xs.name, xs.fields, xs.structRef.fieldTypes, xs.structRef.impls.concat(addedImpls));
628
+ return new CalcitRecord(xs.name, xs.fields, xs.values, nextStruct);
617
629
  }
618
630
  throw new Error("&enum:impl-traits expected an enum or enum record");
619
631
  };
632
+ export let _$n_impl_$o_origin = function (impl) {
633
+ if (arguments.length !== 1)
634
+ throw new Error("&impl:origin expected 1 argument");
635
+ if (impl instanceof CalcitImpl) {
636
+ return impl.origin ?? null;
637
+ }
638
+ throw new Error(`&impl:origin expected an impl, but received: ${toString(impl, true)}`);
639
+ };
620
640
  export let _$n_list_$o_assoc_before = function (xs, k, v) {
621
641
  if (arguments.length !== 3) {
622
642
  throw new Error("assoc takes 3 arguments");
@@ -1485,7 +1505,7 @@ export let _$n_js_object = (...xs) => {
1485
1505
  return ret;
1486
1506
  };
1487
1507
  export let _$o__$o_ = (tagName, ...extra) => {
1488
- return new CalcitTuple(tagName, extra, [], null);
1508
+ return new CalcitTuple(tagName, extra, null);
1489
1509
  };
1490
1510
  export let _PCT__$o__$o_ = (enumPrototype, tag, ...extra) => {
1491
1511
  const proto = assert_enum_tag_args("%::", enumPrototype, tag);
@@ -1505,7 +1525,7 @@ export let _PCT__$o__$o_ = (enumPrototype, tag, ...extra) => {
1505
1525
  throw new Error(`Expected variant definition to be a list, got ${variantDefinition}`);
1506
1526
  }
1507
1527
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1508
- return new CalcitTuple(tag, extra, [], tupleEnumPrototype);
1528
+ return new CalcitTuple(tag, extra, tupleEnumPrototype);
1509
1529
  };
1510
1530
  export let _PCT__PCT__$o__$o_ = (impl, enumPrototype, tag, ...extra) => {
1511
1531
  // Runtime validation: check if tag exists in enum and arity matches
@@ -1527,7 +1547,7 @@ export let _PCT__PCT__$o__$o_ = (impl, enumPrototype, tag, ...extra) => {
1527
1547
  }
1528
1548
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1529
1549
  const implValue = coerce_impl(impl, "%:: with impl");
1530
- return new CalcitTuple(tag, extra, [implValue], tupleEnumPrototype);
1550
+ return new CalcitTuple(tag, extra, tupleEnumPrototype.withImpls(implValue));
1531
1551
  };
1532
1552
  let calcit_builtin_impls = {
1533
1553
  number: null,
@@ -1574,7 +1594,7 @@ function lookup_impls(obj) {
1574
1594
  }
1575
1595
  else if (obj instanceof CalcitRecord) {
1576
1596
  tag = obj.name.toString();
1577
- impls = obj.impls;
1597
+ impls = obj.structRef.impls;
1578
1598
  }
1579
1599
  else if (obj instanceof CalcitTuple) {
1580
1600
  tag = obj.tag.toString();
@@ -1686,7 +1706,8 @@ export function _$n_inspect_methods(obj, note) {
1686
1706
  for (let k = 0; k < impl.fields.length; k++) {
1687
1707
  names.push("." + impl.fields[k].value);
1688
1708
  }
1689
- console.log(` #${i}: ${impl.name.toString()} (${names.join(" ")})`);
1709
+ const originName = impl.origin != null ? impl.origin.name.toString() : impl.name.toString();
1710
+ console.log(` #${i}: ${originName} (${names.join(" ")})`);
1690
1711
  }
1691
1712
  let ms = _$n_methods_of(obj);
1692
1713
  console.log(`\nAll methods (unique, high → low): ${ms.len()}`);
@@ -1716,7 +1737,7 @@ export function _$n_trait_call(traitDef, method, obj, ...args) {
1716
1737
  let idx = reverse ? impls.length - 1 : 0;
1717
1738
  while (reverse ? idx >= 0 : idx < impls.length) {
1718
1739
  const impl = impls[idx];
1719
- if (impl != null && impl.name.value === traitDef.name.value) {
1740
+ if (impl != null && impl.origin != null && impl.origin.name.value === traitDef.name.value) {
1720
1741
  const fn = impl.getOrNil(methodName);
1721
1742
  if (fn != null) {
1722
1743
  if (typeof fn !== "function") {
@@ -149,8 +149,8 @@ export let load_console_formatter_$x_ = () => {
149
149
  }, `${obj.len()}`), preview);
150
150
  }
151
151
  if (obj instanceof CalcitRecord) {
152
- if (obj.impls.length > 0) {
153
- let ret = div({ color: hsl(280, 80, 60, 0.4), maxWidth: "100%" }, span({}, "%{}"), span({ marginLeft: "6px" }, embedObject(obj.impls[0])), span({ marginLeft: "6px" }, embedObject(obj.name)), span({ marginLeft: "6px" }, `...`));
152
+ if (obj.structRef.impls.length > 0) {
153
+ let ret = div({ color: hsl(280, 80, 60, 0.4), maxWidth: "100%" }, span({}, "%{}"), span({ marginLeft: "6px" }, embedObject(obj.structRef.impls[0])), span({ marginLeft: "6px" }, embedObject(obj.name)), span({ marginLeft: "6px" }, `...`));
154
154
  return ret;
155
155
  }
156
156
  else {
package/lib/js-cirru.mjs CHANGED
@@ -360,7 +360,7 @@ export let extract_cirru_edn = (x, options) => {
360
360
  if (!deepEqual(v.fields, fields)) {
361
361
  throw new Error(`Fields mismatch for ${name}, expected ${fields}, got ${v.fields}`);
362
362
  }
363
- return new CalcitRecord(extractFieldTag(name), fields, values, v.impls);
363
+ return new CalcitRecord(extractFieldTag(name), fields, values, v.structRef);
364
364
  }
365
365
  }
366
366
  return new CalcitRecord(extractFieldTag(name), fields, values);
@@ -399,7 +399,7 @@ export let extract_cirru_edn = (x, options) => {
399
399
  return new CalcitTuple(extract_cirru_edn(x[1], options), x
400
400
  .slice(2)
401
401
  .filter(notComment)
402
- .map((x) => extract_cirru_edn(x, options)), []);
402
+ .map((x) => extract_cirru_edn(x, options)));
403
403
  }
404
404
  if (x[0] === "%::") {
405
405
  if (x.length < 3) {
@@ -416,7 +416,7 @@ export let extract_cirru_edn = (x, options) => {
416
416
  return new CalcitTuple(extract_cirru_edn(x[2], options), x
417
417
  .slice(3)
418
418
  .filter(notComment)
419
- .map((x) => extract_cirru_edn(x, options)), [], enumPrototype);
419
+ .map((x) => extract_cirru_edn(x, options)), enumPrototype);
420
420
  }
421
421
  if (x[0] === "atom") {
422
422
  if (x.length !== 2) {
package/lib/js-enum.mjs CHANGED
@@ -1,21 +1,27 @@
1
1
  import { CalcitImpl } from "./js-impl.mjs";
2
2
  export class CalcitEnum {
3
- constructor(prototype, impls = []) {
3
+ constructor(prototype) {
4
4
  this.prototype = prototype;
5
- this.impls = impls;
6
5
  this.cachedHash = null;
7
6
  }
8
7
  name() {
9
8
  return this.prototype.name.value;
10
9
  }
10
+ get impls() {
11
+ return this.prototype.structRef.impls;
12
+ }
11
13
  withImpls(impls) {
14
+ let nextImpls;
12
15
  if (impls instanceof CalcitImpl) {
13
- return new CalcitEnum(this.prototype, [impls]);
16
+ nextImpls = [impls];
14
17
  }
15
18
  else if (Array.isArray(impls)) {
16
- return new CalcitEnum(this.prototype, impls);
19
+ nextImpls = impls;
20
+ }
21
+ else {
22
+ throw new Error("Expected an impl as implementation");
17
23
  }
18
- throw new Error("Expected an impl as implementation");
24
+ return new CalcitEnum(this.prototype.withImpls(nextImpls));
19
25
  }
20
26
  toString() {
21
27
  return `(%enum :${this.prototype.name.value})`;
package/lib/js-impl.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { castTag, findInFields, toString } from "./calcit-data.mjs";
2
2
  export class CalcitImpl {
3
- constructor(name, fields, values) {
3
+ constructor(name, fields, values, origin = null) {
4
4
  this.name = name;
5
+ this.origin = origin;
5
6
  this.fields = fields;
6
7
  this.values = values;
7
8
  this.cachedHash = null;
package/lib/js-record.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  import { CalcitImpl } from "./js-impl.mjs";
2
2
  import { castTag, toString, findInFields } from "./calcit-data.mjs";
3
3
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
4
+ import { CalcitStruct } from "./js-struct.mjs";
4
5
  export class CalcitRecord {
5
- constructor(name, fields, values, impls) {
6
+ constructor(name, fields, values, structRef) {
6
7
  this.name = name;
7
8
  let fieldNames = fields.map(castTag);
8
9
  this.fields = fields;
@@ -16,7 +17,7 @@ export class CalcitRecord {
16
17
  this.values = new Array(fieldNames.length);
17
18
  }
18
19
  this.cachedHash = null;
19
- this.impls = impls || [];
20
+ this.structRef = structRef || new CalcitStruct(name, fields, new Array(fields.length).fill(null));
20
21
  }
21
22
  get(k) {
22
23
  let field = castTag(k);
@@ -49,7 +50,7 @@ export class CalcitRecord {
49
50
  values[idx] = this.values[idx];
50
51
  }
51
52
  }
52
- return new CalcitRecord(this.name, this.fields, values, this.impls);
53
+ return new CalcitRecord(this.name, this.fields, values, this.structRef);
53
54
  }
54
55
  /** return -1 for missing */
55
56
  findIndex(k) {
@@ -71,12 +72,18 @@ export class CalcitRecord {
71
72
  return parts.join("");
72
73
  }
73
74
  withImpls(impl) {
75
+ let nextImpls;
74
76
  if (impl instanceof CalcitImpl) {
75
- return new CalcitRecord(this.name, this.fields, this.values, [impl]);
77
+ nextImpls = [impl];
78
+ }
79
+ else if (Array.isArray(impl)) {
80
+ nextImpls = impl;
76
81
  }
77
82
  else {
78
- throw new Error("Expected an impl");
83
+ throw new Error("Expected an impl or array of impls");
79
84
  }
85
+ let nextStruct = new CalcitStruct(this.name, this.fields, this.structRef.fieldTypes, this.structRef.impls.concat(nextImpls));
86
+ return new CalcitRecord(this.name, this.fields, this.values, nextStruct);
80
87
  }
81
88
  }
82
89
  export let new_record = (name, ...fields) => {
@@ -105,7 +112,9 @@ export let new_impl_record = (impl, name, ...fields) => {
105
112
  throw new Error(`Unexpected duplication in record fields: ${x.toString()}`);
106
113
  }
107
114
  });
108
- return new CalcitRecord(castTag(name), fieldNames, undefined, [impl]);
115
+ let nameTag = castTag(name);
116
+ let structRef = new CalcitStruct(nameTag, fieldNames, new Array(fieldNames.length).fill(null), [impl]);
117
+ return new CalcitRecord(nameTag, fieldNames, undefined, structRef);
109
118
  };
110
119
  export let fieldsEqual = (xs, ys) => {
111
120
  if (xs === ys) {
@@ -147,7 +156,7 @@ export let _$n__PCT__$M_ = (proto, ...xs) => {
147
156
  }
148
157
  values[i] = xs[idx * 2 + 1];
149
158
  }
150
- return new CalcitRecord(proto.name, proto.fields, values, proto.impls);
159
+ return new CalcitRecord(proto.name, proto.fields, values, proto.structRef);
151
160
  }
152
161
  else {
153
162
  throw new Error("Expected prototype to be a record");
@@ -169,7 +178,7 @@ export let _$n_record_$o_with = (proto, ...xs) => {
169
178
  }
170
179
  values[idx] = v;
171
180
  }
172
- return new CalcitRecord(proto.name, proto.fields, values, proto.impls);
181
+ return new CalcitRecord(proto.name, proto.fields, values, proto.structRef);
173
182
  }
174
183
  else {
175
184
  throw new Error("Expected prototype to be a record");
package/lib/js-tuple.mjs CHANGED
@@ -1,13 +1,21 @@
1
1
  import { _$n__$e_, toString } from "./calcit-data.mjs";
2
2
  import { CalcitEnum } from "./js-enum.mjs";
3
3
  export class CalcitTuple {
4
- constructor(tagName, extra, impls = [], enumPrototype = null) {
4
+ constructor(tagName, extra, enumPrototype = null) {
5
5
  this.tag = tagName;
6
6
  this.extra = extra;
7
- this.impls = impls;
8
7
  this.enumPrototype = enumPrototype;
9
8
  this.cachedHash = null;
10
9
  }
10
+ get impls() {
11
+ if (this.enumPrototype == null) {
12
+ return [];
13
+ }
14
+ if (this.enumPrototype instanceof CalcitEnum) {
15
+ return this.enumPrototype.impls;
16
+ }
17
+ return this.enumPrototype.structRef.impls;
18
+ }
11
19
  get(n) {
12
20
  if (n === 0) {
13
21
  return this.tag;
@@ -21,12 +29,12 @@ export class CalcitTuple {
21
29
  }
22
30
  assoc(n, v) {
23
31
  if (n === 0) {
24
- return new CalcitTuple(v, this.extra, this.impls, this.enumPrototype);
32
+ return new CalcitTuple(v, this.extra, this.enumPrototype);
25
33
  }
26
34
  else if (n - 1 < this.extra.length) {
27
35
  let next_extra = this.extra.slice();
28
36
  next_extra[n - 1] = v;
29
- return new CalcitTuple(this.tag, next_extra, this.impls, this.enumPrototype);
37
+ return new CalcitTuple(this.tag, next_extra, this.enumPrototype);
30
38
  }
31
39
  else {
32
40
  throw new Error(`Tuple only have ${this.extra.length} elements`);
@@ -60,15 +68,9 @@ export class CalcitTuple {
60
68
  }
61
69
  const hasEnum = this.enumPrototype != null;
62
70
  const enumName = hasEnum ? (this.enumPrototype instanceof CalcitEnum ? this.enumPrototype.prototype.name.value : this.enumPrototype.name.value) : null;
63
- if (this.impls.length > 0 && hasEnum) {
64
- return `(%:: ${content} (:impls ${this.impls[0].name.value}) (:enum ${enumName}))`;
65
- }
66
71
  if (hasEnum) {
67
72
  return `(%:: ${content} (:enum ${enumName}))`;
68
73
  }
69
- if (this.impls.length > 0) {
70
- return `(:: ${content} (:impls ${this.impls[0].name.value}))`;
71
- }
72
74
  return `(:: ${content})`;
73
75
  }
74
76
  }
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.11.0-a9",
3
+ "version": "0.11.0",
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-a9",
3
+ "version": "0.11.0",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.0.9",
@@ -320,6 +320,9 @@ export let hashFunction = (x: CalcitValue): Hash => {
320
320
  if (x instanceof CalcitImpl) {
321
321
  let base = defaultHash_impl;
322
322
  base = mergeValueHash(base, hashFunction(x.name));
323
+ if (x.origin != null) {
324
+ base = mergeValueHash(base, hashFunction(x.origin));
325
+ }
323
326
  for (let idx = 0; idx < x.fields.length; idx++) {
324
327
  base = mergeValueHash(base, hashFunction(x.fields[idx]));
325
328
  base = mergeValueHash(base, hashFunction(x.values[idx]));
@@ -708,6 +711,12 @@ export let _$n__$e_ = (x: CalcitValue, y: CalcitValue): boolean => {
708
711
  if (x.name !== y.name) {
709
712
  return false;
710
713
  }
714
+ if ((x.origin == null) !== (y.origin == null)) {
715
+ return false;
716
+ }
717
+ if (x.origin != null && y.origin != null && x.origin.name.value !== y.origin.name.value) {
718
+ return false;
719
+ }
711
720
  if (!fieldsEqual(x.fields, y.fields)) {
712
721
  return false;
713
722
  }
@@ -230,14 +230,15 @@ export let defenum = (name: CalcitValue, ...variants: CalcitValue[]): CalcitEnum
230
230
  const tags = entries.map((entry) => entry.tag);
231
231
  const values = entries.map((entry) => entry.payload);
232
232
  const prototype = new CalcitRecord(enumName, tags, values, null);
233
- return new CalcitEnum(prototype, null);
233
+ return new CalcitEnum(prototype);
234
234
  };
235
235
 
236
236
  export let _$n_impl_$o__$o_new = (name: CalcitValue, ...pairs: CalcitValue[]): CalcitImpl => {
237
237
  if (name === undefined) throw new Error("&impl::new expected arguments");
238
- const implName = castTag(name);
238
+ const origin = name instanceof CalcitTrait ? name : null;
239
+ const implName = origin ? origin.name : castTag(name);
239
240
  if (pairs.length === 0) {
240
- return new CalcitImpl(implName, [], []);
241
+ return new CalcitImpl(implName, [], [], origin);
241
242
  }
242
243
  const entries: Array<{ tag: CalcitTag; value: CalcitValue }> = [];
243
244
  for (let idx = 0; idx < pairs.length; idx++) {
@@ -268,7 +269,7 @@ export let _$n_impl_$o__$o_new = (name: CalcitValue, ...pairs: CalcitValue[]): C
268
269
  }
269
270
  const fields = entries.map((entry) => entry.tag);
270
271
  const values = entries.map((entry) => entry.value);
271
- return new CalcitImpl(implName, fields, values);
272
+ return new CalcitImpl(implName, fields, values, origin);
272
273
  };
273
274
 
274
275
  export let _$n_struct_$o__$o_new = (name: CalcitValue, ...entries: CalcitValue[]): CalcitStruct => {
@@ -508,14 +509,26 @@ export let _$n_tuple_$o_with_impls = function (x: CalcitTuple, y: CalcitValue) {
508
509
  if (arguments.length !== 2) throw new Error("&tuple:with-impls takes 2 arguments");
509
510
  if (!(x instanceof CalcitTuple)) throw new Error("&tuple:with-impls expects a tuple");
510
511
  const impl = coerce_impl(y, "&tuple:with-impls");
511
- return new CalcitTuple(x.tag, x.extra, [impl], x.enumPrototype);
512
+ let proto = x.enumPrototype;
513
+ if (proto == null) {
514
+ proto = new CalcitEnum(new CalcitRecord(newTag("anonymous-tuple"), [], [], new CalcitStruct(newTag("anonymous-tuple"), [], [])));
515
+ }
516
+ return new CalcitTuple(x.tag, x.extra, proto.withImpls(impl));
512
517
  };
513
518
 
514
519
  export let _$n_tuple_$o_impl_traits = function (x: CalcitValue, ...traits: CalcitValue[]) {
515
520
  if (traits.length < 1) throw new Error("&tuple:impl-traits takes 2+ arguments");
516
521
  if (!(x instanceof CalcitTuple)) throw new Error("&tuple:impl-traits expects a tuple");
517
522
  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);
523
+ let proto = x.enumPrototype;
524
+ if (proto == null) {
525
+ const tagName = x.tag instanceof CalcitTag ? x.tag : newTag("tag");
526
+ const anyTypes = new CalcitSliceList(new Array(x.extra.length).fill(newTag("any")));
527
+ proto = new CalcitEnum(
528
+ new CalcitRecord(newTag("anonymous-tuple"), [tagName], [anyTypes], new CalcitStruct(newTag("anonymous-tuple"), [tagName], [anyTypes]))
529
+ );
530
+ }
531
+ return new CalcitTuple(x.tag, x.extra, proto.withImpls(impls));
519
532
  };
520
533
 
521
534
  export let _$n_tuple_$o_enum = function (x: CalcitTuple) {
@@ -527,7 +540,7 @@ export let _$n_tuple_$o_enum = function (x: CalcitTuple) {
527
540
  if (x.enumPrototype instanceof CalcitEnum) {
528
541
  return x.enumPrototype;
529
542
  }
530
- return new CalcitEnum(x.enumPrototype as CalcitRecord, null);
543
+ return new CalcitEnum(x.enumPrototype as CalcitRecord);
531
544
  };
532
545
 
533
546
  const unwrap_enum_prototype = (enumPrototype: CalcitValue, procName: string): CalcitRecord => {
@@ -649,7 +662,7 @@ export let _$n_record_$o_assoc = function (xs: CalcitValue, k: CalcitValue, v: C
649
662
 
650
663
  export let _$n_record_$o_impls = function (xs: CalcitValue) {
651
664
  if (arguments.length !== 1) throw new Error("&record:impls takes 1 argument");
652
- if (xs instanceof CalcitRecord) return new CalcitSliceList(xs.impls);
665
+ if (xs instanceof CalcitRecord) return new CalcitSliceList(xs.structRef.impls);
653
666
  throw new Error("&record:impls expected a record");
654
667
  };
655
668
 
@@ -657,7 +670,8 @@ export let _$n_record_$o_impl_traits = function (xs: CalcitValue, ...traits: Cal
657
670
  if (traits.length < 1) throw new Error("&record:impl-traits takes 2+ arguments");
658
671
  if (!(xs instanceof CalcitRecord)) throw new Error("&record:impl-traits expected a record");
659
672
  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));
673
+ const nextStruct = new CalcitStruct(xs.name, xs.fields, xs.structRef.fieldTypes, xs.structRef.impls.concat(impls));
674
+ return new CalcitRecord(xs.name, xs.fields, xs.values, nextStruct);
661
675
  };
662
676
 
663
677
  export let _$n_struct_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
@@ -672,15 +686,23 @@ export let _$n_enum_$o_impl_traits = function (xs: CalcitValue, ...traits: Calci
672
686
  if (traits.length < 1) throw new Error("&enum:impl-traits takes 2+ arguments");
673
687
  const addedImpls = traits.map((trait) => coerce_impl(trait, "&enum:impl-traits"));
674
688
  if (xs instanceof CalcitEnum) {
675
- const baseImpls = xs.impls ?? [];
676
- return new CalcitEnum(xs.prototype, baseImpls.concat(addedImpls));
689
+ return xs.withImpls(addedImpls);
677
690
  }
678
691
  if (xs instanceof CalcitRecord) {
679
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(addedImpls));
692
+ const nextStruct = new CalcitStruct(xs.name, xs.fields, xs.structRef.fieldTypes, xs.structRef.impls.concat(addedImpls));
693
+ return new CalcitRecord(xs.name, xs.fields, xs.values, nextStruct);
680
694
  }
681
695
  throw new Error("&enum:impl-traits expected an enum or enum record");
682
696
  };
683
697
 
698
+ export let _$n_impl_$o_origin = function (impl: CalcitValue): CalcitValue {
699
+ if (arguments.length !== 1) throw new Error("&impl:origin expected 1 argument");
700
+ if (impl instanceof CalcitImpl) {
701
+ return impl.origin ?? null;
702
+ }
703
+ throw new Error(`&impl:origin expected an impl, but received: ${toString(impl, true)}`);
704
+ };
705
+
684
706
  export let _$n_list_$o_assoc_before = function (xs: CalcitList | CalcitSliceList, k: number, v: CalcitValue): CalcitList {
685
707
  if (arguments.length !== 3) {
686
708
  throw new Error("assoc takes 3 arguments");
@@ -1601,7 +1623,7 @@ export let _$n_js_object = (...xs: CalcitValue[]): Record<string, CalcitValue> =
1601
1623
  };
1602
1624
 
1603
1625
  export let _$o__$o_ = (tagName: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
1604
- return new CalcitTuple(tagName, extra, [], null);
1626
+ return new CalcitTuple(tagName, extra, null);
1605
1627
  };
1606
1628
 
1607
1629
  export let _PCT__$o__$o_ = (enumPrototype: CalcitValue, tag: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
@@ -1624,7 +1646,7 @@ export let _PCT__$o__$o_ = (enumPrototype: CalcitValue, tag: CalcitValue, ...ext
1624
1646
  }
1625
1647
 
1626
1648
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1627
- return new CalcitTuple(tag, extra, [], tupleEnumPrototype);
1649
+ return new CalcitTuple(tag, extra, tupleEnumPrototype);
1628
1650
  };
1629
1651
 
1630
1652
  export let _PCT__PCT__$o__$o_ = (impl: CalcitValue, enumPrototype: CalcitValue, tag: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
@@ -1647,9 +1669,9 @@ export let _PCT__PCT__$o__$o_ = (impl: CalcitValue, enumPrototype: CalcitValue,
1647
1669
  throw new Error(`Expected variant definition to be a list, got ${variantDefinition}`);
1648
1670
  }
1649
1671
 
1650
- const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1672
+ const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : (proto as any);
1651
1673
  const implValue = coerce_impl(impl, "%:: with impl");
1652
- return new CalcitTuple(tag, extra, [implValue], tupleEnumPrototype);
1674
+ return new CalcitTuple(tag, extra, tupleEnumPrototype.withImpls(implValue));
1653
1675
  };
1654
1676
 
1655
1677
  // mutable place for core to register
@@ -1699,7 +1721,7 @@ function lookup_impls(obj: CalcitValue): [CalcitImpl[], string] {
1699
1721
  impls = normalize_builtin_impls(calcit_builtin_impls.map);
1700
1722
  } else if (obj instanceof CalcitRecord) {
1701
1723
  tag = obj.name.toString();
1702
- impls = obj.impls;
1724
+ impls = obj.structRef.impls;
1703
1725
  } else if (obj instanceof CalcitTuple) {
1704
1726
  tag = obj.tag.toString();
1705
1727
  impls = obj.impls;
@@ -1808,7 +1830,8 @@ export function _$n_inspect_methods(obj: CalcitValue, note: CalcitValue): Calcit
1808
1830
  for (let k = 0; k < impl.fields.length; k++) {
1809
1831
  names.push("." + impl.fields[k].value);
1810
1832
  }
1811
- console.log(` #${i}: ${impl.name.toString()} (${names.join(" ")})`);
1833
+ const originName = impl.origin != null ? impl.origin.name.toString() : impl.name.toString();
1834
+ console.log(` #${i}: ${originName} (${names.join(" ")})`);
1812
1835
  }
1813
1836
 
1814
1837
  let ms = _$n_methods_of(obj);
@@ -1841,7 +1864,7 @@ export function _$n_trait_call(traitDef: CalcitValue, method: CalcitValue, obj:
1841
1864
  let idx = reverse ? impls.length - 1 : 0;
1842
1865
  while (reverse ? idx >= 0 : idx < impls.length) {
1843
1866
  const impl = impls[idx];
1844
- if (impl != null && impl.name.value === traitDef.name.value) {
1867
+ if (impl != null && impl.origin != null && impl.origin.name.value === traitDef.name.value) {
1845
1868
  const fn = impl.getOrNil(methodName);
1846
1869
  if (fn != null) {
1847
1870
  if (typeof fn !== "function") {
@@ -180,11 +180,11 @@ export let load_console_formatter_$x_ = () => {
180
180
  );
181
181
  }
182
182
  if (obj instanceof CalcitRecord) {
183
- if (obj.impls.length > 0) {
183
+ if (obj.structRef.impls.length > 0) {
184
184
  let ret: any[] = div(
185
185
  { color: hsl(280, 80, 60, 0.4), maxWidth: "100%" },
186
186
  span({}, "%{}"),
187
- span({ marginLeft: "6px" }, embedObject(obj.impls[0])),
187
+ span({ marginLeft: "6px" }, embedObject(obj.structRef.impls[0])),
188
188
  span({ marginLeft: "6px" }, embedObject(obj.name)),
189
189
  span({ marginLeft: "6px" }, `...`)
190
190
  );
@@ -351,7 +351,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat, options: CalcitValue): Calcit
351
351
  if (!deepEqual(v.fields, fields)) {
352
352
  throw new Error(`Fields mismatch for ${name}, expected ${fields}, got ${v.fields}`);
353
353
  }
354
- return new CalcitRecord(extractFieldTag(name), fields, values, v.impls);
354
+ return new CalcitRecord(extractFieldTag(name), fields, values, v.structRef);
355
355
  }
356
356
  }
357
357
 
@@ -397,8 +397,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat, options: CalcitValue): Calcit
397
397
  x
398
398
  .slice(2)
399
399
  .filter(notComment)
400
- .map((x) => extract_cirru_edn(x, options)),
401
- []
400
+ .map((x) => extract_cirru_edn(x, options))
402
401
  );
403
402
  }
404
403
  if (x[0] === "%::") {
@@ -419,7 +418,6 @@ export let extract_cirru_edn = (x: CirruEdnFormat, options: CalcitValue): Calcit
419
418
  .slice(3)
420
419
  .filter(notComment)
421
420
  .map((x) => extract_cirru_edn(x, options)),
422
- [],
423
421
  enumPrototype
424
422
  );
425
423
  }
@@ -3,12 +3,10 @@ import { CalcitImpl } from "./js-impl.mjs";
3
3
 
4
4
  export class CalcitEnum {
5
5
  prototype: CalcitRecord;
6
- impls: CalcitImpl[];
7
6
  cachedHash: number;
8
7
 
9
- constructor(prototype: CalcitRecord, impls: CalcitImpl[] = []) {
8
+ constructor(prototype: CalcitRecord) {
10
9
  this.prototype = prototype;
11
- this.impls = impls;
12
10
  this.cachedHash = null;
13
11
  }
14
12
 
@@ -16,13 +14,20 @@ export class CalcitEnum {
16
14
  return this.prototype.name.value;
17
15
  }
18
16
 
17
+ get impls(): CalcitImpl[] {
18
+ return this.prototype.structRef.impls;
19
+ }
20
+
19
21
  withImpls(impls: CalcitImpl | CalcitImpl[]): CalcitEnum {
22
+ let nextImpls: CalcitImpl[];
20
23
  if (impls instanceof CalcitImpl) {
21
- return new CalcitEnum(this.prototype, [impls]);
24
+ nextImpls = [impls];
22
25
  } else if (Array.isArray(impls)) {
23
- return new CalcitEnum(this.prototype, impls);
26
+ nextImpls = impls;
27
+ } else {
28
+ throw new Error("Expected an impl as implementation");
24
29
  }
25
- throw new Error("Expected an impl as implementation");
30
+ return new CalcitEnum(this.prototype.withImpls(nextImpls));
26
31
  }
27
32
 
28
33
  toString(): string {
@@ -1,15 +1,18 @@
1
1
  import { Hash } from "@calcit/ternary-tree";
2
2
  import { CalcitValue } from "./js-primes.mjs";
3
3
  import { CalcitTag, castTag, findInFields, toString } from "./calcit-data.mjs";
4
+ import type { CalcitTrait } from "./js-trait.mjs";
4
5
 
5
6
  export class CalcitImpl {
6
7
  name: CalcitTag;
8
+ origin: CalcitTrait | null;
7
9
  fields: Array<CalcitTag>;
8
10
  values: Array<CalcitValue>;
9
11
  cachedHash: Hash;
10
12
 
11
- constructor(name: CalcitTag, fields: Array<CalcitTag>, values: Array<CalcitValue>) {
13
+ constructor(name: CalcitTag, fields: Array<CalcitTag>, values: Array<CalcitValue>, origin: CalcitTrait | null = null) {
12
14
  this.name = name;
15
+ this.origin = origin;
13
16
  this.fields = fields;
14
17
  this.values = values;
15
18
  this.cachedHash = null;
@@ -9,6 +9,7 @@ import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
9
9
  import { CalcitSet as CalcitSet } from "./js-set.mjs";
10
10
  import { CalcitTuple } from "./js-tuple.mjs";
11
11
  import { CalcitCirruQuote, cirru_deep_equal } from "./js-cirru.mjs";
12
+ import { CalcitTrait } from "./js-trait.mjs";
12
13
 
13
14
  export type CalcitValue =
14
15
  | string
@@ -27,6 +28,7 @@ export type CalcitValue =
27
28
  | CalcitRecur // should not be exposed to function
28
29
  | CalcitRecord
29
30
  | CalcitImpl
31
+ | CalcitTrait
30
32
  | CalcitStruct
31
33
  | CalcitEnum
32
34
  | CalcitCirruQuote
@@ -5,13 +5,15 @@ import { newTag, castTag, toString, CalcitTag, getStringName, findInFields } fro
5
5
 
6
6
  import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
7
7
 
8
+ import { CalcitStruct } from "./js-struct.mjs";
9
+
8
10
  export class CalcitRecord {
9
11
  name: CalcitTag;
10
12
  fields: Array<CalcitTag>;
11
13
  values: Array<CalcitValue>;
12
- impls: Array<CalcitImpl>;
14
+ structRef: CalcitStruct;
13
15
  cachedHash: Hash;
14
- constructor(name: CalcitTag, fields: Array<CalcitTag>, values?: Array<CalcitValue>, impls?: Array<CalcitImpl>) {
16
+ constructor(name: CalcitTag, fields: Array<CalcitTag>, values?: Array<CalcitValue>, structRef?: CalcitStruct) {
15
17
  this.name = name;
16
18
  let fieldNames = fields.map(castTag);
17
19
  this.fields = fields;
@@ -24,7 +26,7 @@ export class CalcitRecord {
24
26
  this.values = new Array(fieldNames.length);
25
27
  }
26
28
  this.cachedHash = null;
27
- this.impls = impls || [];
29
+ this.structRef = structRef || new CalcitStruct(name, fields, new Array(fields.length).fill(null));
28
30
  }
29
31
  get(k: CalcitValue) {
30
32
  let field = castTag(k);
@@ -54,7 +56,7 @@ export class CalcitRecord {
54
56
  values[idx] = this.values[idx];
55
57
  }
56
58
  }
57
- return new CalcitRecord(this.name, this.fields, values, this.impls);
59
+ return new CalcitRecord(this.name, this.fields, values, this.structRef);
58
60
  }
59
61
  /** return -1 for missing */
60
62
  findIndex(k: CalcitValue) {
@@ -75,12 +77,17 @@ export class CalcitRecord {
75
77
  parts.push(")");
76
78
  return parts.join("");
77
79
  }
78
- withImpls(impl: CalcitValue): CalcitRecord {
80
+ withImpls(impl: CalcitValue | CalcitImpl[]): CalcitRecord {
81
+ let nextImpls: CalcitImpl[];
79
82
  if (impl instanceof CalcitImpl) {
80
- return new CalcitRecord(this.name, this.fields, this.values, [impl]);
83
+ nextImpls = [impl];
84
+ } else if (Array.isArray(impl)) {
85
+ nextImpls = impl;
81
86
  } else {
82
- throw new Error("Expected an impl");
87
+ throw new Error("Expected an impl or array of impls");
83
88
  }
89
+ let nextStruct = new CalcitStruct(this.name, this.fields, this.structRef.fieldTypes, this.structRef.impls.concat(nextImpls));
90
+ return new CalcitRecord(this.name, this.fields, this.values, nextStruct);
84
91
  }
85
92
  }
86
93
 
@@ -107,7 +114,9 @@ export let new_impl_record = (impl: CalcitImpl, name: CalcitValue, ...fields: Ar
107
114
  throw new Error(`Unexpected duplication in record fields: ${x.toString()}`);
108
115
  }
109
116
  });
110
- return new CalcitRecord(castTag(name), fieldNames, undefined, [impl]);
117
+ let nameTag = castTag(name);
118
+ let structRef = new CalcitStruct(nameTag, fieldNames, new Array(fieldNames.length).fill(null), [impl]);
119
+ return new CalcitRecord(nameTag, fieldNames, undefined, structRef);
111
120
  };
112
121
 
113
122
  export let fieldsEqual = (xs: Array<CalcitTag>, ys: Array<CalcitTag>): boolean => {
@@ -155,7 +164,7 @@ export let _$n__PCT__$M_ = (proto: CalcitValue, ...xs: Array<CalcitValue>): Calc
155
164
  values[i] = xs[idx * 2 + 1];
156
165
  }
157
166
 
158
- return new CalcitRecord(proto.name, proto.fields, values, proto.impls);
167
+ return new CalcitRecord(proto.name, proto.fields, values, proto.structRef);
159
168
  } else {
160
169
  throw new Error("Expected prototype to be a record");
161
170
  }
@@ -177,7 +186,7 @@ export let _$n_record_$o_with = (proto: CalcitValue, ...xs: Array<CalcitValue>):
177
186
  }
178
187
  values[idx] = v;
179
188
  }
180
- return new CalcitRecord(proto.name, proto.fields, values, proto.impls);
189
+ return new CalcitRecord(proto.name, proto.fields, values, proto.structRef);
181
190
  } else {
182
191
  throw new Error("Expected prototype to be a record");
183
192
  }
@@ -9,16 +9,25 @@ import { CalcitEnum } from "./js-enum.mjs";
9
9
  export class CalcitTuple {
10
10
  tag: CalcitValue;
11
11
  extra: CalcitValue[];
12
- impls: CalcitImpl[];
13
12
  enumPrototype: CalcitRecord | CalcitEnum;
14
13
  cachedHash: Hash;
15
- constructor(tagName: CalcitValue, extra: CalcitValue[], impls: CalcitImpl[] = [], enumPrototype: CalcitRecord | CalcitEnum = null) {
14
+ constructor(tagName: CalcitValue, extra: CalcitValue[], enumPrototype: CalcitRecord | CalcitEnum = null) {
16
15
  this.tag = tagName;
17
16
  this.extra = extra;
18
- this.impls = impls;
19
17
  this.enumPrototype = enumPrototype;
20
18
  this.cachedHash = null;
21
19
  }
20
+
21
+ get impls(): CalcitImpl[] {
22
+ if (this.enumPrototype == null) {
23
+ return [];
24
+ }
25
+ if (this.enumPrototype instanceof CalcitEnum) {
26
+ return this.enumPrototype.impls;
27
+ }
28
+ return this.enumPrototype.structRef.impls;
29
+ }
30
+
22
31
  get(n: number) {
23
32
  if (n === 0) {
24
33
  return this.tag;
@@ -30,11 +39,11 @@ export class CalcitTuple {
30
39
  }
31
40
  assoc(n: number, v: CalcitValue) {
32
41
  if (n === 0) {
33
- return new CalcitTuple(v, this.extra, this.impls, this.enumPrototype);
42
+ return new CalcitTuple(v, this.extra, this.enumPrototype);
34
43
  } else if (n - 1 < this.extra.length) {
35
44
  let next_extra = this.extra.slice();
36
45
  next_extra[n - 1] = v;
37
- return new CalcitTuple(this.tag, next_extra, this.impls, this.enumPrototype);
46
+ return new CalcitTuple(this.tag, next_extra, this.enumPrototype);
38
47
  } else {
39
48
  throw new Error(`Tuple only have ${this.extra.length} elements`);
40
49
  }
@@ -68,15 +77,9 @@ export class CalcitTuple {
68
77
  const hasEnum = this.enumPrototype != null;
69
78
  const enumName = hasEnum ? (this.enumPrototype instanceof CalcitEnum ? this.enumPrototype.prototype.name.value : this.enumPrototype.name.value) : null;
70
79
 
71
- if (this.impls.length > 0 && hasEnum) {
72
- return `(%:: ${content} (:impls ${this.impls[0].name.value}) (:enum ${enumName}))`;
73
- }
74
80
  if (hasEnum) {
75
81
  return `(%:: ${content} (:enum ${enumName}))`;
76
82
  }
77
- if (this.impls.length > 0) {
78
- return `(:: ${content} (:impls ${this.impls[0].name.value}))`;
79
- }
80
83
  return `(:: ${content})`;
81
84
  }
82
85
  }