@calcit/procs 0.13.43 → 0.13.44
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/RFCs/04-15-match-syntax-rfc.md +14 -8
- package/RFCs/04-15-type-directed-optimization-catalog.md +20 -14
- package/RFCs/08-05-systematic-nil-reduction-rfc.md +16 -5
- package/editing-history/20260824-2119-validate-number-call-metadata.md +8 -0
- package/editing-history/20260824-2155-stable-js-struct-layout.md +11 -0
- package/editing-history/20260824-2224-struct-index-review-followups.md +7 -0
- package/editing-history/20260824-2233-indexed-struct-js-regressions.md +5 -0
- package/editing-history/20260824-2256-dynamic-method-analysis.md +9 -0
- package/editing-history/20260824-2329-dynamic-method-review-followups.md +7 -0
- package/editing-history/202608241731-contiguous-executable-calls.md +34 -0
- package/editing-history/202608241920-borrowed-syntax-arguments.md +34 -0
- package/editing-history/202608241924-unify-editing-history-directory.md +7 -0
- package/editing-history/202608242013-typed-native-number-ops.md +34 -0
- package/editing-history/20260825-0020-indexed-enum-match.md +34 -0
- package/editing-history/20260825-0100-indexed-enum-match-validation.md +7 -0
- package/editing-history/20260825-0120-indexed-enum-match-review.md +7 -0
- package/editing-history/20260825-1215-typed-literal-paths.md +56 -0
- package/editing-history/20260825-1344-typed-literal-path-review.md +17 -0
- package/editing-history/20260825-1505-typed-method-native-op.md +23 -0
- package/editing-history/20260825-1540-nil-unit-runtime-separation.md +15 -0
- package/editing-history/20260825-1725-typed-method-error-stack-review.md +10 -0
- package/editing-history/20260825-1733-nil-unit-doc-review.md +5 -0
- package/editing-history/20260825-1758-nil-unit-review-followup.md +6 -0
- package/editing-history/20260825-1845-release-01344.md +6 -0
- package/examples/bench_enum_match.rs +41 -0
- package/lib/calcit-data.d.mts +4 -0
- package/lib/calcit-data.mjs +59 -9
- package/lib/calcit.procs.d.mts +16 -8
- package/lib/calcit.procs.mjs +68 -46
- package/lib/custom-formatter.mjs +12 -3
- package/lib/js-cirru.mjs +6 -5
- package/lib/js-impl.mjs +4 -3
- package/lib/js-primes.d.mts +1 -1
- package/lib/js-primes.mjs +22 -18
- package/lib/js-struct-def.mjs +4 -6
- package/lib/js-struct-value.d.mts +5 -1
- package/lib/js-struct-value.mjs +66 -38
- package/lib/package.json +8 -2
- package/package.json +8 -2
- package/ts-src/calcit-data.mts +54 -9
- package/ts-src/calcit.procs.mts +66 -49
- package/ts-src/custom-formatter.mts +12 -3
- package/ts-src/js-cirru.mts +6 -5
- package/ts-src/js-impl.mts +4 -3
- package/ts-src/js-primes.mts +5 -1
- package/ts-src/js-struct-def.mts +4 -6
- package/ts-src/js-struct-value.mts +78 -33
- /package/{history → editing-history}/202608191501-release-01326.md +0 -0
- /package/{history → editing-history}/202608191628-revert-transparent-union-types.md +0 -0
- /package/{history → editing-history}/202608191741-release-01327.md +0 -0
- /package/{history → editing-history}/202608212020-release-01328.md +0 -0
- /package/{2026082200-release-01330.md → editing-history/2026082200-release-01330.md} +0 -0
- /package/{2026082200-same-package-module-meta.md → editing-history/2026082200-same-package-module-meta.md} +0 -0
- /package/{2026082200-transitive-module-loading.md → editing-history/2026082200-transitive-module-loading.md} +0 -0
- /package/{2026082222-release-01331.md → editing-history/2026082222-release-01331.md} +0 -0
- /package/{history → editing-history}/2026082223-release-01332.md +0 -0
- /package/{history → editing-history}/2026082223-same-package-namespaces.md +0 -0
- /package/{history → editing-history}/2026082300-fix-cross-package-namespace-merge.md +0 -0
- /package/{history → editing-history}/2026082300-release-01333.md +0 -0
- /package/{history → editing-history}/2026082316-release-01334.md +0 -0
package/lib/js-primes.mjs
CHANGED
|
@@ -27,28 +27,31 @@ export let isLiteral = (x) => {
|
|
|
27
27
|
var PseudoTypeIndex;
|
|
28
28
|
(function (PseudoTypeIndex) {
|
|
29
29
|
PseudoTypeIndex[PseudoTypeIndex["nil"] = 0] = "nil";
|
|
30
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
31
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
32
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
33
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
34
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
35
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
36
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
37
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
38
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
39
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
40
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
41
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
42
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
43
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
44
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
45
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
46
|
-
PseudoTypeIndex[PseudoTypeIndex["
|
|
30
|
+
PseudoTypeIndex[PseudoTypeIndex["unit"] = 1] = "unit";
|
|
31
|
+
PseudoTypeIndex[PseudoTypeIndex["bool"] = 2] = "bool";
|
|
32
|
+
PseudoTypeIndex[PseudoTypeIndex["number"] = 3] = "number";
|
|
33
|
+
PseudoTypeIndex[PseudoTypeIndex["symbol"] = 4] = "symbol";
|
|
34
|
+
PseudoTypeIndex[PseudoTypeIndex["tag"] = 5] = "tag";
|
|
35
|
+
PseudoTypeIndex[PseudoTypeIndex["string"] = 6] = "string";
|
|
36
|
+
PseudoTypeIndex[PseudoTypeIndex["ref"] = 7] = "ref";
|
|
37
|
+
PseudoTypeIndex[PseudoTypeIndex["enum_value"] = 8] = "enum_value";
|
|
38
|
+
PseudoTypeIndex[PseudoTypeIndex["recur"] = 9] = "recur";
|
|
39
|
+
PseudoTypeIndex[PseudoTypeIndex["list"] = 10] = "list";
|
|
40
|
+
PseudoTypeIndex[PseudoTypeIndex["set"] = 11] = "set";
|
|
41
|
+
PseudoTypeIndex[PseudoTypeIndex["map"] = 12] = "map";
|
|
42
|
+
PseudoTypeIndex[PseudoTypeIndex["struct_value"] = 13] = "struct_value";
|
|
43
|
+
PseudoTypeIndex[PseudoTypeIndex["impl"] = 14] = "impl";
|
|
44
|
+
PseudoTypeIndex[PseudoTypeIndex["struct_def"] = 15] = "struct_def";
|
|
45
|
+
PseudoTypeIndex[PseudoTypeIndex["enum_def"] = 16] = "enum_def";
|
|
46
|
+
PseudoTypeIndex[PseudoTypeIndex["fn"] = 17] = "fn";
|
|
47
|
+
PseudoTypeIndex[PseudoTypeIndex["cirru_quote"] = 18] = "cirru_quote";
|
|
47
48
|
})(PseudoTypeIndex || (PseudoTypeIndex = {}));
|
|
48
49
|
let typeAsInt = (x) => {
|
|
49
50
|
// based on order used in Ord trait
|
|
50
|
-
if (x
|
|
51
|
+
if (x === null)
|
|
51
52
|
return PseudoTypeIndex.nil;
|
|
53
|
+
if (x === undefined)
|
|
54
|
+
return PseudoTypeIndex.unit;
|
|
52
55
|
let t = typeof x;
|
|
53
56
|
if (t === "boolean")
|
|
54
57
|
return PseudoTypeIndex.bool;
|
|
@@ -106,6 +109,7 @@ export let _$n_compare = (a, b) => {
|
|
|
106
109
|
if (ta === tb) {
|
|
107
110
|
switch (ta) {
|
|
108
111
|
case PseudoTypeIndex.nil:
|
|
112
|
+
case PseudoTypeIndex.unit:
|
|
109
113
|
return 0;
|
|
110
114
|
case PseudoTypeIndex.bool:
|
|
111
115
|
return rawCompare(a, b);
|
package/lib/js-struct-def.mjs
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { toString } from "./calcit-data.mjs";
|
|
1
|
+
import { canonicalizeTagPairs, toString } from "./calcit-data.mjs";
|
|
2
2
|
import { CalcitImpl } from "./js-impl.mjs";
|
|
3
3
|
export class CalcitStructDef {
|
|
4
4
|
constructor(name, fields, fieldTypes, impls = []) {
|
|
5
|
-
|
|
6
|
-
throw new Error("CalcitStructDef: fields and fieldTypes length mismatch");
|
|
7
|
-
}
|
|
5
|
+
const [canonicalFields, canonicalTypes] = canonicalizeTagPairs(fields, fieldTypes, "CalcitStructDef");
|
|
8
6
|
this.name = name;
|
|
9
|
-
this.fields =
|
|
10
|
-
this.fieldTypes =
|
|
7
|
+
this.fields = canonicalFields;
|
|
8
|
+
this.fieldTypes = canonicalTypes;
|
|
11
9
|
this.impls = impls;
|
|
12
10
|
this.cachedHash = null;
|
|
13
11
|
}
|
|
@@ -14,6 +14,10 @@ export declare class CalcitStructValue {
|
|
|
14
14
|
getRequired(k: CalcitValue): CalcitValue;
|
|
15
15
|
getOrNil(k: CalcitValue): CalcitValue;
|
|
16
16
|
assoc(k: CalcitValue, v: CalcitValue): CalcitStructValue;
|
|
17
|
+
nthAt(index: CalcitValue, field: CalcitValue): CalcitValue;
|
|
18
|
+
assocAt(index: CalcitValue, field: CalcitValue, value: CalcitValue): CalcitStructValue;
|
|
19
|
+
withAt(...triples: CalcitValue[]): CalcitStructValue;
|
|
20
|
+
private assertFieldAt;
|
|
17
21
|
/** return -1 for missing */
|
|
18
22
|
findIndex(k: CalcitValue): number;
|
|
19
23
|
contains(k: CalcitValue): boolean;
|
|
@@ -23,7 +27,7 @@ export declare class CalcitStructValue {
|
|
|
23
27
|
export declare let new_struct_value: (name: CalcitValue, ...fields: Array<CalcitValue>) => CalcitValue;
|
|
24
28
|
export declare let new_impl_struct_value: (impl: CalcitImpl, name: CalcitValue, ...fields: Array<CalcitValue>) => CalcitValue;
|
|
25
29
|
/** Loose record: `?{} :field1 val1 :field2 val2` – record without a declared struct.
|
|
26
|
-
* Fields
|
|
30
|
+
* Fields use the same lexical layout as named structs. The record name is "_". */
|
|
27
31
|
export declare let _$q__$M_: (...xs: Array<CalcitValue>) => CalcitValue;
|
|
28
32
|
export declare let fieldsEqual: (xs: Array<CalcitTag>, ys: Array<CalcitTag>) => boolean;
|
|
29
33
|
export declare let _$n__PCT__$M_: (proto: CalcitValue, ...xs: Array<CalcitValue>) => CalcitValue;
|
package/lib/js-struct-value.mjs
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { CalcitImpl } from "./js-impl.mjs";
|
|
2
|
-
import { newTag, castTag, toString, getStringName, findInFields } from "./calcit-data.mjs";
|
|
2
|
+
import { newTag, castTag, toString, getStringName, findInFields, compareTagNames, canonicalizeTagPairs, tagNamesAreCanonical, } from "./calcit-data.mjs";
|
|
3
3
|
import { CalcitMap, CalcitSliceMap } from "./js-map.mjs";
|
|
4
4
|
import { CalcitStructDef } from "./js-struct-def.mjs";
|
|
5
5
|
export class CalcitStructValue {
|
|
6
6
|
constructor(name, fields, values, structRef) {
|
|
7
7
|
this.name = name;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
this.values = values;
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
this.values = new Array(fieldNames.length);
|
|
18
|
-
}
|
|
8
|
+
const fieldNames = fields.map(castTag);
|
|
9
|
+
const sourceValues = values ?? new Array(fieldNames.length);
|
|
10
|
+
const [canonicalFields, canonicalValues] = canonicalizeTagPairs(fieldNames, sourceValues, "CalcitStructValue");
|
|
11
|
+
this.fields = canonicalFields;
|
|
12
|
+
this.values = canonicalValues;
|
|
19
13
|
this.cachedHash = null;
|
|
20
|
-
this.structRef =
|
|
14
|
+
this.structRef =
|
|
15
|
+
structRef == null
|
|
16
|
+
? new CalcitStructDef(name, canonicalFields, new Array(canonicalFields.length).fill(null))
|
|
17
|
+
: tagNamesAreCanonical(structRef.fields)
|
|
18
|
+
? structRef
|
|
19
|
+
: new CalcitStructDef(structRef.name, structRef.fields, structRef.fieldTypes, structRef.impls);
|
|
21
20
|
}
|
|
22
21
|
get(k) {
|
|
23
22
|
let field = castTag(k);
|
|
@@ -58,6 +57,40 @@ export class CalcitStructValue {
|
|
|
58
57
|
}
|
|
59
58
|
return new CalcitStructValue(this.name, this.fields, values, this.structRef);
|
|
60
59
|
}
|
|
60
|
+
nthAt(index, field) {
|
|
61
|
+
const idx = checkedStructIndex(index, "&struct:nth");
|
|
62
|
+
this.assertFieldAt(idx, field, "&struct:nth");
|
|
63
|
+
return this.values[idx];
|
|
64
|
+
}
|
|
65
|
+
assocAt(index, field, value) {
|
|
66
|
+
const idx = checkedStructIndex(index, "&struct:assoc-at");
|
|
67
|
+
this.assertFieldAt(idx, field, "&struct:assoc-at");
|
|
68
|
+
const values = this.values.slice();
|
|
69
|
+
values[idx] = value;
|
|
70
|
+
return new CalcitStructValue(this.name, this.fields, values, this.structRef);
|
|
71
|
+
}
|
|
72
|
+
withAt(...triples) {
|
|
73
|
+
if (triples.length === 0 || triples.length % 3 !== 0) {
|
|
74
|
+
throw new Error("&struct:with-at expected index/tag/value triples");
|
|
75
|
+
}
|
|
76
|
+
const values = this.values.slice();
|
|
77
|
+
for (let base = 0; base < triples.length; base += 3) {
|
|
78
|
+
const idx = checkedStructIndex(triples[base], "&struct:with-at");
|
|
79
|
+
this.assertFieldAt(idx, triples[base + 1], "&struct:with-at");
|
|
80
|
+
values[idx] = triples[base + 2];
|
|
81
|
+
}
|
|
82
|
+
return new CalcitStructValue(this.name, this.fields, values, this.structRef);
|
|
83
|
+
}
|
|
84
|
+
assertFieldAt(idx, field, operation) {
|
|
85
|
+
if (idx >= this.fields.length) {
|
|
86
|
+
throw new Error(`${operation} index ${idx} out of range for struct '${this.name.value}' with ${this.fields.length} fields`);
|
|
87
|
+
}
|
|
88
|
+
const fieldTag = castTag(field);
|
|
89
|
+
const expectedTag = this.fields[idx];
|
|
90
|
+
if (expectedTag.value !== fieldTag.value) {
|
|
91
|
+
throw new Error(`${operation} index ${idx} expects field :${expectedTag.value}, but received :${fieldTag.value}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
61
94
|
/** return -1 for missing */
|
|
62
95
|
findIndex(k) {
|
|
63
96
|
let field = castTag(k);
|
|
@@ -93,37 +126,19 @@ export class CalcitStructValue {
|
|
|
93
126
|
}
|
|
94
127
|
}
|
|
95
128
|
export let new_struct_value = (name, ...fields) => {
|
|
96
|
-
let fieldNames = fields.map(castTag).sort(
|
|
97
|
-
|
|
98
|
-
return -1;
|
|
99
|
-
}
|
|
100
|
-
else if (x.idx > y.idx) {
|
|
101
|
-
return 1;
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
throw new Error(`Unexpected duplication in struct fields: ${x.toString()}`);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
129
|
+
let fieldNames = fields.map(castTag).sort(compareTagNames);
|
|
130
|
+
assertUniqueFields(fieldNames, "Unexpected duplication in struct fields");
|
|
107
131
|
return new CalcitStructValue(castTag(name), fieldNames);
|
|
108
132
|
};
|
|
109
133
|
export let new_impl_struct_value = (impl, name, ...fields) => {
|
|
110
|
-
let fieldNames = fields.map(castTag).sort(
|
|
111
|
-
|
|
112
|
-
return -1;
|
|
113
|
-
}
|
|
114
|
-
else if (x.idx > y.idx) {
|
|
115
|
-
return 1;
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
throw new Error(`Unexpected duplication in struct fields: ${x.toString()}`);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
134
|
+
let fieldNames = fields.map(castTag).sort(compareTagNames);
|
|
135
|
+
assertUniqueFields(fieldNames, "Unexpected duplication in struct fields");
|
|
121
136
|
let nameTag = castTag(name);
|
|
122
137
|
let structRef = new CalcitStructDef(nameTag, fieldNames, new Array(fieldNames.length).fill(null), [impl]);
|
|
123
138
|
return new CalcitStructValue(nameTag, fieldNames, undefined, structRef);
|
|
124
139
|
};
|
|
125
140
|
/** Loose record: `?{} :field1 val1 :field2 val2` – record without a declared struct.
|
|
126
|
-
* Fields
|
|
141
|
+
* Fields use the same lexical layout as named structs. The record name is "_". */
|
|
127
142
|
export let _$q__$M_ = (...xs) => {
|
|
128
143
|
if (xs.length % 2 !== 0) {
|
|
129
144
|
throw new Error("?{} expected pairs of :field value");
|
|
@@ -132,10 +147,10 @@ export let _$q__$M_ = (...xs) => {
|
|
|
132
147
|
for (let i = 0; i < xs.length; i += 2) {
|
|
133
148
|
pairs.push([castTag(xs[i]), xs[i + 1]]);
|
|
134
149
|
}
|
|
135
|
-
pairs.sort((a, b) => a[0]
|
|
150
|
+
pairs.sort((a, b) => compareTagNames(a[0], b[0]));
|
|
136
151
|
// Check for duplicate fields after sorting
|
|
137
152
|
for (let i = 1; i < pairs.length; i++) {
|
|
138
|
-
if (pairs[i][0].
|
|
153
|
+
if (pairs[i][0].value === pairs[i - 1][0].value) {
|
|
139
154
|
throw new Error(`?{} received duplicate field: :${getStringName(pairs[i][0])}`);
|
|
140
155
|
}
|
|
141
156
|
}
|
|
@@ -144,6 +159,19 @@ export let _$q__$M_ = (...xs) => {
|
|
|
144
159
|
let looseTag = newTag("_");
|
|
145
160
|
return new CalcitStructValue(looseTag, fieldNames, values);
|
|
146
161
|
};
|
|
162
|
+
function checkedStructIndex(value, operation) {
|
|
163
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
164
|
+
throw new Error(`${operation} expected a non-negative integer index, but received: ${value}`);
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
function assertUniqueFields(fields, message) {
|
|
169
|
+
for (let idx = 1; idx < fields.length; idx++) {
|
|
170
|
+
if (fields[idx - 1].value === fields[idx].value) {
|
|
171
|
+
throw new Error(`${message}: ${fields[idx].toString()}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
147
175
|
export let fieldsEqual = (xs, ys) => {
|
|
148
176
|
if (xs === ys) {
|
|
149
177
|
return true; // special case, referential equal
|
package/lib/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calcit/procs",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.44",
|
|
4
4
|
"main": "./lib/calcit.procs.mjs",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@types/node": "^25.7.0",
|
|
@@ -17,9 +17,15 @@
|
|
|
17
17
|
"test-fail": "cargo test -q --bin calcit type_fail_",
|
|
18
18
|
"test-snippets": "cargo test -q snippets::tests",
|
|
19
19
|
"check-js-runtime": "node scripts/check-js-runtime-identity.mjs",
|
|
20
|
+
"check-literal-paths": "cargo run --bin calcit -- calcit/bench-literal-paths.cirru && cargo run --bin calcit -- --emit-path target/literal-path-js calcit/bench-literal-paths.cirru js && node scripts/bench-literal-paths.mjs",
|
|
21
|
+
"check-typed-method-rem": "cargo run --bin calcit -- calcit/fibo.cirru && cargo run --bin calcit -- --emit-path target/typed-method-rem-js calcit/fibo.cirru js && node scripts/bench-typed-method-rem.mjs",
|
|
20
22
|
"bench-recur-smoke": "cargo run --bin calcit -- calcit/test.cirru js && node --input-type=module -e \"import { test_loop } from './js-out/test-recursion.main.mjs'; const n=3000; const t0=process.hrtime.bigint(); for(let i=0;i<n;i++) test_loop(); const dt=Number(process.hrtime.bigint()-t0)/1e6; console.log('test_loop_ms='+dt.toFixed(3));\"",
|
|
23
|
+
"bench-enum-match": "cargo run --release --example bench_enum_match && yarn compile && node scripts/bench-enum-match.mjs",
|
|
24
|
+
"bench-literal-paths": "cargo build --release --bin calcit && yarn compile && target/release/calcit calcit/bench-literal-paths.cirru && node scripts/bench-literal-paths-native.mjs && target/release/calcit --emit-path target/literal-path-js calcit/bench-literal-paths.cirru js && node scripts/bench-literal-paths.mjs",
|
|
25
|
+
"bench-typed-method-rem": "cargo build --release --bin calcit && yarn compile && target/release/calcit calcit/fibo.cirru && node scripts/bench-typed-method-rem-native.mjs && target/release/calcit --emit-path target/typed-method-rem-js calcit/fibo.cirru js && node scripts/bench-typed-method-rem.mjs",
|
|
26
|
+
"bench-struct-index": "yarn compile && node scripts/bench-struct-index.mjs",
|
|
21
27
|
"check-smooth": "yarn fmt-rs && yarn lint-rs && yarn test-rs && yarn check-all",
|
|
22
|
-
"check-all": "yarn compile && yarn check-js-runtime && yarn check-agent-interface && yarn try-core-tests && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm",
|
|
28
|
+
"check-all": "yarn compile && yarn check-js-runtime && yarn check-agent-interface && yarn try-core-tests && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm && yarn check-literal-paths && yarn check-typed-method-rem",
|
|
23
29
|
"check-agent-interface": "cargo build --bin calcit && node scripts/check-agent-interface.mjs",
|
|
24
30
|
"try-all": "yarn check-all",
|
|
25
31
|
"try-core-tests": "cargo run --bin calcit -- src/cirru/calcit-core.cirru test --tag unit --summary-only",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calcit/procs",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.44",
|
|
4
4
|
"main": "./lib/calcit.procs.mjs",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@types/node": "^25.7.0",
|
|
@@ -17,9 +17,15 @@
|
|
|
17
17
|
"test-fail": "cargo test -q --bin calcit type_fail_",
|
|
18
18
|
"test-snippets": "cargo test -q snippets::tests",
|
|
19
19
|
"check-js-runtime": "node scripts/check-js-runtime-identity.mjs",
|
|
20
|
+
"check-literal-paths": "cargo run --bin calcit -- calcit/bench-literal-paths.cirru && cargo run --bin calcit -- --emit-path target/literal-path-js calcit/bench-literal-paths.cirru js && node scripts/bench-literal-paths.mjs",
|
|
21
|
+
"check-typed-method-rem": "cargo run --bin calcit -- calcit/fibo.cirru && cargo run --bin calcit -- --emit-path target/typed-method-rem-js calcit/fibo.cirru js && node scripts/bench-typed-method-rem.mjs",
|
|
20
22
|
"bench-recur-smoke": "cargo run --bin calcit -- calcit/test.cirru js && node --input-type=module -e \"import { test_loop } from './js-out/test-recursion.main.mjs'; const n=3000; const t0=process.hrtime.bigint(); for(let i=0;i<n;i++) test_loop(); const dt=Number(process.hrtime.bigint()-t0)/1e6; console.log('test_loop_ms='+dt.toFixed(3));\"",
|
|
23
|
+
"bench-enum-match": "cargo run --release --example bench_enum_match && yarn compile && node scripts/bench-enum-match.mjs",
|
|
24
|
+
"bench-literal-paths": "cargo build --release --bin calcit && yarn compile && target/release/calcit calcit/bench-literal-paths.cirru && node scripts/bench-literal-paths-native.mjs && target/release/calcit --emit-path target/literal-path-js calcit/bench-literal-paths.cirru js && node scripts/bench-literal-paths.mjs",
|
|
25
|
+
"bench-typed-method-rem": "cargo build --release --bin calcit && yarn compile && target/release/calcit calcit/fibo.cirru && node scripts/bench-typed-method-rem-native.mjs && target/release/calcit --emit-path target/typed-method-rem-js calcit/fibo.cirru js && node scripts/bench-typed-method-rem.mjs",
|
|
26
|
+
"bench-struct-index": "yarn compile && node scripts/bench-struct-index.mjs",
|
|
21
27
|
"check-smooth": "yarn fmt-rs && yarn lint-rs && yarn test-rs && yarn check-all",
|
|
22
|
-
"check-all": "yarn compile && yarn check-js-runtime && yarn check-agent-interface && yarn try-core-tests && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm",
|
|
28
|
+
"check-all": "yarn compile && yarn check-js-runtime && yarn check-agent-interface && yarn try-core-tests && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm && yarn check-literal-paths && yarn check-typed-method-rem",
|
|
23
29
|
"check-agent-interface": "cargo build --bin calcit && node scripts/check-agent-interface.mjs",
|
|
24
30
|
"try-all": "yarn check-all",
|
|
25
31
|
"try-core-tests": "cargo run --bin calcit -- src/cirru/calcit-core.cirru test --tag unit --summary-only",
|
package/ts-src/calcit-data.mts
CHANGED
|
@@ -126,6 +126,49 @@ export let getStringName = (x: CalcitValue): string => {
|
|
|
126
126
|
throw new Error("Cannot get string as name");
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
/** Compare tag names by Unicode scalar value, matching Rust `str` ordering. */
|
|
130
|
+
export function compareTagNames(x: CalcitTag, y: CalcitTag): number {
|
|
131
|
+
let xIdx = 0;
|
|
132
|
+
let yIdx = 0;
|
|
133
|
+
while (xIdx < x.value.length && yIdx < y.value.length) {
|
|
134
|
+
const xCode = x.value.codePointAt(xIdx)!;
|
|
135
|
+
const yCode = y.value.codePointAt(yIdx)!;
|
|
136
|
+
if (xCode < yCode) return -1;
|
|
137
|
+
if (xCode > yCode) return 1;
|
|
138
|
+
xIdx += xCode > 0xffff ? 2 : 1;
|
|
139
|
+
yIdx += yCode > 0xffff ? 2 : 1;
|
|
140
|
+
}
|
|
141
|
+
if (xIdx < x.value.length) return 1;
|
|
142
|
+
if (yIdx < y.value.length) return -1;
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function tagNamesAreCanonical(fields: CalcitTag[]): boolean {
|
|
147
|
+
for (let idx = 1; idx < fields.length; idx++) {
|
|
148
|
+
if (compareTagNames(fields[idx - 1], fields[idx]) >= 0) return false;
|
|
149
|
+
}
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function canonicalizeTagPairs<T>(fields: CalcitTag[], values: T[], context: string): [CalcitTag[], T[]] {
|
|
154
|
+
if (fields.length !== values.length) {
|
|
155
|
+
throw new Error(`${context}: fields and values length mismatch`);
|
|
156
|
+
}
|
|
157
|
+
if (tagNamesAreCanonical(fields)) return [fields, values];
|
|
158
|
+
|
|
159
|
+
const pairs = fields.map((field, idx) => [field, values[idx]] as [CalcitTag, T]);
|
|
160
|
+
pairs.sort((a, b) => compareTagNames(a[0], b[0]));
|
|
161
|
+
for (let idx = 1; idx < pairs.length; idx++) {
|
|
162
|
+
if (pairs[idx - 1][0].value === pairs[idx][0].value) {
|
|
163
|
+
throw new Error(`${context}: duplicated field :${pairs[idx][0].value}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return [
|
|
167
|
+
pairs.map(([field]) => field),
|
|
168
|
+
pairs.map(([, value]) => value),
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
|
|
129
172
|
/** returns -1 when not found */
|
|
130
173
|
export function findInFields(xs: Array<CalcitTag>, y: CalcitTag): number {
|
|
131
174
|
let low = 0;
|
|
@@ -134,9 +177,10 @@ export function findInFields(xs: Array<CalcitTag>, y: CalcitTag): number {
|
|
|
134
177
|
while (low <= high) {
|
|
135
178
|
const mid = Math.floor((low + high) / 2);
|
|
136
179
|
const midVal = xs[mid];
|
|
137
|
-
|
|
180
|
+
const ordering = compareTagNames(midVal, y);
|
|
181
|
+
if (ordering < 0) {
|
|
138
182
|
low = mid + 1;
|
|
139
|
-
} else if (
|
|
183
|
+
} else if (ordering > 0) {
|
|
140
184
|
high = mid - 1;
|
|
141
185
|
} else {
|
|
142
186
|
return mid;
|
|
@@ -180,6 +224,7 @@ export let castTag = (x: CalcitValue): CalcitTag => {
|
|
|
180
224
|
export var refsRegistry = new Map<string, CalcitRef>();
|
|
181
225
|
|
|
182
226
|
let defaultHash_nil = valueHash("nil:");
|
|
227
|
+
let defaultHash_unit = valueHash("unit:");
|
|
183
228
|
let defaultHash_number = valueHash("number:");
|
|
184
229
|
let defaultHash_string = valueHash("string:");
|
|
185
230
|
let defaultHash_tag = valueHash("tag:");
|
|
@@ -204,9 +249,10 @@ let fnHashCounter = 0;
|
|
|
204
249
|
let jsObjectHashCounter = 0;
|
|
205
250
|
|
|
206
251
|
export let hashFunction = (x: CalcitValue): Hash => {
|
|
207
|
-
if (x
|
|
252
|
+
if (x === null) {
|
|
208
253
|
return defaultHash_nil;
|
|
209
254
|
}
|
|
255
|
+
if (x === undefined) return defaultHash_unit;
|
|
210
256
|
if (typeof x === "number") {
|
|
211
257
|
return mergeValueHash(defaultHash_number, x);
|
|
212
258
|
}
|
|
@@ -398,9 +444,10 @@ let hashCirru = (base: number, x: CirruWriterNode) => {
|
|
|
398
444
|
overwriteHashGenerator(hashFunction);
|
|
399
445
|
|
|
400
446
|
export let toString = (x: CalcitValue, escaped: boolean, disableJsDataWarning: boolean = false): string => {
|
|
401
|
-
if (x
|
|
447
|
+
if (x === null) {
|
|
402
448
|
return "nil";
|
|
403
449
|
}
|
|
450
|
+
if (x === undefined) return "&unit";
|
|
404
451
|
if (typeof x === "string") {
|
|
405
452
|
if (escaped) {
|
|
406
453
|
// turn to visual string representation
|
|
@@ -505,9 +552,10 @@ export let to_js_data = (x: CalcitValue, options?: CalcitValue | boolean): any =
|
|
|
505
552
|
};
|
|
506
553
|
|
|
507
554
|
let to_js_data_inner = (x: CalcitValue, addColon: boolean): any => {
|
|
508
|
-
if (x
|
|
555
|
+
if (x === null) {
|
|
509
556
|
return null;
|
|
510
557
|
}
|
|
558
|
+
if (x === undefined) return undefined;
|
|
511
559
|
if (x === true || x === false) {
|
|
512
560
|
return x;
|
|
513
561
|
}
|
|
@@ -596,10 +644,7 @@ export let _$n__$e_ = (x: CalcitValue, y: CalcitValue): boolean => {
|
|
|
596
644
|
if (x === y) {
|
|
597
645
|
return true;
|
|
598
646
|
}
|
|
599
|
-
if (x
|
|
600
|
-
if (y == null) {
|
|
601
|
-
return true;
|
|
602
|
-
}
|
|
647
|
+
if (x === null) {
|
|
603
648
|
return false;
|
|
604
649
|
}
|
|
605
650
|
|