squint-cljs 0.14.201 → 0.14.203

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.
@@ -5,9 +5,19 @@
5
5
  // (e.g. multi.js). Signature and semantics may change without notice.
6
6
  export function __toFn(x) {
7
7
  if (x == null || typeof x === 'function') return x;
8
- const t = typeof x;
9
- if (t === 'string') return (coll, d) => get(coll, x, d);
10
- if (t === 'object') return (k, d) => get(x, k, d);
8
+ if (typeof x === 'string') return (coll, d) => get(coll, x, d);
9
+ // a value is callable as a lookup only if it is a collection or a custom
10
+ // type implementing ILookup; a seq, list or opaque object throws when
11
+ // called, like a non-IFn in CLJS
12
+ switch (typeConst(x)) {
13
+ case MAP_TYPE:
14
+ case ARRAY_TYPE:
15
+ case OBJECT_TYPE:
16
+ case SET_TYPE:
17
+ return (k, d) => get(x, k, d);
18
+ case INSTANCE_TYPE:
19
+ if (x[ILookup__lookup] !== undefined) return (k, d) => get(x, k, d);
20
+ }
11
21
  return x;
12
22
  }
13
23
 
@@ -51,6 +61,12 @@ function dequal(foo, bar) {
51
61
  if (foo === bar) return true;
52
62
  // null and undefined are both nil in CLJS, so they compare equal
53
63
  if (foo == null) return bar == null;
64
+ if (bar == null) return false;
65
+ // -equiv dispatches on the left argument, like CLJS =
66
+ if (typeof foo === 'object' && foo[IEquiv__equiv] !== undefined) return !!foo[IEquiv__equiv](foo, bar);
67
+ // when only the right side has -equiv (the left is e.g. a plain object),
68
+ // dispatch on it so = stays symmetric
69
+ if (typeof bar === 'object' && bar[IEquiv__equiv] !== undefined) return !!bar[IEquiv__equiv](bar, foo);
54
70
  var ctor, len, tmp;
55
71
 
56
72
  // A sorted map compares by entries against any map type (object, Map, sorted).
@@ -193,6 +209,13 @@ export function _(...xs) {
193
209
  return xs.reduce((x, y) => x - y);
194
210
  }
195
211
 
212
+ export function _SLASH_(...xs) {
213
+ if (xs.length === 1) {
214
+ return 1 / xs[0];
215
+ }
216
+ return xs.reduce((x, y) => x / y);
217
+ }
218
+
196
219
  export const __protocol_satisfies = {};
197
220
 
198
221
  export function satisfies_QMARK_(protocol, x) {
@@ -219,12 +242,28 @@ function getAssocMut(m) {
219
242
  return mapAssocMut;
220
243
  case ARRAY_TYPE:
221
244
  case OBJECT_TYPE:
245
+ case INSTANCE_TYPE:
222
246
  return objAssocMut;
223
247
  }
224
248
  }
225
249
 
250
+ function validateArrayKeys(o, k, kvs) {
251
+ // like CLJS: a vector key is an index in [0, count], count appends
252
+ let len = o.length;
253
+ for (let i = 0; i < kvs.length + 2; i += 2) {
254
+ const key = i === 0 ? k : kvs[i - 2];
255
+ if (!Number.isInteger(key)) {
256
+ throw new Error("Vector's key for assoc must be a number.");
257
+ }
258
+ if (key < 0 || key > len) {
259
+ throw new Error(`Index ${key} out of bounds [0,${len}]`);
260
+ }
261
+ if (key === len) len++;
262
+ }
263
+ }
264
+
226
265
  export function assoc_BANG_(m, k, v, ...kvs) {
227
- if (kvs.length % 2 !== 0) {
266
+ if (arguments.length < 3 || kvs.length % 2 !== 0) {
228
267
  throw new Error('Illegal argument: assoc expects an odd number of arguments.');
229
268
  }
230
269
  switch (typeConst(m)) {
@@ -236,6 +275,24 @@ export function assoc_BANG_(m, k, v, ...kvs) {
236
275
  }
237
276
  break;
238
277
  case ARRAY_TYPE:
278
+ validateArrayKeys(m, k, kvs);
279
+ m[k] = v;
280
+
281
+ for (let i = 0; i < kvs.length; i += 2) {
282
+ m[kvs[i]] = kvs[i + 1];
283
+ }
284
+ break;
285
+ case INSTANCE_TYPE:
286
+ if (m[ITransientAssociative__assoc_BANG_] !== undefined) {
287
+ // re-read the slot off the current value: an -assoc! impl may return a
288
+ // different handle
289
+ let ret = m[ITransientAssociative__assoc_BANG_](m, k, v);
290
+ for (let i = 0; i < kvs.length; i += 2) {
291
+ ret = ret[ITransientAssociative__assoc_BANG_](ret, kvs[i], kvs[i + 1]);
292
+ }
293
+ return ret;
294
+ }
295
+ // fall through: an instance without -assoc! keeps the object behavior
239
296
  case OBJECT_TYPE:
240
297
  m[k] = v;
241
298
 
@@ -252,16 +309,14 @@ export function assoc_BANG_(m, k, v, ...kvs) {
252
309
  return m;
253
310
  }
254
311
 
255
- const _metaSym = Symbol('meta');
256
-
257
- // Copies metadata from `from` onto `to` (when present) and returns `to`. Used
258
- // to make value-producing operations (copy, empty, conj, into) carry metadata
259
- // like Clojure does, instead of dropping it on the freshly built structure.
260
- // Kept branch-light for the hot path: reads an absent symbol property (cheap,
261
- // no hidden-class change) and only writes when metadata is actually present.
312
+ // value-producing ops (copy, empty, conj, into) carry metadata by
313
+ // forwarding the instance-level meta slots onto the fresh structure
262
314
  function copyMeta(from, to) {
263
- const m = from?.[_metaSym];
264
- if (m !== undefined) to[_metaSym] = m;
315
+ const f = from?.[IMeta__meta];
316
+ if (f !== undefined) {
317
+ to[IMeta__meta] = f;
318
+ to[IWithMeta__with_meta] = from[IWithMeta__with_meta];
319
+ }
265
320
  return to;
266
321
  }
267
322
 
@@ -274,6 +329,7 @@ function copy(o) {
274
329
  return copyMeta(o, new o.constructor(o));
275
330
  case ARRAY_TYPE:
276
331
  return copyMeta(o, [...o]);
332
+ case INSTANCE_TYPE:
277
333
  case OBJECT_TYPE:
278
334
  return copyMeta(o, { ...o });
279
335
  case LIST_TYPE:
@@ -284,23 +340,19 @@ function copy(o) {
284
340
  }
285
341
 
286
342
  export function assoc(o, k, v, ...kvs) {
343
+ if (arguments.length < 3 || kvs.length % 2 !== 0) {
344
+ throw new Error('Illegal argument: assoc expects an odd number of arguments.');
345
+ }
287
346
  // only nil puns to an empty map; assoc on false throws, like CLJS
288
347
  if (o == null) {
289
348
  o = {};
290
349
  }
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++;
350
+ if (o[IAssociative__assoc] !== undefined) {
351
+ let ret = o[IAssociative__assoc](o, k, v);
352
+ for (let i = 0; i < kvs.length; i += 2) {
353
+ ret = ret[IAssociative__assoc](ret, kvs[i], kvs[i + 1]);
303
354
  }
355
+ return ret;
304
356
  }
305
357
  const ret = copy(o);
306
358
  assoc_BANG_(ret, k, v, ...kvs);
@@ -324,6 +376,9 @@ const OBJECT_TYPE = 3;
324
376
  const LIST_TYPE = 4;
325
377
  const SET_TYPE = 5;
326
378
  const LAZY_ITERABLE_TYPE = 6;
379
+ // a class instance or null-prototype object: the extension point for the
380
+ // map-facing protocols. Plain objects keep the OBJECT_TYPE fast path.
381
+ const INSTANCE_TYPE = 7;
327
382
 
328
383
  // type tag set in each collection ctor, read by typeConst (DCE: no instanceof).
329
384
  const TYPE_TAG = Symbol('squint.lang.type');
@@ -387,7 +442,7 @@ function typeConst(obj) {
387
442
  if (tag !== undefined) return tag;
388
443
  if (isVectorArray(obj)) return ARRAY_TYPE;
389
444
  // any remaining object (class instance, null-proto) is associative
390
- if (typeof obj === 'object') return OBJECT_TYPE;
445
+ if (typeof obj === 'object') return INSTANCE_TYPE;
391
446
 
392
447
  return undefined;
393
448
  }
@@ -396,7 +451,7 @@ function assoc_in_with(f, fname, o, keys, value) {
396
451
  keys = vec(keys);
397
452
  o = o || {}; // default nil behavior is JS object
398
453
  const baseType = typeConst(o);
399
- if (baseType !== MAP_TYPE && baseType !== ARRAY_TYPE && baseType !== OBJECT_TYPE)
454
+ if (baseType !== MAP_TYPE && baseType !== ARRAY_TYPE && baseType !== OBJECT_TYPE && baseType !== INSTANCE_TYPE)
400
455
  throw new Error(
401
456
  `Illegal argument: ${fname} expects the first argument to be a Map, Array, or Object.`
402
457
  );
@@ -408,9 +463,12 @@ function assoc_in_with(f, fname, o, keys, value) {
408
463
  const k = keys[i];
409
464
  let chainValue;
410
465
  if (lastInChain instanceof Map) chainValue = lastInChain.get(k);
411
- else chainValue = lastInChain[k];
466
+ else if (lastInChain != null && lastInChain[ILookup__lookup] !== undefined) {
467
+ chainValue = lastInChain[ILookup__lookup](lastInChain, k, undefined);
468
+ } else chainValue = lastInChain[k];
412
469
  if (!chainValue) {
413
- chainValue = emptyOfType(baseType);
470
+ // an instance root has no empty-of-type: missing levels become plain maps
471
+ chainValue = emptyOfType(baseType) ?? {};
414
472
  }
415
473
  chain.push(chainValue);
416
474
  lastInChain = chainValue;
@@ -515,6 +573,14 @@ export function conj_BANG_(...xs) {
515
573
  else for (const kv of mapEntriesOf(x)) o.set(kv[0], kv[1]);
516
574
  }
517
575
  break;
576
+ case INSTANCE_TYPE:
577
+ if (o[ITransientCollection__conj_BANG_] !== undefined) {
578
+ // re-dispatch per element: a -conj! impl may return a different handle
579
+ let acc = o[ITransientCollection__conj_BANG_](o, rest[0]);
580
+ for (let i = 1; i < rest.length; i++) acc = conj_BANG_(acc, rest[i]);
581
+ return acc;
582
+ }
583
+ // fall through: an instance without -conj! keeps the object behavior
518
584
  case OBJECT_TYPE:
519
585
  for (const x of rest) {
520
586
  if (isVectorArray(x)) { asMapEntry(x); o[x[0]] = x[1]; }
@@ -593,6 +659,14 @@ export function conj(...xs) {
593
659
  yield* rest;
594
660
  yield* o;
595
661
  });
662
+ case INSTANCE_TYPE:
663
+ if (o[ICollection__conj] !== undefined) {
664
+ // re-dispatch per element: a -conj impl may return a different type
665
+ o2 = o[ICollection__conj](o, rest[0]);
666
+ for (let i = 1; i < rest.length; i++) o2 = conj(o2, rest[i]);
667
+ return o2;
668
+ }
669
+ // fall through: an instance without -conj keeps the object behavior
596
670
  case OBJECT_TYPE:
597
671
  o2 = { ...o };
598
672
 
@@ -610,6 +684,13 @@ export function conj(...xs) {
610
684
  }
611
685
 
612
686
  export function disj_BANG_(s, ...xs) {
687
+ if (s != null && s[ITransientSet__disjoin_BANG_] !== undefined) {
688
+ let ret = s;
689
+ for (const x of xs) {
690
+ ret = ret != null && ret[ITransientSet__disjoin_BANG_] !== undefined ? ret[ITransientSet__disjoin_BANG_](ret, x) : disj_BANG_(ret, x);
691
+ }
692
+ return ret;
693
+ }
613
694
  for (const x of xs) {
614
695
  s.delete(x);
615
696
  }
@@ -618,6 +699,12 @@ export function disj_BANG_(s, ...xs) {
618
699
 
619
700
  export function disj(s, ...xs) {
620
701
  if (s == null) return s;
702
+ if (xs.length === 0) return s;
703
+ if (s[ISet__disjoin] !== undefined) {
704
+ let ret = s[ISet__disjoin](s, xs[0]);
705
+ for (let i = 1; i < xs.length; i++) ret = disj(ret, xs[i]);
706
+ return ret;
707
+ }
621
708
  // pass s itself (not a spread) so a SortedSet keeps its comparator
622
709
  const s1 = new s.constructor(s);
623
710
  return copyMeta(s, disj_BANG_(s1, ...xs));
@@ -633,12 +720,22 @@ export function contains_QMARK_(coll, v) {
633
720
  return coll.has(v);
634
721
  case undefined:
635
722
  return false;
723
+ case INSTANCE_TYPE:
724
+ if (coll[IAssociative__contains_key_QMARK_] !== undefined) {
725
+ return coll[IAssociative__contains_key_QMARK_](coll, v);
726
+ }
727
+ // fall through
636
728
  default:
637
729
  return v in coll;
638
730
  }
639
731
  }
640
732
 
641
733
  export function dissoc_BANG_(m, ...ks) {
734
+ if (m != null && m[ITransientMap__dissoc_BANG_] !== undefined) {
735
+ let ret = m;
736
+ for (const k of ks) ret = ret != null && ret[ITransientMap__dissoc_BANG_] !== undefined ? ret[ITransientMap__dissoc_BANG_](ret, k) : dissoc_BANG_(ret, k);
737
+ return ret;
738
+ }
642
739
  for (const k of ks) {
643
740
  delete m[k];
644
741
  }
@@ -650,9 +747,18 @@ export function dissoc(m, ...ks) {
650
747
  if (!m) return;
651
748
  if (ks.length === 0) return m;
652
749
  const tc = typeConst(m);
653
- if (tc !== MAP_TYPE && tc !== OBJECT_TYPE) {
750
+ if (tc !== MAP_TYPE && tc !== OBJECT_TYPE && tc !== INSTANCE_TYPE) {
654
751
  throw new Error('dissoc expects a map, got: ' + typeof m);
655
752
  }
753
+ if (tc === INSTANCE_TYPE && m[IMap__dissoc] !== undefined) {
754
+ let ret = m;
755
+ // re-dispatch per key: a -dissoc impl may return a different type
756
+ for (const k of ks) {
757
+ if (ret == null) return ret;
758
+ ret = ret[IMap__dissoc] !== undefined ? ret[IMap__dissoc](ret, k) : dissoc(ret, k);
759
+ }
760
+ return ret;
761
+ }
656
762
  if (tc === MAP_TYPE) {
657
763
  let present = false;
658
764
  for (const k of ks) if (m.has(k)) { present = true; break; }
@@ -690,6 +796,14 @@ export function println(...args) {
690
796
  if (_STAR_print_newline_STAR_.val) _STAR_print_fn_STAR_.val('\n');
691
797
  }
692
798
 
799
+ export function print_str(...args) {
800
+ return args.map((v) => toEDN(v, undefined, false)).join(' ');
801
+ }
802
+
803
+ export function println_str(...args) {
804
+ return print_str(...args) + '\n';
805
+ }
806
+
693
807
  export function pr(...xs) {
694
808
  _STAR_print_fn_STAR_.val(pr_str(...xs));
695
809
  }
@@ -707,6 +821,8 @@ export function nth(coll, idx, orElse) {
707
821
  if (idx >= 0 && idx < coll.length) {
708
822
  return coll[idx];
709
823
  }
824
+ } else if (coll[IIndexed__nth] !== undefined) {
825
+ return hasDefault ? coll[IIndexed__nth](coll, idx, orElse) : coll[IIndexed__nth](coll, idx);
710
826
  } else if (idx >= 0) {
711
827
  // non-array: skip whole chunks instead of counting elements (handles
712
828
  // infinite seqs since it stops once idx is reached)
@@ -749,6 +865,10 @@ export function get(coll, key, otherwise = undefined) {
749
865
  v = coll[key];
750
866
  break;
751
867
  default:
868
+ if (coll[ILookup__lookup] !== undefined) {
869
+ v = coll[ILookup__lookup](coll, key, otherwise);
870
+ return v === undefined ? otherwise : v;
871
+ }
752
872
  // we choose .get as the default implementation, e.g. fetch Headers are not Maps, but do implement a .get method
753
873
  g = coll['get'];
754
874
  if (typeof g === 'function') {
@@ -772,7 +892,7 @@ export function seq_QMARK_(x) {
772
892
  export function sequential_QMARK_(x) {
773
893
  // vectors and lists are arrays; lazy seqs and cons carry the lazy brand.
774
894
  // Sets, maps and strings are iterable but not sequential.
775
- return Array.isArray(x) || x?.[TYPE_TAG] === LAZY_ITERABLE_TYPE;
895
+ return Array.isArray(x) || x?.[TYPE_TAG] === LAZY_ITERABLE_TYPE || (x != null && x[IVector.__sym] !== undefined);
776
896
  }
777
897
 
778
898
  export function seqable_QMARK_(x) {
@@ -817,7 +937,10 @@ export function iterable(x) {
817
937
  }
818
938
  // a type extended to ISeqable seqs through its -seq method
819
939
  if (x[ISeqable__seq] !== undefined) return iterable(x[ISeqable__seq](x));
820
- if (x instanceof Object) return Object.entries(x).map(tagMapEntry);
940
+ // only a plain object is a squint map; a class instance without a native
941
+ // iterator or ISeqable is not iterable, matching seqable? and CLJS, and
942
+ // never leaks its internal fields
943
+ if (isObj(x)) return Object.entries(x).map(tagMapEntry);
821
944
  throw new TypeError(`${x} is not iterable`);
822
945
  }
823
946
 
@@ -841,10 +964,19 @@ export function seq(x) {
841
964
  if (iter.length === 0 || iter.size === 0) {
842
965
  return null;
843
966
  }
844
- // a set is iterable but not sequential; materialize its elements.
967
+ // a set or map is iterable but not a sequence; materialize its entries
968
+ // into a distinct seq so the result is not itself a set or map, like CLJS
845
969
  if (iter instanceof Set || iter[TYPE_TAG] === SET_TYPE) {
846
970
  return [...iter];
847
971
  }
972
+ if (iter instanceof Map || iter[TYPE_TAG] === MAP_TYPE) {
973
+ return [...iter].map(tagMapEntry);
974
+ }
975
+ // an instance with -dissoc is a map rep: same distinct entry seq
976
+ if (iter[IMap__dissoc] !== undefined) {
977
+ const entries = [...iter].map(tagMapEntry);
978
+ return entries.length === 0 ? null : entries;
979
+ }
848
980
  const _i = iter[Symbol.iterator]();
849
981
  if (_i.next().done) return null;
850
982
  return iter;
@@ -877,6 +1009,14 @@ export function ffirst(coll) {
877
1009
  return first(first(coll));
878
1010
  }
879
1011
 
1012
+ export function fnext(coll) {
1013
+ return first(next(coll));
1014
+ }
1015
+
1016
+ export function nfirst(coll) {
1017
+ return next(first(coll));
1018
+ }
1019
+
880
1020
  export function rest(coll) {
881
1021
  // chunk-aware: drop the first element of the first chunk, keep the rest of
882
1022
  // the chain chunked (preserves chunkedness, unlike re-iterating element-wise)
@@ -1274,6 +1414,13 @@ export function filterv(pred, coll) {
1274
1414
  return pushAll([], filter(pred, coll));
1275
1415
  }
1276
1416
 
1417
+ export function random_sample(prob, coll) {
1418
+ if (arguments.length === 1) {
1419
+ return filter((_) => rand() < prob);
1420
+ }
1421
+ return filter((_) => rand() < prob, coll);
1422
+ }
1423
+
1277
1424
  export function remove(pred, coll) {
1278
1425
  if (arguments.length === 1) {
1279
1426
  return filter1(complement(pred));
@@ -1371,10 +1518,326 @@ export function _deref(o) {
1371
1518
  }
1372
1519
  export const ISeqable = { __sym: ISEQABLE_SYM };
1373
1520
  export const ISeqable__seq = Symbol('ISeqable_-seq');
1521
+
1522
+ // map-facing protocols. Each dispatches through its slot in the extension
1523
+ // path (INSTANCE_TYPE) of the corresponding core fn, so plain objects and
1524
+ // arrays never pay for them. Slot symbols are separate consts so a bundle
1525
+ // using only e.g. conj pulls one symbol, not the whole protocol set.
1526
+ export const ILookup = { __sym: Symbol('squint.core.ILookup') };
1527
+ export const ILookup__lookup = Symbol('ILookup_-lookup');
1528
+ export const IAssociative = { __sym: Symbol('squint.core.IAssociative') };
1529
+ export const IAssociative__assoc = Symbol('IAssociative_-assoc');
1530
+ export const IAssociative__contains_key_QMARK_ = Symbol('IAssociative_-contains-key?');
1531
+ export const IMap = { __sym: Symbol('squint.core.IMap') };
1532
+ export const IMap__dissoc = Symbol('IMap_-dissoc');
1533
+ export const ICounted = { __sym: Symbol('squint.core.ICounted') };
1534
+ export const ICounted__count = Symbol('ICounted_-count');
1535
+ export const IKVReduce = { __sym: Symbol('squint.core.IKVReduce') };
1536
+ export const IKVReduce__kv_reduce = Symbol('IKVReduce_-kv-reduce');
1537
+ export const ICollection = { __sym: Symbol('squint.core.ICollection') };
1538
+ export const ICollection__conj = Symbol('ICollection_-conj');
1539
+ export const IEmptyableCollection = { __sym: Symbol('squint.core.IEmptyableCollection') };
1540
+ export const IEmptyableCollection__empty = Symbol('IEmptyableCollection_-empty');
1541
+ export const IEquiv = { __sym: Symbol('squint.core.IEquiv') };
1542
+ export const IEquiv__equiv = Symbol('IEquiv_-equiv');
1543
+ // set and transient protocols, same extension-path dispatch as the map-facing
1544
+ // protocols above
1545
+ export const ISet = { __sym: Symbol('squint.core.ISet') };
1546
+ export const ISet__disjoin = Symbol('ISet_-disjoin');
1547
+ export const IEditableCollection = { __sym: Symbol('squint.core.IEditableCollection') };
1548
+ export const IEditableCollection__as_transient = Symbol('IEditableCollection_-as-transient');
1549
+ export const ITransientCollection = { __sym: Symbol('squint.core.ITransientCollection') };
1550
+ export const ITransientCollection__conj_BANG_ = Symbol('ITransientCollection_-conj!');
1551
+ export const ITransientCollection__persistent_BANG_ = Symbol('ITransientCollection_-persistent!');
1552
+ export const ITransientAssociative = { __sym: Symbol('squint.core.ITransientAssociative') };
1553
+ export const ITransientAssociative__assoc_BANG_ = Symbol('ITransientAssociative_-assoc!');
1554
+ export const ITransientMap = { __sym: Symbol('squint.core.ITransientMap') };
1555
+ export const ITransientMap__dissoc_BANG_ = Symbol('ITransientMap_-dissoc!');
1556
+ export const ITransientSet = { __sym: Symbol('squint.core.ITransientSet') };
1557
+ export const ITransientSet__disjoin_BANG_ = Symbol('ITransientSet_-disjoin!');
1558
+ // metadata protocols, like CLJS: types implement the slots, plain values
1559
+ // get instance-level impls installed by with-meta
1560
+ export const IMeta = { __sym: Symbol('squint.core.IMeta') };
1561
+ export const IMeta__meta = Symbol('IMeta_-meta');
1562
+ export const IWithMeta = { __sym: Symbol('squint.core.IWithMeta') };
1563
+ export const IWithMeta__with_meta = Symbol('IWithMeta_-with-meta');
1564
+ // hashing (Murmur3, like CLJS). The contract: (= a b) implies (hash a) ===
1565
+ // (hash b), where = is dequal. None of this is referenced by =, so bundles
1566
+ // that only compare pay nothing.
1567
+ // Ported from ClojureScript (cljs/core.cljs), Copyright (c) Rich Hickey and
1568
+ // contributors, Eclipse Public License 1.0. MurmurHash3 by Austin Appleby
1569
+ // (public domain).
1570
+
1571
+ // IHash: a custom type opts into value hashing
1572
+ export const IHash = { __sym: Symbol('squint.core.IHash') };
1573
+ export const IHash__hash = Symbol('IHash_-hash');
1574
+
1575
+ // the equality hashed collections key by: identical or -equiv, never a
1576
+ // deep compare like =
1577
+ export function equiv(x, y) {
1578
+ if (x === y) return true;
1579
+ if (x == null) return y == null;
1580
+ if (y == null) return false;
1581
+ if (x[IEquiv__equiv] !== undefined) return !!x[IEquiv__equiv](x, y);
1582
+ if (y[IEquiv__equiv] !== undefined) return !!y[IEquiv__equiv](y, x);
1583
+ if (x instanceof Date && y instanceof Date) return x.getTime() === y.getTime();
1584
+ return false;
1585
+ }
1586
+
1587
+ // identity uid for reference-keyed values, like CLJS goog/getUid
1588
+ const UIDS = /* @__PURE__ */ new WeakMap();
1589
+ let uidCounter = 0;
1590
+
1591
+ function uid(o) {
1592
+ let id = UIDS.get(o);
1593
+ if (id === undefined) {
1594
+ id = ++uidCounter;
1595
+ UIDS.set(o, id);
1596
+ }
1597
+ return id;
1598
+ }
1599
+
1600
+ const imul = Math.imul;
1601
+ const M3_C1 = 0xcc9e2d51 | 0;
1602
+ const M3_C2 = 0x1b873593 | 0;
1603
+
1604
+ function rotl(x, n) {
1605
+ return (x << n) | (x >>> (32 - n));
1606
+ }
1607
+
1608
+ function m3MixK1(k1) {
1609
+ return imul(rotl(imul(k1 | 0, M3_C1), 15), M3_C2);
1610
+ }
1611
+
1612
+ function m3MixH1(h1, k1) {
1613
+ return (imul(rotl((h1 | 0) ^ (k1 | 0), 13), 5) + (0xe6546b64 | 0)) | 0;
1614
+ }
1615
+
1616
+ function m3Fmix(h1, len) {
1617
+ h1 = (h1 ^ len) | 0;
1618
+ h1 = (h1 ^ (h1 >>> 16)) | 0;
1619
+ h1 = imul(h1, 0x85ebca6b | 0);
1620
+ h1 = (h1 ^ (h1 >>> 13)) | 0;
1621
+ h1 = imul(h1, 0xc2b2ae35 | 0);
1622
+ return (h1 ^ (h1 >>> 16)) | 0;
1623
+ }
1624
+
1625
+ function m3HashInt(x) {
1626
+ return x === 0 ? 0 : m3Fmix(m3MixH1(0, m3MixK1(x)), 4);
1627
+ }
1628
+
1629
+ let stringHashCache = /* @__PURE__ */ Object.create(null);
1630
+ let stringHashCacheCount = 0;
1631
+
1632
+ function hashStringRaw(s) {
1633
+ let h = 0;
1634
+ for (let i = 0; i < s.length; i++) h = (imul(31, h) + s.charCodeAt(i)) | 0;
1635
+ return h;
1636
+ }
1637
+
1638
+ function hashString(s) {
1639
+ if (stringHashCacheCount > 8192) {
1640
+ stringHashCache = Object.create(null);
1641
+ stringHashCacheCount = 0;
1642
+ }
1643
+ let h = stringHashCache[s];
1644
+ if (typeof h !== 'number') {
1645
+ h = hashStringRaw(s);
1646
+ stringHashCache[s] = h;
1647
+ stringHashCacheCount++;
1648
+ }
1649
+ return h;
1650
+ }
1651
+
1652
+ // one IIFE, not two consts: `new Int32Array(F64.buffer)` reads a property,
1653
+ // which pins F64 into bundles even under a pure annotation
1654
+ const HASH_BUF = /* @__PURE__ */ (() => {
1655
+ const f64 = new Float64Array(1);
1656
+ return { f64, i32: new Int32Array(f64.buffer) };
1657
+ })();
1658
+
1659
+ function hashDouble(n) {
1660
+ HASH_BUF.f64[0] = n;
1661
+ return (HASH_BUF.i32[0] ^ HASH_BUF.i32[1]) | 0;
1662
+ }
1663
+
1664
+ function mixCollectionHash(hashBasis, count) {
1665
+ return m3Fmix(m3MixH1(0, m3MixK1(hashBasis)), count);
1666
+ }
1667
+
1668
+ export function hash_ordered_coll(coll) {
1669
+ let n = 0;
1670
+ let h = 1;
1671
+ for (const x of coll) {
1672
+ h = (imul(31, h) + hash(x)) | 0;
1673
+ n++;
1674
+ }
1675
+ return mixCollectionHash(h, n);
1676
+ }
1677
+
1678
+ export function hash_unordered_coll(coll) {
1679
+ let n = 0;
1680
+ let h = 0;
1681
+ for (const x of coll) {
1682
+ h = (h + hash(x)) | 0;
1683
+ n++;
1684
+ }
1685
+ return mixCollectionHash(h, n);
1686
+ }
1687
+
1688
+ // a map entry hashes as (hash-ordered-coll [k v])
1689
+ function hashEntry(k, v) {
1690
+ return mixCollectionHash((imul(31, (imul(31, 1) + hash(k)) | 0) + hash(v)) | 0, 2);
1691
+ }
1692
+
1693
+ function hashMapEntries(entries) {
1694
+ let n = 0;
1695
+ let h = 0;
1696
+ for (const [k, v] of entries) {
1697
+ h = (h + hashEntry(k, v)) | 0;
1698
+ n++;
1699
+ }
1700
+ return mixCollectionHash(h, n);
1701
+ }
1702
+
1703
+ // (equiv a b) implies (hash a) === (hash b): plain mutable data hashes by
1704
+ // uid, a type with -equiv but no -hash gets a structural entry hash
1705
+ export function hash(o) {
1706
+ if (o == null) return 0;
1707
+ switch (typeof o) {
1708
+ case 'number':
1709
+ if (Number.isFinite(o)) {
1710
+ return Number.isSafeInteger(o) ? o % 2147483647 | 0 : hashDouble(o);
1711
+ }
1712
+ if (o === Infinity) return 2146435072;
1713
+ if (o === -Infinity) return -1048576;
1714
+ return 2146959360; // NaN
1715
+ case 'boolean':
1716
+ return o ? 1231 : 1237;
1717
+ case 'string':
1718
+ return m3HashInt(hashString(o));
1719
+ case 'bigint':
1720
+ return Number(o % 2147483647n) | 0;
1721
+ case 'function':
1722
+ return uid(o) | 0;
1723
+ case 'object':
1724
+ break;
1725
+ default:
1726
+ // JS symbols compare by identity; a constant hash is consistent
1727
+ return 0;
1728
+ }
1729
+ if (o[IHash__hash] !== undefined) return o[IHash__hash](o) | 0;
1730
+ if (o instanceof Date) return o.valueOf() | 0;
1731
+ if (o[IEquiv__equiv] !== undefined) return hashMapEntries(Object.entries(o));
1732
+ return uid(o) | 0;
1733
+ }
1734
+
1735
+ // printing protocols, like CLJS: a type prints itself through
1736
+ // (-pr-writer [obj writer opts]), writing strings via (-write writer s)
1737
+ export const IWriter = { __sym: Symbol('squint.core.IWriter') };
1738
+ export const IWriter__write = Symbol('IWriter_-write');
1739
+ export const IPrintWithWriter = { __sym: Symbol('squint.core.IPrintWithWriter') };
1740
+ export const IPrintWithWriter__pr_writer = Symbol('IPrintWithWriter_-pr-writer');
1741
+ export function _write(writer, s) {
1742
+ if (writer != null && writer[IWriter__write] !== undefined) return writer[IWriter__write](writer, s);
1743
+ return nilImpl(_write, 'IWriter.-write', writer)(writer, s);
1744
+ }
1745
+ export function write_all(writer, ...ss) {
1746
+ for (const s of ss) _write(writer, s);
1747
+ }
1748
+ // vector-facing protocols, dispatched like the map-facing set above
1749
+ export const IStack = { __sym: Symbol('squint.core.IStack') };
1750
+ export const IStack__peek = Symbol('IStack_-peek');
1751
+ export const IStack__pop = Symbol('IStack_-pop');
1752
+ export const IIndexed = { __sym: Symbol('squint.core.IIndexed') };
1753
+ export const IIndexed__nth = Symbol('IIndexed_-nth');
1754
+ export const ITransientVector = { __sym: Symbol('squint.core.ITransientVector') };
1755
+ export const ITransientVector__pop_BANG_ = Symbol('ITransientVector_-pop!');
1756
+ // marker protocol: a non-array type that counts as a vector (vector?,
1757
+ // sequential?, vec, subvec route through it)
1758
+ export const IVector = { __sym: Symbol('squint.core.IVector') };
1759
+ // a type converts itself in clj->js through this slot, like CLJS IEncodeJS;
1760
+ // the impl receives (x, recur) with recur a cycle-safe clj->js
1761
+ export const IEncodeJS = { __sym: Symbol('squint.core.IEncodeJS') };
1762
+ export const IEncodeJS__clj__GT_js = Symbol('IEncodeJS_-clj->js');
1763
+ // marker protocol set by defrecord
1764
+ export const IRecord = { __sym: Symbol('squint.core.IRecord') };
1765
+
1766
+ export function record_QMARK_(x) {
1767
+ return x != null && x[IRecord.__sym] !== undefined;
1768
+ }
1769
+
1770
+ // The protocol-method fns below share one shape but stay hand-written on
1771
+ // purpose: a shared factory makes V8 share type feedback across all of them,
1772
+ // turning every slot access megamorphic (measured 1.8 -> 11 ns per call).
1773
+ export function _lookup(o, k, nf) {
1774
+ if (o != null && o[ILookup__lookup] !== undefined) return o[ILookup__lookup](o, k, nf);
1775
+ return nilImpl(_lookup, 'ILookup.-lookup', o)(o, k, nf);
1776
+ }
1777
+ export function _assoc(o, k, v) {
1778
+ if (o != null && o[IAssociative__assoc] !== undefined) return o[IAssociative__assoc](o, k, v);
1779
+ return nilImpl(_assoc, 'IAssociative.-assoc', o)(o, k, v);
1780
+ }
1781
+ export function _contains_key_QMARK_(o, k) {
1782
+ if (o != null && o[IAssociative__contains_key_QMARK_] !== undefined) return o[IAssociative__contains_key_QMARK_](o, k);
1783
+ return nilImpl(_contains_key_QMARK_, 'IAssociative.-contains-key?', o)(o, k);
1784
+ }
1785
+ export function _dissoc(o, k) {
1786
+ if (o != null && o[IMap__dissoc] !== undefined) return o[IMap__dissoc](o, k);
1787
+ return nilImpl(_dissoc, 'IMap.-dissoc', o)(o, k);
1788
+ }
1789
+ export function _count(o) {
1790
+ if (o != null && o[ICounted__count] !== undefined) return o[ICounted__count](o);
1791
+ return nilImpl(_count, 'ICounted.-count', o)(o);
1792
+ }
1793
+ export function _kv_reduce(o, f, init) {
1794
+ if (o != null && o[IKVReduce__kv_reduce] !== undefined) return o[IKVReduce__kv_reduce](o, f, init);
1795
+ return nilImpl(_kv_reduce, 'IKVReduce.-kv-reduce', o)(o, f, init);
1796
+ }
1797
+ export function _conj(o, x) {
1798
+ if (o != null && o[ICollection__conj] !== undefined) return o[ICollection__conj](o, x);
1799
+ return nilImpl(_conj, 'ICollection.-conj', o)(o, x);
1800
+ }
1801
+ export function _empty(o) {
1802
+ if (o != null && o[IEmptyableCollection__empty] !== undefined) return o[IEmptyableCollection__empty](o);
1803
+ return nilImpl(_empty, 'IEmptyableCollection.-empty', o)(o);
1804
+ }
1805
+ export function _equiv(o, other) {
1806
+ if (o != null && o[IEquiv__equiv] !== undefined) return o[IEquiv__equiv](o, other);
1807
+ return nilImpl(_equiv, 'IEquiv.-equiv', o)(o, other);
1808
+ }
1374
1809
  export function _seq(o) {
1375
1810
  if (o != null && o[ISeqable__seq] !== undefined) return o[ISeqable__seq](o);
1376
1811
  return nilImpl(_seq, 'ISeqable.-seq', o)(o);
1377
1812
  }
1813
+ export function _disjoin(o, x) {
1814
+ if (o != null && o[ISet__disjoin] !== undefined) return o[ISet__disjoin](o, x);
1815
+ return nilImpl(_disjoin, 'ISet.-disjoin', o)(o, x);
1816
+ }
1817
+ export function _as_transient(o) {
1818
+ if (o != null && o[IEditableCollection__as_transient] !== undefined) return o[IEditableCollection__as_transient](o);
1819
+ return nilImpl(_as_transient, 'IEditableCollection.-as-transient', o)(o);
1820
+ }
1821
+ export function _conj_BANG_(o, x) {
1822
+ if (o != null && o[ITransientCollection__conj_BANG_] !== undefined) return o[ITransientCollection__conj_BANG_](o, x);
1823
+ return nilImpl(_conj_BANG_, 'ITransientCollection.-conj!', o)(o, x);
1824
+ }
1825
+ export function _persistent_BANG_(o) {
1826
+ if (o != null && o[ITransientCollection__persistent_BANG_] !== undefined) return o[ITransientCollection__persistent_BANG_](o);
1827
+ return nilImpl(_persistent_BANG_, 'ITransientCollection.-persistent!', o)(o);
1828
+ }
1829
+ export function _assoc_BANG_(o, k, v) {
1830
+ if (o != null && o[ITransientAssociative__assoc_BANG_] !== undefined) return o[ITransientAssociative__assoc_BANG_](o, k, v);
1831
+ return nilImpl(_assoc_BANG_, 'ITransientAssociative.-assoc!', o)(o, k, v);
1832
+ }
1833
+ export function _dissoc_BANG_(o, k) {
1834
+ if (o != null && o[ITransientMap__dissoc_BANG_] !== undefined) return o[ITransientMap__dissoc_BANG_](o, k);
1835
+ return nilImpl(_dissoc_BANG_, 'ITransientMap.-dissoc!', o)(o, k);
1836
+ }
1837
+ export function _disjoin_BANG_(o, x) {
1838
+ if (o != null && o[ITransientSet__disjoin_BANG_] !== undefined) return o[ITransientSet__disjoin_BANG_](o, x);
1839
+ return nilImpl(_disjoin_BANG_, 'ITransientSet.-disjoin!', o)(o, x);
1840
+ }
1378
1841
 
1379
1842
  // an extend-type on nil stores the impl on the dispatch fn under null,
1380
1843
  // the same convention the generated protocol dispatch fns use
@@ -1470,12 +1933,28 @@ export class Atom {
1470
1933
  export function atom(init, ...opts) {
1471
1934
  const a = new Atom(init);
1472
1935
  for (let i = 0; i < opts.length; i += 2) {
1473
- if (opts[i] === 'meta') a[_metaSym] = opts[i + 1];
1936
+ // IMeta only, like CLJS Atom: keeps with-meta's copy machinery out of atom-only bundles
1937
+ if (opts[i] === 'meta') {
1938
+ const mv = opts[i + 1];
1939
+ a[IMeta__meta] = () => mv;
1940
+ }
1474
1941
  else if (opts[i] === 'validator') a._validator = opts[i + 1];
1475
1942
  }
1476
1943
  return a;
1477
1944
  }
1478
1945
 
1946
+ export function get_validator(ref) {
1947
+ return ref._validator ?? null;
1948
+ }
1949
+
1950
+ export function set_validator_BANG_(ref, f) {
1951
+ if (f != null && !truth_(f(deref(ref)))) {
1952
+ throw new Error('Validator rejected reference state');
1953
+ }
1954
+ ref._validator = f;
1955
+ return null;
1956
+ }
1957
+
1479
1958
  // the CLJS missing-protocol error, used by every protocol dispatch miss
1480
1959
  export function missing_protocol(proto, obj) {
1481
1960
  let ty;
@@ -1613,6 +2092,21 @@ export function re_pattern(s) {
1613
2092
  }
1614
2093
 
1615
2094
  export function subvec(arr, start, end) {
2095
+ // an IVector type slices through its own slots (bounds-checked nth + conj)
2096
+ if (arr != null && arr[IVector.__sym] !== undefined) {
2097
+ if (end === undefined) end = _count(arr);
2098
+ if (start == null || end == null) {
2099
+ throw new Error('subvec: start and end must not be nil');
2100
+ }
2101
+ start = start | 0;
2102
+ end = end | 0;
2103
+ if (start < 0 || end < start || end > _count(arr)) {
2104
+ throw new Error('subvec: index out of bounds');
2105
+ }
2106
+ let ret = arr[IEmptyableCollection__empty](arr);
2107
+ for (let i = start; i < end; i++) ret = ret[ICollection__conj](ret, arr[IIndexed__nth](arr, i));
2108
+ return ret;
2109
+ }
1616
2110
  if (!isVectorArray(arr)) {
1617
2111
  throw new Error('subvec: argument must be a vector');
1618
2112
  }
@@ -1636,7 +2130,8 @@ export function vector(...args) {
1636
2130
  export const array = vector;
1637
2131
 
1638
2132
  export function vector_QMARK_(x) {
1639
- return isVectorArray(x);
2133
+ if (x == null) return false;
2134
+ return isVectorArray(x) || x[IVector.__sym] !== undefined;
1640
2135
  }
1641
2136
 
1642
2137
  export function mapv(...args) {
@@ -1690,6 +2185,7 @@ function toArray(coll) {
1690
2185
 
1691
2186
  export function vec(x) {
1692
2187
  if (isVectorArray(x)) return x;
2188
+ if (x != null && x[IVector.__sym] !== undefined) return x;
1693
2189
  return pushAll([], x);
1694
2190
  }
1695
2191
 
@@ -1698,7 +2194,8 @@ export function set(coll) {
1698
2194
  }
1699
2195
 
1700
2196
  export function set_QMARK_(x) {
1701
- return typeConst(x) === SET_TYPE;
2197
+ if (x == null) return false;
2198
+ return typeConst(x) === SET_TYPE || x[ISet.__sym] !== undefined;
1702
2199
  }
1703
2200
 
1704
2201
  export function hash_set(...xs) {
@@ -1713,6 +2210,12 @@ export function char_QMARK_(x) {
1713
2210
  return typeof x === 'string' && x.length === 1;
1714
2211
  }
1715
2212
 
2213
+ export function char$(x) {
2214
+ if (typeof x === 'string' && x.length === 1) return x;
2215
+ if (typeof x === 'number') return String.fromCharCode(x);
2216
+ throw new Error('Argument to char must be a character or number: ' + x);
2217
+ }
2218
+
1716
2219
  export function apply(f, ...args) {
1717
2220
  f = __toFn(f);
1718
2221
  const xs = args.slice(0, args.length - 1);
@@ -2087,10 +2590,16 @@ export function partition_by(f, coll) {
2087
2590
  export function empty(coll) {
2088
2591
  const type = typeConst(coll);
2089
2592
  if (type != null) {
2593
+ if (type === INSTANCE_TYPE) {
2594
+ if (coll[IEmptyableCollection__empty] !== undefined) return coll[IEmptyableCollection__empty](coll);
2595
+ // a null-prototype object is a map rep; any other instance is not an
2596
+ // emptyable collection, like CLJS
2597
+ return coll.constructor === undefined ? copyMeta(coll, {}) : null;
2598
+ }
2090
2599
  return copyMeta(coll, emptyOfType(type));
2091
- } else {
2092
- throw new Error(`Can't create empty of ${typeof coll}`);
2093
2600
  }
2601
+ // non-collections give nil, like CLJS
2602
+ return null;
2094
2603
  }
2095
2604
 
2096
2605
  export function merge(...args) {
@@ -2104,9 +2613,22 @@ export function merge(...args) {
2104
2613
  } else if (typeConst(firstArg) === undefined) {
2105
2614
  // a non-collection passes through; conj! throws when maps follow, like CLJS
2106
2615
  obj = firstArg;
2616
+ } else if (firstArg[ICollection__conj] !== undefined) {
2617
+ // a -conj type is immutable: no defensive copy needed, and a record has
2618
+ // no empty to rebuild from
2619
+ obj = firstArg;
2107
2620
  } else {
2108
2621
  obj = into(empty(firstArg), firstArg);
2109
2622
  }
2623
+ // an ICollection target merges through -conj instead of mutation
2624
+ if (obj != null && obj[ICollection__conj] !== undefined) {
2625
+ for (let i = 1; i < args.length; i++) {
2626
+ obj = obj != null && obj[ICollection__conj] !== undefined
2627
+ ? obj[ICollection__conj](obj, args[i])
2628
+ : conj_BANG_(obj, args[i]);
2629
+ }
2630
+ return obj;
2631
+ }
2110
2632
  return conj_BANG_(obj, ...args.slice(1));
2111
2633
  }
2112
2634
 
@@ -2164,17 +2686,31 @@ export function into(...args) {
2164
2686
  if (isVectorArray(to)) {
2165
2687
  return pushAll(copy(to), args[1]);
2166
2688
  }
2689
+ // a type with -conj is immutable: fold through the slot instead of
2690
+ // mutating a copy. Direct slot calls keep conj out of the bundle.
2691
+ if (to[ICollection__conj] !== undefined) {
2692
+ return reduce(
2693
+ (acc, x) =>
2694
+ acc != null && acc[ICollection__conj] !== undefined
2695
+ ? acc[ICollection__conj](acc, x)
2696
+ : conj_BANG_(acc, x),
2697
+ to,
2698
+ args[1]
2699
+ );
2700
+ }
2167
2701
  return reduce(conj_BANG_, copy(to), args[1]);
2168
2702
  case 3:
2169
2703
  to = args[0];
2170
2704
  xform = args[1];
2171
2705
  from = args[2];
2172
- c = copy(to);
2706
+ c = to != null && to[ICollection__conj] !== undefined ? to : copy(to);
2173
2707
  rf = (coll, v) => {
2174
2708
  if (v === undefined) {
2175
2709
  return coll;
2176
2710
  }
2177
- return conj_BANG_(coll, v);
2711
+ return coll != null && coll[ICollection__conj] !== undefined
2712
+ ? coll[ICollection__conj](coll, v)
2713
+ : conj_BANG_(coll, v);
2178
2714
  };
2179
2715
  return transduce(xform, rf, c, from);
2180
2716
  default:
@@ -2296,6 +2832,7 @@ function take_nth1(n) {
2296
2832
  }
2297
2833
 
2298
2834
  export function take_nth(n, coll) {
2835
+ assertNumber(n);
2299
2836
  if (arguments.length === 1) return take_nth1(n);
2300
2837
  if (n <= 0) {
2301
2838
  return repeat(first(coll));
@@ -2504,6 +3041,10 @@ export function reverse(coll) {
2504
3041
  return toArray(coll).reverse();
2505
3042
  }
2506
3043
 
3044
+ export function reversible_QMARK_(x) {
3045
+ return isVectorArray(x) || (x != null && x[SORTED_TAG] === true);
3046
+ }
3047
+
2507
3048
  export function rseq(x) {
2508
3049
  // vectors and sorted maps/sets are reversible, like CLJS
2509
3050
  if (isVectorArray(x)) {
@@ -2717,6 +3258,7 @@ export function count(coll) {
2717
3258
  if (typeof len === 'number') {
2718
3259
  return len;
2719
3260
  }
3261
+ if (coll[ICounted__count] !== undefined) return coll[ICounted__count](coll);
2720
3262
  // sum chunk lengths instead of counting elements one by one
2721
3263
  const next = chunkCursor(coll);
2722
3264
  let ret = 0;
@@ -2741,6 +3283,15 @@ export function boolean$(x) {
2741
3283
  return truth_(x);
2742
3284
  }
2743
3285
 
3286
+ export function parse_boolean(s) {
3287
+ if (typeof s !== 'string') {
3288
+ throw new Error('Argument must be a string');
3289
+ }
3290
+ if (s === 'true') return true;
3291
+ if (s === 'false') return false;
3292
+ return null;
3293
+ }
3294
+
2744
3295
  export function zero_QMARK_(x) {
2745
3296
  return x === 0;
2746
3297
  }
@@ -2867,6 +3418,7 @@ export function reduce_kv(f, init, m) {
2867
3418
  if (!m) {
2868
3419
  return init;
2869
3420
  }
3421
+ if (m[IKVReduce__kv_reduce] !== undefined) return m[IKVReduce__kv_reduce](m, f, init);
2870
3422
  var ret = init;
2871
3423
  for (const o of iterable(m)) {
2872
3424
  ret = f(ret, o[0], o[1]);
@@ -2888,11 +3440,25 @@ export function min(x, ...more) {
2888
3440
  return m;
2889
3441
  }
2890
3442
 
3443
+ export function associative_QMARK_(x) {
3444
+ switch (typeConst(x)) {
3445
+ case MAP_TYPE:
3446
+ case ARRAY_TYPE:
3447
+ case OBJECT_TYPE:
3448
+ return true;
3449
+ case INSTANCE_TYPE:
3450
+ return x[IAssociative__assoc] !== undefined;
3451
+ default:
3452
+ return false;
3453
+ }
3454
+ }
3455
+
2891
3456
  export function map_QMARK_(coll) {
2892
3457
  if (coll == null) return false;
2893
3458
  if (isObj(coll)) return true;
2894
3459
  if (coll instanceof Map) return true;
2895
3460
  if (coll[TYPE_TAG] === MAP_TYPE) return true;
3461
+ if (coll[IMap.__sym] !== undefined) return true;
2896
3462
  return false;
2897
3463
  }
2898
3464
 
@@ -2967,6 +3533,24 @@ export function nnext(x) {
2967
3533
  return next(next(x));
2968
3534
  }
2969
3535
 
3536
+ export function nthnext(coll, n) {
3537
+ let xs = seq(coll);
3538
+ while (xs != null && n > 0) {
3539
+ xs = next(xs);
3540
+ n = n - 1;
3541
+ }
3542
+ return xs;
3543
+ }
3544
+
3545
+ export function nthrest(coll, n) {
3546
+ let xs = coll;
3547
+ while (n > 0 && seq(xs) != null) {
3548
+ xs = rest(xs);
3549
+ n = n - 1;
3550
+ }
3551
+ return xs;
3552
+ }
3553
+
2970
3554
  export function compare(x, y) {
2971
3555
  if (x === y) {
2972
3556
  return 0;
@@ -3076,6 +3660,14 @@ export function keys(obj) {
3076
3660
  if (obj == null) return null;
3077
3661
  const t = typeConst(obj);
3078
3662
  switch (t) {
3663
+ case INSTANCE_TYPE:
3664
+ // Object.keys on an instance would leak internals: go through -kv-reduce
3665
+ if (obj[IKVReduce__kv_reduce] !== undefined) {
3666
+ const ks = obj[IKVReduce__kv_reduce](obj, (acc, k, _) => (acc.push(k), acc), []);
3667
+ if (ks.length) return ks;
3668
+ return;
3669
+ }
3670
+ // fall through
3079
3671
  case OBJECT_TYPE: {
3080
3672
  const ks = Object.keys(obj);
3081
3673
  if (ks.length) return ks;
@@ -3100,6 +3692,13 @@ export function vals(obj) {
3100
3692
  if (obj == null) return null;
3101
3693
  const t = typeConst(obj);
3102
3694
  switch (t) {
3695
+ case INSTANCE_TYPE:
3696
+ if (obj[IKVReduce__kv_reduce] !== undefined) {
3697
+ const vs = obj[IKVReduce__kv_reduce](obj, (acc, _, v) => (acc.push(v), acc), []);
3698
+ if (vs.length) return vs;
3699
+ return;
3700
+ }
3701
+ // fall through
3103
3702
  case OBJECT_TYPE: {
3104
3703
  const vs = Object.values(obj);
3105
3704
  if (vs.length) return vs;
@@ -3183,6 +3782,26 @@ export function qualified_keyword_QMARK_(x) {
3183
3782
  return typeof x === 'string' && x.includes('/');
3184
3783
  }
3185
3784
 
3785
+ export function ident_QMARK_(x) {
3786
+ return typeof x === 'string';
3787
+ }
3788
+
3789
+ export function simple_ident_QMARK_(x) {
3790
+ return typeof x === 'string' && namespace(x) == null;
3791
+ }
3792
+
3793
+ export function qualified_ident_QMARK_(x) {
3794
+ return typeof x === 'string' && namespace(x) != null;
3795
+ }
3796
+
3797
+ export function simple_symbol_QMARK_(x) {
3798
+ return symbol_QMARK_(x) && namespace(x) == null;
3799
+ }
3800
+
3801
+ export function qualified_symbol_QMARK_(x) {
3802
+ return symbol_QMARK_(x) && namespace(x) != null;
3803
+ }
3804
+
3186
3805
  export function coll_QMARK_(coll) {
3187
3806
  return typeConst(coll) != undefined;
3188
3807
  }
@@ -3226,6 +3845,11 @@ export function double_QMARK_(x) {
3226
3845
  return typeof x === 'number';
3227
3846
  }
3228
3847
 
3848
+ // like CLJS: every number is a float
3849
+ export function float_QMARK_(x) {
3850
+ return double_QMARK_(x);
3851
+ }
3852
+
3229
3853
  export const integer_QMARK_ = int_QMARK_;
3230
3854
 
3231
3855
  export function pos_int_QMARK_(x) {
@@ -3241,30 +3865,41 @@ export function neg_int_QMARK_(x) {
3241
3865
  }
3242
3866
 
3243
3867
  export function meta(x) {
3244
- if (x instanceof Object) {
3245
- return x[_metaSym];
3246
- } else return null;
3868
+ if (x != null && x[IMeta__meta] !== undefined) {
3869
+ return x[IMeta__meta](x);
3870
+ }
3871
+ return null;
3247
3872
  }
3248
3873
 
3249
3874
  export function with_meta(x, m) {
3875
+ if (x != null && x[IWithMeta__with_meta] !== undefined) {
3876
+ return x[IWithMeta__with_meta](x, m);
3877
+ }
3878
+ return with_meta_copy(x, m);
3879
+ }
3880
+
3881
+ // instance-level impls for a plain value; the meta lives in the closure
3882
+ function installMeta(x, m) {
3883
+ x[IMeta__meta] = () => m;
3884
+ x[IWithMeta__with_meta] = with_meta_copy;
3885
+ return x;
3886
+ }
3887
+
3888
+ function with_meta_copy(x, m) {
3250
3889
  // For functions, wrap in a new callable that forwards to the original
3251
3890
  // so fn? stays true and the original isn't mutated. copy() can't handle
3252
3891
  // functions - a {...x} spread loses the call signature.
3253
3892
  if (typeof x === 'function') {
3254
3893
  const wrapped = function (...args) { return x.apply(this, args); };
3255
- wrapped[_metaSym] = m;
3256
- return wrapped;
3894
+ return installMeta(wrapped, m);
3257
3895
  }
3258
3896
  // A lazy seq or cons is not copied element-wise: clone the head so the new
3259
3897
  // value carries its own metadata without forcing realization.
3260
3898
  if (x?.[TYPE_TAG] === LAZY_ITERABLE_TYPE) {
3261
3899
  const ret = Object.assign(Object.create(Object.getPrototypeOf(x)), x);
3262
- ret[_metaSym] = m;
3263
- return ret;
3900
+ return installMeta(ret, m);
3264
3901
  }
3265
- const ret = copy(x);
3266
- ret[_metaSym] = m;
3267
- return ret;
3902
+ return installMeta(copy(x), m);
3268
3903
  }
3269
3904
 
3270
3905
  export function vary_meta(x, f, ...args) {
@@ -3281,6 +3916,7 @@ export function counted_QMARK_(x) {
3281
3916
  case ARRAY_TYPE:
3282
3917
  case MAP_TYPE:
3283
3918
  case OBJECT_TYPE:
3919
+ case INSTANCE_TYPE:
3284
3920
  case LIST_TYPE:
3285
3921
  case SET_TYPE:
3286
3922
  return true;
@@ -3454,10 +4090,12 @@ export function flatten(x) {
3454
4090
  }
3455
4091
 
3456
4092
  export function transient$(x) {
4093
+ if (x != null && x[IEditableCollection__as_transient] !== undefined) return x[IEditableCollection__as_transient](x);
3457
4094
  return copy(x);
3458
4095
  }
3459
4096
 
3460
4097
  export function persistent_BANG_(x) {
4098
+ if (x != null && x[ITransientCollection__persistent_BANG_] !== undefined) return x[ITransientCollection__persistent_BANG_](x);
3461
4099
  // no Object.freeze: persistent structures stay extensible so symbol-keyed
3462
4100
  // metadata can be attached
3463
4101
  return x;
@@ -3691,6 +4329,18 @@ export function double$(x) {
3691
4329
  return x;
3692
4330
  }
3693
4331
 
4332
+ export function num(x) {
4333
+ return x;
4334
+ }
4335
+
4336
+ export function byte$(x) {
4337
+ return x;
4338
+ }
4339
+
4340
+ export function short$(x) {
4341
+ return x;
4342
+ }
4343
+
3694
4344
  export function type(x) {
3695
4345
  return x != null && x.constructor;
3696
4346
  }
@@ -3744,6 +4394,8 @@ export function peek(vec) {
3744
4394
  return first(vec);
3745
4395
  } else if (array_QMARK_(vec)) {
3746
4396
  return vec[vec.length - 1];
4397
+ } else if (vec[IStack__peek] !== undefined) {
4398
+ return vec[IStack__peek](vec);
3747
4399
  } else {
3748
4400
  throw missing_protocol('IStack.-peek', vec);
3749
4401
  }
@@ -3759,13 +4411,30 @@ export function pop(vec) {
3759
4411
  const ret = [...vec];
3760
4412
  ret.pop();
3761
4413
  return ret;
4414
+ } else if (vec[IStack__pop] !== undefined) {
4415
+ return vec[IStack__pop](vec);
3762
4416
  } else {
3763
4417
  throw missing_protocol('IStack.-pop', vec);
3764
4418
  }
3765
4419
  }
3766
4420
 
4421
+ export function pop_BANG_(v) {
4422
+ if (v != null && isVectorArray(v)) {
4423
+ if (v.length === 0) throw new Error("Can't pop empty vector");
4424
+ v.pop();
4425
+ return v;
4426
+ }
4427
+ if (v != null && v[ITransientVector__pop_BANG_] !== undefined) {
4428
+ return v[ITransientVector__pop_BANG_](v);
4429
+ }
4430
+ throw missing_protocol('ITransientVector.-pop!', v);
4431
+ }
4432
+
3767
4433
  export function update_keys(m, f) {
3768
4434
  const m2 = empty(m);
4435
+ if (m2 != null && m2[IAssociative__assoc] !== undefined) {
4436
+ return reduce_kv((acc, k, v) => acc[IAssociative__assoc](acc, f(k), v), m2, m);
4437
+ }
3769
4438
  const assocFn = getAssocMut(m) || assoc_BANG_;
3770
4439
  reduce_kv(
3771
4440
  (acc, k, v) => {
@@ -3779,6 +4448,9 @@ export function update_keys(m, f) {
3779
4448
 
3780
4449
  export function update_vals(m, f) {
3781
4450
  const m2 = empty(m);
4451
+ if (m2 != null && m2[IAssociative__assoc] !== undefined) {
4452
+ return reduce_kv((acc, k, v) => acc[IAssociative__assoc](acc, k, f(v)), m2, m);
4453
+ }
3782
4454
  const assocFn = getAssocMut(m) || assoc_BANG_;
3783
4455
  reduce_kv(
3784
4456
  (acc, k, v) => {
@@ -3859,12 +4531,15 @@ function clj__GT_js_(x, seen) {
3859
4531
  // we need to protect against circular objects
3860
4532
  if (seen.has(x)) return x;
3861
4533
  seen.add(x);
4534
+ if (x != null && x[IEncodeJS__clj__GT_js] !== undefined) {
4535
+ return x[IEncodeJS__clj__GT_js](x, (v) => clj__GT_js_(v, seen));
4536
+ }
3862
4537
  if (map_QMARK_(x)) {
3863
4538
  return update_vals(x, (x) => clj__GT_js_(x, seen));
3864
4539
  }
3865
4540
 
3866
4541
  const tc = typeConst(x);
3867
- if (tc && tc != OBJECT_TYPE) {
4542
+ if (tc && tc != OBJECT_TYPE && tc != INSTANCE_TYPE) {
3868
4543
  return mapv((x) => clj__GT_js_(x, seen), x);
3869
4544
  }
3870
4545
  return x;
@@ -3940,6 +4615,18 @@ function toEDN(value, seen = new WeakSet(), readably = true) {
3940
4615
  result = `(${mapv((v) => `${toEDN(v, seen, readably)}`, value).join(', ')})`;
3941
4616
  break;
3942
4617
  default:
4618
+ if (value[IPrintWithWriter__pr_writer] !== undefined) {
4619
+ let buf = '';
4620
+ const writer = { [IWriter__write]: (_w, s) => (buf += s), [IWriter.__sym]: true };
4621
+ value[IPrintWithWriter__pr_writer](value, writer, { readably: readably });
4622
+ result = buf;
4623
+ break;
4624
+ }
4625
+ if (value[IRecord.__sym] !== undefined) {
4626
+ keys = Object.keys(value);
4627
+ result = `#${value.constructor.name}{${keys.map((k) => `:${k} ${toEDN(value[k], seen, readably)}`).join(', ')}}`;
4628
+ break;
4629
+ }
3943
4630
  // Non-plain objects (Promise, Error, Date, class instances, ...) have a
3944
4631
  // constructor other than Object. Print them as #<Name> rather than {}
3945
4632
  // (which is what Object.keys would yield for opaque values like a
@@ -3966,3 +4653,8 @@ export function prn(...xs) {
3966
4653
  _STAR_print_fn_STAR_.val(pr_str(...xs));
3967
4654
  if (_STAR_print_newline_STAR_.val) _STAR_print_fn_STAR_.val('\n');
3968
4655
  }
4656
+
4657
+ export function prn_str(...xs) {
4658
+ return pr_str(...xs) + '\n';
4659
+ }
4660
+