@calcit/procs 0.11.0-a8 → 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
+ }
@@ -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,19 @@ 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
+ if (x.origin != null) {
295
+ base = mergeValueHash(base, hashFunction(x.origin));
296
+ }
297
+ for (let idx = 0; idx < x.fields.length; idx++) {
298
+ base = mergeValueHash(base, hashFunction(x.fields[idx]));
299
+ base = mergeValueHash(base, hashFunction(x.values[idx]));
300
+ }
301
+ x.cachedHash = base;
302
+ return base;
303
+ }
283
304
  if (x instanceof CalcitStruct) {
284
305
  let base = defaultHash_struct;
285
306
  base = mergeValueHash(base, hashFunction(x.name));
@@ -376,6 +397,9 @@ export let toString = (x, escaped, disableJsDataWarning = false) => {
376
397
  if (x instanceof CalcitRecord) {
377
398
  return x.toString(disableJsDataWarning);
378
399
  }
400
+ if (x instanceof CalcitImpl) {
401
+ return x.toString(disableJsDataWarning);
402
+ }
379
403
  if (x instanceof CalcitStruct) {
380
404
  return x.toString(disableJsDataWarning);
381
405
  }
@@ -644,6 +668,32 @@ export let _$n__$e_ = (x, y) => {
644
668
  }
645
669
  return false;
646
670
  }
671
+ if (x instanceof CalcitImpl) {
672
+ if (y instanceof CalcitImpl) {
673
+ if (x.name !== y.name) {
674
+ return false;
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
+ }
682
+ if (!fieldsEqual(x.fields, y.fields)) {
683
+ return false;
684
+ }
685
+ if (x.values.length !== y.values.length) {
686
+ return false;
687
+ }
688
+ for (let idx = 0; idx < x.fields.length; idx++) {
689
+ if (!_$n__$e_(x.values[idx], y.values[idx])) {
690
+ return false;
691
+ }
692
+ }
693
+ return true;
694
+ }
695
+ return false;
696
+ }
647
697
  if (x instanceof CalcitStruct) {
648
698
  if (y instanceof CalcitStruct) {
649
699
  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
  }
@@ -193,7 +198,47 @@ export let defenum = (name, ...variants) => {
193
198
  const tags = entries.map((entry) => entry.tag);
194
199
  const values = entries.map((entry) => entry.payload);
195
200
  const prototype = new CalcitRecord(enumName, tags, values, null);
196
- return new CalcitEnum(prototype, null);
201
+ return new CalcitEnum(prototype);
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 origin = name instanceof CalcitTrait ? name : null;
207
+ const implName = origin ? origin.name : castTag(name);
208
+ if (pairs.length === 0) {
209
+ return new CalcitImpl(implName, [], [], origin);
210
+ }
211
+ const entries = [];
212
+ for (let idx = 0; idx < pairs.length; idx++) {
213
+ const pairValue = pairs[idx];
214
+ let fieldTag;
215
+ let value;
216
+ if (pairValue instanceof CalcitTuple) {
217
+ if (pairValue.extra.length !== 1) {
218
+ throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
219
+ }
220
+ fieldTag = castTag(pairValue.tag);
221
+ value = pairValue.extra[0];
222
+ }
223
+ else {
224
+ const pair = list_items(pairValue);
225
+ if (pair.length !== 2) {
226
+ throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
227
+ }
228
+ fieldTag = castTag(pair[0]);
229
+ value = pair[1];
230
+ }
231
+ entries.push({ tag: fieldTag, value });
232
+ }
233
+ entries.sort((a, b) => a.tag.idx - b.tag.idx);
234
+ for (let i = 1; i < entries.length; i++) {
235
+ if (entries[i - 1].tag.value === entries[i].tag.value) {
236
+ throw new Error(`&impl::new duplicated field: ${entries[i].tag.toString()}`);
237
+ }
238
+ }
239
+ const fields = entries.map((entry) => entry.tag);
240
+ const values = entries.map((entry) => entry.value);
241
+ return new CalcitImpl(implName, fields, values, origin);
197
242
  };
198
243
  export let _$n_struct_$o__$o_new = (name, ...entries) => {
199
244
  return defstruct(name, ...entries);
@@ -385,6 +430,12 @@ export let _$n_tuple_$o_count = function (xs) {
385
430
  return xs.count();
386
431
  throw new Error("Does not support `count` on this type");
387
432
  };
433
+ const coerce_impl = (value, procName) => {
434
+ if (value instanceof CalcitImpl) {
435
+ return value;
436
+ }
437
+ throw new Error(`${procName} expects trait impls as impls`);
438
+ };
388
439
  export let _$n_tuple_$o_impls = function (x) {
389
440
  if (arguments.length !== 1)
390
441
  throw new Error("&tuple:impls takes 1 argument");
@@ -400,21 +451,26 @@ export let _$n_tuple_$o_with_impls = function (x, y) {
400
451
  throw new Error("&tuple:with-impls takes 2 arguments");
401
452
  if (!(x instanceof CalcitTuple))
402
453
  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);
454
+ const impl = coerce_impl(y, "&tuple:with-impls");
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));
406
460
  };
407
461
  export let _$n_tuple_$o_impl_traits = function (x, ...traits) {
408
462
  if (traits.length < 1)
409
463
  throw new Error("&tuple:impl-traits takes 2+ arguments");
410
464
  if (!(x instanceof CalcitTuple))
411
465
  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
- }
466
+ const impls = traits.map((trait) => coerce_impl(trait, "&tuple:impl-traits"));
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])));
416
472
  }
417
- return new CalcitTuple(x.tag, x.extra, x.impls.concat(traits), x.enumPrototype);
473
+ return new CalcitTuple(x.tag, x.extra, proto.withImpls(impls));
418
474
  };
419
475
  export let _$n_tuple_$o_enum = function (x) {
420
476
  if (arguments.length !== 1)
@@ -427,7 +483,7 @@ export let _$n_tuple_$o_enum = function (x) {
427
483
  if (x.enumPrototype instanceof CalcitEnum) {
428
484
  return x.enumPrototype;
429
485
  }
430
- return new CalcitEnum(x.enumPrototype, null);
486
+ return new CalcitEnum(x.enumPrototype);
431
487
  };
432
488
  const unwrap_enum_prototype = (enumPrototype, procName) => {
433
489
  if (enumPrototype instanceof CalcitEnum) {
@@ -539,7 +595,7 @@ export let _$n_record_$o_impls = function (xs) {
539
595
  if (arguments.length !== 1)
540
596
  throw new Error("&record:impls takes 1 argument");
541
597
  if (xs instanceof CalcitRecord)
542
- return new CalcitSliceList(xs.impls);
598
+ return new CalcitSliceList(xs.structRef.impls);
543
599
  throw new Error("&record:impls expected a record");
544
600
  };
545
601
  export let _$n_record_$o_impl_traits = function (xs, ...traits) {
@@ -547,43 +603,40 @@ export let _$n_record_$o_impl_traits = function (xs, ...traits) {
547
603
  throw new Error("&record:impl-traits takes 2+ arguments");
548
604
  if (!(xs instanceof CalcitRecord))
549
605
  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));
606
+ const impls = traits.map((trait) => coerce_impl(trait, "&record:impl-traits"));
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);
556
609
  };
557
610
  export let _$n_struct_$o_impl_traits = function (xs, ...traits) {
558
611
  if (traits.length < 1)
559
612
  throw new Error("&struct:impl-traits takes 2+ arguments");
560
613
  if (!(xs instanceof CalcitStruct))
561
614
  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));
615
+ const addedImpls = traits.map((trait) => coerce_impl(trait, "&struct:impl-traits"));
616
+ const baseImpls = xs.impls ?? [];
617
+ return new CalcitStruct(xs.name, xs.fields, xs.fieldTypes, baseImpls.concat(addedImpls));
569
618
  };
570
619
  export let _$n_enum_$o_impl_traits = function (xs, ...traits) {
571
620
  if (traits.length < 1)
572
621
  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
- }
622
+ const addedImpls = traits.map((trait) => coerce_impl(trait, "&enum:impl-traits"));
578
623
  if (xs instanceof CalcitEnum) {
579
- const impls = xs.impls ?? [];
580
- return new CalcitEnum(xs.prototype, impls.concat(traits));
624
+ return xs.withImpls(addedImpls);
581
625
  }
582
626
  if (xs instanceof CalcitRecord) {
583
- return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(traits));
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);
584
629
  }
585
630
  throw new Error("&enum:impl-traits expected an enum or enum record");
586
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
+ };
587
640
  export let _$n_list_$o_assoc_before = function (xs, k, v) {
588
641
  if (arguments.length !== 3) {
589
642
  throw new Error("assoc takes 3 arguments");
@@ -1452,7 +1505,7 @@ export let _$n_js_object = (...xs) => {
1452
1505
  return ret;
1453
1506
  };
1454
1507
  export let _$o__$o_ = (tagName, ...extra) => {
1455
- return new CalcitTuple(tagName, extra, [], null);
1508
+ return new CalcitTuple(tagName, extra, null);
1456
1509
  };
1457
1510
  export let _PCT__$o__$o_ = (enumPrototype, tag, ...extra) => {
1458
1511
  const proto = assert_enum_tag_args("%::", enumPrototype, tag);
@@ -1472,7 +1525,7 @@ export let _PCT__$o__$o_ = (enumPrototype, tag, ...extra) => {
1472
1525
  throw new Error(`Expected variant definition to be a list, got ${variantDefinition}`);
1473
1526
  }
1474
1527
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1475
- return new CalcitTuple(tag, extra, [], tupleEnumPrototype);
1528
+ return new CalcitTuple(tag, extra, tupleEnumPrototype);
1476
1529
  };
1477
1530
  export let _PCT__PCT__$o__$o_ = (impl, enumPrototype, tag, ...extra) => {
1478
1531
  // Runtime validation: check if tag exists in enum and arity matches
@@ -1493,7 +1546,8 @@ export let _PCT__PCT__$o__$o_ = (impl, enumPrototype, tag, ...extra) => {
1493
1546
  throw new Error(`Expected variant definition to be a list, got ${variantDefinition}`);
1494
1547
  }
1495
1548
  const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
1496
- return new CalcitTuple(tag, extra, [impl], tupleEnumPrototype);
1549
+ const implValue = coerce_impl(impl, "%:: with impl");
1550
+ return new CalcitTuple(tag, extra, tupleEnumPrototype.withImpls(implValue));
1497
1551
  };
1498
1552
  let calcit_builtin_impls = {
1499
1553
  number: null,
@@ -1516,10 +1570,14 @@ export function invoke_method_closure(p) {
1516
1570
  function normalize_builtin_impls(entry) {
1517
1571
  if (entry == null)
1518
1572
  return null;
1519
- if (entry instanceof CalcitRecord)
1573
+ if (entry instanceof CalcitImpl)
1520
1574
  return [entry];
1521
1575
  if (entry instanceof CalcitList || entry instanceof CalcitSliceList) {
1522
- return list_items(entry);
1576
+ return list_items(entry).map((item) => {
1577
+ if (item instanceof CalcitImpl)
1578
+ return item;
1579
+ throw new Error(`invoke-method expects impls in list, but received: ${toString(item, true)}`);
1580
+ });
1523
1581
  }
1524
1582
  return null;
1525
1583
  }
@@ -1536,7 +1594,7 @@ function lookup_impls(obj) {
1536
1594
  }
1537
1595
  else if (obj instanceof CalcitRecord) {
1538
1596
  tag = obj.name.toString();
1539
- impls = obj.impls;
1597
+ impls = obj.structRef.impls;
1540
1598
  }
1541
1599
  else if (obj instanceof CalcitTuple) {
1542
1600
  tag = obj.tag.toString();
@@ -1641,14 +1699,15 @@ export function _$n_inspect_methods(obj, note) {
1641
1699
  implsInOrder.push(impl);
1642
1700
  idx += reverse ? -1 : 1;
1643
1701
  }
1644
- console.log(`Impl records (high → low precedence): ${implsInOrder.length}`);
1702
+ console.log(`Impls (high → low precedence): ${implsInOrder.length}`);
1645
1703
  for (let i = 0; i < implsInOrder.length; i++) {
1646
1704
  let impl = implsInOrder[i];
1647
1705
  let names = [];
1648
1706
  for (let k = 0; k < impl.fields.length; k++) {
1649
1707
  names.push("." + impl.fields[k].value);
1650
1708
  }
1651
- 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(" ")})`);
1652
1711
  }
1653
1712
  let ms = _$n_methods_of(obj);
1654
1713
  console.log(`\nAll methods (unique, high → low): ${ms.len()}`);
@@ -1678,7 +1737,7 @@ export function _$n_trait_call(traitDef, method, obj, ...args) {
1678
1737
  let idx = reverse ? impls.length - 1 : 0;
1679
1738
  while (reverse ? idx >= 0 : idx < impls.length) {
1680
1739
  const impl = impls[idx];
1681
- if (impl != null && impl.name.value === traitDef.name.value) {
1740
+ if (impl != null && impl.origin != null && impl.origin.name.value === traitDef.name.value) {
1682
1741
  const fn = impl.getOrNil(methodName);
1683
1742
  if (fn != null) {
1684
1743
  if (typeof fn !== "function") {
@@ -1689,7 +1748,7 @@ export function _$n_trait_call(traitDef, method, obj, ...args) {
1689
1748
  }
1690
1749
  idx += reverse ? -1 : 1;
1691
1750
  }
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.`);
1751
+ 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
1752
  }
1694
1753
  export let _$n_map_$o_to_list = (m) => {
1695
1754
  if (m instanceof CalcitMap || m instanceof CalcitSliceMap) {
@@ -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
@@ -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
  }
@@ -353,7 +360,7 @@ export let extract_cirru_edn = (x, options) => {
353
360
  if (!deepEqual(v.fields, fields)) {
354
361
  throw new Error(`Fields mismatch for ${name}, expected ${fields}, got ${v.fields}`);
355
362
  }
356
- return new CalcitRecord(extractFieldTag(name), fields, values, v.impls);
363
+ return new CalcitRecord(extractFieldTag(name), fields, values, v.structRef);
357
364
  }
358
365
  }
359
366
  return new CalcitRecord(extractFieldTag(name), fields, values);
@@ -392,7 +399,7 @@ export let extract_cirru_edn = (x, options) => {
392
399
  return new CalcitTuple(extract_cirru_edn(x[1], options), x
393
400
  .slice(2)
394
401
  .filter(notComment)
395
- .map((x) => extract_cirru_edn(x, options)), []);
402
+ .map((x) => extract_cirru_edn(x, options)));
396
403
  }
397
404
  if (x[0] === "%::") {
398
405
  if (x.length < 3) {
@@ -409,7 +416,7 @@ export let extract_cirru_edn = (x, options) => {
409
416
  return new CalcitTuple(extract_cirru_edn(x[2], options), x
410
417
  .slice(3)
411
418
  .filter(notComment)
412
- .map((x) => extract_cirru_edn(x, options)), [], enumPrototype);
419
+ .map((x) => extract_cirru_edn(x, options)), enumPrototype);
413
420
  }
414
421
  if (x[0] === "atom") {
415
422
  if (x.length !== 2) {
package/lib/js-enum.mjs CHANGED
@@ -1,21 +1,27 @@
1
- import { CalcitRecord } from "./js-record.mjs";
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) {
12
- if (impls instanceof CalcitRecord) {
13
- return new CalcitEnum(this.prototype, [impls]);
14
+ let nextImpls;
15
+ if (impls instanceof CalcitImpl) {
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 a record as implementation");
24
+ return new CalcitEnum(this.prototype.withImpls(nextImpls));
19
25
  }
20
26
  toString() {
21
27
  return `(%enum :${this.prototype.name.value})`;
@@ -0,0 +1,34 @@
1
+ import { castTag, findInFields, toString } from "./calcit-data.mjs";
2
+ export class CalcitImpl {
3
+ constructor(name, fields, values, origin = null) {
4
+ this.name = name;
5
+ this.origin = origin;
6
+ this.fields = fields;
7
+ this.values = values;
8
+ this.cachedHash = null;
9
+ }
10
+ get(k) {
11
+ let field = castTag(k);
12
+ let idx = findInFields(this.fields, field);
13
+ if (idx >= 0) {
14
+ return this.values[idx];
15
+ }
16
+ throw new Error(`Cannot find :${field} among (${this.fields.join(",")})`);
17
+ }
18
+ getOrNil(k) {
19
+ let field = castTag(k);
20
+ let idx = findInFields(this.fields, field);
21
+ if (idx >= 0) {
22
+ return this.values[idx];
23
+ }
24
+ return undefined;
25
+ }
26
+ toString(disableJsDataWarning = false) {
27
+ const parts = ["(%impl ", this.name.toString()];
28
+ for (let idx = 0; idx < this.fields.length; idx++) {
29
+ parts.push(" (", this.fields[idx].toString(), " ", toString(this.values[idx], true, disableJsDataWarning), ")");
30
+ }
31
+ parts.push(")");
32
+ return parts.join("");
33
+ }
34
+ }
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)