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.
- package/README.md +3 -0
- package/lib/cli.js +115 -113
- package/lib/cljs.pprint.js +262 -262
- package/lib/compiler.js +1400 -1367
- package/lib/compiler.node.js +45 -45
- package/lib/compiler.sci.js +1280 -1281
- package/lib/node.nrepl_server.js +29 -29
- package/lib/squint.core.umd.js +5 -3
- package/package.json +3 -1
- package/src/squint/core.js +743 -51
- package/src/squint/multi.js +9 -1
- package/src/squint/record.js +103 -0
- package/src/squint/set.js +142 -46
package/src/squint/multi.js
CHANGED
|
@@ -208,6 +208,8 @@ export function underive(a, b, c) {
|
|
|
208
208
|
// internally holds the entry but .get misses on reference equality.
|
|
209
209
|
function hAnd(a, b, field) {
|
|
210
210
|
const [h, tag] = b === undefined ? [gh(), a] : [a, b];
|
|
211
|
+
// an invalid hierarchy gives nil instead of throwing
|
|
212
|
+
if (h == null || typeof h !== 'object') return null;
|
|
211
213
|
const m = fieldMap(h[field]);
|
|
212
214
|
const key = findKeyByEquiv(m, tag);
|
|
213
215
|
if (key === undefined) return null;
|
|
@@ -216,7 +218,13 @@ function hAnd(a, b, field) {
|
|
|
216
218
|
}
|
|
217
219
|
export function parents(a, b) { return hAnd(a, b, 'parents'); }
|
|
218
220
|
export function ancestors(a, b) { return hAnd(a, b, 'ancestors'); }
|
|
219
|
-
export function descendants(a, b) {
|
|
221
|
+
export function descendants(a, b) {
|
|
222
|
+
// like CLJS: a constructor has no derive-based descendants, JS type
|
|
223
|
+
// inheritance is not tracked
|
|
224
|
+
const tag = b === undefined ? a : b;
|
|
225
|
+
if (typeof tag === 'function') throw new Error("Can't get descendants of constructors");
|
|
226
|
+
return hAnd(a, b, 'descendants');
|
|
227
|
+
}
|
|
220
228
|
|
|
221
229
|
function _prefers(prefer, a, b) {
|
|
222
230
|
const key = findKeyByEquiv(prefer, a);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IRecord,
|
|
3
|
+
ILookup__lookup,
|
|
4
|
+
IAssociative__assoc,
|
|
5
|
+
IAssociative__contains_key_QMARK_,
|
|
6
|
+
IMap__dissoc,
|
|
7
|
+
ICounted__count,
|
|
8
|
+
IKVReduce__kv_reduce,
|
|
9
|
+
ICollection__conj,
|
|
10
|
+
IEquiv__equiv,
|
|
11
|
+
ISeqable__seq,
|
|
12
|
+
ISeqable,
|
|
13
|
+
_EQ_,
|
|
14
|
+
vector_QMARK_,
|
|
15
|
+
seq,
|
|
16
|
+
} from './core.js';
|
|
17
|
+
|
|
18
|
+
// shared defrecord implementations: every record type points its protocol
|
|
19
|
+
// slots at these, so call sites stay monomorphic across record types
|
|
20
|
+
function recordLookup(rec, k, nf) {
|
|
21
|
+
const v = rec[k];
|
|
22
|
+
return v === undefined ? nf : v;
|
|
23
|
+
}
|
|
24
|
+
function recordCopy(rec) {
|
|
25
|
+
return Object.assign(Object.create(Object.getPrototypeOf(rec)), rec);
|
|
26
|
+
}
|
|
27
|
+
function recordAssoc(rec, k, v) {
|
|
28
|
+
const r = recordCopy(rec);
|
|
29
|
+
r[k] = v;
|
|
30
|
+
return r;
|
|
31
|
+
}
|
|
32
|
+
function recordContains(rec, k) {
|
|
33
|
+
return Object.prototype.hasOwnProperty.call(rec, k);
|
|
34
|
+
}
|
|
35
|
+
function recordDissoc(rec, k) {
|
|
36
|
+
// removing a basis field demotes to a plain map, like CLJS
|
|
37
|
+
if (rec[IRecord.__sym].includes(k)) {
|
|
38
|
+
const m = { ...rec };
|
|
39
|
+
delete m[k];
|
|
40
|
+
return m;
|
|
41
|
+
}
|
|
42
|
+
const r = recordCopy(rec);
|
|
43
|
+
delete r[k];
|
|
44
|
+
return r;
|
|
45
|
+
}
|
|
46
|
+
function recordCount(rec) {
|
|
47
|
+
return Object.keys(rec).length;
|
|
48
|
+
}
|
|
49
|
+
function recordKvReduce(rec, f, init) {
|
|
50
|
+
let acc = init;
|
|
51
|
+
for (const k of Object.keys(rec)) acc = f(acc, k, rec[k]);
|
|
52
|
+
return acc;
|
|
53
|
+
}
|
|
54
|
+
function recordConj(rec, x) {
|
|
55
|
+
if (vector_QMARK_(x)) return recordAssoc(rec, x[0], x[1]);
|
|
56
|
+
let r = rec;
|
|
57
|
+
for (const e of seq(x) ?? []) r = recordAssoc(r, e[0], e[1]);
|
|
58
|
+
return r;
|
|
59
|
+
}
|
|
60
|
+
function recordEquiv(rec, other) {
|
|
61
|
+
if (other == null || Object.getPrototypeOf(rec) !== Object.getPrototypeOf(other)) return false;
|
|
62
|
+
const ka = Object.keys(rec);
|
|
63
|
+
if (ka.length !== Object.keys(other).length) return false;
|
|
64
|
+
for (const k of ka) {
|
|
65
|
+
if (!Object.prototype.hasOwnProperty.call(other, k) || !_EQ_(rec[k], other[k])) return false;
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
function recordSeq(rec) {
|
|
70
|
+
return seq(Object.entries(rec));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function attach(proto, basis, aliases) {
|
|
74
|
+
proto[IRecord.__sym] = basis;
|
|
75
|
+
proto[ILookup__lookup] = recordLookup;
|
|
76
|
+
proto[IAssociative__assoc] = recordAssoc;
|
|
77
|
+
proto[IAssociative__contains_key_QMARK_] = recordContains;
|
|
78
|
+
proto[IMap__dissoc] = recordDissoc;
|
|
79
|
+
proto[ICounted__count] = recordCount;
|
|
80
|
+
proto[IKVReduce__kv_reduce] = recordKvReduce;
|
|
81
|
+
proto[ICollection__conj] = recordConj;
|
|
82
|
+
proto[IEquiv__equiv] = recordEquiv;
|
|
83
|
+
proto[ISeqable__seq] = recordSeq;
|
|
84
|
+
proto[ISeqable.__sym] = true;
|
|
85
|
+
proto[Symbol.iterator] = function* () {
|
|
86
|
+
for (const k of Object.keys(this)) yield [k, this[k]];
|
|
87
|
+
};
|
|
88
|
+
Object.defineProperty(proto, Symbol.toStringTag, {
|
|
89
|
+
get() { return this.constructor.name; },
|
|
90
|
+
});
|
|
91
|
+
proto[Symbol.for('nodejs.util.inspect.custom')] = function (_depth, opts, inspect) {
|
|
92
|
+
return '#' + this.constructor.name + ' ' + inspect({ ...this }, opts);
|
|
93
|
+
};
|
|
94
|
+
if (aliases !== undefined) {
|
|
95
|
+
for (const munged of Object.keys(aliases)) {
|
|
96
|
+
const field = aliases[munged];
|
|
97
|
+
Object.defineProperty(proto, munged, {
|
|
98
|
+
get() { return this[field]; },
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
package/src/squint/set.js
CHANGED
|
@@ -1,43 +1,120 @@
|
|
|
1
1
|
import * as core from './core.js';
|
|
2
|
+
import {
|
|
3
|
+
ICounted__count,
|
|
4
|
+
IAssociative__contains_key_QMARK_,
|
|
5
|
+
ICollection__conj,
|
|
6
|
+
ISet__disjoin,
|
|
7
|
+
IEditableCollection__as_transient,
|
|
8
|
+
ITransientCollection__conj_BANG_,
|
|
9
|
+
ITransientCollection__persistent_BANG_,
|
|
10
|
+
ITransientSet__disjoin_BANG_,
|
|
11
|
+
} from './core.js';
|
|
2
12
|
|
|
3
13
|
function _bubble_max_key(k, coll) {
|
|
4
14
|
const max = core.max_key(k, ...coll);
|
|
5
15
|
return [max, ...coll.filter(x => x !== max)];
|
|
6
16
|
}
|
|
7
17
|
|
|
18
|
+
// a js/Set or set-like with reference .has/.add (SortedSet); a persistent
|
|
19
|
+
// set from squint.immutable dispatches through core instead
|
|
20
|
+
function jsSetLike(x) {
|
|
21
|
+
return x instanceof Set || (x != null && typeof x.has === 'function' && typeof x.add === 'function');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// the persistent paths dispatch through the slot symbols directly: the
|
|
25
|
+
// symbols are tiny consts, where the core wrapper fns (count, conj!, ...)
|
|
26
|
+
// drag their whole dispatch chains into js-Set-only bundles
|
|
27
|
+
function setSize(x) {
|
|
28
|
+
return typeof x.size === 'number' ? x.size : x[ICounted__count](x);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function setHas(x, e) {
|
|
32
|
+
return jsSetLike(x) ? x.has(e) : x[IAssociative__contains_key_QMARK_](x, e);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// fold elements into a copy of target, preserving its type: js/Set mutates a
|
|
36
|
+
// copy, a protocol set goes through its transient when it has one and folds
|
|
37
|
+
// persistent -conj otherwise (a set type need not implement transients)
|
|
38
|
+
function addAll(target, elems) {
|
|
39
|
+
if (jsSetLike(target)) {
|
|
40
|
+
const res = new Set(target);
|
|
41
|
+
for (const e of elems) res.add(e);
|
|
42
|
+
return res;
|
|
43
|
+
}
|
|
44
|
+
const es = core.iterable(elems);
|
|
45
|
+
if (target[IEditableCollection__as_transient] !== undefined) {
|
|
46
|
+
let t = target[IEditableCollection__as_transient](target);
|
|
47
|
+
for (const e of es) t = t[ITransientCollection__conj_BANG_](t, e);
|
|
48
|
+
return t[ITransientCollection__persistent_BANG_](t);
|
|
49
|
+
}
|
|
50
|
+
let res = target;
|
|
51
|
+
for (const e of es) res = res[ICollection__conj](res, e);
|
|
52
|
+
return res;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// remove each elem for which pred is true, preserving the set's type
|
|
56
|
+
function removeWhere(xset, pred) {
|
|
57
|
+
const es = core.iterable(xset);
|
|
58
|
+
if (xset[IEditableCollection__as_transient] !== undefined) {
|
|
59
|
+
let t = xset[IEditableCollection__as_transient](xset);
|
|
60
|
+
for (const e of es) {
|
|
61
|
+
if (pred(e)) t = t[ITransientSet__disjoin_BANG_](t, e);
|
|
62
|
+
}
|
|
63
|
+
return t[ITransientCollection__persistent_BANG_](t);
|
|
64
|
+
}
|
|
65
|
+
let res = xset;
|
|
66
|
+
for (const e of es) {
|
|
67
|
+
if (pred(e)) res = res[ISet__disjoin](res, e);
|
|
68
|
+
}
|
|
69
|
+
return res;
|
|
70
|
+
}
|
|
71
|
+
|
|
8
72
|
function _intersection2(x, y) {
|
|
9
|
-
if (x
|
|
73
|
+
if (setSize(x) > setSize(y)) {
|
|
10
74
|
const tmp = y;
|
|
11
75
|
y = x;
|
|
12
76
|
x = tmp;
|
|
13
77
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
78
|
+
if (jsSetLike(x)) {
|
|
79
|
+
const res = new Set();
|
|
80
|
+
for (const elem of x) {
|
|
81
|
+
if (setHas(y, elem)) {
|
|
82
|
+
res.add(elem);
|
|
83
|
+
}
|
|
18
84
|
}
|
|
85
|
+
return res;
|
|
19
86
|
}
|
|
20
|
-
|
|
87
|
+
// protocol set: disj the non-members, keeping the type and sharing
|
|
88
|
+
return removeWhere(x, (elem) => !setHas(y, elem));
|
|
21
89
|
}
|
|
22
90
|
|
|
23
91
|
export function intersection(...xs) {
|
|
24
92
|
switch (xs.length) {
|
|
25
93
|
case 0: return null;
|
|
26
94
|
case 1: return xs[0];
|
|
27
|
-
case 2: return xs[0]
|
|
28
|
-
|
|
29
|
-
_intersection2(xs[1], xs[0]);
|
|
30
|
-
default: return _bubble_max_key((x) => 0 - x.size, xs).reduce(_intersection2);
|
|
95
|
+
case 2: return _intersection2(xs[0], xs[1]);
|
|
96
|
+
default: return _bubble_max_key((x) => 0 - setSize(x), xs).reduce(_intersection2);
|
|
31
97
|
}
|
|
32
98
|
}
|
|
33
99
|
|
|
34
100
|
function _difference2(x, y) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
101
|
+
if (jsSetLike(x)) {
|
|
102
|
+
const res = new Set();
|
|
103
|
+
for (const elem of x) {
|
|
104
|
+
if (!setHas(y, elem)) {
|
|
105
|
+
res.add(elem);
|
|
106
|
+
}
|
|
39
107
|
}
|
|
108
|
+
return res;
|
|
109
|
+
}
|
|
110
|
+
const ys = core.iterable(y);
|
|
111
|
+
if (x[IEditableCollection__as_transient] !== undefined) {
|
|
112
|
+
let t = x[IEditableCollection__as_transient](x);
|
|
113
|
+
for (const elem of ys) t = t[ITransientSet__disjoin_BANG_](t, elem);
|
|
114
|
+
return t[ITransientCollection__persistent_BANG_](t);
|
|
40
115
|
}
|
|
116
|
+
let res = x;
|
|
117
|
+
for (const elem of ys) res = res[ISet__disjoin](res, elem);
|
|
41
118
|
return res;
|
|
42
119
|
}
|
|
43
120
|
|
|
@@ -51,32 +128,31 @@ export function difference(...xs) {
|
|
|
51
128
|
}
|
|
52
129
|
|
|
53
130
|
function _union2(x, y) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
131
|
+
if (setSize(x) < setSize(y)) {
|
|
132
|
+
const tmp = y;
|
|
133
|
+
y = x;
|
|
134
|
+
x = tmp;
|
|
57
135
|
}
|
|
58
|
-
return
|
|
136
|
+
return addAll(x, y);
|
|
59
137
|
}
|
|
60
138
|
|
|
61
139
|
export function union(...xs) {
|
|
62
140
|
switch (xs.length) {
|
|
63
141
|
case 0: return null;
|
|
64
142
|
case 1: return xs[0];
|
|
65
|
-
case 2: return xs[0]
|
|
66
|
-
|
|
67
|
-
_union2(xs[1], xs[0]);
|
|
68
|
-
default: return _bubble_max_key((x) => x.size, xs).reduce(_union2);
|
|
143
|
+
case 2: return _union2(xs[0], xs[1]);
|
|
144
|
+
default: return _bubble_max_key((x) => setSize(x), xs).reduce(_union2);
|
|
69
145
|
}
|
|
70
146
|
}
|
|
71
147
|
|
|
72
148
|
function _subset_QMARK_2(x, y) {
|
|
73
|
-
for (const elem of x) {
|
|
74
|
-
if (!y
|
|
149
|
+
for (const elem of core.iterable(x)) {
|
|
150
|
+
if (!setHas(y, elem)) {
|
|
75
151
|
return false;
|
|
76
152
|
}
|
|
77
153
|
}
|
|
78
154
|
return true;
|
|
79
|
-
}
|
|
155
|
+
}
|
|
80
156
|
|
|
81
157
|
export function subset_QMARK_(x, y) {
|
|
82
158
|
if (x === undefined) {
|
|
@@ -85,21 +161,12 @@ export function subset_QMARK_(x, y) {
|
|
|
85
161
|
if (y === undefined) {
|
|
86
162
|
return false;
|
|
87
163
|
}
|
|
88
|
-
if (x
|
|
164
|
+
if (setSize(x) > setSize(y)) {
|
|
89
165
|
return false;
|
|
90
166
|
}
|
|
91
167
|
return _subset_QMARK_2(x, y);
|
|
92
168
|
}
|
|
93
169
|
|
|
94
|
-
function _superset_QMARK_2(x, y) {
|
|
95
|
-
for (const elem of x) {
|
|
96
|
-
if (!y.has(elem)) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
170
|
export function superset_QMARK_(x, y) {
|
|
104
171
|
if (x === undefined) {
|
|
105
172
|
return true;
|
|
@@ -107,28 +174,44 @@ export function superset_QMARK_(x, y) {
|
|
|
107
174
|
if (y === undefined) {
|
|
108
175
|
return true;
|
|
109
176
|
}
|
|
110
|
-
if (x
|
|
177
|
+
if (setSize(x) < setSize(y)) {
|
|
111
178
|
return false;
|
|
112
179
|
}
|
|
113
|
-
return
|
|
180
|
+
return _subset_QMARK_2(y, x);
|
|
114
181
|
}
|
|
115
182
|
|
|
116
183
|
export function select(pred, xset) {
|
|
117
184
|
if (xset === undefined) {
|
|
118
185
|
return null;
|
|
119
186
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
187
|
+
if (jsSetLike(xset)) {
|
|
188
|
+
const res = new Set();
|
|
189
|
+
for (const elem of xset) {
|
|
190
|
+
if (core.truth_(pred(elem))) {
|
|
191
|
+
res.add(elem);
|
|
192
|
+
}
|
|
124
193
|
}
|
|
194
|
+
return res;
|
|
125
195
|
}
|
|
126
|
-
return
|
|
196
|
+
return removeWhere(xset, (elem) => !core.truth_(pred(elem)));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// true when m is an immutable slot-map: mutate-in-place helpers would corrupt it
|
|
200
|
+
function slotMap(m) {
|
|
201
|
+
return m != null && m[core.IAssociative__assoc] !== undefined;
|
|
127
202
|
}
|
|
128
203
|
|
|
129
204
|
export function rename_keys(map, kmap) {
|
|
130
205
|
const ks = core.keys(kmap);
|
|
131
206
|
let without = core.dissoc(map, ...ks);
|
|
207
|
+
if (slotMap(without)) {
|
|
208
|
+
return ks.reduce((m, k) => {
|
|
209
|
+
if (core.contains_QMARK_(map, k)) {
|
|
210
|
+
return core.assoc(m, core.get(kmap, k), core.get(map, k));
|
|
211
|
+
}
|
|
212
|
+
return m;
|
|
213
|
+
}, without);
|
|
214
|
+
}
|
|
132
215
|
if (without === map) {
|
|
133
216
|
without = {...map};
|
|
134
217
|
}
|
|
@@ -142,18 +225,31 @@ export function rename_keys(map, kmap) {
|
|
|
142
225
|
}
|
|
143
226
|
|
|
144
227
|
export function rename(xrel, kmap) {
|
|
145
|
-
return
|
|
228
|
+
return into_set_like(xrel, core.map(x => rename_keys(x, kmap), xrel));
|
|
146
229
|
}
|
|
147
230
|
|
|
148
231
|
export function project(xrel, ...ks) {
|
|
149
|
-
return
|
|
232
|
+
return into_set_like(xrel, core.map(x => core.select_keys(x, ...ks), xrel));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// an empty set of the same kind as rel (a persistent set stays persistent),
|
|
236
|
+
// filled from elems
|
|
237
|
+
function into_set_like(rel, elems) {
|
|
238
|
+
const empty = rel != null && !jsSetLike(rel) && rel[ISet__disjoin] !== undefined
|
|
239
|
+
? core.empty(rel)
|
|
240
|
+
: new Set();
|
|
241
|
+
return addAll(empty, elems);
|
|
150
242
|
}
|
|
151
243
|
|
|
152
244
|
export function map_invert(xmap) {
|
|
153
245
|
if (xmap === undefined) {
|
|
154
246
|
return {};
|
|
155
247
|
}
|
|
156
|
-
|
|
248
|
+
const empty = core.empty(xmap);
|
|
249
|
+
if (slotMap(empty)) {
|
|
250
|
+
return core.reduce_kv((m, k, v) => core.assoc(m, v, k), empty, xmap);
|
|
251
|
+
}
|
|
252
|
+
return core.reduce_kv((m, k, v) => core.assoc_BANG_(m, v, k), empty, xmap);
|
|
157
253
|
}
|
|
158
254
|
|
|
159
255
|
export function join(xrel, yrel, kmap) {
|
|
@@ -179,4 +275,4 @@ export function join(xrel, yrel, kmap) {
|
|
|
179
275
|
return found ? core.reduce((acc, y) => acc.add(core.merge(y, x)), ret, found) : ret;
|
|
180
276
|
}, new Set(), s);
|
|
181
277
|
}
|
|
182
|
-
}
|
|
278
|
+
}
|