squint-cljs 0.14.197 → 0.14.199
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/cli.js +108 -108
- package/lib/cljs.pprint.js +253 -253
- package/lib/compiler.js +1314 -1305
- package/lib/compiler.node.js +40 -40
- package/lib/compiler.sci.js +1282 -1281
- package/lib/node.nrepl_server.js +29 -29
- package/lib/squint.core.umd.js +3 -3
- package/package.json +1 -1
- package/src/squint/core.js +291 -56
- package/src/squint/test.js +134 -139
package/src/squint/core.js
CHANGED
|
@@ -20,6 +20,28 @@ function findKey(iter, tar, key) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
function isSortedMap(m) {
|
|
24
|
+
return m != null && m[SORTED_TAG] === true && m[TYPE_TAG] === MAP_TYPE;
|
|
25
|
+
}
|
|
26
|
+
function isMapLike(m) {
|
|
27
|
+
return (
|
|
28
|
+
m != null &&
|
|
29
|
+
typeof m === 'object' &&
|
|
30
|
+
(m.constructor === Object || m instanceof Map || m[TYPE_TAG] === MAP_TYPE)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function mapHas(m, k) {
|
|
34
|
+
return m instanceof Map || m[TYPE_TAG] === MAP_TYPE ? m.has(k) : has.call(m, k);
|
|
35
|
+
}
|
|
36
|
+
function mapGet(m, k) {
|
|
37
|
+
return m instanceof Map || m[TYPE_TAG] === MAP_TYPE ? m.get(k) : m[k];
|
|
38
|
+
}
|
|
39
|
+
function mapCount(m) {
|
|
40
|
+
return m instanceof Map || m[TYPE_TAG] === MAP_TYPE
|
|
41
|
+
? m.size
|
|
42
|
+
: Object.keys(m).length;
|
|
43
|
+
}
|
|
44
|
+
|
|
23
45
|
function dequal(foo, bar) {
|
|
24
46
|
// supports primitives, Array, Set, Map and plain objects
|
|
25
47
|
// like CLJS: does not support NaN
|
|
@@ -28,7 +50,21 @@ function dequal(foo, bar) {
|
|
|
28
50
|
if (foo == null) return bar == null;
|
|
29
51
|
var ctor, len, tmp;
|
|
30
52
|
|
|
53
|
+
// A sorted map compares by entries against any map type (object, Map, sorted).
|
|
54
|
+
const fooSorted = isSortedMap(foo);
|
|
55
|
+
if (fooSorted || isSortedMap(bar)) {
|
|
56
|
+
const sm = fooSorted ? foo : bar;
|
|
57
|
+
const other = sm === foo ? bar : foo;
|
|
58
|
+
if (!isMapLike(other) || mapCount(sm) !== mapCount(other)) return false;
|
|
59
|
+
for (const k of sm.keys()) {
|
|
60
|
+
if (!mapHas(other, k) || !dequal(sm.get(k), mapGet(other, k))) return false;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
31
65
|
if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
|
|
66
|
+
if (ctor === Date) return foo.getTime() === bar.getTime();
|
|
67
|
+
|
|
32
68
|
if (ctor === Array) {
|
|
33
69
|
if ((len = foo.length) === bar.length) {
|
|
34
70
|
while (len-- && dequal(foo[len], bar[len]));
|
|
@@ -219,7 +255,8 @@ function copyMeta(from, to) {
|
|
|
219
255
|
function copy(o) {
|
|
220
256
|
switch (typeConst(o)) {
|
|
221
257
|
case MAP_TYPE:
|
|
222
|
-
|
|
258
|
+
// new o.constructor(o) preserves a SortedMap; for a plain Map it is new Map(o)
|
|
259
|
+
return copyMeta(o, new o.constructor(o));
|
|
223
260
|
case SET_TYPE:
|
|
224
261
|
return copyMeta(o, new o.constructor(o));
|
|
225
262
|
case ARRAY_TYPE:
|
|
@@ -242,6 +279,14 @@ export function assoc(o, k, v, ...kvs) {
|
|
|
242
279
|
return ret;
|
|
243
280
|
}
|
|
244
281
|
|
|
282
|
+
// squint has no distinct hash-map or array-map type; both build a plain object.
|
|
283
|
+
export function hash_map(...kvs) {
|
|
284
|
+
if (kvs.length === 0) return {};
|
|
285
|
+
return assoc({}, ...kvs);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export const array_map = hash_map;
|
|
289
|
+
|
|
245
290
|
const MAP_TYPE = 1;
|
|
246
291
|
const ARRAY_TYPE = 2;
|
|
247
292
|
const OBJECT_TYPE = 3;
|
|
@@ -457,6 +502,8 @@ export function conj(...xs) {
|
|
|
457
502
|
}
|
|
458
503
|
|
|
459
504
|
const [_o, ...rest] = xs;
|
|
505
|
+
// (conj coll) with nothing to add returns coll unchanged, including nil.
|
|
506
|
+
if (rest.length === 0) return _o;
|
|
460
507
|
|
|
461
508
|
let o = _o;
|
|
462
509
|
if (o === null || o === undefined) {
|
|
@@ -518,11 +565,15 @@ export function disj_BANG_(s, ...xs) {
|
|
|
518
565
|
|
|
519
566
|
export function disj(s, ...xs) {
|
|
520
567
|
if (s == null) return s;
|
|
521
|
-
|
|
568
|
+
// pass s itself (not a spread) so a SortedSet keeps its comparator
|
|
569
|
+
const s1 = new s.constructor(s);
|
|
522
570
|
return disj_BANG_(s1, ...xs);
|
|
523
571
|
}
|
|
524
572
|
|
|
525
573
|
export function contains_QMARK_(coll, v) {
|
|
574
|
+
if (typeof coll === 'string') {
|
|
575
|
+
return int_QMARK_(v) && v >= 0 && v < coll.length;
|
|
576
|
+
}
|
|
526
577
|
switch (typeConst(coll)) {
|
|
527
578
|
case SET_TYPE:
|
|
528
579
|
case MAP_TYPE:
|
|
@@ -658,7 +709,11 @@ export function seq_QMARK_(x) {
|
|
|
658
709
|
return x != null && !!x[Symbol.iterator];
|
|
659
710
|
}
|
|
660
711
|
|
|
661
|
-
export
|
|
712
|
+
export function sequential_QMARK_(x) {
|
|
713
|
+
// vectors and lists are arrays; lazy seqs and cons carry the lazy brand.
|
|
714
|
+
// Sets, maps and strings are iterable but not sequential.
|
|
715
|
+
return Array.isArray(x) || x?.[TYPE_TAG] === LAZY_ITERABLE_TYPE;
|
|
716
|
+
}
|
|
662
717
|
|
|
663
718
|
export function seqable_QMARK_(x) {
|
|
664
719
|
return (
|
|
@@ -715,11 +770,17 @@ export const es6_iterator = _iterator;
|
|
|
715
770
|
|
|
716
771
|
export function seq(x) {
|
|
717
772
|
if (x == null) return x;
|
|
773
|
+
// a string seqs into its characters, like CLJS.
|
|
774
|
+
if (typeof x === 'string') return x.length ? [...x] : null;
|
|
718
775
|
const iter = iterable(x);
|
|
719
776
|
// return nil for terminal checking
|
|
720
777
|
if (iter.length === 0 || iter.size === 0) {
|
|
721
778
|
return null;
|
|
722
779
|
}
|
|
780
|
+
// a set is iterable but not sequential; materialize its elements.
|
|
781
|
+
if (iter instanceof Set || iter[TYPE_TAG] === SET_TYPE) {
|
|
782
|
+
return [...iter];
|
|
783
|
+
}
|
|
723
784
|
const _i = iter[Symbol.iterator]();
|
|
724
785
|
if (_i.next().done) return null;
|
|
725
786
|
return iter;
|
|
@@ -1034,6 +1095,7 @@ function mapChunks(coll, xf) {
|
|
|
1034
1095
|
export const Cons = defclass(
|
|
1035
1096
|
class Cons {
|
|
1036
1097
|
constructor(x, coll) {
|
|
1098
|
+
this[TYPE_TAG] = LAZY_ITERABLE_TYPE;
|
|
1037
1099
|
this.x = x;
|
|
1038
1100
|
this.coll = coll;
|
|
1039
1101
|
}
|
|
@@ -1366,6 +1428,19 @@ export function re_pattern(s) {
|
|
|
1366
1428
|
}
|
|
1367
1429
|
|
|
1368
1430
|
export function subvec(arr, start, end) {
|
|
1431
|
+
if (!isVectorArray(arr)) {
|
|
1432
|
+
throw new Error('subvec: argument must be a vector');
|
|
1433
|
+
}
|
|
1434
|
+
if (end === undefined) end = arr.length;
|
|
1435
|
+
if (start == null || end == null) {
|
|
1436
|
+
throw new Error('subvec: start and end must not be nil');
|
|
1437
|
+
}
|
|
1438
|
+
// CLJS coerces the indices with (int x) before bounds-checking.
|
|
1439
|
+
start = start | 0;
|
|
1440
|
+
end = end | 0;
|
|
1441
|
+
if (start < 0 || end < start || end > arr.length) {
|
|
1442
|
+
throw new Error('subvec: index out of bounds');
|
|
1443
|
+
}
|
|
1369
1444
|
return arr.slice(start, end);
|
|
1370
1445
|
}
|
|
1371
1446
|
|
|
@@ -1471,6 +1546,9 @@ export function apply(f, ...args) {
|
|
|
1471
1546
|
}
|
|
1472
1547
|
|
|
1473
1548
|
export function even_QMARK_(x) {
|
|
1549
|
+
if (!Number.isInteger(x)) {
|
|
1550
|
+
throw new Error(`Argument must be an integer: ${x}`);
|
|
1551
|
+
}
|
|
1474
1552
|
return x % 2 == 0;
|
|
1475
1553
|
}
|
|
1476
1554
|
|
|
@@ -1496,7 +1574,7 @@ class List extends Array {
|
|
|
1496
1574
|
}
|
|
1497
1575
|
|
|
1498
1576
|
export function list_QMARK_(x) {
|
|
1499
|
-
return
|
|
1577
|
+
return x?.[TYPE_TAG] === LIST_TYPE;
|
|
1500
1578
|
}
|
|
1501
1579
|
|
|
1502
1580
|
export function list(...args) {
|
|
@@ -1682,8 +1760,10 @@ export function partition_all(n, ...args) {
|
|
|
1682
1760
|
}
|
|
1683
1761
|
|
|
1684
1762
|
export function partition(n, ...args) {
|
|
1763
|
+
// pad stays undefined for arity 1 and 2: only arity 4 provides a pad, which
|
|
1764
|
+
// makes the final partial partition be emitted (padded when pad has elements).
|
|
1685
1765
|
let step = n,
|
|
1686
|
-
pad
|
|
1766
|
+
pad,
|
|
1687
1767
|
coll = args[0];
|
|
1688
1768
|
|
|
1689
1769
|
if (args.length === 2) {
|
|
@@ -1718,8 +1798,10 @@ function partitionInternal(n, step, pad, coll, all) {
|
|
|
1718
1798
|
if (p.length > 0) {
|
|
1719
1799
|
if (p.length === n || all) {
|
|
1720
1800
|
yield p;
|
|
1721
|
-
} else if (pad
|
|
1722
|
-
|
|
1801
|
+
} else if (pad !== undefined) {
|
|
1802
|
+
if (pad != null) {
|
|
1803
|
+
p.push(...[...iterable(pad)].slice(0, n - p.length));
|
|
1804
|
+
}
|
|
1723
1805
|
yield p;
|
|
1724
1806
|
}
|
|
1725
1807
|
}
|
|
@@ -1814,6 +1896,8 @@ export function empty(coll) {
|
|
|
1814
1896
|
}
|
|
1815
1897
|
|
|
1816
1898
|
export function merge(...args) {
|
|
1899
|
+
// with no truthy maps, return nil like CLJS `(when (some identity maps) ...)`.
|
|
1900
|
+
if (!args.some(truth_)) return null;
|
|
1817
1901
|
// if the first arg is nil we coerce it into a map.
|
|
1818
1902
|
const firstArg = args[0];
|
|
1819
1903
|
let obj;
|
|
@@ -1905,20 +1989,16 @@ export function repeat(...args) {
|
|
|
1905
1989
|
if (args.length == 0 || args.length > 2) {
|
|
1906
1990
|
throw new Error(`Invalid arity: ${args.length}`);
|
|
1907
1991
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
const [n, x] = args;
|
|
1919
|
-
for (var i = 0; i < n; i++) yield x;
|
|
1920
|
-
},
|
|
1921
|
-
};
|
|
1992
|
+
if (args.length == 1) {
|
|
1993
|
+
const x = args[0];
|
|
1994
|
+
return lazy(function* () {
|
|
1995
|
+
while (true) yield x;
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
const [n, x] = args;
|
|
1999
|
+
return lazy(function* () {
|
|
2000
|
+
for (var i = 0; i < n; i++) yield x;
|
|
2001
|
+
});
|
|
1922
2002
|
}
|
|
1923
2003
|
|
|
1924
2004
|
export function ensure_reduced(x) {
|
|
@@ -1970,6 +2050,8 @@ export function take_last(n, coll) {
|
|
|
1970
2050
|
lastN[i % n] = x;
|
|
1971
2051
|
i++;
|
|
1972
2052
|
}
|
|
2053
|
+
// an empty or nil coll has no last n elements; return nil like CLJS.
|
|
2054
|
+
if (i === 0) return null;
|
|
1973
2055
|
if (i % n !== 0 && i >= n) {
|
|
1974
2056
|
return lastN.slice(i % n).concat(lastN.slice(0, i % n));
|
|
1975
2057
|
} else {
|
|
@@ -2147,14 +2229,14 @@ export function update_in(coll, path, f, ...args) {
|
|
|
2147
2229
|
return assoc_in(coll, path, f(get_in(coll, path), ...args));
|
|
2148
2230
|
}
|
|
2149
2231
|
|
|
2150
|
-
export function fnil(f,
|
|
2232
|
+
export function fnil(f, ...defaults) {
|
|
2151
2233
|
f = __toFn(f);
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
return f(a, ...xs, ...args);
|
|
2234
|
+
const n = defaults.length;
|
|
2235
|
+
return function (...args) {
|
|
2236
|
+
for (let i = 0; i < n; i++) {
|
|
2237
|
+
if (args[i] == null) args[i] = defaults[i];
|
|
2157
2238
|
}
|
|
2239
|
+
return f(...args);
|
|
2158
2240
|
};
|
|
2159
2241
|
}
|
|
2160
2242
|
|
|
@@ -2328,7 +2410,10 @@ export function repeatedly(n, f) {
|
|
|
2328
2410
|
n = undefined;
|
|
2329
2411
|
}
|
|
2330
2412
|
const res = _repeatedly(f);
|
|
2331
|
-
if (n) {
|
|
2413
|
+
if (n !== undefined) {
|
|
2414
|
+
if (typeof n !== 'number') {
|
|
2415
|
+
throw new Error('repeatedly: count must be a number, got: ' + str(n));
|
|
2416
|
+
}
|
|
2332
2417
|
return take(n, res);
|
|
2333
2418
|
} else {
|
|
2334
2419
|
return res;
|
|
@@ -2363,6 +2448,11 @@ export function frequencies(coll) {
|
|
|
2363
2448
|
// The lazy-seq macro emits `new LazySeq(() => body)`: a LazyIterable whose step
|
|
2364
2449
|
// evaluates the body thunk on first force and reads it unchunked.
|
|
2365
2450
|
export class LazySeq extends LazyIterable {
|
|
2451
|
+
// Core fns build the base LazyIterable, not this subclass, so widen
|
|
2452
|
+
// instanceof to any lazy cell for `(instance? LazySeq x)` parity with CLJS.
|
|
2453
|
+
static [Symbol.hasInstance](x) {
|
|
2454
|
+
return x instanceof LazyIterable;
|
|
2455
|
+
}
|
|
2366
2456
|
constructor(f) {
|
|
2367
2457
|
super(() => unchunkedSteps(es6_iterator(iterable(f())))());
|
|
2368
2458
|
}
|
|
@@ -2414,7 +2504,7 @@ export function some_QMARK_(x) {
|
|
|
2414
2504
|
}
|
|
2415
2505
|
|
|
2416
2506
|
export function boolean$(x) {
|
|
2417
|
-
return
|
|
2507
|
+
return truth_(x);
|
|
2418
2508
|
}
|
|
2419
2509
|
|
|
2420
2510
|
export function zero_QMARK_(x) {
|
|
@@ -2488,11 +2578,13 @@ export function aclone(arr) {
|
|
|
2488
2578
|
}
|
|
2489
2579
|
|
|
2490
2580
|
export function add_watch(ref, key, fn) {
|
|
2491
|
-
|
|
2581
|
+
ref._add_watch(key, fn);
|
|
2582
|
+
return ref;
|
|
2492
2583
|
}
|
|
2493
2584
|
|
|
2494
2585
|
export function remove_watch(ref, key) {
|
|
2495
|
-
|
|
2586
|
+
ref._remove_watch(key);
|
|
2587
|
+
return ref;
|
|
2496
2588
|
}
|
|
2497
2589
|
|
|
2498
2590
|
export function reduce_kv(f, init, m) {
|
|
@@ -2506,24 +2598,25 @@ export function reduce_kv(f, init, m) {
|
|
|
2506
2598
|
return ret;
|
|
2507
2599
|
}
|
|
2508
2600
|
|
|
2509
|
-
export function max(x,
|
|
2510
|
-
if (
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2601
|
+
export function max(x, ...more) {
|
|
2602
|
+
// (if (> a b) a b) reduce, like CLJS: returns one of the values, so nil acts
|
|
2603
|
+
// like zero and NaN propagates, instead of Math.max coercing nil to 0.
|
|
2604
|
+
let m = x;
|
|
2605
|
+
for (const y of more) m = m > y ? m : y;
|
|
2606
|
+
return m;
|
|
2514
2607
|
}
|
|
2515
2608
|
|
|
2516
|
-
export function min(x,
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
return Math.min(x, y, ...more);
|
|
2609
|
+
export function min(x, ...more) {
|
|
2610
|
+
let m = x;
|
|
2611
|
+
for (const y of more) m = m < y ? m : y;
|
|
2612
|
+
return m;
|
|
2521
2613
|
}
|
|
2522
2614
|
|
|
2523
2615
|
export function map_QMARK_(coll) {
|
|
2524
2616
|
if (coll == null) return false;
|
|
2525
2617
|
if (isObj(coll)) return true;
|
|
2526
2618
|
if (coll instanceof Map) return true;
|
|
2619
|
+
if (coll[TYPE_TAG] === MAP_TYPE) return true;
|
|
2527
2620
|
return false;
|
|
2528
2621
|
}
|
|
2529
2622
|
|
|
@@ -2706,25 +2799,33 @@ export function keys(obj) {
|
|
|
2706
2799
|
if (obj == null) return;
|
|
2707
2800
|
const t = typeConst(obj);
|
|
2708
2801
|
switch (t) {
|
|
2709
|
-
case OBJECT_TYPE:
|
|
2710
|
-
|
|
2802
|
+
case OBJECT_TYPE: {
|
|
2803
|
+
const ks = Object.keys(obj);
|
|
2804
|
+
if (ks.length) return ks;
|
|
2805
|
+
return;
|
|
2806
|
+
}
|
|
2711
2807
|
case MAP_TYPE:
|
|
2712
|
-
return Array.from(obj.keys());
|
|
2808
|
+
if (obj.size) return Array.from(obj.keys());
|
|
2809
|
+
return;
|
|
2713
2810
|
}
|
|
2714
2811
|
}
|
|
2715
2812
|
|
|
2716
2813
|
export function js_keys(obj) {
|
|
2717
|
-
return keys(obj);
|
|
2814
|
+
return keys(obj) ?? [];
|
|
2718
2815
|
}
|
|
2719
2816
|
|
|
2720
2817
|
export function vals(obj) {
|
|
2721
2818
|
if (obj == null) return;
|
|
2722
2819
|
const t = typeConst(obj);
|
|
2723
2820
|
switch (t) {
|
|
2724
|
-
case OBJECT_TYPE:
|
|
2725
|
-
|
|
2821
|
+
case OBJECT_TYPE: {
|
|
2822
|
+
const vs = Object.values(obj);
|
|
2823
|
+
if (vs.length) return vs;
|
|
2824
|
+
return;
|
|
2825
|
+
}
|
|
2726
2826
|
case MAP_TYPE:
|
|
2727
|
-
return Array.from(obj.values());
|
|
2827
|
+
if (obj.size) return Array.from(obj.values());
|
|
2828
|
+
return;
|
|
2728
2829
|
}
|
|
2729
2830
|
}
|
|
2730
2831
|
|
|
@@ -2867,6 +2968,13 @@ export function with_meta(x, m) {
|
|
|
2867
2968
|
wrapped[_metaSym] = m;
|
|
2868
2969
|
return wrapped;
|
|
2869
2970
|
}
|
|
2971
|
+
// A lazy seq or cons is not copied element-wise: clone the head so the new
|
|
2972
|
+
// value carries its own metadata without forcing realization.
|
|
2973
|
+
if (x?.[TYPE_TAG] === LAZY_ITERABLE_TYPE) {
|
|
2974
|
+
const ret = Object.assign(Object.create(Object.getPrototypeOf(x)), x);
|
|
2975
|
+
ret[_metaSym] = m;
|
|
2976
|
+
return ret;
|
|
2977
|
+
}
|
|
2870
2978
|
const ret = copy(x);
|
|
2871
2979
|
ret[_metaSym] = m;
|
|
2872
2980
|
return ret;
|
|
@@ -3082,12 +3190,13 @@ export function persistent_BANG_(x) {
|
|
|
3082
3190
|
|
|
3083
3191
|
const SortedSet = defclass(
|
|
3084
3192
|
class SortedSet {
|
|
3085
|
-
constructor(xs) {
|
|
3193
|
+
constructor(xs, cmp) {
|
|
3086
3194
|
this[TYPE_TAG] = SET_TYPE;
|
|
3087
3195
|
this[SORTED_TAG] = true;
|
|
3088
|
-
|
|
3196
|
+
this._cmp = cmp ?? xs?._cmp;
|
|
3197
|
+
const isSorted = xs instanceof SortedSet && xs._cmp === this._cmp;
|
|
3089
3198
|
if (!isSorted) {
|
|
3090
|
-
xs = sort(xs);
|
|
3199
|
+
xs = this._cmp ? sort(this._cmp, xs) : sort(xs);
|
|
3091
3200
|
}
|
|
3092
3201
|
const s = new Set(xs);
|
|
3093
3202
|
// we don't re-use xs since xs can contain duplicates
|
|
@@ -3097,9 +3206,10 @@ class SortedSet {
|
|
|
3097
3206
|
add(x) {
|
|
3098
3207
|
if (this._set.has(x)) return this;
|
|
3099
3208
|
const xs = this._elts;
|
|
3209
|
+
const cmp = this._cmp;
|
|
3100
3210
|
let added = false;
|
|
3101
3211
|
for (let i = 0; i < xs.length; i++) {
|
|
3102
|
-
if (compare(x, xs[i]) <= 0) {
|
|
3212
|
+
if ((cmp ? cmp(x, xs[i]) : compare(x, xs[i])) <= 0) {
|
|
3103
3213
|
xs.splice(i, 0, x);
|
|
3104
3214
|
added = true;
|
|
3105
3215
|
break;
|
|
@@ -3153,6 +3263,85 @@ export function sorted_set(...xs) {
|
|
|
3153
3263
|
return new SortedSet(xs);
|
|
3154
3264
|
}
|
|
3155
3265
|
|
|
3266
|
+
export function sorted_set_by(cmp, ...xs) {
|
|
3267
|
+
return new SortedSet(xs, fnToComparator(__toFn(cmp)));
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
// A map that keeps its keys in sorted order. Backed by a sorted key array plus
|
|
3271
|
+
// a plain Map for lookup, and branded MAP_TYPE so map ops dispatch normally.
|
|
3272
|
+
const SortedMap = defclass(
|
|
3273
|
+
class SortedMap {
|
|
3274
|
+
constructor(entries, cmp) {
|
|
3275
|
+
this[TYPE_TAG] = MAP_TYPE;
|
|
3276
|
+
this[SORTED_TAG] = true;
|
|
3277
|
+
this._cmp = cmp ?? entries?._cmp;
|
|
3278
|
+
this._map = new Map();
|
|
3279
|
+
this._keys = [];
|
|
3280
|
+
this.size = 0;
|
|
3281
|
+
if (entries) {
|
|
3282
|
+
for (const [k, v] of entries) this.set(k, v);
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
set(k, v) {
|
|
3286
|
+
if (!this._map.has(k)) {
|
|
3287
|
+
const ks = this._keys;
|
|
3288
|
+
const cmp = this._cmp;
|
|
3289
|
+
let i = 0;
|
|
3290
|
+
while (i < ks.length && (cmp ? cmp(k, ks[i]) : compare(k, ks[i])) > 0) i++;
|
|
3291
|
+
ks.splice(i, 0, k);
|
|
3292
|
+
}
|
|
3293
|
+
this._map.set(k, v);
|
|
3294
|
+
this.size = this._map.size;
|
|
3295
|
+
return this;
|
|
3296
|
+
}
|
|
3297
|
+
get(k) {
|
|
3298
|
+
return this._map.get(k);
|
|
3299
|
+
}
|
|
3300
|
+
has(k) {
|
|
3301
|
+
return this._map.has(k);
|
|
3302
|
+
}
|
|
3303
|
+
delete(k) {
|
|
3304
|
+
if (this._map.delete(k)) {
|
|
3305
|
+
this._keys.splice(this._keys.indexOf(k), 1);
|
|
3306
|
+
this.size = this._map.size;
|
|
3307
|
+
}
|
|
3308
|
+
return this;
|
|
3309
|
+
}
|
|
3310
|
+
*keys() {
|
|
3311
|
+
yield* this._keys;
|
|
3312
|
+
}
|
|
3313
|
+
*values() {
|
|
3314
|
+
for (const k of this._keys) yield this._map.get(k);
|
|
3315
|
+
}
|
|
3316
|
+
*entries() {
|
|
3317
|
+
for (const k of this._keys) yield [k, this._map.get(k)];
|
|
3318
|
+
}
|
|
3319
|
+
forEach(f) {
|
|
3320
|
+
for (const k of this._keys) f(this._map.get(k), k, this);
|
|
3321
|
+
}
|
|
3322
|
+
clear() {
|
|
3323
|
+
this._map.clear();
|
|
3324
|
+
this._keys = [];
|
|
3325
|
+
this.size = 0;
|
|
3326
|
+
}
|
|
3327
|
+
[Symbol.iterator]() {
|
|
3328
|
+
return this.entries();
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
);
|
|
3332
|
+
|
|
3333
|
+
export function sorted_map(...kvs) {
|
|
3334
|
+
const m = new SortedMap();
|
|
3335
|
+
for (let i = 0; i < kvs.length; i += 2) m.set(kvs[i], kvs[i + 1]);
|
|
3336
|
+
return m;
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3339
|
+
export function sorted_map_by(cmp, ...kvs) {
|
|
3340
|
+
const m = new SortedMap(null, fnToComparator(__toFn(cmp)));
|
|
3341
|
+
for (let i = 0; i < kvs.length; i += 2) m.set(kvs[i], kvs[i + 1]);
|
|
3342
|
+
return m;
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3156
3345
|
function mkBoundFn(_sc, test, key) {
|
|
3157
3346
|
return (e) => {
|
|
3158
3347
|
return test(compare(e, key), 0);
|
|
@@ -3218,6 +3407,14 @@ export function long$(x) {
|
|
|
3218
3407
|
return fix(x);
|
|
3219
3408
|
}
|
|
3220
3409
|
|
|
3410
|
+
export function float$(x) {
|
|
3411
|
+
return x;
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
export function double$(x) {
|
|
3415
|
+
return x;
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3221
3418
|
export function type(x) {
|
|
3222
3419
|
return x != null && x.constructor;
|
|
3223
3420
|
}
|
|
@@ -3232,7 +3429,7 @@ function preserving_reduced(rf) {
|
|
|
3232
3429
|
}
|
|
3233
3430
|
|
|
3234
3431
|
export function cat(rf) {
|
|
3235
|
-
|
|
3432
|
+
const rrf = preserving_reduced(rf);
|
|
3236
3433
|
return (...args) => {
|
|
3237
3434
|
switch (args.length) {
|
|
3238
3435
|
case 0:
|
|
@@ -3240,7 +3437,7 @@ export function cat(rf) {
|
|
|
3240
3437
|
case 1:
|
|
3241
3438
|
return rf(args[0]);
|
|
3242
3439
|
case 2:
|
|
3243
|
-
return reduce(
|
|
3440
|
+
return reduce(rrf, args[0], args[1]);
|
|
3244
3441
|
}
|
|
3245
3442
|
};
|
|
3246
3443
|
}
|
|
@@ -3264,7 +3461,11 @@ export function memoize(f) {
|
|
|
3264
3461
|
}
|
|
3265
3462
|
|
|
3266
3463
|
export function peek(vec) {
|
|
3267
|
-
|
|
3464
|
+
// A list peeks at its front; squint lists are array-backed, so check list
|
|
3465
|
+
// before array to avoid returning the last element.
|
|
3466
|
+
if (list_QMARK_(vec)) {
|
|
3467
|
+
return first(vec);
|
|
3468
|
+
} else if (array_QMARK_(vec)) {
|
|
3268
3469
|
return vec[vec.length - 1];
|
|
3269
3470
|
} else {
|
|
3270
3471
|
return first(vec);
|
|
@@ -3272,7 +3473,12 @@ export function peek(vec) {
|
|
|
3272
3473
|
}
|
|
3273
3474
|
|
|
3274
3475
|
export function pop(vec) {
|
|
3275
|
-
if (
|
|
3476
|
+
if (vec == null) return null;
|
|
3477
|
+
if (list_QMARK_(vec)) {
|
|
3478
|
+
if (vec.length === 0) throw new Error("Can't pop empty list");
|
|
3479
|
+
return rest(vec);
|
|
3480
|
+
} else if (array_QMARK_(vec)) {
|
|
3481
|
+
if (vec.length === 0) throw new Error("Can't pop empty vector");
|
|
3276
3482
|
const ret = [...vec];
|
|
3277
3483
|
ret.pop();
|
|
3278
3484
|
return ret;
|
|
@@ -3311,6 +3517,27 @@ export function random_uuid() {
|
|
|
3311
3517
|
return crypto.randomUUID();
|
|
3312
3518
|
}
|
|
3313
3519
|
|
|
3520
|
+
export class UUID {
|
|
3521
|
+
constructor(uuid) {
|
|
3522
|
+
this.uuid = uuid;
|
|
3523
|
+
}
|
|
3524
|
+
toString() {
|
|
3525
|
+
return this.uuid;
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
|
|
3529
|
+
export function uuid(s) {
|
|
3530
|
+
return new UUID(s);
|
|
3531
|
+
}
|
|
3532
|
+
|
|
3533
|
+
export function uuid_QMARK_(x) {
|
|
3534
|
+
return x instanceof UUID;
|
|
3535
|
+
}
|
|
3536
|
+
|
|
3537
|
+
export function inst_QMARK_(x) {
|
|
3538
|
+
return x instanceof Date;
|
|
3539
|
+
}
|
|
3540
|
+
|
|
3314
3541
|
export class Delay {
|
|
3315
3542
|
constructor(f) {
|
|
3316
3543
|
this.f = f;
|
|
@@ -3326,6 +3553,13 @@ export class Delay {
|
|
|
3326
3553
|
}
|
|
3327
3554
|
}
|
|
3328
3555
|
|
|
3556
|
+
export function realized_QMARK_(x) {
|
|
3557
|
+
if (x instanceof Delay || x instanceof LazyIterable) {
|
|
3558
|
+
return x.realized === true;
|
|
3559
|
+
}
|
|
3560
|
+
throw new Error('realized? not supported on: ' + str(x));
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3329
3563
|
function clj__GT_js_(x, seen) {
|
|
3330
3564
|
// we need to protect against circular objects
|
|
3331
3565
|
if (seen.has(x)) return x;
|
|
@@ -3385,6 +3619,7 @@ function toEDN(value, seen = new WeakSet(), readably = true) {
|
|
|
3385
3619
|
if (typeof value === 'bigint') return `${value}N`;
|
|
3386
3620
|
|
|
3387
3621
|
if (typeof value === 'object') {
|
|
3622
|
+
if (value instanceof UUID) return readably ? `#uuid "${value.uuid}"` : value.uuid;
|
|
3388
3623
|
// seen tracks the current ancestor path only. A shared reference that
|
|
3389
3624
|
// appears under sibling branches is a DAG, not a cycle, so delete on exit.
|
|
3390
3625
|
if (seen.has(value)) return '#object[circular]';
|