squint-cljs 0.14.200 → 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 +108 -108
- package/lib/cljs.pprint.js +257 -257
- package/lib/compiler.js +1281 -1241
- package/lib/compiler.node.js +45 -45
- package/lib/compiler.sci.js +1252 -1251
- package/lib/node.nrepl_server.js +28 -28
- package/lib/squint.core.umd.js +3 -3
- package/package.json +1 -1
- package/src/squint/core.js +388 -97
- package/src/squint/multi.js +63 -8
- package/src/squint/string.js +22 -5
package/src/squint/core.js
CHANGED
|
@@ -65,6 +65,16 @@ function dequal(foo, bar) {
|
|
|
65
65
|
return true;
|
|
66
66
|
}
|
|
67
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
|
+
|
|
68
78
|
// Sets (hash or sorted) compare by elements, across concrete types.
|
|
69
79
|
if (isSetLike(foo) || isSetLike(bar)) {
|
|
70
80
|
if (!isSetLike(foo) || !isSetLike(bar) || foo.size !== bar.size) return false;
|
|
@@ -80,6 +90,8 @@ function dequal(foo, bar) {
|
|
|
80
90
|
|
|
81
91
|
if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
|
|
82
92
|
if (ctor === Date) return foo.getTime() === bar.getTime();
|
|
93
|
+
// regexes only compare by identity, like CLJS
|
|
94
|
+
if (ctor === RegExp) return false;
|
|
83
95
|
|
|
84
96
|
if (ctor === Array) {
|
|
85
97
|
if ((len = foo.length) === bar.length) {
|
|
@@ -272,9 +284,24 @@ function copy(o) {
|
|
|
272
284
|
}
|
|
273
285
|
|
|
274
286
|
export function assoc(o, k, v, ...kvs) {
|
|
275
|
-
|
|
287
|
+
// only nil puns to an empty map; assoc on false throws, like CLJS
|
|
288
|
+
if (o == null) {
|
|
276
289
|
o = {};
|
|
277
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
|
+
}
|
|
278
305
|
const ret = copy(o);
|
|
279
306
|
assoc_BANG_(ret, k, v, ...kvs);
|
|
280
307
|
return ret;
|
|
@@ -283,6 +310,9 @@ export function assoc(o, k, v, ...kvs) {
|
|
|
283
310
|
// squint has no distinct hash-map or array-map type; both build a plain object.
|
|
284
311
|
export function hash_map(...kvs) {
|
|
285
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
|
+
}
|
|
286
316
|
return assoc({}, ...kvs);
|
|
287
317
|
}
|
|
288
318
|
|
|
@@ -444,6 +474,10 @@ export function conj_BANG_(...xs) {
|
|
|
444
474
|
if (n === 0) {
|
|
445
475
|
return vector();
|
|
446
476
|
}
|
|
477
|
+
// single arg: return the coll unchanged, including nil, like CLJS
|
|
478
|
+
if (n === 1) {
|
|
479
|
+
return xs[0];
|
|
480
|
+
}
|
|
447
481
|
|
|
448
482
|
let o = xs[0];
|
|
449
483
|
if (o === null || o === undefined) {
|
|
@@ -477,17 +511,14 @@ export function conj_BANG_(...xs) {
|
|
|
477
511
|
break;
|
|
478
512
|
case MAP_TYPE:
|
|
479
513
|
for (const x of rest) {
|
|
480
|
-
if (
|
|
481
|
-
|
|
482
|
-
o.set(kv[0], kv[1]);
|
|
483
|
-
});
|
|
484
|
-
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]);
|
|
485
516
|
}
|
|
486
517
|
break;
|
|
487
518
|
case OBJECT_TYPE:
|
|
488
519
|
for (const x of rest) {
|
|
489
|
-
if (
|
|
490
|
-
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];
|
|
491
522
|
}
|
|
492
523
|
break;
|
|
493
524
|
default:
|
|
@@ -499,6 +530,28 @@ export function conj_BANG_(...xs) {
|
|
|
499
530
|
return o;
|
|
500
531
|
}
|
|
501
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
|
+
|
|
502
555
|
export function conj(...xs) {
|
|
503
556
|
if (xs.length === 0) {
|
|
504
557
|
return vector();
|
|
@@ -530,11 +583,8 @@ export function conj(...xs) {
|
|
|
530
583
|
case MAP_TYPE:
|
|
531
584
|
m = new Map(o);
|
|
532
585
|
for (const x of rest) {
|
|
533
|
-
if (
|
|
534
|
-
|
|
535
|
-
m.set(kv[0], kv[1]);
|
|
536
|
-
});
|
|
537
|
-
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]);
|
|
538
588
|
}
|
|
539
589
|
|
|
540
590
|
return copyMeta(o, m);
|
|
@@ -547,8 +597,8 @@ export function conj(...xs) {
|
|
|
547
597
|
o2 = { ...o };
|
|
548
598
|
|
|
549
599
|
for (const x of rest) {
|
|
550
|
-
if (
|
|
551
|
-
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];
|
|
552
602
|
}
|
|
553
603
|
|
|
554
604
|
return copyMeta(o, o2);
|
|
@@ -570,7 +620,7 @@ export function disj(s, ...xs) {
|
|
|
570
620
|
if (s == null) return s;
|
|
571
621
|
// pass s itself (not a spread) so a SortedSet keeps its comparator
|
|
572
622
|
const s1 = new s.constructor(s);
|
|
573
|
-
return disj_BANG_(s1, ...xs);
|
|
623
|
+
return copyMeta(s, disj_BANG_(s1, ...xs));
|
|
574
624
|
}
|
|
575
625
|
|
|
576
626
|
export function contains_QMARK_(coll, v) {
|
|
@@ -599,7 +649,11 @@ export function dissoc_BANG_(m, ...ks) {
|
|
|
599
649
|
export function dissoc(m, ...ks) {
|
|
600
650
|
if (!m) return;
|
|
601
651
|
if (ks.length === 0) return m;
|
|
602
|
-
|
|
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) {
|
|
603
657
|
let present = false;
|
|
604
658
|
for (const k of ks) if (m.has(k)) { present = true; break; }
|
|
605
659
|
if (!present) return m;
|
|
@@ -641,6 +695,9 @@ export function pr(...xs) {
|
|
|
641
695
|
}
|
|
642
696
|
|
|
643
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
|
+
}
|
|
644
701
|
const hasDefault = arguments.length > 2;
|
|
645
702
|
// nil coll puns to nil, like Clojure
|
|
646
703
|
if (coll == null) return hasDefault ? orElse : null;
|
|
@@ -727,7 +784,8 @@ export function seqable_QMARK_(x) {
|
|
|
727
784
|
object_QMARK_(x) ||
|
|
728
785
|
// we used to check instanceof Object but this returns false for TC39 Records
|
|
729
786
|
// also we used to write `Symbol.iterator in` but this does not work for strings and some other types
|
|
730
|
-
!!x[Symbol.iterator]
|
|
787
|
+
!!x[Symbol.iterator] ||
|
|
788
|
+
!!x[ISEQABLE_SYM]
|
|
731
789
|
);
|
|
732
790
|
}
|
|
733
791
|
|
|
@@ -757,6 +815,8 @@ export function iterable(x) {
|
|
|
757
815
|
if (x[Symbol.iterator]) {
|
|
758
816
|
return x;
|
|
759
817
|
}
|
|
818
|
+
// a type extended to ISeqable seqs through its -seq method
|
|
819
|
+
if (x[ISeqable__seq] !== undefined) return iterable(x[ISeqable__seq](x));
|
|
760
820
|
if (x instanceof Object) return Object.entries(x).map(tagMapEntry);
|
|
761
821
|
throw new TypeError(`${x} is not iterable`);
|
|
762
822
|
}
|
|
@@ -773,6 +833,7 @@ export const es6_iterator = _iterator;
|
|
|
773
833
|
|
|
774
834
|
export function seq(x) {
|
|
775
835
|
if (x == null) return x;
|
|
836
|
+
if (!seqable_QMARK_(x)) throw new TypeError(x + ' is not ISeqable');
|
|
776
837
|
// a string seqs into its characters, like CLJS.
|
|
777
838
|
if (typeof x === 'string') return x.length ? [...x] : null;
|
|
778
839
|
const iter = iterable(x);
|
|
@@ -833,13 +894,13 @@ export function rest(coll) {
|
|
|
833
894
|
return cell._rest; // first chunk had one element; the next cell is the rest
|
|
834
895
|
}
|
|
835
896
|
|
|
897
|
+
const REDUCED_DEREF = (self) => self.value;
|
|
898
|
+
|
|
836
899
|
class Reduced {
|
|
837
900
|
value;
|
|
838
901
|
constructor(x) {
|
|
839
902
|
this.value = x;
|
|
840
|
-
|
|
841
|
-
_deref() {
|
|
842
|
-
return this.value;
|
|
903
|
+
this[IDeref__deref] = REDUCED_DEREF;
|
|
843
904
|
}
|
|
844
905
|
}
|
|
845
906
|
|
|
@@ -1128,6 +1189,8 @@ class Cons {
|
|
|
1128
1189
|
);
|
|
1129
1190
|
|
|
1130
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');
|
|
1131
1194
|
return new Cons(x, coll);
|
|
1132
1195
|
}
|
|
1133
1196
|
|
|
@@ -1291,48 +1354,167 @@ export function nil_QMARK_(v) {
|
|
|
1291
1354
|
|
|
1292
1355
|
export const PROTOCOL_SENTINEL = {};
|
|
1293
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
|
+
|
|
1294
1451
|
export class Atom {
|
|
1295
1452
|
constructor(init) {
|
|
1296
1453
|
this.val = init;
|
|
1297
1454
|
this._watches = {};
|
|
1298
|
-
this._deref = () => this.val;
|
|
1299
1455
|
this._hasWatches = false;
|
|
1300
|
-
this
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
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
|
+
);
|
|
1324
1491
|
}
|
|
1325
1492
|
|
|
1326
1493
|
export function deref(ref) {
|
|
1327
|
-
return ref
|
|
1494
|
+
if (ref?.[IDeref__deref] !== undefined) return ref[IDeref__deref](ref);
|
|
1495
|
+
return nilImpl(_deref, 'IDeref.-deref', ref)(ref);
|
|
1328
1496
|
}
|
|
1329
1497
|
|
|
1330
1498
|
export function reset_BANG_(atm, v) {
|
|
1331
|
-
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);
|
|
1332
1501
|
}
|
|
1333
1502
|
|
|
1334
1503
|
export function swap_BANG_(atm, f, ...args) {
|
|
1335
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
|
+
}
|
|
1336
1518
|
const v = f(deref(atm), ...args);
|
|
1337
1519
|
reset_BANG_(atm, v);
|
|
1338
1520
|
return v;
|
|
@@ -1342,19 +1524,19 @@ export function swap_vals_BANG_(atm, f, ...args) {
|
|
|
1342
1524
|
const oldv = deref(atm);
|
|
1343
1525
|
f = __toFn(f);
|
|
1344
1526
|
const newv = f(oldv, ...args);
|
|
1345
|
-
atm
|
|
1527
|
+
reset_BANG_(atm, newv);
|
|
1346
1528
|
return [oldv, newv];
|
|
1347
1529
|
}
|
|
1348
1530
|
|
|
1349
1531
|
export function reset_vals_BANG_(atm, newv) {
|
|
1350
1532
|
const oldv = deref(atm);
|
|
1351
|
-
atm
|
|
1533
|
+
reset_BANG_(atm, newv);
|
|
1352
1534
|
return [oldv, newv];
|
|
1353
1535
|
}
|
|
1354
1536
|
|
|
1355
1537
|
export function compare_and_set_BANG_(atm, oldv, newv) {
|
|
1356
1538
|
if (deref(atm) === oldv) {
|
|
1357
|
-
atm
|
|
1539
|
+
reset_BANG_(atm, newv);
|
|
1358
1540
|
return true;
|
|
1359
1541
|
} else {
|
|
1360
1542
|
return false;
|
|
@@ -1519,6 +1701,18 @@ export function set_QMARK_(x) {
|
|
|
1519
1701
|
return typeConst(x) === SET_TYPE;
|
|
1520
1702
|
}
|
|
1521
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
|
+
|
|
1522
1716
|
export function apply(f, ...args) {
|
|
1523
1717
|
f = __toFn(f);
|
|
1524
1718
|
const xs = args.slice(0, args.length - 1);
|
|
@@ -1697,9 +1891,10 @@ export function interpose(sep, coll) {
|
|
|
1697
1891
|
|
|
1698
1892
|
export function select_keys(o, ks) {
|
|
1699
1893
|
const type = typeConst(o);
|
|
1700
|
-
//
|
|
1701
|
-
const ret =
|
|
1702
|
-
|
|
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)) {
|
|
1703
1898
|
const v = get(o, k);
|
|
1704
1899
|
if (v !== undefined) {
|
|
1705
1900
|
assoc_BANG_(ret, k, v);
|
|
@@ -1906,6 +2101,9 @@ export function merge(...args) {
|
|
|
1906
2101
|
let obj;
|
|
1907
2102
|
if (firstArg === null || firstArg === undefined) {
|
|
1908
2103
|
obj = {};
|
|
2104
|
+
} else if (typeConst(firstArg) === undefined) {
|
|
2105
|
+
// a non-collection passes through; conj! throws when maps follow, like CLJS
|
|
2106
|
+
obj = firstArg;
|
|
1909
2107
|
} else {
|
|
1910
2108
|
obj = into(empty(firstArg), firstArg);
|
|
1911
2109
|
}
|
|
@@ -2023,7 +2221,15 @@ function take1(n) {
|
|
|
2023
2221
|
});
|
|
2024
2222
|
}
|
|
2025
2223
|
|
|
2224
|
+
function assertNumber(n) {
|
|
2225
|
+
if (typeof n !== 'number') {
|
|
2226
|
+
throw new Error('Assert failed: (number? n)');
|
|
2227
|
+
}
|
|
2228
|
+
return n;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2026
2231
|
export function take(n, coll) {
|
|
2232
|
+
assertNumber(n);
|
|
2027
2233
|
if (arguments.length === 1) {
|
|
2028
2234
|
return take1(n);
|
|
2029
2235
|
}
|
|
@@ -2041,6 +2247,7 @@ export function take(n, coll) {
|
|
|
2041
2247
|
}
|
|
2042
2248
|
|
|
2043
2249
|
export function take_last(n, coll) {
|
|
2250
|
+
assertNumber(n);
|
|
2044
2251
|
if (n <= 0) {
|
|
2045
2252
|
return null;
|
|
2046
2253
|
}
|
|
@@ -2113,8 +2320,18 @@ export function partial(f, ...xs) {
|
|
|
2113
2320
|
}
|
|
2114
2321
|
|
|
2115
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);
|
|
2116
2328
|
return lazy(function* () {
|
|
2117
|
-
|
|
2329
|
+
const cache = [];
|
|
2330
|
+
for (const x of it) {
|
|
2331
|
+
cache.push(x);
|
|
2332
|
+
yield x;
|
|
2333
|
+
}
|
|
2334
|
+
while (cache.length) yield* cache;
|
|
2118
2335
|
});
|
|
2119
2336
|
}
|
|
2120
2337
|
|
|
@@ -2126,6 +2343,7 @@ function drop1(n) {
|
|
|
2126
2343
|
}
|
|
2127
2344
|
|
|
2128
2345
|
export function drop(n, xs) {
|
|
2346
|
+
assertNumber(n);
|
|
2129
2347
|
if (arguments.length === 1) return drop1(n);
|
|
2130
2348
|
return lazyIter(xs, function* (iter) {
|
|
2131
2349
|
for (let x = 0; x < n; x++) {
|
|
@@ -2220,7 +2438,8 @@ export function update(coll, k, f, ...args) {
|
|
|
2220
2438
|
|
|
2221
2439
|
export function get_in(coll, path, orElse) {
|
|
2222
2440
|
let entry = coll;
|
|
2223
|
-
|
|
2441
|
+
// iterable puns a nil path to an empty path, like CLJS
|
|
2442
|
+
for (const item of iterable(path)) {
|
|
2224
2443
|
entry = get(entry, item);
|
|
2225
2444
|
}
|
|
2226
2445
|
if (entry === undefined) return orElse;
|
|
@@ -2285,6 +2504,18 @@ export function reverse(coll) {
|
|
|
2285
2504
|
return toArray(coll).reverse();
|
|
2286
2505
|
}
|
|
2287
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
|
+
|
|
2288
2519
|
export function sort(f, coll) {
|
|
2289
2520
|
if (arguments.length === 1) {
|
|
2290
2521
|
coll = f;
|
|
@@ -2571,8 +2802,10 @@ export function dorun(x) {
|
|
|
2571
2802
|
}
|
|
2572
2803
|
|
|
2573
2804
|
export function doall(x) {
|
|
2574
|
-
// realize
|
|
2575
|
-
|
|
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;
|
|
2576
2809
|
}
|
|
2577
2810
|
|
|
2578
2811
|
export function aclone(arr) {
|
|
@@ -2580,13 +2813,53 @@ export function aclone(arr) {
|
|
|
2580
2813
|
return cloned;
|
|
2581
2814
|
}
|
|
2582
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
|
+
|
|
2583
2848
|
export function add_watch(ref, key, fn) {
|
|
2584
|
-
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);
|
|
2585
2854
|
return ref;
|
|
2586
2855
|
}
|
|
2587
2856
|
|
|
2588
2857
|
export function remove_watch(ref, key) {
|
|
2589
|
-
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);
|
|
2590
2863
|
return ref;
|
|
2591
2864
|
}
|
|
2592
2865
|
|
|
@@ -2639,15 +2912,15 @@ export function every_pred(...preds) {
|
|
|
2639
2912
|
|
|
2640
2913
|
export function some_fn(...fns) {
|
|
2641
2914
|
return (...args) => {
|
|
2915
|
+
let res;
|
|
2642
2916
|
for (const f of fns) {
|
|
2643
2917
|
for (const a of args) {
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
}
|
|
2918
|
+
res = f(a);
|
|
2919
|
+
// truth_, not JS truthiness: 0 and "" are truthy in CLJS
|
|
2920
|
+
if (truth_(res)) return res;
|
|
2648
2921
|
}
|
|
2649
2922
|
}
|
|
2650
|
-
return
|
|
2923
|
+
return res;
|
|
2651
2924
|
};
|
|
2652
2925
|
}
|
|
2653
2926
|
|
|
@@ -2791,7 +3064,8 @@ export function re_seq(re, s) {
|
|
|
2791
3064
|
}
|
|
2792
3065
|
|
|
2793
3066
|
export function NaN_QMARK_(x) {
|
|
2794
|
-
|
|
3067
|
+
// coercing, like CLJS js/isNaN: (NaN? "foo") is true
|
|
3068
|
+
return isNaN(x);
|
|
2795
3069
|
}
|
|
2796
3070
|
|
|
2797
3071
|
export function number_QMARK_(x) {
|
|
@@ -2799,7 +3073,7 @@ export function number_QMARK_(x) {
|
|
|
2799
3073
|
}
|
|
2800
3074
|
|
|
2801
3075
|
export function keys(obj) {
|
|
2802
|
-
if (obj == null) return;
|
|
3076
|
+
if (obj == null) return null;
|
|
2803
3077
|
const t = typeConst(obj);
|
|
2804
3078
|
switch (t) {
|
|
2805
3079
|
case OBJECT_TYPE: {
|
|
@@ -2811,6 +3085,11 @@ export function keys(obj) {
|
|
|
2811
3085
|
if (obj.size) return Array.from(obj.keys());
|
|
2812
3086
|
return;
|
|
2813
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;
|
|
2814
3093
|
}
|
|
2815
3094
|
|
|
2816
3095
|
export function js_keys(obj) {
|
|
@@ -2818,7 +3097,7 @@ export function js_keys(obj) {
|
|
|
2818
3097
|
}
|
|
2819
3098
|
|
|
2820
3099
|
export function vals(obj) {
|
|
2821
|
-
if (obj == null) return;
|
|
3100
|
+
if (obj == null) return null;
|
|
2822
3101
|
const t = typeConst(obj);
|
|
2823
3102
|
switch (t) {
|
|
2824
3103
|
case OBJECT_TYPE: {
|
|
@@ -2830,6 +3109,11 @@ export function vals(obj) {
|
|
|
2830
3109
|
if (obj.size) return Array.from(obj.values());
|
|
2831
3110
|
return;
|
|
2832
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;
|
|
2833
3117
|
}
|
|
2834
3118
|
|
|
2835
3119
|
export function string_QMARK_(s) {
|
|
@@ -3024,34 +3308,22 @@ export function mod(x, y) {
|
|
|
3024
3308
|
}
|
|
3025
3309
|
|
|
3026
3310
|
export function min_key(k, x, ...more) {
|
|
3027
|
-
|
|
3028
|
-
|
|
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;
|
|
3029
3316
|
}
|
|
3030
|
-
var kx = k(x);
|
|
3031
|
-
var min = x;
|
|
3032
|
-
more.forEach((y) => {
|
|
3033
|
-
var ky = k(y);
|
|
3034
|
-
if (ky <= kx) {
|
|
3035
|
-
kx = ky;
|
|
3036
|
-
min = y;
|
|
3037
|
-
}
|
|
3038
|
-
});
|
|
3039
3317
|
return min;
|
|
3040
3318
|
}
|
|
3041
3319
|
|
|
3042
3320
|
export function max_key(k, x, ...more) {
|
|
3043
|
-
|
|
3044
|
-
|
|
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;
|
|
3045
3326
|
}
|
|
3046
|
-
var kx = k(x);
|
|
3047
|
-
var max = x;
|
|
3048
|
-
more.forEach((y) => {
|
|
3049
|
-
var ky = k(y);
|
|
3050
|
-
if (ky >= kx) {
|
|
3051
|
-
kx = ky;
|
|
3052
|
-
max = y;
|
|
3053
|
-
}
|
|
3054
|
-
});
|
|
3055
3327
|
return max;
|
|
3056
3328
|
}
|
|
3057
3329
|
|
|
@@ -3465,6 +3737,7 @@ export function memoize(f) {
|
|
|
3465
3737
|
}
|
|
3466
3738
|
|
|
3467
3739
|
export function peek(vec) {
|
|
3740
|
+
if (vec == null) return null;
|
|
3468
3741
|
// A list peeks at its front; squint lists are array-backed, so check list
|
|
3469
3742
|
// before array to avoid returning the last element.
|
|
3470
3743
|
if (list_QMARK_(vec)) {
|
|
@@ -3472,7 +3745,7 @@ export function peek(vec) {
|
|
|
3472
3745
|
} else if (array_QMARK_(vec)) {
|
|
3473
3746
|
return vec[vec.length - 1];
|
|
3474
3747
|
} else {
|
|
3475
|
-
|
|
3748
|
+
throw missing_protocol('IStack.-peek', vec);
|
|
3476
3749
|
}
|
|
3477
3750
|
}
|
|
3478
3751
|
|
|
@@ -3487,7 +3760,7 @@ export function pop(vec) {
|
|
|
3487
3760
|
ret.pop();
|
|
3488
3761
|
return ret;
|
|
3489
3762
|
} else {
|
|
3490
|
-
|
|
3763
|
+
throw missing_protocol('IStack.-pop', vec);
|
|
3491
3764
|
}
|
|
3492
3765
|
}
|
|
3493
3766
|
|
|
@@ -3518,7 +3791,7 @@ export function update_vals(m, f) {
|
|
|
3518
3791
|
}
|
|
3519
3792
|
|
|
3520
3793
|
export function random_uuid() {
|
|
3521
|
-
return crypto.randomUUID();
|
|
3794
|
+
return new UUID(crypto.randomUUID());
|
|
3522
3795
|
}
|
|
3523
3796
|
|
|
3524
3797
|
export class UUID {
|
|
@@ -3531,20 +3804,34 @@ export class UUID {
|
|
|
3531
3804
|
}
|
|
3532
3805
|
|
|
3533
3806
|
export function uuid(s) {
|
|
3534
|
-
|
|
3807
|
+
// lowercased, like CLJS
|
|
3808
|
+
return new UUID(s.toLowerCase());
|
|
3535
3809
|
}
|
|
3536
3810
|
|
|
3537
3811
|
export function uuid_QMARK_(x) {
|
|
3538
3812
|
return x instanceof UUID;
|
|
3539
3813
|
}
|
|
3540
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
|
+
|
|
3541
3824
|
export function inst_QMARK_(x) {
|
|
3542
3825
|
return x instanceof Date;
|
|
3543
3826
|
}
|
|
3544
3827
|
|
|
3828
|
+
const DELAY_DEREF = (self) => self._deref();
|
|
3829
|
+
|
|
3545
3830
|
export class Delay {
|
|
3546
3831
|
constructor(f) {
|
|
3547
3832
|
this.f = f;
|
|
3833
|
+
this[IDEREF_SYM] = true;
|
|
3834
|
+
this[IDeref__deref] = DELAY_DEREF;
|
|
3548
3835
|
}
|
|
3549
3836
|
_deref() {
|
|
3550
3837
|
if (this.realized) {
|
|
@@ -3564,6 +3851,10 @@ export function realized_QMARK_(x) {
|
|
|
3564
3851
|
throw new Error('realized? not supported on: ' + str(x));
|
|
3565
3852
|
}
|
|
3566
3853
|
|
|
3854
|
+
export function force(x) {
|
|
3855
|
+
return x instanceof Delay ? x._deref() : x;
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3567
3858
|
function clj__GT_js_(x, seen) {
|
|
3568
3859
|
// we need to protect against circular objects
|
|
3569
3860
|
if (seen.has(x)) return x;
|
|
@@ -3591,12 +3882,12 @@ export function not_EQ_(...more) {
|
|
|
3591
3882
|
return not(_EQ_(...more));
|
|
3592
3883
|
}
|
|
3593
3884
|
|
|
3885
|
+
const VOLATILE_DEREF = (self) => self.v;
|
|
3886
|
+
|
|
3594
3887
|
class Volatile {
|
|
3595
3888
|
constructor(v) {
|
|
3596
3889
|
this.v = v;
|
|
3597
|
-
|
|
3598
|
-
_deref() {
|
|
3599
|
-
return this.v;
|
|
3890
|
+
this[IDeref__deref] = VOLATILE_DEREF;
|
|
3600
3891
|
}
|
|
3601
3892
|
}
|
|
3602
3893
|
|