@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.
- package/.yarn/install-state.gz +0 -0
- package/build.rs +74 -0
- package/lib/calcit-data.mjs +50 -0
- package/lib/calcit.procs.mjs +101 -42
- package/lib/custom-formatter.mjs +2 -2
- package/lib/js-cirru.mjs +10 -3
- package/lib/js-enum.mjs +13 -7
- package/lib/js-impl.mjs +34 -0
- package/lib/js-primes.mjs +8 -4
- package/lib/js-record.mjs +19 -9
- package/lib/js-struct.mjs +3 -3
- package/lib/js-tuple.mjs +12 -10
- package/lib/package.json +1 -1
- package/package.json +1 -1
- package/ts-src/calcit-data.mts +50 -0
- package/ts-src/calcit.procs.mts +110 -49
- package/ts-src/custom-formatter.mts +2 -2
- package/ts-src/js-cirru.mts +7 -4
- package/ts-src/js-enum.mts +14 -8
- package/ts-src/js-impl.mts +47 -0
- package/ts-src/js-primes.mts +6 -0
- package/ts-src/js-record.mts +22 -12
- package/ts-src/js-struct.mts +6 -6
- package/ts-src/js-tuple.mts +15 -11
package/lib/js-record.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
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";
|
|
4
|
+
import { CalcitStruct } from "./js-struct.mjs";
|
|
3
5
|
export class CalcitRecord {
|
|
4
|
-
constructor(name, fields, values,
|
|
6
|
+
constructor(name, fields, values, structRef) {
|
|
5
7
|
this.name = name;
|
|
6
8
|
let fieldNames = fields.map(castTag);
|
|
7
9
|
this.fields = fields;
|
|
@@ -15,7 +17,7 @@ export class CalcitRecord {
|
|
|
15
17
|
this.values = new Array(fieldNames.length);
|
|
16
18
|
}
|
|
17
19
|
this.cachedHash = null;
|
|
18
|
-
this.
|
|
20
|
+
this.structRef = structRef || new CalcitStruct(name, fields, new Array(fields.length).fill(null));
|
|
19
21
|
}
|
|
20
22
|
get(k) {
|
|
21
23
|
let field = castTag(k);
|
|
@@ -48,7 +50,7 @@ export class CalcitRecord {
|
|
|
48
50
|
values[idx] = this.values[idx];
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
|
-
return new CalcitRecord(this.name, this.fields, values, this.
|
|
53
|
+
return new CalcitRecord(this.name, this.fields, values, this.structRef);
|
|
52
54
|
}
|
|
53
55
|
/** return -1 for missing */
|
|
54
56
|
findIndex(k) {
|
|
@@ -70,12 +72,18 @@ export class CalcitRecord {
|
|
|
70
72
|
return parts.join("");
|
|
71
73
|
}
|
|
72
74
|
withImpls(impl) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
let nextImpls;
|
|
76
|
+
if (impl instanceof CalcitImpl) {
|
|
77
|
+
nextImpls = [impl];
|
|
78
|
+
}
|
|
79
|
+
else if (Array.isArray(impl)) {
|
|
80
|
+
nextImpls = impl;
|
|
75
81
|
}
|
|
76
82
|
else {
|
|
77
|
-
throw new Error("Expected
|
|
83
|
+
throw new Error("Expected an impl or array of impls");
|
|
78
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);
|
|
79
87
|
}
|
|
80
88
|
}
|
|
81
89
|
export let new_record = (name, ...fields) => {
|
|
@@ -104,7 +112,9 @@ export let new_impl_record = (impl, name, ...fields) => {
|
|
|
104
112
|
throw new Error(`Unexpected duplication in record fields: ${x.toString()}`);
|
|
105
113
|
}
|
|
106
114
|
});
|
|
107
|
-
|
|
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);
|
|
108
118
|
};
|
|
109
119
|
export let fieldsEqual = (xs, ys) => {
|
|
110
120
|
if (xs === ys) {
|
|
@@ -146,7 +156,7 @@ export let _$n__PCT__$M_ = (proto, ...xs) => {
|
|
|
146
156
|
}
|
|
147
157
|
values[i] = xs[idx * 2 + 1];
|
|
148
158
|
}
|
|
149
|
-
return new CalcitRecord(proto.name, proto.fields, values, proto.
|
|
159
|
+
return new CalcitRecord(proto.name, proto.fields, values, proto.structRef);
|
|
150
160
|
}
|
|
151
161
|
else {
|
|
152
162
|
throw new Error("Expected prototype to be a record");
|
|
@@ -168,7 +178,7 @@ export let _$n_record_$o_with = (proto, ...xs) => {
|
|
|
168
178
|
}
|
|
169
179
|
values[idx] = v;
|
|
170
180
|
}
|
|
171
|
-
return new CalcitRecord(proto.name, proto.fields, values, proto.
|
|
181
|
+
return new CalcitRecord(proto.name, proto.fields, values, proto.structRef);
|
|
172
182
|
}
|
|
173
183
|
else {
|
|
174
184
|
throw new Error("Expected prototype to be a record");
|
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/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,
|
|
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.
|
|
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.
|
|
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
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,19 @@ 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
|
+
if (x.origin != null) {
|
|
324
|
+
base = mergeValueHash(base, hashFunction(x.origin));
|
|
325
|
+
}
|
|
326
|
+
for (let idx = 0; idx < x.fields.length; idx++) {
|
|
327
|
+
base = mergeValueHash(base, hashFunction(x.fields[idx]));
|
|
328
|
+
base = mergeValueHash(base, hashFunction(x.values[idx]));
|
|
329
|
+
}
|
|
330
|
+
x.cachedHash = base;
|
|
331
|
+
return base;
|
|
332
|
+
}
|
|
312
333
|
if (x instanceof CalcitStruct) {
|
|
313
334
|
let base = defaultHash_struct;
|
|
314
335
|
base = mergeValueHash(base, hashFunction(x.name));
|
|
@@ -405,6 +426,9 @@ export let toString = (x: CalcitValue, escaped: boolean, disableJsDataWarning: b
|
|
|
405
426
|
if (x instanceof CalcitRecord) {
|
|
406
427
|
return x.toString(disableJsDataWarning);
|
|
407
428
|
}
|
|
429
|
+
if (x instanceof CalcitImpl) {
|
|
430
|
+
return x.toString(disableJsDataWarning);
|
|
431
|
+
}
|
|
408
432
|
if (x instanceof CalcitStruct) {
|
|
409
433
|
return x.toString(disableJsDataWarning);
|
|
410
434
|
}
|
|
@@ -682,6 +706,32 @@ export let _$n__$e_ = (x: CalcitValue, y: CalcitValue): boolean => {
|
|
|
682
706
|
}
|
|
683
707
|
return false;
|
|
684
708
|
}
|
|
709
|
+
if (x instanceof CalcitImpl) {
|
|
710
|
+
if (y instanceof CalcitImpl) {
|
|
711
|
+
if (x.name !== y.name) {
|
|
712
|
+
return false;
|
|
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
|
+
}
|
|
720
|
+
if (!fieldsEqual(x.fields, y.fields)) {
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
723
|
+
if (x.values.length !== y.values.length) {
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
for (let idx = 0; idx < x.fields.length; idx++) {
|
|
727
|
+
if (!_$n__$e_(x.values[idx], y.values[idx])) {
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return true;
|
|
732
|
+
}
|
|
733
|
+
return false;
|
|
734
|
+
}
|
|
685
735
|
if (x instanceof CalcitStruct) {
|
|
686
736
|
if (y instanceof CalcitStruct) {
|
|
687
737
|
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
|
}
|
|
@@ -225,7 +230,46 @@ export let defenum = (name: CalcitValue, ...variants: CalcitValue[]): CalcitEnum
|
|
|
225
230
|
const tags = entries.map((entry) => entry.tag);
|
|
226
231
|
const values = entries.map((entry) => entry.payload);
|
|
227
232
|
const prototype = new CalcitRecord(enumName, tags, values, null);
|
|
228
|
-
return new CalcitEnum(prototype
|
|
233
|
+
return new CalcitEnum(prototype);
|
|
234
|
+
};
|
|
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 origin = name instanceof CalcitTrait ? name : null;
|
|
239
|
+
const implName = origin ? origin.name : castTag(name);
|
|
240
|
+
if (pairs.length === 0) {
|
|
241
|
+
return new CalcitImpl(implName, [], [], origin);
|
|
242
|
+
}
|
|
243
|
+
const entries: Array<{ tag: CalcitTag; value: CalcitValue }> = [];
|
|
244
|
+
for (let idx = 0; idx < pairs.length; idx++) {
|
|
245
|
+
const pairValue = pairs[idx];
|
|
246
|
+
let fieldTag: CalcitTag;
|
|
247
|
+
let value: CalcitValue;
|
|
248
|
+
if (pairValue instanceof CalcitTuple) {
|
|
249
|
+
if (pairValue.extra.length !== 1) {
|
|
250
|
+
throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
|
|
251
|
+
}
|
|
252
|
+
fieldTag = castTag(pairValue.tag);
|
|
253
|
+
value = pairValue.extra[0];
|
|
254
|
+
} else {
|
|
255
|
+
const pair = list_items(pairValue);
|
|
256
|
+
if (pair.length !== 2) {
|
|
257
|
+
throw new Error(`&impl::new expects (field value) pairs, got: ${toString(pairValue, true)}`);
|
|
258
|
+
}
|
|
259
|
+
fieldTag = castTag(pair[0]);
|
|
260
|
+
value = pair[1];
|
|
261
|
+
}
|
|
262
|
+
entries.push({ tag: fieldTag, value });
|
|
263
|
+
}
|
|
264
|
+
entries.sort((a, b) => a.tag.idx - b.tag.idx);
|
|
265
|
+
for (let i = 1; i < entries.length; i++) {
|
|
266
|
+
if (entries[i - 1].tag.value === entries[i].tag.value) {
|
|
267
|
+
throw new Error(`&impl::new duplicated field: ${entries[i].tag.toString()}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const fields = entries.map((entry) => entry.tag);
|
|
271
|
+
const values = entries.map((entry) => entry.value);
|
|
272
|
+
return new CalcitImpl(implName, fields, values, origin);
|
|
229
273
|
};
|
|
230
274
|
|
|
231
275
|
export let _$n_struct_$o__$o_new = (name: CalcitValue, ...entries: CalcitValue[]): CalcitStruct => {
|
|
@@ -444,6 +488,13 @@ export let _$n_tuple_$o_count = function (xs: CalcitValue) {
|
|
|
444
488
|
throw new Error("Does not support `count` on this type");
|
|
445
489
|
};
|
|
446
490
|
|
|
491
|
+
const coerce_impl = (value: CalcitValue, procName: string): CalcitImpl => {
|
|
492
|
+
if (value instanceof CalcitImpl) {
|
|
493
|
+
return value;
|
|
494
|
+
}
|
|
495
|
+
throw new Error(`${procName} expects trait impls as impls`);
|
|
496
|
+
};
|
|
497
|
+
|
|
447
498
|
export let _$n_tuple_$o_impls = function (x: CalcitTuple) {
|
|
448
499
|
if (arguments.length !== 1) throw new Error("&tuple:impls takes 1 argument");
|
|
449
500
|
return new CalcitSliceList(x.impls);
|
|
@@ -454,22 +505,30 @@ export let _$n_tuple_$o_params = function (x: CalcitTuple) {
|
|
|
454
505
|
return new CalcitSliceList(x.extra);
|
|
455
506
|
};
|
|
456
507
|
|
|
457
|
-
export let _$n_tuple_$o_with_impls = function (x: CalcitTuple, y:
|
|
508
|
+
export let _$n_tuple_$o_with_impls = function (x: CalcitTuple, y: CalcitValue) {
|
|
458
509
|
if (arguments.length !== 2) throw new Error("&tuple:with-impls takes 2 arguments");
|
|
459
510
|
if (!(x instanceof CalcitTuple)) throw new Error("&tuple:with-impls expects a tuple");
|
|
460
|
-
|
|
461
|
-
|
|
511
|
+
const impl = coerce_impl(y, "&tuple:with-impls");
|
|
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));
|
|
462
517
|
};
|
|
463
518
|
|
|
464
519
|
export let _$n_tuple_$o_impl_traits = function (x: CalcitValue, ...traits: CalcitValue[]) {
|
|
465
520
|
if (traits.length < 1) throw new Error("&tuple:impl-traits takes 2+ arguments");
|
|
466
521
|
if (!(x instanceof CalcitTuple)) throw new Error("&tuple:impl-traits expects a tuple");
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
522
|
+
const impls = traits.map((trait) => coerce_impl(trait, "&tuple:impl-traits"));
|
|
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
|
+
);
|
|
471
530
|
}
|
|
472
|
-
return new CalcitTuple(x.tag, x.extra,
|
|
531
|
+
return new CalcitTuple(x.tag, x.extra, proto.withImpls(impls));
|
|
473
532
|
};
|
|
474
533
|
|
|
475
534
|
export let _$n_tuple_$o_enum = function (x: CalcitTuple) {
|
|
@@ -481,7 +540,7 @@ export let _$n_tuple_$o_enum = function (x: CalcitTuple) {
|
|
|
481
540
|
if (x.enumPrototype instanceof CalcitEnum) {
|
|
482
541
|
return x.enumPrototype;
|
|
483
542
|
}
|
|
484
|
-
return new CalcitEnum(x.enumPrototype as CalcitRecord
|
|
543
|
+
return new CalcitEnum(x.enumPrototype as CalcitRecord);
|
|
485
544
|
};
|
|
486
545
|
|
|
487
546
|
const unwrap_enum_prototype = (enumPrototype: CalcitValue, procName: string): CalcitRecord => {
|
|
@@ -603,50 +662,47 @@ export let _$n_record_$o_assoc = function (xs: CalcitValue, k: CalcitValue, v: C
|
|
|
603
662
|
|
|
604
663
|
export let _$n_record_$o_impls = function (xs: CalcitValue) {
|
|
605
664
|
if (arguments.length !== 1) throw new Error("&record:impls takes 1 argument");
|
|
606
|
-
if (xs instanceof CalcitRecord) return new CalcitSliceList(xs.impls);
|
|
665
|
+
if (xs instanceof CalcitRecord) return new CalcitSliceList(xs.structRef.impls);
|
|
607
666
|
throw new Error("&record:impls expected a record");
|
|
608
667
|
};
|
|
609
668
|
|
|
610
669
|
export let _$n_record_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
|
|
611
670
|
if (traits.length < 1) throw new Error("&record:impl-traits takes 2+ arguments");
|
|
612
671
|
if (!(xs instanceof CalcitRecord)) throw new Error("&record:impl-traits expected a record");
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
return new CalcitRecord(xs.name, xs.fields, xs.values, xs.impls.concat(traits as CalcitRecord[]));
|
|
672
|
+
const impls = traits.map((trait) => coerce_impl(trait, "&record:impl-traits"));
|
|
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);
|
|
619
675
|
};
|
|
620
676
|
|
|
621
677
|
export let _$n_struct_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
|
|
622
678
|
if (traits.length < 1) throw new Error("&struct:impl-traits takes 2+ arguments");
|
|
623
679
|
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[]));
|
|
680
|
+
const addedImpls = traits.map((trait) => coerce_impl(trait, "&struct:impl-traits"));
|
|
681
|
+
const baseImpls = xs.impls ?? [];
|
|
682
|
+
return new CalcitStruct(xs.name, xs.fields, xs.fieldTypes, baseImpls.concat(addedImpls));
|
|
631
683
|
};
|
|
632
684
|
|
|
633
685
|
export let _$n_enum_$o_impl_traits = function (xs: CalcitValue, ...traits: CalcitValue[]) {
|
|
634
686
|
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
|
-
}
|
|
687
|
+
const addedImpls = traits.map((trait) => coerce_impl(trait, "&enum:impl-traits"));
|
|
640
688
|
if (xs instanceof CalcitEnum) {
|
|
641
|
-
|
|
642
|
-
return new CalcitEnum(xs.prototype, impls.concat(traits as CalcitRecord[]));
|
|
689
|
+
return xs.withImpls(addedImpls);
|
|
643
690
|
}
|
|
644
691
|
if (xs instanceof CalcitRecord) {
|
|
645
|
-
|
|
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);
|
|
646
694
|
}
|
|
647
695
|
throw new Error("&enum:impl-traits expected an enum or enum record");
|
|
648
696
|
};
|
|
649
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
|
+
|
|
650
706
|
export let _$n_list_$o_assoc_before = function (xs: CalcitList | CalcitSliceList, k: number, v: CalcitValue): CalcitList {
|
|
651
707
|
if (arguments.length !== 3) {
|
|
652
708
|
throw new Error("assoc takes 3 arguments");
|
|
@@ -1567,7 +1623,7 @@ export let _$n_js_object = (...xs: CalcitValue[]): Record<string, CalcitValue> =
|
|
|
1567
1623
|
};
|
|
1568
1624
|
|
|
1569
1625
|
export let _$o__$o_ = (tagName: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
|
|
1570
|
-
return new CalcitTuple(tagName, extra,
|
|
1626
|
+
return new CalcitTuple(tagName, extra, null);
|
|
1571
1627
|
};
|
|
1572
1628
|
|
|
1573
1629
|
export let _PCT__$o__$o_ = (enumPrototype: CalcitValue, tag: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
|
|
@@ -1590,10 +1646,10 @@ export let _PCT__$o__$o_ = (enumPrototype: CalcitValue, tag: CalcitValue, ...ext
|
|
|
1590
1646
|
}
|
|
1591
1647
|
|
|
1592
1648
|
const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
|
|
1593
|
-
return new CalcitTuple(tag, extra,
|
|
1649
|
+
return new CalcitTuple(tag, extra, tupleEnumPrototype);
|
|
1594
1650
|
};
|
|
1595
1651
|
|
|
1596
|
-
export let _PCT__PCT__$o__$o_ = (impl:
|
|
1652
|
+
export let _PCT__PCT__$o__$o_ = (impl: CalcitValue, enumPrototype: CalcitValue, tag: CalcitValue, ...extra: CalcitValue[]): CalcitTuple => {
|
|
1597
1653
|
// Runtime validation: check if tag exists in enum and arity matches
|
|
1598
1654
|
const proto = assert_enum_tag_args("%%::", enumPrototype, tag as CalcitTag);
|
|
1599
1655
|
const tagValue = tag as CalcitTag;
|
|
@@ -1613,12 +1669,13 @@ export let _PCT__PCT__$o__$o_ = (impl: CalcitRecord, enumPrototype: CalcitValue,
|
|
|
1613
1669
|
throw new Error(`Expected variant definition to be a list, got ${variantDefinition}`);
|
|
1614
1670
|
}
|
|
1615
1671
|
|
|
1616
|
-
const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : proto;
|
|
1617
|
-
|
|
1672
|
+
const tupleEnumPrototype = enumPrototype instanceof CalcitEnum ? enumPrototype : (proto as any);
|
|
1673
|
+
const implValue = coerce_impl(impl, "%:: with impl");
|
|
1674
|
+
return new CalcitTuple(tag, extra, tupleEnumPrototype.withImpls(implValue));
|
|
1618
1675
|
};
|
|
1619
1676
|
|
|
1620
1677
|
// mutable place for core to register
|
|
1621
|
-
type CalcitImplEntry =
|
|
1678
|
+
type CalcitImplEntry = CalcitImpl | CalcitList | CalcitSliceList | null;
|
|
1622
1679
|
|
|
1623
1680
|
let calcit_builtin_impls = {
|
|
1624
1681
|
number: null as CalcitImplEntry,
|
|
@@ -1641,17 +1698,20 @@ export function invoke_method_closure(p: string) {
|
|
|
1641
1698
|
};
|
|
1642
1699
|
}
|
|
1643
1700
|
|
|
1644
|
-
function normalize_builtin_impls(entry: CalcitImplEntry):
|
|
1701
|
+
function normalize_builtin_impls(entry: CalcitImplEntry): CalcitImpl[] | null {
|
|
1645
1702
|
if (entry == null) return null;
|
|
1646
|
-
if (entry instanceof
|
|
1703
|
+
if (entry instanceof CalcitImpl) return [entry];
|
|
1647
1704
|
if (entry instanceof CalcitList || entry instanceof CalcitSliceList) {
|
|
1648
|
-
return list_items(entry)
|
|
1705
|
+
return list_items(entry).map((item) => {
|
|
1706
|
+
if (item instanceof CalcitImpl) return item;
|
|
1707
|
+
throw new Error(`invoke-method expects impls in list, but received: ${toString(item, true)}`);
|
|
1708
|
+
}) as CalcitImpl[];
|
|
1649
1709
|
}
|
|
1650
1710
|
return null;
|
|
1651
1711
|
}
|
|
1652
1712
|
|
|
1653
|
-
function lookup_impls(obj: CalcitValue): [
|
|
1654
|
-
let impls:
|
|
1713
|
+
function lookup_impls(obj: CalcitValue): [CalcitImpl[], string] {
|
|
1714
|
+
let impls: CalcitImpl[];
|
|
1655
1715
|
let tag: string;
|
|
1656
1716
|
if (obj instanceof CalcitList || obj instanceof CalcitSliceList) {
|
|
1657
1717
|
tag = "&core-list-methods";
|
|
@@ -1661,7 +1721,7 @@ function lookup_impls(obj: CalcitValue): [CalcitRecord[], string] {
|
|
|
1661
1721
|
impls = normalize_builtin_impls(calcit_builtin_impls.map);
|
|
1662
1722
|
} else if (obj instanceof CalcitRecord) {
|
|
1663
1723
|
tag = obj.name.toString();
|
|
1664
|
-
impls = obj.impls;
|
|
1724
|
+
impls = obj.structRef.impls;
|
|
1665
1725
|
} else if (obj instanceof CalcitTuple) {
|
|
1666
1726
|
tag = obj.tag.toString();
|
|
1667
1727
|
impls = obj.impls;
|
|
@@ -1755,7 +1815,7 @@ export function _$n_inspect_methods(obj: CalcitValue, note: CalcitValue): Calcit
|
|
|
1755
1815
|
console.log("Method call syntax: `.method self p1 p2`");
|
|
1756
1816
|
console.log(" - dot is part of the method name, first arg is the receiver\n");
|
|
1757
1817
|
|
|
1758
|
-
let implsInOrder:
|
|
1818
|
+
let implsInOrder: CalcitImpl[] = [];
|
|
1759
1819
|
let idx = reverse ? impls.length - 1 : 0;
|
|
1760
1820
|
while (reverse ? idx >= 0 : idx < impls.length) {
|
|
1761
1821
|
let impl = impls[idx];
|
|
@@ -1763,14 +1823,15 @@ export function _$n_inspect_methods(obj: CalcitValue, note: CalcitValue): Calcit
|
|
|
1763
1823
|
idx += reverse ? -1 : 1;
|
|
1764
1824
|
}
|
|
1765
1825
|
|
|
1766
|
-
console.log(`
|
|
1826
|
+
console.log(`Impls (high → low precedence): ${implsInOrder.length}`);
|
|
1767
1827
|
for (let i = 0; i < implsInOrder.length; i++) {
|
|
1768
1828
|
let impl = implsInOrder[i];
|
|
1769
1829
|
let names: string[] = [];
|
|
1770
1830
|
for (let k = 0; k < impl.fields.length; k++) {
|
|
1771
1831
|
names.push("." + impl.fields[k].value);
|
|
1772
1832
|
}
|
|
1773
|
-
|
|
1833
|
+
const originName = impl.origin != null ? impl.origin.name.toString() : impl.name.toString();
|
|
1834
|
+
console.log(` #${i}: ${originName} (${names.join(" ")})`);
|
|
1774
1835
|
}
|
|
1775
1836
|
|
|
1776
1837
|
let ms = _$n_methods_of(obj);
|
|
@@ -1803,7 +1864,7 @@ export function _$n_trait_call(traitDef: CalcitValue, method: CalcitValue, obj:
|
|
|
1803
1864
|
let idx = reverse ? impls.length - 1 : 0;
|
|
1804
1865
|
while (reverse ? idx >= 0 : idx < impls.length) {
|
|
1805
1866
|
const impl = impls[idx];
|
|
1806
|
-
if (impl != null && impl.name.value === traitDef.name.value) {
|
|
1867
|
+
if (impl != null && impl.origin != null && impl.origin.name.value === traitDef.name.value) {
|
|
1807
1868
|
const fn = impl.getOrNil(methodName);
|
|
1808
1869
|
if (fn != null) {
|
|
1809
1870
|
if (typeof fn !== "function") {
|
|
@@ -1815,7 +1876,7 @@ export function _$n_trait_call(traitDef: CalcitValue, method: CalcitValue, obj:
|
|
|
1815
1876
|
idx += reverse ? -1 : 1;
|
|
1816
1877
|
}
|
|
1817
1878
|
throw new Error(
|
|
1818
|
-
`&trait-call: cannot find impl for trait ${traitDef.name.toString()} on ${toString(obj, true)}. Hint: use defimpl to create
|
|
1879
|
+
`&trait-call: cannot find impl for trait ${traitDef.name.toString()} on ${toString(obj, true)}. Hint: use defimpl to create impls tagged by trait.`
|
|
1819
1880
|
);
|
|
1820
1881
|
}
|
|
1821
1882
|
|
|
@@ -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
|
);
|
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
|
}
|
|
@@ -346,7 +351,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat, options: CalcitValue): Calcit
|
|
|
346
351
|
if (!deepEqual(v.fields, fields)) {
|
|
347
352
|
throw new Error(`Fields mismatch for ${name}, expected ${fields}, got ${v.fields}`);
|
|
348
353
|
}
|
|
349
|
-
return new CalcitRecord(extractFieldTag(name), fields, values, v.
|
|
354
|
+
return new CalcitRecord(extractFieldTag(name), fields, values, v.structRef);
|
|
350
355
|
}
|
|
351
356
|
}
|
|
352
357
|
|
|
@@ -392,8 +397,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat, options: CalcitValue): Calcit
|
|
|
392
397
|
x
|
|
393
398
|
.slice(2)
|
|
394
399
|
.filter(notComment)
|
|
395
|
-
.map((x) => extract_cirru_edn(x, options))
|
|
396
|
-
[]
|
|
400
|
+
.map((x) => extract_cirru_edn(x, options))
|
|
397
401
|
);
|
|
398
402
|
}
|
|
399
403
|
if (x[0] === "%::") {
|
|
@@ -414,7 +418,6 @@ export let extract_cirru_edn = (x: CirruEdnFormat, options: CalcitValue): Calcit
|
|
|
414
418
|
.slice(3)
|
|
415
419
|
.filter(notComment)
|
|
416
420
|
.map((x) => extract_cirru_edn(x, options)),
|
|
417
|
-
[],
|
|
418
421
|
enumPrototype
|
|
419
422
|
);
|
|
420
423
|
}
|