squint-cljs 0.14.199 → 0.14.201
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 +113 -113
- package/lib/cljs.pprint.js +258 -258
- package/lib/compiler.js +1318 -1279
- package/lib/compiler.node.js +45 -40
- package/lib/compiler.sci.js +1267 -1263
- 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 +415 -120
- package/src/squint/multi.js +63 -8
- package/src/squint/string.js +22 -5
package/src/squint/core.js
CHANGED
|
@@ -23,6 +23,9 @@ function findKey(iter, tar, key) {
|
|
|
23
23
|
function isSortedMap(m) {
|
|
24
24
|
return m != null && m[SORTED_TAG] === true && m[TYPE_TAG] === MAP_TYPE;
|
|
25
25
|
}
|
|
26
|
+
function isSetLike(s) {
|
|
27
|
+
return s != null && (s instanceof Set || s[TYPE_TAG] === SET_TYPE);
|
|
28
|
+
}
|
|
26
29
|
function isMapLike(m) {
|
|
27
30
|
return (
|
|
28
31
|
m != null &&
|
|
@@ -62,8 +65,33 @@ function dequal(foo, bar) {
|
|
|
62
65
|
return true;
|
|
63
66
|
}
|
|
64
67
|
|
|
68
|
+
// A plain object and a js/Map are both map reps; compare by entries.
|
|
69
|
+
// Same-type pairs skip this and keep their fast paths below.
|
|
70
|
+
if (isMapLike(foo) && isMapLike(bar) && foo.constructor !== bar.constructor) {
|
|
71
|
+
if (mapCount(foo) !== mapCount(bar)) return false;
|
|
72
|
+
for (const k of foo instanceof Map ? foo.keys() : Object.keys(foo)) {
|
|
73
|
+
if (!mapHas(bar, k) || !dequal(mapGet(foo, k), mapGet(bar, k))) return false;
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Sets (hash or sorted) compare by elements, across concrete types.
|
|
79
|
+
if (isSetLike(foo) || isSetLike(bar)) {
|
|
80
|
+
if (!isSetLike(foo) || !isSetLike(bar) || foo.size !== bar.size) return false;
|
|
81
|
+
for (let e of foo) {
|
|
82
|
+
if (e && typeof e === 'object') {
|
|
83
|
+
e = findKey(bar, e);
|
|
84
|
+
if (!e) return false;
|
|
85
|
+
}
|
|
86
|
+
if (!bar.has(e)) return false;
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
65
91
|
if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
|
|
66
92
|
if (ctor === Date) return foo.getTime() === bar.getTime();
|
|
93
|
+
// regexes only compare by identity, like CLJS
|
|
94
|
+
if (ctor === RegExp) return false;
|
|
67
95
|
|
|
68
96
|
if (ctor === Array) {
|
|
69
97
|
if ((len = foo.length) === bar.length) {
|
|
@@ -72,21 +100,6 @@ function dequal(foo, bar) {
|
|
|
72
100
|
return len === -1;
|
|
73
101
|
}
|
|
74
102
|
|
|
75
|
-
if (ctor === Set) {
|
|
76
|
-
if (foo.size !== bar.size) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
for (const elt of foo) {
|
|
80
|
-
tmp = elt;
|
|
81
|
-
if (tmp && typeof tmp === 'object') {
|
|
82
|
-
tmp = findKey(bar, tmp);
|
|
83
|
-
if (!tmp) return false;
|
|
84
|
-
}
|
|
85
|
-
if (!bar.has(tmp)) return false;
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
103
|
if (ctor === Map) {
|
|
91
104
|
if (foo.size !== bar.size) {
|
|
92
105
|
return false;
|
|
@@ -271,9 +284,24 @@ function copy(o) {
|
|
|
271
284
|
}
|
|
272
285
|
|
|
273
286
|
export function assoc(o, k, v, ...kvs) {
|
|
274
|
-
|
|
287
|
+
// only nil puns to an empty map; assoc on false throws, like CLJS
|
|
288
|
+
if (o == null) {
|
|
275
289
|
o = {};
|
|
276
290
|
}
|
|
291
|
+
if (isVectorArray(o)) {
|
|
292
|
+
// like CLJS: a vector key is an index in [0, count], count appends
|
|
293
|
+
let len = o.length;
|
|
294
|
+
for (let i = 0; i < kvs.length + 2; i += 2) {
|
|
295
|
+
const key = i === 0 ? k : kvs[i - 2];
|
|
296
|
+
if (!Number.isInteger(key)) {
|
|
297
|
+
throw new Error("Vector's key for assoc must be a number.");
|
|
298
|
+
}
|
|
299
|
+
if (key < 0 || key > len) {
|
|
300
|
+
throw new Error(`Index ${key} out of bounds [0,${len}]`);
|
|
301
|
+
}
|
|
302
|
+
if (key === len) len++;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
277
305
|
const ret = copy(o);
|
|
278
306
|
assoc_BANG_(ret, k, v, ...kvs);
|
|
279
307
|
return ret;
|
|
@@ -282,6 +310,9 @@ export function assoc(o, k, v, ...kvs) {
|
|
|
282
310
|
// squint has no distinct hash-map or array-map type; both build a plain object.
|
|
283
311
|
export function hash_map(...kvs) {
|
|
284
312
|
if (kvs.length === 0) return {};
|
|
313
|
+
if (kvs.length % 2 !== 0) {
|
|
314
|
+
throw new Error('No value supplied for key: ' + kvs[kvs.length - 1]);
|
|
315
|
+
}
|
|
285
316
|
return assoc({}, ...kvs);
|
|
286
317
|
}
|
|
287
318
|
|
|
@@ -355,6 +386,8 @@ function typeConst(obj) {
|
|
|
355
386
|
const tag = obj[TYPE_TAG];
|
|
356
387
|
if (tag !== undefined) return tag;
|
|
357
388
|
if (isVectorArray(obj)) return ARRAY_TYPE;
|
|
389
|
+
// any remaining object (class instance, null-proto) is associative
|
|
390
|
+
if (typeof obj === 'object') return OBJECT_TYPE;
|
|
358
391
|
|
|
359
392
|
return undefined;
|
|
360
393
|
}
|
|
@@ -441,6 +474,10 @@ export function conj_BANG_(...xs) {
|
|
|
441
474
|
if (n === 0) {
|
|
442
475
|
return vector();
|
|
443
476
|
}
|
|
477
|
+
// single arg: return the coll unchanged, including nil, like CLJS
|
|
478
|
+
if (n === 1) {
|
|
479
|
+
return xs[0];
|
|
480
|
+
}
|
|
444
481
|
|
|
445
482
|
let o = xs[0];
|
|
446
483
|
if (o === null || o === undefined) {
|
|
@@ -474,17 +511,14 @@ export function conj_BANG_(...xs) {
|
|
|
474
511
|
break;
|
|
475
512
|
case MAP_TYPE:
|
|
476
513
|
for (const x of rest) {
|
|
477
|
-
if (
|
|
478
|
-
|
|
479
|
-
o.set(kv[0], kv[1]);
|
|
480
|
-
});
|
|
481
|
-
else o.set(x[0], x[1]);
|
|
514
|
+
if (isVectorArray(x)) { asMapEntry(x); o.set(x[0], x[1]); }
|
|
515
|
+
else for (const kv of mapEntriesOf(x)) o.set(kv[0], kv[1]);
|
|
482
516
|
}
|
|
483
517
|
break;
|
|
484
518
|
case OBJECT_TYPE:
|
|
485
519
|
for (const x of rest) {
|
|
486
|
-
if (
|
|
487
|
-
else o[
|
|
520
|
+
if (isVectorArray(x)) { asMapEntry(x); o[x[0]] = x[1]; }
|
|
521
|
+
else for (const kv of mapEntriesOf(x)) o[kv[0]] = kv[1];
|
|
488
522
|
}
|
|
489
523
|
break;
|
|
490
524
|
default:
|
|
@@ -496,6 +530,28 @@ export function conj_BANG_(...xs) {
|
|
|
496
530
|
return o;
|
|
497
531
|
}
|
|
498
532
|
|
|
533
|
+
// entries carried by a non-entry conj arg onto a map: a map merges, a
|
|
534
|
+
// seqable must contain entry vectors, like CLJS
|
|
535
|
+
function* mapEntriesOf(x) {
|
|
536
|
+
if (isMapLike(x)) {
|
|
537
|
+
yield* iterable(x);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
for (const kv of iterable(x)) {
|
|
541
|
+
if (!isVectorArray(kv)) {
|
|
542
|
+
throw new Error('conj on a map takes map entries or seqables of map entries');
|
|
543
|
+
}
|
|
544
|
+
yield kv;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function asMapEntry(x) {
|
|
549
|
+
if (x.length < 2) {
|
|
550
|
+
throw new Error('Vector arg to map conj must be a pair');
|
|
551
|
+
}
|
|
552
|
+
return x;
|
|
553
|
+
}
|
|
554
|
+
|
|
499
555
|
export function conj(...xs) {
|
|
500
556
|
if (xs.length === 0) {
|
|
501
557
|
return vector();
|
|
@@ -527,11 +583,8 @@ export function conj(...xs) {
|
|
|
527
583
|
case MAP_TYPE:
|
|
528
584
|
m = new Map(o);
|
|
529
585
|
for (const x of rest) {
|
|
530
|
-
if (
|
|
531
|
-
|
|
532
|
-
m.set(kv[0], kv[1]);
|
|
533
|
-
});
|
|
534
|
-
else m.set(x[0], x[1]);
|
|
586
|
+
if (isVectorArray(x)) { asMapEntry(x); m.set(x[0], x[1]); }
|
|
587
|
+
else for (const kv of mapEntriesOf(x)) m.set(kv[0], kv[1]);
|
|
535
588
|
}
|
|
536
589
|
|
|
537
590
|
return copyMeta(o, m);
|
|
@@ -544,8 +597,8 @@ export function conj(...xs) {
|
|
|
544
597
|
o2 = { ...o };
|
|
545
598
|
|
|
546
599
|
for (const x of rest) {
|
|
547
|
-
if (
|
|
548
|
-
else o2[
|
|
600
|
+
if (isVectorArray(x)) { asMapEntry(x); o2[x[0]] = x[1]; }
|
|
601
|
+
else for (const kv of mapEntriesOf(x)) o2[kv[0]] = kv[1];
|
|
549
602
|
}
|
|
550
603
|
|
|
551
604
|
return copyMeta(o, o2);
|
|
@@ -567,7 +620,7 @@ export function disj(s, ...xs) {
|
|
|
567
620
|
if (s == null) return s;
|
|
568
621
|
// pass s itself (not a spread) so a SortedSet keeps its comparator
|
|
569
622
|
const s1 = new s.constructor(s);
|
|
570
|
-
return disj_BANG_(s1, ...xs);
|
|
623
|
+
return copyMeta(s, disj_BANG_(s1, ...xs));
|
|
571
624
|
}
|
|
572
625
|
|
|
573
626
|
export function contains_QMARK_(coll, v) {
|
|
@@ -596,7 +649,11 @@ export function dissoc_BANG_(m, ...ks) {
|
|
|
596
649
|
export function dissoc(m, ...ks) {
|
|
597
650
|
if (!m) return;
|
|
598
651
|
if (ks.length === 0) return m;
|
|
599
|
-
|
|
652
|
+
const tc = typeConst(m);
|
|
653
|
+
if (tc !== MAP_TYPE && tc !== OBJECT_TYPE) {
|
|
654
|
+
throw new Error('dissoc expects a map, got: ' + typeof m);
|
|
655
|
+
}
|
|
656
|
+
if (tc === MAP_TYPE) {
|
|
600
657
|
let present = false;
|
|
601
658
|
for (const k of ks) if (m.has(k)) { present = true; break; }
|
|
602
659
|
if (!present) return m;
|
|
@@ -638,6 +695,9 @@ export function pr(...xs) {
|
|
|
638
695
|
}
|
|
639
696
|
|
|
640
697
|
export function nth(coll, idx, orElse) {
|
|
698
|
+
if (typeof idx !== 'number') {
|
|
699
|
+
throw new Error('Index argument to nth must be a number');
|
|
700
|
+
}
|
|
641
701
|
const hasDefault = arguments.length > 2;
|
|
642
702
|
// nil coll puns to nil, like Clojure
|
|
643
703
|
if (coll == null) return hasDefault ? orElse : null;
|
|
@@ -724,7 +784,8 @@ export function seqable_QMARK_(x) {
|
|
|
724
784
|
object_QMARK_(x) ||
|
|
725
785
|
// we used to check instanceof Object but this returns false for TC39 Records
|
|
726
786
|
// also we used to write `Symbol.iterator in` but this does not work for strings and some other types
|
|
727
|
-
!!x[Symbol.iterator]
|
|
787
|
+
!!x[Symbol.iterator] ||
|
|
788
|
+
!!x[ISEQABLE_SYM]
|
|
728
789
|
);
|
|
729
790
|
}
|
|
730
791
|
|
|
@@ -754,6 +815,8 @@ export function iterable(x) {
|
|
|
754
815
|
if (x[Symbol.iterator]) {
|
|
755
816
|
return x;
|
|
756
817
|
}
|
|
818
|
+
// a type extended to ISeqable seqs through its -seq method
|
|
819
|
+
if (x[ISeqable__seq] !== undefined) return iterable(x[ISeqable__seq](x));
|
|
757
820
|
if (x instanceof Object) return Object.entries(x).map(tagMapEntry);
|
|
758
821
|
throw new TypeError(`${x} is not iterable`);
|
|
759
822
|
}
|
|
@@ -770,6 +833,7 @@ export const es6_iterator = _iterator;
|
|
|
770
833
|
|
|
771
834
|
export function seq(x) {
|
|
772
835
|
if (x == null) return x;
|
|
836
|
+
if (!seqable_QMARK_(x)) throw new TypeError(x + ' is not ISeqable');
|
|
773
837
|
// a string seqs into its characters, like CLJS.
|
|
774
838
|
if (typeof x === 'string') return x.length ? [...x] : null;
|
|
775
839
|
const iter = iterable(x);
|
|
@@ -830,13 +894,13 @@ export function rest(coll) {
|
|
|
830
894
|
return cell._rest; // first chunk had one element; the next cell is the rest
|
|
831
895
|
}
|
|
832
896
|
|
|
897
|
+
const REDUCED_DEREF = (self) => self.value;
|
|
898
|
+
|
|
833
899
|
class Reduced {
|
|
834
900
|
value;
|
|
835
901
|
constructor(x) {
|
|
836
902
|
this.value = x;
|
|
837
|
-
|
|
838
|
-
_deref() {
|
|
839
|
-
return this.value;
|
|
903
|
+
this[IDeref__deref] = REDUCED_DEREF;
|
|
840
904
|
}
|
|
841
905
|
}
|
|
842
906
|
|
|
@@ -996,12 +1060,12 @@ class LazyIterable {
|
|
|
996
1060
|
},
|
|
997
1061
|
};
|
|
998
1062
|
}
|
|
999
|
-
//
|
|
1000
|
-
//
|
|
1063
|
+
// Mirrors Array.prototype.indexOf so lazy seqs support (.indexOf coll x):
|
|
1064
|
+
// reference equality, returns -1 when absent. Unlike cljs.core, not by value.
|
|
1001
1065
|
indexOf(x, fromIndex = 0) {
|
|
1002
1066
|
let i = 0;
|
|
1003
1067
|
for (const v of this) {
|
|
1004
|
-
if (i >= fromIndex &&
|
|
1068
|
+
if (i >= fromIndex && v === x) return i;
|
|
1005
1069
|
i++;
|
|
1006
1070
|
}
|
|
1007
1071
|
return -1;
|
|
@@ -1125,6 +1189,8 @@ class Cons {
|
|
|
1125
1189
|
);
|
|
1126
1190
|
|
|
1127
1191
|
export function cons(x, coll) {
|
|
1192
|
+
// like CLJS cons, which seqs a non-ISeq tail
|
|
1193
|
+
if (!seqable_QMARK_(coll)) throw new TypeError(coll + ' is not ISeqable');
|
|
1128
1194
|
return new Cons(x, coll);
|
|
1129
1195
|
}
|
|
1130
1196
|
|
|
@@ -1288,48 +1354,167 @@ export function nil_QMARK_(v) {
|
|
|
1288
1354
|
|
|
1289
1355
|
export const PROTOCOL_SENTINEL = {};
|
|
1290
1356
|
|
|
1357
|
+
// marker protocols so (satisfies? IAtom x) works, like CLJS. Marked in the
|
|
1358
|
+
// constructor, not on the prototype, so no top-level mutation pins Atom
|
|
1359
|
+
// into bundles that do not use it.
|
|
1360
|
+
const IATOM_SYM = Symbol('squint.core.IAtom');
|
|
1361
|
+
const IDEREF_SYM = Symbol('squint.core.IDeref');
|
|
1362
|
+
const ISEQABLE_SYM = Symbol('squint.core.ISeqable');
|
|
1363
|
+
export const IAtom = { __sym: IATOM_SYM };
|
|
1364
|
+
export const IDeref = { __sym: IDEREF_SYM };
|
|
1365
|
+
// method slot for (-deref x), named like the defprotocol emission so
|
|
1366
|
+
// (extend-type T IDeref (-deref [x] ...)) fills it
|
|
1367
|
+
export const IDeref__deref = Symbol('IDeref_-deref');
|
|
1368
|
+
export function _deref(o) {
|
|
1369
|
+
if (o != null && o[IDeref__deref] !== undefined) return o[IDeref__deref](o);
|
|
1370
|
+
return nilImpl(_deref, 'IDeref.-deref', o)(o);
|
|
1371
|
+
}
|
|
1372
|
+
export const ISeqable = { __sym: ISEQABLE_SYM };
|
|
1373
|
+
export const ISeqable__seq = Symbol('ISeqable_-seq');
|
|
1374
|
+
export function _seq(o) {
|
|
1375
|
+
if (o != null && o[ISeqable__seq] !== undefined) return o[ISeqable__seq](o);
|
|
1376
|
+
return nilImpl(_seq, 'ISeqable.-seq', o)(o);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// an extend-type on nil stores the impl on the dispatch fn under null,
|
|
1380
|
+
// the same convention the generated protocol dispatch fns use
|
|
1381
|
+
function nilImpl(dispatchFn, protoMethod, o) {
|
|
1382
|
+
const f = dispatchFn[null];
|
|
1383
|
+
if (f === undefined) throw missing_protocol(protoMethod, o);
|
|
1384
|
+
return f;
|
|
1385
|
+
}
|
|
1386
|
+
export const IReset = { __sym: Symbol('squint.core.IReset') };
|
|
1387
|
+
export const IReset__reset_BANG_ = Symbol('IReset_-reset!');
|
|
1388
|
+
export function _reset_BANG_(o, v) {
|
|
1389
|
+
if (o != null && o[IReset__reset_BANG_] !== undefined) return o[IReset__reset_BANG_](o, v);
|
|
1390
|
+
return nilImpl(_reset_BANG_, 'IReset.-reset!', o)(o, v);
|
|
1391
|
+
}
|
|
1392
|
+
export const ISwap = { __sym: Symbol('squint.core.ISwap') };
|
|
1393
|
+
export const ISwap__swap_BANG_ = Symbol('ISwap_-swap!');
|
|
1394
|
+
export function _swap_BANG_(o, f, ...args) {
|
|
1395
|
+
if (o != null && o[ISwap__swap_BANG_] !== undefined) return o[ISwap__swap_BANG_](o, f, ...args);
|
|
1396
|
+
return nilImpl(_swap_BANG_, 'ISwap.-swap!', o)(o, f, ...args);
|
|
1397
|
+
}
|
|
1398
|
+
export const IWatchable = { __sym: Symbol('squint.core.IWatchable') };
|
|
1399
|
+
export const IWatchable__add_watch = Symbol('IWatchable_-add-watch');
|
|
1400
|
+
export const IWatchable__remove_watch = Symbol('IWatchable_-remove-watch');
|
|
1401
|
+
export const IWatchable__notify_watches = Symbol('IWatchable_-notify-watches');
|
|
1402
|
+
export function _add_watch(o, k, f) {
|
|
1403
|
+
if (o != null && o[IWatchable__add_watch] !== undefined) return o[IWatchable__add_watch](o, k, f);
|
|
1404
|
+
return nilImpl(_add_watch, 'IWatchable.-add-watch', o)(o, k, f);
|
|
1405
|
+
}
|
|
1406
|
+
export function _remove_watch(o, k) {
|
|
1407
|
+
if (o != null && o[IWatchable__remove_watch] !== undefined) return o[IWatchable__remove_watch](o, k);
|
|
1408
|
+
return nilImpl(_remove_watch, 'IWatchable.-remove-watch', o)(o, k);
|
|
1409
|
+
}
|
|
1410
|
+
export function _notify_watches(o, oldv, newv) {
|
|
1411
|
+
if (o != null && o[IWatchable__notify_watches] !== undefined) return o[IWatchable__notify_watches](o, oldv, newv);
|
|
1412
|
+
return nilImpl(_notify_watches, 'IWatchable.-notify-watches', o)(o, oldv, newv);
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
// shared protocol impls: one fn per operation, a pointer per instance
|
|
1416
|
+
const ATOM_DEREF = (self) => self.val;
|
|
1417
|
+
const ATOM_RESET = (self, x) => {
|
|
1418
|
+
if (self._validator && !truth_(self._validator(x))) {
|
|
1419
|
+
throw new Error('Validator rejected reference state');
|
|
1420
|
+
}
|
|
1421
|
+
const old_val = self.val;
|
|
1422
|
+
self.val = x;
|
|
1423
|
+
if (self._hasWatches) {
|
|
1424
|
+
for (const [k, f] of Object.entries(self._watches)) f(k, self, old_val, x);
|
|
1425
|
+
}
|
|
1426
|
+
return x;
|
|
1427
|
+
};
|
|
1428
|
+
const ATOM_SWAP = function (self, f, a, b, xs) {
|
|
1429
|
+
switch (arguments.length) {
|
|
1430
|
+
case 2:
|
|
1431
|
+
return ATOM_RESET(self, f(self.val));
|
|
1432
|
+
case 3:
|
|
1433
|
+
return ATOM_RESET(self, f(self.val, a));
|
|
1434
|
+
case 4:
|
|
1435
|
+
return ATOM_RESET(self, f(self.val, a, b));
|
|
1436
|
+
default:
|
|
1437
|
+
return ATOM_RESET(self, f(self.val, a, b, ...xs));
|
|
1438
|
+
}
|
|
1439
|
+
};
|
|
1440
|
+
const ATOM_ADD_WATCH = (self, k, f) => {
|
|
1441
|
+
self._watches[k] = f;
|
|
1442
|
+
self._hasWatches = true;
|
|
1443
|
+
};
|
|
1444
|
+
const ATOM_REMOVE_WATCH = (self, k) => {
|
|
1445
|
+
delete self._watches[k];
|
|
1446
|
+
};
|
|
1447
|
+
const ATOM_NOTIFY = (self, oldv, newv) => {
|
|
1448
|
+
for (const [k, f] of Object.entries(self._watches)) f(k, self, oldv, newv);
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1291
1451
|
export class Atom {
|
|
1292
1452
|
constructor(init) {
|
|
1293
1453
|
this.val = init;
|
|
1294
1454
|
this._watches = {};
|
|
1295
|
-
this._deref = () => this.val;
|
|
1296
1455
|
this._hasWatches = false;
|
|
1297
|
-
this
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1456
|
+
this[IATOM_SYM] = true;
|
|
1457
|
+
this[IDEREF_SYM] = true;
|
|
1458
|
+
this[IDeref__deref] = ATOM_DEREF;
|
|
1459
|
+
this[IReset.__sym] = true;
|
|
1460
|
+
this[IReset__reset_BANG_] = ATOM_RESET;
|
|
1461
|
+
this[ISwap.__sym] = true;
|
|
1462
|
+
this[ISwap__swap_BANG_] = ATOM_SWAP;
|
|
1463
|
+
this[IWatchable.__sym] = true;
|
|
1464
|
+
this[IWatchable__add_watch] = ATOM_ADD_WATCH;
|
|
1465
|
+
this[IWatchable__remove_watch] = ATOM_REMOVE_WATCH;
|
|
1466
|
+
this[IWatchable__notify_watches] = ATOM_NOTIFY;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
export function atom(init, ...opts) {
|
|
1471
|
+
const a = new Atom(init);
|
|
1472
|
+
for (let i = 0; i < opts.length; i += 2) {
|
|
1473
|
+
if (opts[i] === 'meta') a[_metaSym] = opts[i + 1];
|
|
1474
|
+
else if (opts[i] === 'validator') a._validator = opts[i + 1];
|
|
1475
|
+
}
|
|
1476
|
+
return a;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
// the CLJS missing-protocol error, used by every protocol dispatch miss
|
|
1480
|
+
export function missing_protocol(proto, obj) {
|
|
1481
|
+
let ty;
|
|
1482
|
+
if (obj === null) ty = 'null';
|
|
1483
|
+
else if (obj === undefined) ty = 'undefined';
|
|
1484
|
+
else if (Array.isArray(obj)) ty = 'array';
|
|
1485
|
+
else if (typeof obj === 'object' && obj.constructor && obj.constructor !== Object) {
|
|
1486
|
+
ty = obj.constructor.name;
|
|
1487
|
+
} else ty = typeof obj;
|
|
1488
|
+
return new Error(
|
|
1489
|
+
`No protocol method ${proto} defined for type ${ty}: ${obj ?? ''}`
|
|
1490
|
+
);
|
|
1321
1491
|
}
|
|
1322
1492
|
|
|
1323
1493
|
export function deref(ref) {
|
|
1324
|
-
return ref
|
|
1494
|
+
if (ref?.[IDeref__deref] !== undefined) return ref[IDeref__deref](ref);
|
|
1495
|
+
return nilImpl(_deref, 'IDeref.-deref', ref)(ref);
|
|
1325
1496
|
}
|
|
1326
1497
|
|
|
1327
1498
|
export function reset_BANG_(atm, v) {
|
|
1328
|
-
atm
|
|
1499
|
+
if (atm?.[IReset__reset_BANG_] !== undefined) return atm[IReset__reset_BANG_](atm, v);
|
|
1500
|
+
return nilImpl(_reset_BANG_, 'IReset.-reset!', atm)(atm, v);
|
|
1329
1501
|
}
|
|
1330
1502
|
|
|
1331
1503
|
export function swap_BANG_(atm, f, ...args) {
|
|
1332
1504
|
f = __toFn(f);
|
|
1505
|
+
if (atm?.[ISwap__swap_BANG_] !== undefined) {
|
|
1506
|
+
// the CLJS -swap! contract: up to two positional args, the rest packed
|
|
1507
|
+
switch (args.length) {
|
|
1508
|
+
case 0:
|
|
1509
|
+
return atm[ISwap__swap_BANG_](atm, f);
|
|
1510
|
+
case 1:
|
|
1511
|
+
return atm[ISwap__swap_BANG_](atm, f, args[0]);
|
|
1512
|
+
case 2:
|
|
1513
|
+
return atm[ISwap__swap_BANG_](atm, f, args[0], args[1]);
|
|
1514
|
+
default:
|
|
1515
|
+
return atm[ISwap__swap_BANG_](atm, f, args[0], args[1], args.slice(2));
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1333
1518
|
const v = f(deref(atm), ...args);
|
|
1334
1519
|
reset_BANG_(atm, v);
|
|
1335
1520
|
return v;
|
|
@@ -1339,19 +1524,19 @@ export function swap_vals_BANG_(atm, f, ...args) {
|
|
|
1339
1524
|
const oldv = deref(atm);
|
|
1340
1525
|
f = __toFn(f);
|
|
1341
1526
|
const newv = f(oldv, ...args);
|
|
1342
|
-
atm
|
|
1527
|
+
reset_BANG_(atm, newv);
|
|
1343
1528
|
return [oldv, newv];
|
|
1344
1529
|
}
|
|
1345
1530
|
|
|
1346
1531
|
export function reset_vals_BANG_(atm, newv) {
|
|
1347
1532
|
const oldv = deref(atm);
|
|
1348
|
-
atm
|
|
1533
|
+
reset_BANG_(atm, newv);
|
|
1349
1534
|
return [oldv, newv];
|
|
1350
1535
|
}
|
|
1351
1536
|
|
|
1352
1537
|
export function compare_and_set_BANG_(atm, oldv, newv) {
|
|
1353
1538
|
if (deref(atm) === oldv) {
|
|
1354
|
-
atm
|
|
1539
|
+
reset_BANG_(atm, newv);
|
|
1355
1540
|
return true;
|
|
1356
1541
|
} else {
|
|
1357
1542
|
return false;
|
|
@@ -1516,11 +1701,23 @@ export function set_QMARK_(x) {
|
|
|
1516
1701
|
return typeConst(x) === SET_TYPE;
|
|
1517
1702
|
}
|
|
1518
1703
|
|
|
1704
|
+
export function hash_set(...xs) {
|
|
1705
|
+
return new Set(xs);
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
export function sorted_QMARK_(x) {
|
|
1709
|
+
return x != null && x[SORTED_TAG] === true;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
export function char_QMARK_(x) {
|
|
1713
|
+
return typeof x === 'string' && x.length === 1;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1519
1716
|
export function apply(f, ...args) {
|
|
1520
1717
|
f = __toFn(f);
|
|
1521
1718
|
const xs = args.slice(0, args.length - 1);
|
|
1522
1719
|
const last = args[args.length - 1];
|
|
1523
|
-
// variadic impl hint; see doc/adr/0001
|
|
1720
|
+
// variadic impl hint; see doc/ai/adr/0001
|
|
1524
1721
|
const v = f.squint$lang$variadic;
|
|
1525
1722
|
if (v) {
|
|
1526
1723
|
// pull maxfa fixed args (bounded, lazy-safe); more left -> variadic, else fixed
|
|
@@ -1694,9 +1891,10 @@ export function interpose(sep, coll) {
|
|
|
1694
1891
|
|
|
1695
1892
|
export function select_keys(o, ks) {
|
|
1696
1893
|
const type = typeConst(o);
|
|
1697
|
-
//
|
|
1698
|
-
const ret =
|
|
1699
|
-
|
|
1894
|
+
// always a map, like CLJS; a js/Map source keeps its rep
|
|
1895
|
+
const ret = type === MAP_TYPE ? new Map() : {};
|
|
1896
|
+
// iterable puns nil to no keys and a map to its entries, like CLJS seq
|
|
1897
|
+
for (const k of iterable(ks)) {
|
|
1700
1898
|
const v = get(o, k);
|
|
1701
1899
|
if (v !== undefined) {
|
|
1702
1900
|
assoc_BANG_(ret, k, v);
|
|
@@ -1903,6 +2101,9 @@ export function merge(...args) {
|
|
|
1903
2101
|
let obj;
|
|
1904
2102
|
if (firstArg === null || firstArg === undefined) {
|
|
1905
2103
|
obj = {};
|
|
2104
|
+
} else if (typeConst(firstArg) === undefined) {
|
|
2105
|
+
// a non-collection passes through; conj! throws when maps follow, like CLJS
|
|
2106
|
+
obj = firstArg;
|
|
1906
2107
|
} else {
|
|
1907
2108
|
obj = into(empty(firstArg), firstArg);
|
|
1908
2109
|
}
|
|
@@ -2020,7 +2221,15 @@ function take1(n) {
|
|
|
2020
2221
|
});
|
|
2021
2222
|
}
|
|
2022
2223
|
|
|
2224
|
+
function assertNumber(n) {
|
|
2225
|
+
if (typeof n !== 'number') {
|
|
2226
|
+
throw new Error('Assert failed: (number? n)');
|
|
2227
|
+
}
|
|
2228
|
+
return n;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2023
2231
|
export function take(n, coll) {
|
|
2232
|
+
assertNumber(n);
|
|
2024
2233
|
if (arguments.length === 1) {
|
|
2025
2234
|
return take1(n);
|
|
2026
2235
|
}
|
|
@@ -2038,6 +2247,7 @@ export function take(n, coll) {
|
|
|
2038
2247
|
}
|
|
2039
2248
|
|
|
2040
2249
|
export function take_last(n, coll) {
|
|
2250
|
+
assertNumber(n);
|
|
2041
2251
|
if (n <= 0) {
|
|
2042
2252
|
return null;
|
|
2043
2253
|
}
|
|
@@ -2110,8 +2320,18 @@ export function partial(f, ...xs) {
|
|
|
2110
2320
|
}
|
|
2111
2321
|
|
|
2112
2322
|
export function cycle(coll) {
|
|
2323
|
+
// seq the coll eagerly: nil or empty cycles to an empty seq and a
|
|
2324
|
+
// non-iterable throws, like the seq call in CLJS cycle. The first lap
|
|
2325
|
+
// is cached and replayed, like the retained seq in CLJS Cycle, so a
|
|
2326
|
+
// one-shot iterator source cycles instead of ending after one lap.
|
|
2327
|
+
const it = iterable(coll);
|
|
2113
2328
|
return lazy(function* () {
|
|
2114
|
-
|
|
2329
|
+
const cache = [];
|
|
2330
|
+
for (const x of it) {
|
|
2331
|
+
cache.push(x);
|
|
2332
|
+
yield x;
|
|
2333
|
+
}
|
|
2334
|
+
while (cache.length) yield* cache;
|
|
2115
2335
|
});
|
|
2116
2336
|
}
|
|
2117
2337
|
|
|
@@ -2123,6 +2343,7 @@ function drop1(n) {
|
|
|
2123
2343
|
}
|
|
2124
2344
|
|
|
2125
2345
|
export function drop(n, xs) {
|
|
2346
|
+
assertNumber(n);
|
|
2126
2347
|
if (arguments.length === 1) return drop1(n);
|
|
2127
2348
|
return lazyIter(xs, function* (iter) {
|
|
2128
2349
|
for (let x = 0; x < n; x++) {
|
|
@@ -2217,7 +2438,8 @@ export function update(coll, k, f, ...args) {
|
|
|
2217
2438
|
|
|
2218
2439
|
export function get_in(coll, path, orElse) {
|
|
2219
2440
|
let entry = coll;
|
|
2220
|
-
|
|
2441
|
+
// iterable puns a nil path to an empty path, like CLJS
|
|
2442
|
+
for (const item of iterable(path)) {
|
|
2221
2443
|
entry = get(entry, item);
|
|
2222
2444
|
}
|
|
2223
2445
|
if (entry === undefined) return orElse;
|
|
@@ -2282,6 +2504,18 @@ export function reverse(coll) {
|
|
|
2282
2504
|
return toArray(coll).reverse();
|
|
2283
2505
|
}
|
|
2284
2506
|
|
|
2507
|
+
export function rseq(x) {
|
|
2508
|
+
// vectors and sorted maps/sets are reversible, like CLJS
|
|
2509
|
+
if (isVectorArray(x)) {
|
|
2510
|
+
return x.length === 0 ? null : [...x].reverse();
|
|
2511
|
+
}
|
|
2512
|
+
if (x != null && x[SORTED_TAG] === true) {
|
|
2513
|
+
const xs = [...x].reverse();
|
|
2514
|
+
return xs.length === 0 ? null : xs;
|
|
2515
|
+
}
|
|
2516
|
+
throw new Error('rseq not supported on: ' + typeof x);
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2285
2519
|
export function sort(f, coll) {
|
|
2286
2520
|
if (arguments.length === 1) {
|
|
2287
2521
|
coll = f;
|
|
@@ -2568,8 +2802,10 @@ export function dorun(x) {
|
|
|
2568
2802
|
}
|
|
2569
2803
|
|
|
2570
2804
|
export function doall(x) {
|
|
2571
|
-
// realize
|
|
2572
|
-
|
|
2805
|
+
// realize a lazy seq and return it, like CLJS; anything else is
|
|
2806
|
+
// already concrete
|
|
2807
|
+
if (x != null && x[TYPE_TAG] === LAZY_ITERABLE_TYPE) for (const _ of x);
|
|
2808
|
+
return x;
|
|
2573
2809
|
}
|
|
2574
2810
|
|
|
2575
2811
|
export function aclone(arr) {
|
|
@@ -2577,13 +2813,53 @@ export function aclone(arr) {
|
|
|
2577
2813
|
return cloned;
|
|
2578
2814
|
}
|
|
2579
2815
|
|
|
2816
|
+
function typed_array(sizeOrSeq, initValOrSeq) {
|
|
2817
|
+
if (initValOrSeq !== undefined) {
|
|
2818
|
+
const a = new Array(sizeOrSeq);
|
|
2819
|
+
if (typeof initValOrSeq === 'number') return a.fill(initValOrSeq);
|
|
2820
|
+
let i = 0;
|
|
2821
|
+
for (const x of iterable(initValOrSeq)) {
|
|
2822
|
+
if (i >= sizeOrSeq) break;
|
|
2823
|
+
a[i++] = x;
|
|
2824
|
+
}
|
|
2825
|
+
return a;
|
|
2826
|
+
}
|
|
2827
|
+
if (typeof sizeOrSeq === 'number') return new Array(sizeOrSeq).fill(null);
|
|
2828
|
+
return [...iterable(sizeOrSeq)];
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
// like CLJS: provided for compatibility, all make a plain array
|
|
2832
|
+
export function int_array(sizeOrSeq, initValOrSeq) {
|
|
2833
|
+
return typed_array(sizeOrSeq, initValOrSeq);
|
|
2834
|
+
}
|
|
2835
|
+
export function long_array(sizeOrSeq, initValOrSeq) {
|
|
2836
|
+
return typed_array(sizeOrSeq, initValOrSeq);
|
|
2837
|
+
}
|
|
2838
|
+
export function float_array(sizeOrSeq, initValOrSeq) {
|
|
2839
|
+
return typed_array(sizeOrSeq, initValOrSeq);
|
|
2840
|
+
}
|
|
2841
|
+
export function double_array(sizeOrSeq, initValOrSeq) {
|
|
2842
|
+
return typed_array(sizeOrSeq, initValOrSeq);
|
|
2843
|
+
}
|
|
2844
|
+
export function object_array(sizeOrSeq, initValOrSeq) {
|
|
2845
|
+
return typed_array(sizeOrSeq, initValOrSeq);
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2580
2848
|
export function add_watch(ref, key, fn) {
|
|
2581
|
-
ref
|
|
2849
|
+
if (ref?.[IWatchable__add_watch] !== undefined) {
|
|
2850
|
+
ref[IWatchable__add_watch](ref, key, fn);
|
|
2851
|
+
return ref;
|
|
2852
|
+
}
|
|
2853
|
+
nilImpl(_add_watch, 'IWatchable.-add-watch', ref)(ref, key, fn);
|
|
2582
2854
|
return ref;
|
|
2583
2855
|
}
|
|
2584
2856
|
|
|
2585
2857
|
export function remove_watch(ref, key) {
|
|
2586
|
-
ref
|
|
2858
|
+
if (ref?.[IWatchable__remove_watch] !== undefined) {
|
|
2859
|
+
ref[IWatchable__remove_watch](ref, key);
|
|
2860
|
+
return ref;
|
|
2861
|
+
}
|
|
2862
|
+
nilImpl(_remove_watch, 'IWatchable.-remove-watch', ref)(ref, key);
|
|
2587
2863
|
return ref;
|
|
2588
2864
|
}
|
|
2589
2865
|
|
|
@@ -2598,17 +2874,17 @@ export function reduce_kv(f, init, m) {
|
|
|
2598
2874
|
return ret;
|
|
2599
2875
|
}
|
|
2600
2876
|
|
|
2877
|
+
// CLJS reduce of (cond (NaN? x) x (NaN? y) y (> x y) x :else y): returns one of
|
|
2878
|
+
// the values, so nil acts like zero, and a NaN propagates. NaN? is js/isNaN.
|
|
2601
2879
|
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
2880
|
let m = x;
|
|
2605
|
-
for (const y of more) m = m > y ? m : y;
|
|
2881
|
+
for (const y of more) m = isNaN(m) ? m : isNaN(y) ? y : m > y ? m : y;
|
|
2606
2882
|
return m;
|
|
2607
2883
|
}
|
|
2608
2884
|
|
|
2609
2885
|
export function min(x, ...more) {
|
|
2610
2886
|
let m = x;
|
|
2611
|
-
for (const y of more) m = m < y ? m : y;
|
|
2887
|
+
for (const y of more) m = isNaN(m) ? m : isNaN(y) ? y : m < y ? m : y;
|
|
2612
2888
|
return m;
|
|
2613
2889
|
}
|
|
2614
2890
|
|
|
@@ -2636,15 +2912,15 @@ export function every_pred(...preds) {
|
|
|
2636
2912
|
|
|
2637
2913
|
export function some_fn(...fns) {
|
|
2638
2914
|
return (...args) => {
|
|
2915
|
+
let res;
|
|
2639
2916
|
for (const f of fns) {
|
|
2640
2917
|
for (const a of args) {
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
}
|
|
2918
|
+
res = f(a);
|
|
2919
|
+
// truth_, not JS truthiness: 0 and "" are truthy in CLJS
|
|
2920
|
+
if (truth_(res)) return res;
|
|
2645
2921
|
}
|
|
2646
2922
|
}
|
|
2647
|
-
return
|
|
2923
|
+
return res;
|
|
2648
2924
|
};
|
|
2649
2925
|
}
|
|
2650
2926
|
|
|
@@ -2788,7 +3064,8 @@ export function re_seq(re, s) {
|
|
|
2788
3064
|
}
|
|
2789
3065
|
|
|
2790
3066
|
export function NaN_QMARK_(x) {
|
|
2791
|
-
|
|
3067
|
+
// coercing, like CLJS js/isNaN: (NaN? "foo") is true
|
|
3068
|
+
return isNaN(x);
|
|
2792
3069
|
}
|
|
2793
3070
|
|
|
2794
3071
|
export function number_QMARK_(x) {
|
|
@@ -2796,7 +3073,7 @@ export function number_QMARK_(x) {
|
|
|
2796
3073
|
}
|
|
2797
3074
|
|
|
2798
3075
|
export function keys(obj) {
|
|
2799
|
-
if (obj == null) return;
|
|
3076
|
+
if (obj == null) return null;
|
|
2800
3077
|
const t = typeConst(obj);
|
|
2801
3078
|
switch (t) {
|
|
2802
3079
|
case OBJECT_TYPE: {
|
|
@@ -2808,6 +3085,11 @@ export function keys(obj) {
|
|
|
2808
3085
|
if (obj.size) return Array.from(obj.keys());
|
|
2809
3086
|
return;
|
|
2810
3087
|
}
|
|
3088
|
+
// not a map: nil when empty, like seq in CLJS, else throw
|
|
3089
|
+
for (const _ of iterable(obj)) {
|
|
3090
|
+
throw new TypeError(obj + ' is not a map');
|
|
3091
|
+
}
|
|
3092
|
+
return null;
|
|
2811
3093
|
}
|
|
2812
3094
|
|
|
2813
3095
|
export function js_keys(obj) {
|
|
@@ -2815,7 +3097,7 @@ export function js_keys(obj) {
|
|
|
2815
3097
|
}
|
|
2816
3098
|
|
|
2817
3099
|
export function vals(obj) {
|
|
2818
|
-
if (obj == null) return;
|
|
3100
|
+
if (obj == null) return null;
|
|
2819
3101
|
const t = typeConst(obj);
|
|
2820
3102
|
switch (t) {
|
|
2821
3103
|
case OBJECT_TYPE: {
|
|
@@ -2827,6 +3109,11 @@ export function vals(obj) {
|
|
|
2827
3109
|
if (obj.size) return Array.from(obj.values());
|
|
2828
3110
|
return;
|
|
2829
3111
|
}
|
|
3112
|
+
// not a map: nil when empty, like seq in CLJS, else throw
|
|
3113
|
+
for (const _ of iterable(obj)) {
|
|
3114
|
+
throw new TypeError(obj + ' is not a map');
|
|
3115
|
+
}
|
|
3116
|
+
return null;
|
|
2830
3117
|
}
|
|
2831
3118
|
|
|
2832
3119
|
export function string_QMARK_(s) {
|
|
@@ -3021,34 +3308,22 @@ export function mod(x, y) {
|
|
|
3021
3308
|
}
|
|
3022
3309
|
|
|
3023
3310
|
export function min_key(k, x, ...more) {
|
|
3024
|
-
|
|
3025
|
-
|
|
3311
|
+
k = __toFn(k);
|
|
3312
|
+
// pairwise (if (< (k x) (k y)) x y), like CLJS, so NaN propagates right
|
|
3313
|
+
let min = x;
|
|
3314
|
+
for (const y of more) {
|
|
3315
|
+
if (!(k(min) < k(y))) min = y;
|
|
3026
3316
|
}
|
|
3027
|
-
var kx = k(x);
|
|
3028
|
-
var min = x;
|
|
3029
|
-
more.forEach((y) => {
|
|
3030
|
-
var ky = k(y);
|
|
3031
|
-
if (ky <= kx) {
|
|
3032
|
-
kx = ky;
|
|
3033
|
-
min = y;
|
|
3034
|
-
}
|
|
3035
|
-
});
|
|
3036
3317
|
return min;
|
|
3037
3318
|
}
|
|
3038
3319
|
|
|
3039
3320
|
export function max_key(k, x, ...more) {
|
|
3040
|
-
|
|
3041
|
-
|
|
3321
|
+
k = __toFn(k);
|
|
3322
|
+
// pairwise (if (> (k x) (k y)) x y), like CLJS, so NaN propagates right
|
|
3323
|
+
let max = x;
|
|
3324
|
+
for (const y of more) {
|
|
3325
|
+
if (!(k(max) > k(y))) max = y;
|
|
3042
3326
|
}
|
|
3043
|
-
var kx = k(x);
|
|
3044
|
-
var max = x;
|
|
3045
|
-
more.forEach((y) => {
|
|
3046
|
-
var ky = k(y);
|
|
3047
|
-
if (ky >= kx) {
|
|
3048
|
-
kx = ky;
|
|
3049
|
-
max = y;
|
|
3050
|
-
}
|
|
3051
|
-
});
|
|
3052
3327
|
return max;
|
|
3053
3328
|
}
|
|
3054
3329
|
|
|
@@ -3202,6 +3477,7 @@ class SortedSet {
|
|
|
3202
3477
|
// we don't re-use xs since xs can contain duplicates
|
|
3203
3478
|
this._elts = [...s];
|
|
3204
3479
|
this._set = s;
|
|
3480
|
+
this.size = this._elts.length;
|
|
3205
3481
|
}
|
|
3206
3482
|
add(x) {
|
|
3207
3483
|
if (this._set.has(x)) return this;
|
|
@@ -3461,6 +3737,7 @@ export function memoize(f) {
|
|
|
3461
3737
|
}
|
|
3462
3738
|
|
|
3463
3739
|
export function peek(vec) {
|
|
3740
|
+
if (vec == null) return null;
|
|
3464
3741
|
// A list peeks at its front; squint lists are array-backed, so check list
|
|
3465
3742
|
// before array to avoid returning the last element.
|
|
3466
3743
|
if (list_QMARK_(vec)) {
|
|
@@ -3468,7 +3745,7 @@ export function peek(vec) {
|
|
|
3468
3745
|
} else if (array_QMARK_(vec)) {
|
|
3469
3746
|
return vec[vec.length - 1];
|
|
3470
3747
|
} else {
|
|
3471
|
-
|
|
3748
|
+
throw missing_protocol('IStack.-peek', vec);
|
|
3472
3749
|
}
|
|
3473
3750
|
}
|
|
3474
3751
|
|
|
@@ -3483,7 +3760,7 @@ export function pop(vec) {
|
|
|
3483
3760
|
ret.pop();
|
|
3484
3761
|
return ret;
|
|
3485
3762
|
} else {
|
|
3486
|
-
|
|
3763
|
+
throw missing_protocol('IStack.-pop', vec);
|
|
3487
3764
|
}
|
|
3488
3765
|
}
|
|
3489
3766
|
|
|
@@ -3514,7 +3791,7 @@ export function update_vals(m, f) {
|
|
|
3514
3791
|
}
|
|
3515
3792
|
|
|
3516
3793
|
export function random_uuid() {
|
|
3517
|
-
return crypto.randomUUID();
|
|
3794
|
+
return new UUID(crypto.randomUUID());
|
|
3518
3795
|
}
|
|
3519
3796
|
|
|
3520
3797
|
export class UUID {
|
|
@@ -3527,20 +3804,34 @@ export class UUID {
|
|
|
3527
3804
|
}
|
|
3528
3805
|
|
|
3529
3806
|
export function uuid(s) {
|
|
3530
|
-
|
|
3807
|
+
// lowercased, like CLJS
|
|
3808
|
+
return new UUID(s.toLowerCase());
|
|
3531
3809
|
}
|
|
3532
3810
|
|
|
3533
3811
|
export function uuid_QMARK_(x) {
|
|
3534
3812
|
return x instanceof UUID;
|
|
3535
3813
|
}
|
|
3536
3814
|
|
|
3815
|
+
const UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
3816
|
+
|
|
3817
|
+
export function parse_uuid(s) {
|
|
3818
|
+
if (typeof s !== 'string') {
|
|
3819
|
+
throw new Error('Expected string, got: ' + (s === null ? 'nil' : typeof s));
|
|
3820
|
+
}
|
|
3821
|
+
return UUID_REGEX.test(s) ? uuid(s) : null;
|
|
3822
|
+
}
|
|
3823
|
+
|
|
3537
3824
|
export function inst_QMARK_(x) {
|
|
3538
3825
|
return x instanceof Date;
|
|
3539
3826
|
}
|
|
3540
3827
|
|
|
3828
|
+
const DELAY_DEREF = (self) => self._deref();
|
|
3829
|
+
|
|
3541
3830
|
export class Delay {
|
|
3542
3831
|
constructor(f) {
|
|
3543
3832
|
this.f = f;
|
|
3833
|
+
this[IDEREF_SYM] = true;
|
|
3834
|
+
this[IDeref__deref] = DELAY_DEREF;
|
|
3544
3835
|
}
|
|
3545
3836
|
_deref() {
|
|
3546
3837
|
if (this.realized) {
|
|
@@ -3560,6 +3851,10 @@ export function realized_QMARK_(x) {
|
|
|
3560
3851
|
throw new Error('realized? not supported on: ' + str(x));
|
|
3561
3852
|
}
|
|
3562
3853
|
|
|
3854
|
+
export function force(x) {
|
|
3855
|
+
return x instanceof Delay ? x._deref() : x;
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3563
3858
|
function clj__GT_js_(x, seen) {
|
|
3564
3859
|
// we need to protect against circular objects
|
|
3565
3860
|
if (seen.has(x)) return x;
|
|
@@ -3587,12 +3882,12 @@ export function not_EQ_(...more) {
|
|
|
3587
3882
|
return not(_EQ_(...more));
|
|
3588
3883
|
}
|
|
3589
3884
|
|
|
3885
|
+
const VOLATILE_DEREF = (self) => self.v;
|
|
3886
|
+
|
|
3590
3887
|
class Volatile {
|
|
3591
3888
|
constructor(v) {
|
|
3592
3889
|
this.v = v;
|
|
3593
|
-
|
|
3594
|
-
_deref() {
|
|
3595
|
-
return this.v;
|
|
3890
|
+
this[IDeref__deref] = VOLATILE_DEREF;
|
|
3596
3891
|
}
|
|
3597
3892
|
}
|
|
3598
3893
|
|