squint-cljs 0.13.195 → 0.14.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -1
- package/lib/cli.js +100 -100
- package/lib/cljs.pprint.js +149 -149
- package/lib/compiler.js +758 -764
- package/lib/compiler.node.js +39 -38
- package/lib/compiler.sci.js +1111 -1112
- package/lib/node.nrepl_server.js +25 -25
- package/lib/squint.core.umd.js +3 -1
- package/package.json +5 -3
- package/src/squint/core.js +159 -60
- package/src/squint/edn.js +341 -0
- package/src/squint/string.js +4 -0
- package/src/squint/test.js +143 -169
package/src/squint/core.js
CHANGED
|
@@ -70,7 +70,7 @@ function dequal(foo, bar) {
|
|
|
70
70
|
|
|
71
71
|
// LazyIterable falls through to the sequential-equality path below; it is an
|
|
72
72
|
// object but must compare element-wise, not by enumerable properties
|
|
73
|
-
if ((!ctor || typeof foo === 'object') &&
|
|
73
|
+
if ((!ctor || typeof foo === 'object') && foo[TYPE_TAG] !== LAZY_ITERABLE_TYPE) {
|
|
74
74
|
len = 0;
|
|
75
75
|
for (const k in foo) {
|
|
76
76
|
if (has.call(foo, k) && ++len && !has.call(bar, k)) return false;
|
|
@@ -86,12 +86,12 @@ function dequal(foo, bar) {
|
|
|
86
86
|
// collections keep their fast paths.
|
|
87
87
|
if (
|
|
88
88
|
foo && bar &&
|
|
89
|
-
(Array.isArray(foo) || foo
|
|
90
|
-
(Array.isArray(bar) || bar
|
|
89
|
+
(Array.isArray(foo) || foo[TYPE_TAG] === LAZY_ITERABLE_TYPE) &&
|
|
90
|
+
(Array.isArray(bar) || bar[TYPE_TAG] === LAZY_ITERABLE_TYPE)
|
|
91
91
|
) {
|
|
92
92
|
const fi = foo[Symbol.iterator]();
|
|
93
93
|
const bi = bar[Symbol.iterator]();
|
|
94
|
-
|
|
94
|
+
for (;;) {
|
|
95
95
|
const a = fi.next();
|
|
96
96
|
const b = bi.next();
|
|
97
97
|
if (a.done || b.done) return !!(a.done && b.done);
|
|
@@ -249,6 +249,21 @@ const LIST_TYPE = 4;
|
|
|
249
249
|
const SET_TYPE = 5;
|
|
250
250
|
const LAZY_ITERABLE_TYPE = 6;
|
|
251
251
|
|
|
252
|
+
// type tag set in each collection ctor, read by typeConst (DCE: no instanceof).
|
|
253
|
+
const TYPE_TAG = Symbol('squint.lang.type');
|
|
254
|
+
const SORTED_TAG = Symbol('squint.lang.sorted');
|
|
255
|
+
|
|
256
|
+
// @__NO_SIDE_EFFECTS__ lets a bundler drop unused defclass/withApply calls; see doc/dev/dce.md
|
|
257
|
+
// @__NO_SIDE_EFFECTS__
|
|
258
|
+
function defclass(c) {
|
|
259
|
+
return c;
|
|
260
|
+
}
|
|
261
|
+
// @__NO_SIDE_EFFECTS__
|
|
262
|
+
function withApply(f, applyFn) {
|
|
263
|
+
f.squint$lang$variadic = applyFn;
|
|
264
|
+
return f;
|
|
265
|
+
}
|
|
266
|
+
|
|
252
267
|
function emptyOfType(type) {
|
|
253
268
|
switch (type) {
|
|
254
269
|
case MAP_TYPE:
|
|
@@ -274,7 +289,7 @@ function isObj(coll) {
|
|
|
274
289
|
}
|
|
275
290
|
|
|
276
291
|
function isVectorArray(x) {
|
|
277
|
-
return Array.isArray(x) &&
|
|
292
|
+
return Array.isArray(x) && x[TYPE_TAG] !== LIST_TYPE;
|
|
278
293
|
}
|
|
279
294
|
|
|
280
295
|
export function object_QMARK_(coll) {
|
|
@@ -291,13 +306,10 @@ function typeConst(obj) {
|
|
|
291
306
|
}
|
|
292
307
|
if (obj instanceof Map) return MAP_TYPE;
|
|
293
308
|
if (obj instanceof Set) return SET_TYPE;
|
|
294
|
-
|
|
309
|
+
// brand, not instanceof, so dispatch does not reference the classes
|
|
310
|
+
const tag = obj[TYPE_TAG];
|
|
311
|
+
if (tag !== undefined) return tag;
|
|
295
312
|
if (isVectorArray(obj)) return ARRAY_TYPE;
|
|
296
|
-
if (obj instanceof LazyIterable) return LAZY_ITERABLE_TYPE;
|
|
297
|
-
if (obj instanceof SortedSet) return SET_TYPE;
|
|
298
|
-
|
|
299
|
-
// everything more specific than Object should go before this
|
|
300
|
-
if (obj instanceof Object) return OBJECT_TYPE;
|
|
301
313
|
|
|
302
314
|
return undefined;
|
|
303
315
|
}
|
|
@@ -380,17 +392,31 @@ function conj_BANG_set(o, rest) {
|
|
|
380
392
|
}
|
|
381
393
|
|
|
382
394
|
export function conj_BANG_(...xs) {
|
|
383
|
-
|
|
395
|
+
const n = xs.length;
|
|
396
|
+
if (n === 0) {
|
|
384
397
|
return vector();
|
|
385
398
|
}
|
|
386
399
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
let o = _o;
|
|
400
|
+
let o = xs[0];
|
|
390
401
|
if (o === null || o === undefined) {
|
|
391
402
|
o = [];
|
|
392
403
|
}
|
|
393
404
|
|
|
405
|
+
// Fast path for the common single-element conj! onto an array or set,
|
|
406
|
+
// avoiding the rest-array allocation and spread.
|
|
407
|
+
if (n === 2) {
|
|
408
|
+
switch (typeConst(o)) {
|
|
409
|
+
case ARRAY_TYPE:
|
|
410
|
+
o.push(xs[1]);
|
|
411
|
+
return o;
|
|
412
|
+
case SET_TYPE:
|
|
413
|
+
o.add(xs[1]);
|
|
414
|
+
return o;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const rest = xs.slice(1);
|
|
419
|
+
|
|
394
420
|
switch (typeConst(o)) {
|
|
395
421
|
case SET_TYPE:
|
|
396
422
|
conj_BANG_set(o, rest);
|
|
@@ -440,7 +466,8 @@ export function conj(...xs) {
|
|
|
440
466
|
|
|
441
467
|
switch (typeConst(o)) {
|
|
442
468
|
case SET_TYPE:
|
|
443
|
-
|
|
469
|
+
// brand, not instanceof, so conj does not pin SortedSet
|
|
470
|
+
if (o[SORTED_TAG]) {
|
|
444
471
|
// prevent re-sorting of collection
|
|
445
472
|
return copyMeta(o, conj_BANG_set(new o.constructor(o), rest));
|
|
446
473
|
} else {
|
|
@@ -518,19 +545,19 @@ export function dissoc_BANG_(m, ...ks) {
|
|
|
518
545
|
export function dissoc(m, ...ks) {
|
|
519
546
|
if (!m) return;
|
|
520
547
|
if (ks.length === 0) return m;
|
|
548
|
+
if (typeConst(m) === MAP_TYPE) {
|
|
549
|
+
let present = false;
|
|
550
|
+
for (const k of ks) if (m.has(k)) { present = true; break; }
|
|
551
|
+
if (!present) return m;
|
|
552
|
+
const m2 = copy(m);
|
|
553
|
+
for (const k of ks) m2.delete(k);
|
|
554
|
+
return m2;
|
|
555
|
+
}
|
|
556
|
+
let present = false;
|
|
557
|
+
for (const k of ks) if (k in m) { present = true; break; }
|
|
558
|
+
if (!present) return m;
|
|
521
559
|
const m2 = copy(m);
|
|
522
|
-
|
|
523
|
-
case MAP_TYPE:
|
|
524
|
-
for (const k of ks) {
|
|
525
|
-
m2.delete(k);
|
|
526
|
-
}
|
|
527
|
-
break;
|
|
528
|
-
default:
|
|
529
|
-
for (const k of ks) {
|
|
530
|
-
delete m2[k];
|
|
531
|
-
}
|
|
532
|
-
break;
|
|
533
|
-
}
|
|
560
|
+
for (const k of ks) delete m2[k];
|
|
534
561
|
return m2;
|
|
535
562
|
}
|
|
536
563
|
|
|
@@ -542,8 +569,21 @@ export function dec(n) {
|
|
|
542
569
|
return n - 1;
|
|
543
570
|
}
|
|
544
571
|
|
|
572
|
+
export const _STAR_print_newline_STAR_ = { val: false };
|
|
573
|
+
export const _STAR_print_fn_STAR_ = { val: (s) => console.log(s) };
|
|
574
|
+
export const _STAR_print_err_fn_STAR_ = { val: (s) => console.error(s) };
|
|
575
|
+
|
|
576
|
+
export function print(...args) {
|
|
577
|
+
_STAR_print_fn_STAR_.val(args.map((v) => toEDN(v, undefined, false)).join(' '));
|
|
578
|
+
}
|
|
579
|
+
|
|
545
580
|
export function println(...args) {
|
|
546
|
-
|
|
581
|
+
print(...args);
|
|
582
|
+
if (_STAR_print_newline_STAR_.val) _STAR_print_fn_STAR_.val('\n');
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
export function pr(...xs) {
|
|
586
|
+
_STAR_print_fn_STAR_.val(pr_str(...xs));
|
|
547
587
|
}
|
|
548
588
|
|
|
549
589
|
export function nth(coll, idx, orElse) {
|
|
@@ -813,8 +853,8 @@ function* _reductions2(f, s) {
|
|
|
813
853
|
}
|
|
814
854
|
|
|
815
855
|
function* _reductions3(f, init, coll) {
|
|
816
|
-
let i = init
|
|
817
|
-
|
|
856
|
+
let i = init;
|
|
857
|
+
const rst = coll;
|
|
818
858
|
while (true) {
|
|
819
859
|
if (reduced_QMARK_(i)) {
|
|
820
860
|
yield i.value;
|
|
@@ -854,8 +894,11 @@ const CHUNK_SIZE = 32;
|
|
|
854
894
|
|
|
855
895
|
// One cell of a self-caching chunked seq. `step` is a thunk returning
|
|
856
896
|
// [nonEmptyChunkArray, nextStep] or null at the end. See doc/dev/lazy-seqs.md.
|
|
897
|
+
const LazyIterable = defclass(
|
|
857
898
|
class LazyIterable {
|
|
858
899
|
constructor(step) {
|
|
900
|
+
this[TYPE_TAG] = LAZY_ITERABLE_TYPE;
|
|
901
|
+
this[IIterable] = true; // Closure compatibility
|
|
859
902
|
this.step = step;
|
|
860
903
|
this.realized = false;
|
|
861
904
|
this.chunk = null; // array, or null when this is the terminal (empty) cell
|
|
@@ -892,9 +935,18 @@ class LazyIterable {
|
|
|
892
935
|
},
|
|
893
936
|
};
|
|
894
937
|
}
|
|
938
|
+
// CLJS supports (.indexOf coll x) on seqs; mirror it so lazy seqs work like
|
|
939
|
+
// arrays. Uses value equality, like cljs.core, and returns -1 when absent.
|
|
940
|
+
indexOf(x, fromIndex = 0) {
|
|
941
|
+
let i = 0;
|
|
942
|
+
for (const v of this) {
|
|
943
|
+
if (i >= fromIndex && dequal(v, x)) return i;
|
|
944
|
+
i++;
|
|
945
|
+
}
|
|
946
|
+
return -1;
|
|
947
|
+
}
|
|
895
948
|
}
|
|
896
|
-
|
|
897
|
-
LazyIterable.prototype[IIterable] = true; // Closure compatibility
|
|
949
|
+
);
|
|
898
950
|
|
|
899
951
|
// One-element chunks: an unchunked seq, realized one element at a time.
|
|
900
952
|
function unchunkedSteps(iter) {
|
|
@@ -979,7 +1031,8 @@ function mapChunks(coll, xf) {
|
|
|
979
1031
|
return new LazyIterable(step(src, 0));
|
|
980
1032
|
}
|
|
981
1033
|
|
|
982
|
-
export
|
|
1034
|
+
export const Cons = defclass(
|
|
1035
|
+
class Cons {
|
|
983
1036
|
constructor(x, coll) {
|
|
984
1037
|
this.x = x;
|
|
985
1038
|
this.coll = coll;
|
|
@@ -1007,6 +1060,7 @@ export class Cons {
|
|
|
1007
1060
|
};
|
|
1008
1061
|
}
|
|
1009
1062
|
}
|
|
1063
|
+
);
|
|
1010
1064
|
|
|
1011
1065
|
export function cons(x, coll) {
|
|
1012
1066
|
return new Cons(x, coll);
|
|
@@ -1387,17 +1441,33 @@ export function set_QMARK_(x) {
|
|
|
1387
1441
|
return typeConst(x) === SET_TYPE;
|
|
1388
1442
|
}
|
|
1389
1443
|
|
|
1390
|
-
const IApply__apply = Symbol('IApply__apply');
|
|
1391
|
-
|
|
1392
1444
|
export function apply(f, ...args) {
|
|
1393
1445
|
f = __toFn(f);
|
|
1394
1446
|
const xs = args.slice(0, args.length - 1);
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1447
|
+
const last = args[args.length - 1];
|
|
1448
|
+
// variadic impl hint; see doc/adr/0001
|
|
1449
|
+
const v = f.squint$lang$variadic;
|
|
1450
|
+
if (v) {
|
|
1451
|
+
// pull maxfa fixed args (bounded, lazy-safe); more left -> variadic, else fixed
|
|
1452
|
+
const maxfa = v.length - 1;
|
|
1453
|
+
const fixed = [];
|
|
1454
|
+
let i = 0, rest;
|
|
1455
|
+
for (; i < maxfa && i < xs.length; i++) fixed.push(xs[i]);
|
|
1456
|
+
if (i < maxfa) {
|
|
1457
|
+
let s = seq(last);
|
|
1458
|
+
for (; i < maxfa && s != null; i++) {
|
|
1459
|
+
fixed.push(first(s));
|
|
1460
|
+
s = next(s);
|
|
1461
|
+
}
|
|
1462
|
+
rest = s;
|
|
1463
|
+
} else {
|
|
1464
|
+
rest = i < xs.length ? concat1([xs.slice(i), last]) : last;
|
|
1465
|
+
}
|
|
1466
|
+
rest = rest == null ? null : seq(rest);
|
|
1467
|
+
if (rest == null) return f(...fixed);
|
|
1468
|
+
return v(...fixed, rest);
|
|
1399
1469
|
}
|
|
1400
|
-
return f(...xs, ...
|
|
1470
|
+
return f(...xs, ...iterable(last));
|
|
1401
1471
|
}
|
|
1402
1472
|
|
|
1403
1473
|
export function even_QMARK_(x) {
|
|
@@ -1420,6 +1490,7 @@ export function constantly(x) {
|
|
|
1420
1490
|
class List extends Array {
|
|
1421
1491
|
constructor(...args) {
|
|
1422
1492
|
super();
|
|
1493
|
+
this[TYPE_TAG] = LIST_TYPE;
|
|
1423
1494
|
this.push(...args);
|
|
1424
1495
|
}
|
|
1425
1496
|
}
|
|
@@ -1491,14 +1562,10 @@ function concat1(colls) {
|
|
|
1491
1562
|
return new LazyIterable(step(null));
|
|
1492
1563
|
}
|
|
1493
1564
|
|
|
1494
|
-
export
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
// lazy seqable argument
|
|
1499
|
-
concat[IApply__apply] = (colls) => {
|
|
1500
|
-
return concat1(colls);
|
|
1501
|
-
};
|
|
1565
|
+
export const concat = withApply(
|
|
1566
|
+
(...colls) => concat1(colls),
|
|
1567
|
+
(colls) => concat1(colls), // lazy seqable argument
|
|
1568
|
+
);
|
|
1502
1569
|
|
|
1503
1570
|
export function mapcat(f, ...colls) {
|
|
1504
1571
|
if (colls.length === 0) {
|
|
@@ -2699,6 +2766,13 @@ export function keyword(arg1, arg2) {
|
|
|
2699
2766
|
return arg1;
|
|
2700
2767
|
}
|
|
2701
2768
|
|
|
2769
|
+
export function symbol(arg1, arg2) {
|
|
2770
|
+
if (arg2 !== undefined) {
|
|
2771
|
+
return (arg1 != null ? arg1 + '/' : '') + arg2;
|
|
2772
|
+
}
|
|
2773
|
+
return arg1;
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2702
2776
|
export function keyword_QMARK_(x) {
|
|
2703
2777
|
return typeof x === 'string';
|
|
2704
2778
|
}
|
|
@@ -2760,6 +2834,10 @@ export function int_QMARK_(x) {
|
|
|
2760
2834
|
return Number.isInteger(x);
|
|
2761
2835
|
}
|
|
2762
2836
|
|
|
2837
|
+
export function double_QMARK_(x) {
|
|
2838
|
+
return typeof x === 'number';
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2763
2841
|
export const integer_QMARK_ = int_QMARK_;
|
|
2764
2842
|
|
|
2765
2843
|
export function pos_int_QMARK_(x) {
|
|
@@ -2794,6 +2872,10 @@ export function with_meta(x, m) {
|
|
|
2794
2872
|
return ret;
|
|
2795
2873
|
}
|
|
2796
2874
|
|
|
2875
|
+
export function vary_meta(x, f, ...args) {
|
|
2876
|
+
return with_meta(x, f(meta(x), ...args));
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2797
2879
|
export function boolean_QMARK_(x) {
|
|
2798
2880
|
return x === true || x === false;
|
|
2799
2881
|
}
|
|
@@ -2881,9 +2963,11 @@ export function parse_long(s) {
|
|
|
2881
2963
|
|
|
2882
2964
|
export function parse_double(s) {
|
|
2883
2965
|
if (string_QMARK_(s)) {
|
|
2966
|
+
// eslint-disable-next-line no-control-regex -- \x00-\x20 mirrors Java trim
|
|
2884
2967
|
if (/^[\x00-\x20]*[+-]?NaN[\x00-\x20]*$/.test(s)) {
|
|
2885
2968
|
return NaN;
|
|
2886
2969
|
} else if (
|
|
2970
|
+
// eslint-disable-next-line no-control-regex -- \x00-\x20 mirrors Java trim
|
|
2887
2971
|
/^[\x00-\x20]*[+-]?(Infinity|((\d+\.?\d*|\.\d+)([eE][+-]?\d+)?)[dDfF]?)[\x00-\x20]*$/.test(
|
|
2888
2972
|
s
|
|
2889
2973
|
)
|
|
@@ -2996,8 +3080,11 @@ export function persistent_BANG_(x) {
|
|
|
2996
3080
|
return x;
|
|
2997
3081
|
}
|
|
2998
3082
|
|
|
3083
|
+
const SortedSet = defclass(
|
|
2999
3084
|
class SortedSet {
|
|
3000
3085
|
constructor(xs) {
|
|
3086
|
+
this[TYPE_TAG] = SET_TYPE;
|
|
3087
|
+
this[SORTED_TAG] = true;
|
|
3001
3088
|
const isSorted = xs instanceof SortedSet;
|
|
3002
3089
|
if (!isSorted) {
|
|
3003
3090
|
xs = sort(xs);
|
|
@@ -3060,6 +3147,7 @@ class SortedSet {
|
|
|
3060
3147
|
return this.keys();
|
|
3061
3148
|
}
|
|
3062
3149
|
}
|
|
3150
|
+
);
|
|
3063
3151
|
|
|
3064
3152
|
export function sorted_set(...xs) {
|
|
3065
3153
|
return new SortedSet(xs);
|
|
@@ -3283,7 +3371,8 @@ export function vreset_BANG_(vol, v) {
|
|
|
3283
3371
|
return v;
|
|
3284
3372
|
}
|
|
3285
3373
|
|
|
3286
|
-
|
|
3374
|
+
// readably false: strings unquoted
|
|
3375
|
+
function toEDN(value, seen = new WeakSet(), readably = true) {
|
|
3287
3376
|
if (value == null) return 'nil';
|
|
3288
3377
|
if (typeof value === 'number') {
|
|
3289
3378
|
if (value === Infinity) return '##Inf';
|
|
@@ -3292,39 +3381,48 @@ function toEDN(value, seen = new WeakSet()) {
|
|
|
3292
3381
|
return String(value);
|
|
3293
3382
|
}
|
|
3294
3383
|
if (typeof value === 'boolean') return String(value);
|
|
3295
|
-
if (typeof value === 'string') return JSON.stringify(value);
|
|
3384
|
+
if (typeof value === 'string') return readably ? JSON.stringify(value) : value;
|
|
3296
3385
|
if (typeof value === 'bigint') return `${value}N`;
|
|
3297
3386
|
|
|
3298
3387
|
if (typeof value === 'object') {
|
|
3388
|
+
// seen tracks the current ancestor path only. A shared reference that
|
|
3389
|
+
// appears under sibling branches is a DAG, not a cycle, so delete on exit.
|
|
3299
3390
|
if (seen.has(value)) return '#object[circular]';
|
|
3300
3391
|
seen.add(value);
|
|
3301
3392
|
const T = typeConst(value);
|
|
3302
|
-
let keys;
|
|
3393
|
+
let keys, result;
|
|
3303
3394
|
switch (T) {
|
|
3304
3395
|
case ARRAY_TYPE:
|
|
3305
|
-
|
|
3396
|
+
result = `[${value.map((v) => toEDN(v, seen, readably)).join(' ')}]`;
|
|
3397
|
+
break;
|
|
3306
3398
|
case SET_TYPE:
|
|
3307
|
-
|
|
3308
|
-
.map((v) => toEDN(v, seen))
|
|
3399
|
+
result = `#{${Array.from(value)
|
|
3400
|
+
.map((v) => toEDN(v, seen, readably))
|
|
3309
3401
|
.join(' ')}}`;
|
|
3402
|
+
break;
|
|
3310
3403
|
case MAP_TYPE:
|
|
3311
|
-
|
|
3312
|
-
.map(([k, v]) => `${toEDN(k, seen)} ${toEDN(v, seen)}`)
|
|
3404
|
+
result = `#js/Map {${Array.from(value.entries())
|
|
3405
|
+
.map(([k, v]) => `${toEDN(k, seen, readably)} ${toEDN(v, seen, readably)}`)
|
|
3313
3406
|
.join(', ')}}`;
|
|
3407
|
+
break;
|
|
3314
3408
|
case LAZY_ITERABLE_TYPE:
|
|
3315
3409
|
case LIST_TYPE:
|
|
3316
|
-
|
|
3410
|
+
result = `(${mapv((v) => `${toEDN(v, seen, readably)}`, value).join(', ')})`;
|
|
3411
|
+
break;
|
|
3317
3412
|
default:
|
|
3318
3413
|
// Non-plain objects (Promise, Error, Date, class instances, ...) have a
|
|
3319
3414
|
// constructor other than Object. Print them as #<Name> rather than {}
|
|
3320
3415
|
// (which is what Object.keys would yield for opaque values like a
|
|
3321
3416
|
// Promise).
|
|
3322
3417
|
if (value.constructor && value.constructor !== Object) {
|
|
3418
|
+
seen.delete(value);
|
|
3323
3419
|
return `#<${value.constructor.name}>`;
|
|
3324
3420
|
}
|
|
3325
3421
|
keys = Object.keys(value);
|
|
3326
|
-
|
|
3422
|
+
result = `{${keys.map((k) => `:${k} ${toEDN(value[k], seen, readably)}`).join(', ')}}`;
|
|
3327
3423
|
}
|
|
3424
|
+
seen.delete(value);
|
|
3425
|
+
return result;
|
|
3328
3426
|
}
|
|
3329
3427
|
|
|
3330
3428
|
return `#object[${value.constructor.name}]`;
|
|
@@ -3335,5 +3433,6 @@ export function pr_str(...xs) {
|
|
|
3335
3433
|
}
|
|
3336
3434
|
|
|
3337
3435
|
export function prn(...xs) {
|
|
3338
|
-
|
|
3436
|
+
_STAR_print_fn_STAR_.val(pr_str(...xs));
|
|
3437
|
+
if (_STAR_print_newline_STAR_.val) _STAR_print_fn_STAR_.val('\n');
|
|
3339
3438
|
}
|