squint-cljs 0.14.202 → 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,6 +242,7 @@ 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
  }
@@ -258,6 +282,17 @@ export function assoc_BANG_(m, k, v, ...kvs) {
258
282
  m[kvs[i]] = kvs[i + 1];
259
283
  }
260
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
261
296
  case OBJECT_TYPE:
262
297
  m[k] = v;
263
298
 
@@ -274,16 +309,14 @@ export function assoc_BANG_(m, k, v, ...kvs) {
274
309
  return m;
275
310
  }
276
311
 
277
- const _metaSym = Symbol('meta');
278
-
279
- // Copies metadata from `from` onto `to` (when present) and returns `to`. Used
280
- // to make value-producing operations (copy, empty, conj, into) carry metadata
281
- // like Clojure does, instead of dropping it on the freshly built structure.
282
- // Kept branch-light for the hot path: reads an absent symbol property (cheap,
283
- // 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
284
314
  function copyMeta(from, to) {
285
- const m = from?.[_metaSym];
286
- 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
+ }
287
320
  return to;
288
321
  }
289
322
 
@@ -296,6 +329,7 @@ function copy(o) {
296
329
  return copyMeta(o, new o.constructor(o));
297
330
  case ARRAY_TYPE:
298
331
  return copyMeta(o, [...o]);
332
+ case INSTANCE_TYPE:
299
333
  case OBJECT_TYPE:
300
334
  return copyMeta(o, { ...o });
301
335
  case LIST_TYPE:
@@ -313,6 +347,13 @@ export function assoc(o, k, v, ...kvs) {
313
347
  if (o == null) {
314
348
  o = {};
315
349
  }
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]);
354
+ }
355
+ return ret;
356
+ }
316
357
  const ret = copy(o);
317
358
  assoc_BANG_(ret, k, v, ...kvs);
318
359
  return ret;
@@ -335,6 +376,9 @@ const OBJECT_TYPE = 3;
335
376
  const LIST_TYPE = 4;
336
377
  const SET_TYPE = 5;
337
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;
338
382
 
339
383
  // type tag set in each collection ctor, read by typeConst (DCE: no instanceof).
340
384
  const TYPE_TAG = Symbol('squint.lang.type');
@@ -398,7 +442,7 @@ function typeConst(obj) {
398
442
  if (tag !== undefined) return tag;
399
443
  if (isVectorArray(obj)) return ARRAY_TYPE;
400
444
  // any remaining object (class instance, null-proto) is associative
401
- if (typeof obj === 'object') return OBJECT_TYPE;
445
+ if (typeof obj === 'object') return INSTANCE_TYPE;
402
446
 
403
447
  return undefined;
404
448
  }
@@ -407,7 +451,7 @@ function assoc_in_with(f, fname, o, keys, value) {
407
451
  keys = vec(keys);
408
452
  o = o || {}; // default nil behavior is JS object
409
453
  const baseType = typeConst(o);
410
- if (baseType !== MAP_TYPE && baseType !== ARRAY_TYPE && baseType !== OBJECT_TYPE)
454
+ if (baseType !== MAP_TYPE && baseType !== ARRAY_TYPE && baseType !== OBJECT_TYPE && baseType !== INSTANCE_TYPE)
411
455
  throw new Error(
412
456
  `Illegal argument: ${fname} expects the first argument to be a Map, Array, or Object.`
413
457
  );
@@ -419,9 +463,12 @@ function assoc_in_with(f, fname, o, keys, value) {
419
463
  const k = keys[i];
420
464
  let chainValue;
421
465
  if (lastInChain instanceof Map) chainValue = lastInChain.get(k);
422
- 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];
423
469
  if (!chainValue) {
424
- chainValue = emptyOfType(baseType);
470
+ // an instance root has no empty-of-type: missing levels become plain maps
471
+ chainValue = emptyOfType(baseType) ?? {};
425
472
  }
426
473
  chain.push(chainValue);
427
474
  lastInChain = chainValue;
@@ -526,6 +573,14 @@ export function conj_BANG_(...xs) {
526
573
  else for (const kv of mapEntriesOf(x)) o.set(kv[0], kv[1]);
527
574
  }
528
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
529
584
  case OBJECT_TYPE:
530
585
  for (const x of rest) {
531
586
  if (isVectorArray(x)) { asMapEntry(x); o[x[0]] = x[1]; }
@@ -604,6 +659,14 @@ export function conj(...xs) {
604
659
  yield* rest;
605
660
  yield* o;
606
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
607
670
  case OBJECT_TYPE:
608
671
  o2 = { ...o };
609
672
 
@@ -621,6 +684,13 @@ export function conj(...xs) {
621
684
  }
622
685
 
623
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
+ }
624
694
  for (const x of xs) {
625
695
  s.delete(x);
626
696
  }
@@ -629,6 +699,12 @@ export function disj_BANG_(s, ...xs) {
629
699
 
630
700
  export function disj(s, ...xs) {
631
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
+ }
632
708
  // pass s itself (not a spread) so a SortedSet keeps its comparator
633
709
  const s1 = new s.constructor(s);
634
710
  return copyMeta(s, disj_BANG_(s1, ...xs));
@@ -644,12 +720,22 @@ export function contains_QMARK_(coll, v) {
644
720
  return coll.has(v);
645
721
  case undefined:
646
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
647
728
  default:
648
729
  return v in coll;
649
730
  }
650
731
  }
651
732
 
652
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
+ }
653
739
  for (const k of ks) {
654
740
  delete m[k];
655
741
  }
@@ -661,9 +747,18 @@ export function dissoc(m, ...ks) {
661
747
  if (!m) return;
662
748
  if (ks.length === 0) return m;
663
749
  const tc = typeConst(m);
664
- if (tc !== MAP_TYPE && tc !== OBJECT_TYPE) {
750
+ if (tc !== MAP_TYPE && tc !== OBJECT_TYPE && tc !== INSTANCE_TYPE) {
665
751
  throw new Error('dissoc expects a map, got: ' + typeof m);
666
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
+ }
667
762
  if (tc === MAP_TYPE) {
668
763
  let present = false;
669
764
  for (const k of ks) if (m.has(k)) { present = true; break; }
@@ -701,6 +796,14 @@ export function println(...args) {
701
796
  if (_STAR_print_newline_STAR_.val) _STAR_print_fn_STAR_.val('\n');
702
797
  }
703
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
+
704
807
  export function pr(...xs) {
705
808
  _STAR_print_fn_STAR_.val(pr_str(...xs));
706
809
  }
@@ -718,6 +821,8 @@ export function nth(coll, idx, orElse) {
718
821
  if (idx >= 0 && idx < coll.length) {
719
822
  return coll[idx];
720
823
  }
824
+ } else if (coll[IIndexed__nth] !== undefined) {
825
+ return hasDefault ? coll[IIndexed__nth](coll, idx, orElse) : coll[IIndexed__nth](coll, idx);
721
826
  } else if (idx >= 0) {
722
827
  // non-array: skip whole chunks instead of counting elements (handles
723
828
  // infinite seqs since it stops once idx is reached)
@@ -760,6 +865,10 @@ export function get(coll, key, otherwise = undefined) {
760
865
  v = coll[key];
761
866
  break;
762
867
  default:
868
+ if (coll[ILookup__lookup] !== undefined) {
869
+ v = coll[ILookup__lookup](coll, key, otherwise);
870
+ return v === undefined ? otherwise : v;
871
+ }
763
872
  // we choose .get as the default implementation, e.g. fetch Headers are not Maps, but do implement a .get method
764
873
  g = coll['get'];
765
874
  if (typeof g === 'function') {
@@ -783,7 +892,7 @@ export function seq_QMARK_(x) {
783
892
  export function sequential_QMARK_(x) {
784
893
  // vectors and lists are arrays; lazy seqs and cons carry the lazy brand.
785
894
  // Sets, maps and strings are iterable but not sequential.
786
- 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);
787
896
  }
788
897
 
789
898
  export function seqable_QMARK_(x) {
@@ -828,7 +937,10 @@ export function iterable(x) {
828
937
  }
829
938
  // a type extended to ISeqable seqs through its -seq method
830
939
  if (x[ISeqable__seq] !== undefined) return iterable(x[ISeqable__seq](x));
831
- 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);
832
944
  throw new TypeError(`${x} is not iterable`);
833
945
  }
834
946
 
@@ -852,10 +964,19 @@ export function seq(x) {
852
964
  if (iter.length === 0 || iter.size === 0) {
853
965
  return null;
854
966
  }
855
- // 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
856
969
  if (iter instanceof Set || iter[TYPE_TAG] === SET_TYPE) {
857
970
  return [...iter];
858
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
+ }
859
980
  const _i = iter[Symbol.iterator]();
860
981
  if (_i.next().done) return null;
861
982
  return iter;
@@ -888,6 +1009,14 @@ export function ffirst(coll) {
888
1009
  return first(first(coll));
889
1010
  }
890
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
+
891
1020
  export function rest(coll) {
892
1021
  // chunk-aware: drop the first element of the first chunk, keep the rest of
893
1022
  // the chain chunked (preserves chunkedness, unlike re-iterating element-wise)
@@ -1285,6 +1414,13 @@ export function filterv(pred, coll) {
1285
1414
  return pushAll([], filter(pred, coll));
1286
1415
  }
1287
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
+
1288
1424
  export function remove(pred, coll) {
1289
1425
  if (arguments.length === 1) {
1290
1426
  return filter1(complement(pred));
@@ -1382,10 +1518,326 @@ export function _deref(o) {
1382
1518
  }
1383
1519
  export const ISeqable = { __sym: ISEQABLE_SYM };
1384
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
+ }
1385
1809
  export function _seq(o) {
1386
1810
  if (o != null && o[ISeqable__seq] !== undefined) return o[ISeqable__seq](o);
1387
1811
  return nilImpl(_seq, 'ISeqable.-seq', o)(o);
1388
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
+ }
1389
1841
 
1390
1842
  // an extend-type on nil stores the impl on the dispatch fn under null,
1391
1843
  // the same convention the generated protocol dispatch fns use
@@ -1481,7 +1933,11 @@ export class Atom {
1481
1933
  export function atom(init, ...opts) {
1482
1934
  const a = new Atom(init);
1483
1935
  for (let i = 0; i < opts.length; i += 2) {
1484
- 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
+ }
1485
1941
  else if (opts[i] === 'validator') a._validator = opts[i + 1];
1486
1942
  }
1487
1943
  return a;
@@ -1636,6 +2092,21 @@ export function re_pattern(s) {
1636
2092
  }
1637
2093
 
1638
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
+ }
1639
2110
  if (!isVectorArray(arr)) {
1640
2111
  throw new Error('subvec: argument must be a vector');
1641
2112
  }
@@ -1659,7 +2130,8 @@ export function vector(...args) {
1659
2130
  export const array = vector;
1660
2131
 
1661
2132
  export function vector_QMARK_(x) {
1662
- return isVectorArray(x);
2133
+ if (x == null) return false;
2134
+ return isVectorArray(x) || x[IVector.__sym] !== undefined;
1663
2135
  }
1664
2136
 
1665
2137
  export function mapv(...args) {
@@ -1713,6 +2185,7 @@ function toArray(coll) {
1713
2185
 
1714
2186
  export function vec(x) {
1715
2187
  if (isVectorArray(x)) return x;
2188
+ if (x != null && x[IVector.__sym] !== undefined) return x;
1716
2189
  return pushAll([], x);
1717
2190
  }
1718
2191
 
@@ -1721,7 +2194,8 @@ export function set(coll) {
1721
2194
  }
1722
2195
 
1723
2196
  export function set_QMARK_(x) {
1724
- return typeConst(x) === SET_TYPE;
2197
+ if (x == null) return false;
2198
+ return typeConst(x) === SET_TYPE || x[ISet.__sym] !== undefined;
1725
2199
  }
1726
2200
 
1727
2201
  export function hash_set(...xs) {
@@ -1736,6 +2210,12 @@ export function char_QMARK_(x) {
1736
2210
  return typeof x === 'string' && x.length === 1;
1737
2211
  }
1738
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
+
1739
2219
  export function apply(f, ...args) {
1740
2220
  f = __toFn(f);
1741
2221
  const xs = args.slice(0, args.length - 1);
@@ -2110,9 +2590,12 @@ export function partition_by(f, coll) {
2110
2590
  export function empty(coll) {
2111
2591
  const type = typeConst(coll);
2112
2592
  if (type != null) {
2113
- // a class instance is not an emptyable collection, like CLJS;
2114
- // a plain or null-prototype object still empties to {}
2115
- if (type === OBJECT_TYPE && coll.constructor !== undefined && coll.constructor !== Object) return 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
+ }
2116
2599
  return copyMeta(coll, emptyOfType(type));
2117
2600
  }
2118
2601
  // non-collections give nil, like CLJS
@@ -2130,9 +2613,22 @@ export function merge(...args) {
2130
2613
  } else if (typeConst(firstArg) === undefined) {
2131
2614
  // a non-collection passes through; conj! throws when maps follow, like CLJS
2132
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;
2133
2620
  } else {
2134
2621
  obj = into(empty(firstArg), firstArg);
2135
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
+ }
2136
2632
  return conj_BANG_(obj, ...args.slice(1));
2137
2633
  }
2138
2634
 
@@ -2190,17 +2686,31 @@ export function into(...args) {
2190
2686
  if (isVectorArray(to)) {
2191
2687
  return pushAll(copy(to), args[1]);
2192
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
+ }
2193
2701
  return reduce(conj_BANG_, copy(to), args[1]);
2194
2702
  case 3:
2195
2703
  to = args[0];
2196
2704
  xform = args[1];
2197
2705
  from = args[2];
2198
- c = copy(to);
2706
+ c = to != null && to[ICollection__conj] !== undefined ? to : copy(to);
2199
2707
  rf = (coll, v) => {
2200
2708
  if (v === undefined) {
2201
2709
  return coll;
2202
2710
  }
2203
- return conj_BANG_(coll, v);
2711
+ return coll != null && coll[ICollection__conj] !== undefined
2712
+ ? coll[ICollection__conj](coll, v)
2713
+ : conj_BANG_(coll, v);
2204
2714
  };
2205
2715
  return transduce(xform, rf, c, from);
2206
2716
  default:
@@ -2531,6 +3041,10 @@ export function reverse(coll) {
2531
3041
  return toArray(coll).reverse();
2532
3042
  }
2533
3043
 
3044
+ export function reversible_QMARK_(x) {
3045
+ return isVectorArray(x) || (x != null && x[SORTED_TAG] === true);
3046
+ }
3047
+
2534
3048
  export function rseq(x) {
2535
3049
  // vectors and sorted maps/sets are reversible, like CLJS
2536
3050
  if (isVectorArray(x)) {
@@ -2744,6 +3258,7 @@ export function count(coll) {
2744
3258
  if (typeof len === 'number') {
2745
3259
  return len;
2746
3260
  }
3261
+ if (coll[ICounted__count] !== undefined) return coll[ICounted__count](coll);
2747
3262
  // sum chunk lengths instead of counting elements one by one
2748
3263
  const next = chunkCursor(coll);
2749
3264
  let ret = 0;
@@ -2768,6 +3283,15 @@ export function boolean$(x) {
2768
3283
  return truth_(x);
2769
3284
  }
2770
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
+
2771
3295
  export function zero_QMARK_(x) {
2772
3296
  return x === 0;
2773
3297
  }
@@ -2894,6 +3418,7 @@ export function reduce_kv(f, init, m) {
2894
3418
  if (!m) {
2895
3419
  return init;
2896
3420
  }
3421
+ if (m[IKVReduce__kv_reduce] !== undefined) return m[IKVReduce__kv_reduce](m, f, init);
2897
3422
  var ret = init;
2898
3423
  for (const o of iterable(m)) {
2899
3424
  ret = f(ret, o[0], o[1]);
@@ -2915,11 +3440,25 @@ export function min(x, ...more) {
2915
3440
  return m;
2916
3441
  }
2917
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
+
2918
3456
  export function map_QMARK_(coll) {
2919
3457
  if (coll == null) return false;
2920
3458
  if (isObj(coll)) return true;
2921
3459
  if (coll instanceof Map) return true;
2922
3460
  if (coll[TYPE_TAG] === MAP_TYPE) return true;
3461
+ if (coll[IMap.__sym] !== undefined) return true;
2923
3462
  return false;
2924
3463
  }
2925
3464
 
@@ -2994,6 +3533,24 @@ export function nnext(x) {
2994
3533
  return next(next(x));
2995
3534
  }
2996
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
+
2997
3554
  export function compare(x, y) {
2998
3555
  if (x === y) {
2999
3556
  return 0;
@@ -3103,6 +3660,14 @@ export function keys(obj) {
3103
3660
  if (obj == null) return null;
3104
3661
  const t = typeConst(obj);
3105
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
3106
3671
  case OBJECT_TYPE: {
3107
3672
  const ks = Object.keys(obj);
3108
3673
  if (ks.length) return ks;
@@ -3127,6 +3692,13 @@ export function vals(obj) {
3127
3692
  if (obj == null) return null;
3128
3693
  const t = typeConst(obj);
3129
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
3130
3702
  case OBJECT_TYPE: {
3131
3703
  const vs = Object.values(obj);
3132
3704
  if (vs.length) return vs;
@@ -3210,6 +3782,26 @@ export function qualified_keyword_QMARK_(x) {
3210
3782
  return typeof x === 'string' && x.includes('/');
3211
3783
  }
3212
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
+
3213
3805
  export function coll_QMARK_(coll) {
3214
3806
  return typeConst(coll) != undefined;
3215
3807
  }
@@ -3253,6 +3845,11 @@ export function double_QMARK_(x) {
3253
3845
  return typeof x === 'number';
3254
3846
  }
3255
3847
 
3848
+ // like CLJS: every number is a float
3849
+ export function float_QMARK_(x) {
3850
+ return double_QMARK_(x);
3851
+ }
3852
+
3256
3853
  export const integer_QMARK_ = int_QMARK_;
3257
3854
 
3258
3855
  export function pos_int_QMARK_(x) {
@@ -3268,30 +3865,41 @@ export function neg_int_QMARK_(x) {
3268
3865
  }
3269
3866
 
3270
3867
  export function meta(x) {
3271
- if (x instanceof Object) {
3272
- return x[_metaSym];
3273
- } else return null;
3868
+ if (x != null && x[IMeta__meta] !== undefined) {
3869
+ return x[IMeta__meta](x);
3870
+ }
3871
+ return null;
3274
3872
  }
3275
3873
 
3276
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) {
3277
3889
  // For functions, wrap in a new callable that forwards to the original
3278
3890
  // so fn? stays true and the original isn't mutated. copy() can't handle
3279
3891
  // functions - a {...x} spread loses the call signature.
3280
3892
  if (typeof x === 'function') {
3281
3893
  const wrapped = function (...args) { return x.apply(this, args); };
3282
- wrapped[_metaSym] = m;
3283
- return wrapped;
3894
+ return installMeta(wrapped, m);
3284
3895
  }
3285
3896
  // A lazy seq or cons is not copied element-wise: clone the head so the new
3286
3897
  // value carries its own metadata without forcing realization.
3287
3898
  if (x?.[TYPE_TAG] === LAZY_ITERABLE_TYPE) {
3288
3899
  const ret = Object.assign(Object.create(Object.getPrototypeOf(x)), x);
3289
- ret[_metaSym] = m;
3290
- return ret;
3900
+ return installMeta(ret, m);
3291
3901
  }
3292
- const ret = copy(x);
3293
- ret[_metaSym] = m;
3294
- return ret;
3902
+ return installMeta(copy(x), m);
3295
3903
  }
3296
3904
 
3297
3905
  export function vary_meta(x, f, ...args) {
@@ -3308,6 +3916,7 @@ export function counted_QMARK_(x) {
3308
3916
  case ARRAY_TYPE:
3309
3917
  case MAP_TYPE:
3310
3918
  case OBJECT_TYPE:
3919
+ case INSTANCE_TYPE:
3311
3920
  case LIST_TYPE:
3312
3921
  case SET_TYPE:
3313
3922
  return true;
@@ -3481,10 +4090,12 @@ export function flatten(x) {
3481
4090
  }
3482
4091
 
3483
4092
  export function transient$(x) {
4093
+ if (x != null && x[IEditableCollection__as_transient] !== undefined) return x[IEditableCollection__as_transient](x);
3484
4094
  return copy(x);
3485
4095
  }
3486
4096
 
3487
4097
  export function persistent_BANG_(x) {
4098
+ if (x != null && x[ITransientCollection__persistent_BANG_] !== undefined) return x[ITransientCollection__persistent_BANG_](x);
3488
4099
  // no Object.freeze: persistent structures stay extensible so symbol-keyed
3489
4100
  // metadata can be attached
3490
4101
  return x;
@@ -3718,6 +4329,18 @@ export function double$(x) {
3718
4329
  return x;
3719
4330
  }
3720
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
+
3721
4344
  export function type(x) {
3722
4345
  return x != null && x.constructor;
3723
4346
  }
@@ -3771,6 +4394,8 @@ export function peek(vec) {
3771
4394
  return first(vec);
3772
4395
  } else if (array_QMARK_(vec)) {
3773
4396
  return vec[vec.length - 1];
4397
+ } else if (vec[IStack__peek] !== undefined) {
4398
+ return vec[IStack__peek](vec);
3774
4399
  } else {
3775
4400
  throw missing_protocol('IStack.-peek', vec);
3776
4401
  }
@@ -3786,13 +4411,30 @@ export function pop(vec) {
3786
4411
  const ret = [...vec];
3787
4412
  ret.pop();
3788
4413
  return ret;
4414
+ } else if (vec[IStack__pop] !== undefined) {
4415
+ return vec[IStack__pop](vec);
3789
4416
  } else {
3790
4417
  throw missing_protocol('IStack.-pop', vec);
3791
4418
  }
3792
4419
  }
3793
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
+
3794
4433
  export function update_keys(m, f) {
3795
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
+ }
3796
4438
  const assocFn = getAssocMut(m) || assoc_BANG_;
3797
4439
  reduce_kv(
3798
4440
  (acc, k, v) => {
@@ -3806,6 +4448,9 @@ export function update_keys(m, f) {
3806
4448
 
3807
4449
  export function update_vals(m, f) {
3808
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
+ }
3809
4454
  const assocFn = getAssocMut(m) || assoc_BANG_;
3810
4455
  reduce_kv(
3811
4456
  (acc, k, v) => {
@@ -3886,12 +4531,15 @@ function clj__GT_js_(x, seen) {
3886
4531
  // we need to protect against circular objects
3887
4532
  if (seen.has(x)) return x;
3888
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
+ }
3889
4537
  if (map_QMARK_(x)) {
3890
4538
  return update_vals(x, (x) => clj__GT_js_(x, seen));
3891
4539
  }
3892
4540
 
3893
4541
  const tc = typeConst(x);
3894
- if (tc && tc != OBJECT_TYPE) {
4542
+ if (tc && tc != OBJECT_TYPE && tc != INSTANCE_TYPE) {
3895
4543
  return mapv((x) => clj__GT_js_(x, seen), x);
3896
4544
  }
3897
4545
  return x;
@@ -3967,6 +4615,18 @@ function toEDN(value, seen = new WeakSet(), readably = true) {
3967
4615
  result = `(${mapv((v) => `${toEDN(v, seen, readably)}`, value).join(', ')})`;
3968
4616
  break;
3969
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
+ }
3970
4630
  // Non-plain objects (Promise, Error, Date, class instances, ...) have a
3971
4631
  // constructor other than Object. Print them as #<Name> rather than {}
3972
4632
  // (which is what Object.keys would yield for opaque values like a
@@ -3993,3 +4653,8 @@ export function prn(...xs) {
3993
4653
  _STAR_print_fn_STAR_.val(pr_str(...xs));
3994
4654
  if (_STAR_print_newline_STAR_.val) _STAR_print_fn_STAR_.val('\n');
3995
4655
  }
4656
+
4657
+ export function prn_str(...xs) {
4658
+ return pr_str(...xs) + '\n';
4659
+ }
4660
+