@calcit/procs 0.29.0-alpha.19 → 0.29.0-alpha.20
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/lib/calcit-data.mjs +14 -5
- package/lib/calcit.procs.mjs +6 -1
- package/lib/js-primes.d.mts +2 -0
- package/lib/js-primes.mjs +88 -1
- package/lib/package.json +1 -1
- package/package.json +1 -1
package/lib/calcit-data.mjs
CHANGED
|
@@ -208,6 +208,7 @@ export var refsRegistry = new Map();
|
|
|
208
208
|
let defaultHash_nil = valueHash("nil:");
|
|
209
209
|
let defaultHash_unit = valueHash("unit:");
|
|
210
210
|
let defaultHash_number = valueHash("number:");
|
|
211
|
+
let defaultHash_nan = valueHash("number:NaN");
|
|
211
212
|
let defaultHash_string = valueHash("string:");
|
|
212
213
|
let defaultHash_tag = valueHash("tag:");
|
|
213
214
|
let defaultHash_true = valueHash("bool:true");
|
|
@@ -237,7 +238,10 @@ export let hashFunction = (x) => {
|
|
|
237
238
|
if (x === undefined)
|
|
238
239
|
return defaultHash_unit;
|
|
239
240
|
if (typeof x === "number") {
|
|
240
|
-
|
|
241
|
+
// NaN equals NaN, so it needs a hash that equals itself; `0` and `-0` share one hash
|
|
242
|
+
if (Number.isNaN(x))
|
|
243
|
+
return defaultHash_nan;
|
|
244
|
+
return mergeValueHash(defaultHash_number, x === 0 ? 0 : x);
|
|
241
245
|
}
|
|
242
246
|
if (typeof x === "string") {
|
|
243
247
|
return mergeValueHash(defaultHash_string, x);
|
|
@@ -369,7 +373,8 @@ export let hashFunction = (x) => {
|
|
|
369
373
|
let base = defaultHash_impl;
|
|
370
374
|
base = mergeValueHash(base, hashFunction(x.name));
|
|
371
375
|
if (x.origin != null) {
|
|
372
|
-
|
|
376
|
+
// Impl equality compares origin names, not trait object identities.
|
|
377
|
+
base = mergeValueHash(base, hashFunction(x.origin.name.value));
|
|
373
378
|
}
|
|
374
379
|
for (let idx = 0; idx < x.fields.length; idx++) {
|
|
375
380
|
base = mergeValueHash(base, hashFunction(x.fields[idx]));
|
|
@@ -656,8 +661,8 @@ export let _$n__$e_ = (x, y) => {
|
|
|
656
661
|
return false;
|
|
657
662
|
}
|
|
658
663
|
if (tx === "number") {
|
|
659
|
-
// already
|
|
660
|
-
return
|
|
664
|
+
// value equality: NaN equals NaN (`0 === -0` already held above)
|
|
665
|
+
return Number.isNaN(x) && Number.isNaN(y);
|
|
661
666
|
}
|
|
662
667
|
if (tx === "function") {
|
|
663
668
|
// method values are closures created on the fly (see invoke_method_closure),
|
|
@@ -837,7 +842,11 @@ export let _$n__$e_ = (x, y) => {
|
|
|
837
842
|
}
|
|
838
843
|
if (x instanceof CalcitEnumDef) {
|
|
839
844
|
if (y instanceof CalcitEnumDef) {
|
|
840
|
-
|
|
845
|
+
// The prototype carries the nominal origin, variant tags and payload
|
|
846
|
+
// schemas. Comparing name methods compares one shared function object.
|
|
847
|
+
return _$n__$e_(x.prototype, y.prototype)
|
|
848
|
+
&& x.impls.length === y.impls.length
|
|
849
|
+
&& x.impls.every((impl, index) => _$n__$e_(impl, y.impls[index]));
|
|
841
850
|
}
|
|
842
851
|
return false;
|
|
843
852
|
}
|
package/lib/calcit.procs.mjs
CHANGED
|
@@ -1419,7 +1419,12 @@ export let _$n_str_$o_replace = (x, y, z) => {
|
|
|
1419
1419
|
return x.replace(new RegExp(literalPattern, "gu"), () => z);
|
|
1420
1420
|
};
|
|
1421
1421
|
export let split = (xs, x) => {
|
|
1422
|
-
|
|
1422
|
+
// An empty delimiter splits by code point, matching native for astral characters.
|
|
1423
|
+
if (x === "") {
|
|
1424
|
+
return new CalcitSliceList(Array.from(xs));
|
|
1425
|
+
}
|
|
1426
|
+
// Drop empty pieces to match native and WASM: `split | |,` is an empty list.
|
|
1427
|
+
return new CalcitSliceList(xs.split(x).filter((piece) => piece !== ""));
|
|
1423
1428
|
};
|
|
1424
1429
|
export let split_lines = (xs) => {
|
|
1425
1430
|
return new CalcitSliceList(xs.split("\n"));
|
package/lib/js-primes.d.mts
CHANGED
|
@@ -12,4 +12,6 @@ import { CalcitCirruQuote } from "./js-cirru.mjs";
|
|
|
12
12
|
import { CalcitTrait } from "./js-trait.mjs";
|
|
13
13
|
export type CalcitValue = string | number | boolean | CalcitMap | CalcitSliceMap | CalcitList | CalcitSliceList | CalcitSet | CalcitTag | CalcitSymbol | CalcitRef | CalcitEnumValue | CalcitFn | CalcitRecur | CalcitStructValue | CalcitImpl | CalcitTrait | CalcitStructDef | CalcitEnumDef | CalcitCirruQuote | Uint8Array | undefined | null;
|
|
14
14
|
export declare let isLiteral: (x: CalcitValue) => boolean;
|
|
15
|
+
/** total order over numbers: `-0` equals `0`, NaN equals NaN and sorts after every number */
|
|
16
|
+
export declare let compareNumbers: (x: number, y: number) => number;
|
|
15
17
|
export declare let _$n_compare: (a: CalcitValue, b: CalcitValue) => number;
|
package/lib/js-primes.mjs
CHANGED
|
@@ -101,6 +101,14 @@ let rawCompare = (x, y) => {
|
|
|
101
101
|
return 0;
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
|
+
/** total order over numbers: `-0` equals `0`, NaN equals NaN and sorts after every number */
|
|
105
|
+
export let compareNumbers = (x, y) => {
|
|
106
|
+
if (x < y)
|
|
107
|
+
return -1;
|
|
108
|
+
if (x > y)
|
|
109
|
+
return 1;
|
|
110
|
+
return (Number.isNaN(x) ? 1 : 0) - (Number.isNaN(y) ? 1 : 0);
|
|
111
|
+
};
|
|
104
112
|
/** lexicographic order over two sequences of values, a shorter prefix sorts first (same as Rust `Vec::cmp`) */
|
|
105
113
|
let compareSequences = (xs, ys) => {
|
|
106
114
|
let n = Math.min(xs.length, ys.length);
|
|
@@ -112,6 +120,18 @@ let compareSequences = (xs, ys) => {
|
|
|
112
120
|
return rawCompare(xs.length, ys.length);
|
|
113
121
|
};
|
|
114
122
|
let listToArray = (x) => Array.from(x.items());
|
|
123
|
+
// Plain functions compare by identity. IDs are process-local, never serialized,
|
|
124
|
+
// and kept weakly so ordering does not retain closures or mutate frozen hosts.
|
|
125
|
+
const functionOrderIds = new WeakMap();
|
|
126
|
+
let nextFunctionOrderId = 0;
|
|
127
|
+
const functionOrderId = (fn) => {
|
|
128
|
+
let id = functionOrderIds.get(fn);
|
|
129
|
+
if (id === undefined) {
|
|
130
|
+
id = ++nextFunctionOrderId;
|
|
131
|
+
functionOrderIds.set(fn, id);
|
|
132
|
+
}
|
|
133
|
+
return id;
|
|
134
|
+
};
|
|
115
135
|
export let _$n_compare = (a, b) => {
|
|
116
136
|
if (a === b)
|
|
117
137
|
return 0;
|
|
@@ -125,7 +145,7 @@ export let _$n_compare = (a, b) => {
|
|
|
125
145
|
case PseudoTypeIndex.bool:
|
|
126
146
|
return rawCompare(a, b);
|
|
127
147
|
case PseudoTypeIndex.number:
|
|
128
|
-
return
|
|
148
|
+
return compareNumbers(a, b);
|
|
129
149
|
case PseudoTypeIndex.tag:
|
|
130
150
|
return rawCompare(a.value, b.value);
|
|
131
151
|
case PseudoTypeIndex.symbol:
|
|
@@ -134,6 +154,36 @@ export let _$n_compare = (a, b) => {
|
|
|
134
154
|
return rawCompare(a, b);
|
|
135
155
|
case PseudoTypeIndex.ref:
|
|
136
156
|
return rawCompare(a.path, b.path);
|
|
157
|
+
case PseudoTypeIndex.fn: {
|
|
158
|
+
const left = a;
|
|
159
|
+
const right = b;
|
|
160
|
+
// Method closures use name equality, unlike ordinary function values.
|
|
161
|
+
if (left.__calcitMethodName != null || right.__calcitMethodName != null) {
|
|
162
|
+
if (left.__calcitMethodName == null)
|
|
163
|
+
return -1;
|
|
164
|
+
if (right.__calcitMethodName == null)
|
|
165
|
+
return 1;
|
|
166
|
+
return compareUnicodeStrings(left.__calcitMethodName, right.__calcitMethodName);
|
|
167
|
+
}
|
|
168
|
+
return rawCompare(functionOrderId(left), functionOrderId(right));
|
|
169
|
+
}
|
|
170
|
+
case PseudoTypeIndex.impl: {
|
|
171
|
+
const left = a;
|
|
172
|
+
const right = b;
|
|
173
|
+
const nameOrder = compareUnicodeStrings(left.name.value, right.name.value);
|
|
174
|
+
if (nameOrder !== 0)
|
|
175
|
+
return nameOrder;
|
|
176
|
+
if (left.origin == null && right.origin != null)
|
|
177
|
+
return -1;
|
|
178
|
+
if (left.origin != null && right.origin == null)
|
|
179
|
+
return 1;
|
|
180
|
+
if (left.origin != null && right.origin != null) {
|
|
181
|
+
const originOrder = compareUnicodeStrings(left.origin.name.value, right.origin.name.value);
|
|
182
|
+
if (originOrder !== 0)
|
|
183
|
+
return originOrder;
|
|
184
|
+
}
|
|
185
|
+
return compareSequences(left.fields, right.fields) || compareSequences(left.values, right.values);
|
|
186
|
+
}
|
|
137
187
|
case PseudoTypeIndex.struct_value: {
|
|
138
188
|
const left = a;
|
|
139
189
|
const right = b;
|
|
@@ -176,6 +226,43 @@ export let _$n_compare = (a, b) => {
|
|
|
176
226
|
return tagOrder;
|
|
177
227
|
return compareSequences(left.extra, right.extra);
|
|
178
228
|
}
|
|
229
|
+
case PseudoTypeIndex.enum_def: {
|
|
230
|
+
const left = a;
|
|
231
|
+
const right = b;
|
|
232
|
+
const leftRef = left.prototype.structRef.definitionRef;
|
|
233
|
+
const rightRef = right.prototype.structRef.definitionRef;
|
|
234
|
+
if (leftRef !== rightRef) {
|
|
235
|
+
if (leftRef == null)
|
|
236
|
+
return -1;
|
|
237
|
+
if (rightRef == null)
|
|
238
|
+
return 1;
|
|
239
|
+
return compareUnicodeStrings(leftRef, rightRef);
|
|
240
|
+
}
|
|
241
|
+
const nameOrder = compareUnicodeStrings(left.name(), right.name());
|
|
242
|
+
if (nameOrder !== 0)
|
|
243
|
+
return nameOrder;
|
|
244
|
+
const variantCountOrder = rawCompare(left.prototype.fields.length, right.prototype.fields.length);
|
|
245
|
+
if (variantCountOrder !== 0)
|
|
246
|
+
return variantCountOrder;
|
|
247
|
+
for (let index = 0; index < left.prototype.fields.length; index++) {
|
|
248
|
+
const tagOrder = _$n_compare(left.prototype.fields[index], right.prototype.fields[index]);
|
|
249
|
+
if (tagOrder !== 0)
|
|
250
|
+
return tagOrder;
|
|
251
|
+
const leftPayload = left.prototype.values[index];
|
|
252
|
+
const rightPayload = right.prototype.values[index];
|
|
253
|
+
// Native orders variant payloads by arity before comparing types.
|
|
254
|
+
if ((leftPayload instanceof CalcitList || leftPayload instanceof CalcitSliceList)
|
|
255
|
+
&& (rightPayload instanceof CalcitList || rightPayload instanceof CalcitSliceList)) {
|
|
256
|
+
const arityOrder = rawCompare(leftPayload.len(), rightPayload.len());
|
|
257
|
+
if (arityOrder !== 0)
|
|
258
|
+
return arityOrder;
|
|
259
|
+
}
|
|
260
|
+
const payloadOrder = _$n_compare(leftPayload, rightPayload);
|
|
261
|
+
if (payloadOrder !== 0)
|
|
262
|
+
return payloadOrder;
|
|
263
|
+
}
|
|
264
|
+
return rawCompare(left.impls.length, right.impls.length) || compareSequences(left.impls, right.impls);
|
|
265
|
+
}
|
|
179
266
|
case PseudoTypeIndex.set: {
|
|
180
267
|
// like native: smaller sets first, then the sorted elements
|
|
181
268
|
const left = Array.from(a.values());
|
package/lib/package.json
CHANGED