@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.
- package/.yarn/install-state.gz +0 -0
- package/lib/calcit-data.mjs +41 -0
- package/lib/calcit.procs.mjs +73 -35
- package/lib/js-cirru.mjs +7 -0
- package/lib/js-enum.mjs +3 -3
- package/lib/js-impl.mjs +33 -0
- package/lib/js-primes.mjs +8 -4
- package/lib/js-record.mjs +3 -2
- package/lib/js-struct.mjs +3 -3
- package/lib/package.json +1 -1
- package/package.json +1 -1
- package/ts-src/calcit-data.mts +41 -0
- package/ts-src/calcit.procs.mts +79 -41
- package/ts-src/js-cirru.mts +5 -0
- package/ts-src/js-enum.mts +6 -5
- package/ts-src/js-impl.mts +44 -0
- package/ts-src/js-primes.mts +4 -0
- package/ts-src/js-record.mts +6 -5
- package/ts-src/js-struct.mts +6 -6
- package/ts-src/js-tuple.mts +3 -2
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/lib/calcit-data.mjs
CHANGED
|
@@ -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);
|
package/lib/calcit.procs.mjs
CHANGED
|
@@ -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
|
-
|
|
404
|
-
|
|
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
|
-
|
|
413
|
-
|
|
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
|
-
|
|
551
|
-
|
|
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
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
-
|
|
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
|
|
580
|
-
return new CalcitEnum(xs.prototype,
|
|
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(
|
|
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
|
-
|
|
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
|
|
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(`
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
18
|
+
throw new Error("Expected an impl as implementation");
|
|
19
19
|
}
|
|
20
20
|
toString() {
|
|
21
21
|
return `(%enum :${this.prototype.name.value})`;
|
package/lib/js-impl.mjs
ADDED
|
@@ -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["
|
|
42
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
43
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
44
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
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
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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
package/package.json
CHANGED
package/ts-src/calcit-data.mts
CHANGED
|
@@ -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);
|
package/ts-src/calcit.procs.mts
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
461
|
-
return new CalcitTuple(x.tag, x.extra, [
|
|
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
|
-
|
|
468
|
-
|
|
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
|
-
|
|
614
|
-
|
|
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
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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
|
-
|
|
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
|
|
642
|
-
return new CalcitEnum(xs.prototype,
|
|
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(
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
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):
|
|
1679
|
+
function normalize_builtin_impls(entry: CalcitImplEntry): CalcitImpl[] | null {
|
|
1645
1680
|
if (entry == null) return null;
|
|
1646
|
-
if (entry instanceof
|
|
1681
|
+
if (entry instanceof CalcitImpl) return [entry];
|
|
1647
1682
|
if (entry instanceof CalcitList || entry instanceof CalcitSliceList) {
|
|
1648
|
-
return list_items(entry)
|
|
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): [
|
|
1654
|
-
let impls:
|
|
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:
|
|
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(`
|
|
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
|
|
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
|
|
package/ts-src/js-cirru.mts
CHANGED
|
@@ -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
|
}
|
package/ts-src/js-enum.mts
CHANGED
|
@@ -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:
|
|
6
|
+
impls: CalcitImpl[];
|
|
6
7
|
cachedHash: number;
|
|
7
8
|
|
|
8
|
-
constructor(prototype: CalcitRecord, impls:
|
|
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:
|
|
19
|
-
if (impls instanceof
|
|
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
|
|
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
|
+
}
|
package/ts-src/js-primes.mts
CHANGED
|
@@ -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;
|
package/ts-src/js-record.mts
CHANGED
|
@@ -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<
|
|
12
|
+
impls: Array<CalcitImpl>;
|
|
12
13
|
cachedHash: Hash;
|
|
13
|
-
constructor(name: CalcitTag, fields: Array<CalcitTag>, values?: Array<CalcitValue>, impls?: Array<
|
|
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
|
|
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
|
|
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:
|
|
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;
|
package/ts-src/js-struct.mts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { CalcitTag, toString } from "./calcit-data.mjs";
|
|
2
2
|
import { CalcitValue } from "./js-primes.mjs";
|
|
3
|
-
import {
|
|
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:
|
|
9
|
+
impls: CalcitImpl[];
|
|
10
10
|
cachedHash: number;
|
|
11
11
|
|
|
12
|
-
constructor(name: CalcitTag, fields: CalcitTag[], fieldTypes: CalcitValue[], impls:
|
|
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:
|
|
24
|
-
if (impls instanceof
|
|
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
|
|
29
|
+
throw new Error("Expected an impl as implementation");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
toString(disableJsDataWarning: boolean = false): string {
|
package/ts-src/js-tuple.mts
CHANGED
|
@@ -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:
|
|
12
|
+
impls: CalcitImpl[];
|
|
12
13
|
enumPrototype: CalcitRecord | CalcitEnum;
|
|
13
14
|
cachedHash: Hash;
|
|
14
|
-
constructor(tagName: CalcitValue, extra: CalcitValue[], impls:
|
|
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;
|