squint-cljs 0.14.200 → 0.14.202
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli.js +108 -108
- package/lib/cljs.pprint.js +260 -260
- package/lib/compiler.js +1333 -1290
- package/lib/compiler.node.js +45 -45
- package/lib/compiler.sci.js +1277 -1276
- package/lib/node.nrepl_server.js +29 -29
- package/lib/squint.core.umd.js +3 -3
- package/package.json +1 -1
- package/src/squint/core.js +415 -97
- package/src/squint/multi.js +65 -8
- package/src/squint/string.js +22 -5
package/src/squint/multi.js
CHANGED
|
@@ -46,6 +46,46 @@ function gh() {
|
|
|
46
46
|
return _globalHierarchy ?? (_globalHierarchy = make_hierarchy());
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// A hierarchy may also be a plain map literal like
|
|
50
|
+
// {:parents {} :ancestors {} :descendants {}} with set values, as in CLJS.
|
|
51
|
+
// Normalize such a rep to the Map-based one the internals expect.
|
|
52
|
+
function fieldMap(m) {
|
|
53
|
+
if (m instanceof Map) return m;
|
|
54
|
+
const out = new Map();
|
|
55
|
+
if (m) for (const k of Object.keys(m)) out.set(k, new Set(m[k]));
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
function toHierarchy(h) {
|
|
59
|
+
if (h.parents instanceof Map && h.ancestors instanceof Map && h.descendants instanceof Map) {
|
|
60
|
+
return h;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
parents: fieldMap(h.parents),
|
|
64
|
+
ancestors: fieldMap(h.ancestors),
|
|
65
|
+
descendants: fieldMap(h.descendants),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// derive/underive with an explicit hierarchy throw on a malformed one,
|
|
70
|
+
// like CLJS. A field is a map: a js/Map or a plain object.
|
|
71
|
+
function checkHierarchy(h) {
|
|
72
|
+
const ok =
|
|
73
|
+
h != null &&
|
|
74
|
+
typeof h === 'object' &&
|
|
75
|
+
['parents', 'ancestors', 'descendants'].every((f) => {
|
|
76
|
+
const m = h[f];
|
|
77
|
+
return m instanceof Map || (m != null && typeof m === 'object' && m.constructor === Object);
|
|
78
|
+
});
|
|
79
|
+
if (!ok) throw new Error('Invalid hierarchy: expected map with :parents, :ancestors and :descendants');
|
|
80
|
+
return h;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// keywords and symbols are strings in squint; namespaced means a '/' past
|
|
84
|
+
// position 0, the same threshold as `namespace`
|
|
85
|
+
function namespaced(x) {
|
|
86
|
+
return typeof x === 'string' && x.indexOf('/') > 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
49
89
|
function _isa(h, child, parent) {
|
|
50
90
|
if (_EQ_(child, parent)) return true;
|
|
51
91
|
if (typeof child === 'function' && typeof parent === 'function') {
|
|
@@ -64,7 +104,7 @@ function _isa(h, child, parent) {
|
|
|
64
104
|
|
|
65
105
|
export function isa_QMARK_(a, b, c) {
|
|
66
106
|
if (c === undefined) return _isa(gh(), a, b);
|
|
67
|
-
return _isa(a, b, c);
|
|
107
|
+
return _isa(toHierarchy(a), b, c);
|
|
68
108
|
}
|
|
69
109
|
|
|
70
110
|
function _deriveInto(h, tag, parent) {
|
|
@@ -102,6 +142,11 @@ function _deriveInto(h, tag, parent) {
|
|
|
102
142
|
|
|
103
143
|
export function derive(a, b, c) {
|
|
104
144
|
if (c === undefined) {
|
|
145
|
+
// validation matches the CLJS asserts
|
|
146
|
+
if (!namespaced(b)) throw new Error('Parent must be a namespace-qualified keyword or symbol');
|
|
147
|
+
if (!(typeof a === 'function' || namespaced(a))) {
|
|
148
|
+
throw new Error('Tag must be a namespace-qualified keyword or symbol, or a class');
|
|
149
|
+
}
|
|
105
150
|
// Rebuild-and-swap the global hierarchy so its identity changes;
|
|
106
151
|
// MultiFn's cache compares hierarchy identity to decide when to
|
|
107
152
|
// invalidate, so in-place mutation would leave stale cached
|
|
@@ -111,6 +156,14 @@ export function derive(a, b, c) {
|
|
|
111
156
|
_deriveInto(_globalHierarchy, a, b);
|
|
112
157
|
return null;
|
|
113
158
|
}
|
|
159
|
+
checkHierarchy(a);
|
|
160
|
+
// vectors are allowed as compound dispatch tags, beyond CLJS
|
|
161
|
+
if (!(typeof b === 'function' || typeof b === 'string' || Array.isArray(b))) {
|
|
162
|
+
throw new Error('Tag must be a keyword or symbol, or a class');
|
|
163
|
+
}
|
|
164
|
+
if (!(typeof c === 'string' || Array.isArray(c))) {
|
|
165
|
+
throw new Error('Parent must be a keyword or symbol');
|
|
166
|
+
}
|
|
114
167
|
const next = cloneHierarchy(a);
|
|
115
168
|
_deriveInto(next, b, c);
|
|
116
169
|
return next;
|
|
@@ -125,15 +178,15 @@ function rebuildFromPairs(pairs) {
|
|
|
125
178
|
function cloneHierarchy(h) {
|
|
126
179
|
const out = make_hierarchy();
|
|
127
180
|
for (const f of ['parents', 'ancestors', 'descendants']) {
|
|
128
|
-
for (const [k, s] of h[f]) out[f].set(k, new Set(s));
|
|
181
|
+
for (const [k, s] of fieldMap(h[f])) out[f].set(k, new Set(s));
|
|
129
182
|
}
|
|
130
183
|
return out;
|
|
131
184
|
}
|
|
132
185
|
|
|
133
186
|
export function underive(a, b, c) {
|
|
134
|
-
const [h, tag, parent] = c === undefined ? [gh(), a, b] : [a, b, c];
|
|
187
|
+
const [h, tag, parent] = c === undefined ? [gh(), a, b] : [checkHierarchy(a), b, c];
|
|
135
188
|
const pairs = [];
|
|
136
|
-
for (const [child, parents] of h.parents) {
|
|
189
|
+
for (const [child, parents] of fieldMap(h.parents)) {
|
|
137
190
|
for (const p of parents) {
|
|
138
191
|
if (!(_EQ_(child, tag) && _EQ_(p, parent))) pairs.push([child, p]);
|
|
139
192
|
}
|
|
@@ -155,9 +208,12 @@ export function underive(a, b, c) {
|
|
|
155
208
|
// internally holds the entry but .get misses on reference equality.
|
|
156
209
|
function hAnd(a, b, field) {
|
|
157
210
|
const [h, tag] = b === undefined ? [gh(), a] : [a, b];
|
|
158
|
-
|
|
211
|
+
// an invalid hierarchy gives nil instead of throwing
|
|
212
|
+
if (h == null || typeof h !== 'object') return null;
|
|
213
|
+
const m = fieldMap(h[field]);
|
|
214
|
+
const key = findKeyByEquiv(m, tag);
|
|
159
215
|
if (key === undefined) return null;
|
|
160
|
-
const s =
|
|
216
|
+
const s = m.get(key);
|
|
161
217
|
return s && s.size ? new Set(s) : null;
|
|
162
218
|
}
|
|
163
219
|
export function parents(a, b) { return hAnd(a, b, 'parents'); }
|
|
@@ -220,7 +276,8 @@ class MultiFn {
|
|
|
220
276
|
this.resetCache();
|
|
221
277
|
}
|
|
222
278
|
findBest(val) {
|
|
223
|
-
|
|
279
|
+
// an atom-held hierarchy can hold the plain-map rep
|
|
280
|
+
const h = toHierarchy(this.hierarchy.deref());
|
|
224
281
|
let best = null;
|
|
225
282
|
for (const [dv, fn] of this.methodTable) {
|
|
226
283
|
if (_isa(h, val, dv)) {
|
|
@@ -279,7 +336,7 @@ export function defmulti(name, dispatchFn, opts) {
|
|
|
279
336
|
let hierarchy;
|
|
280
337
|
if (opts.hierarchy == null) hierarchy = { deref: gh };
|
|
281
338
|
else if (typeof opts.hierarchy.deref === 'function') hierarchy = opts.hierarchy;
|
|
282
|
-
else { const h = opts.hierarchy; hierarchy = { deref: () => h }; }
|
|
339
|
+
else { const h = toHierarchy(opts.hierarchy); hierarchy = { deref: () => h }; }
|
|
283
340
|
const mf = new MultiFn(name, dispatchFn, defaultVal, hierarchy);
|
|
284
341
|
const call = function (...args) { return mf.invoke(args); };
|
|
285
342
|
call.multiFn = mf;
|
package/src/squint/string.js
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
/*eslint no-unused-vars: ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_", "destructuredArrayIgnorePattern": "^_"}]*/
|
|
2
2
|
|
|
3
|
-
import { iterable, string_QMARK_ } from './core.js';
|
|
3
|
+
import { get, iterable, string_QMARK_ } from './core.js';
|
|
4
4
|
|
|
5
5
|
export function blank_QMARK_(s) {
|
|
6
|
-
if (
|
|
6
|
+
if (s == null) return true;
|
|
7
|
+
// a non-string is not blank, like CLJS
|
|
8
|
+
if (typeof s !== 'string') return false;
|
|
7
9
|
if (s.length === 0) return true;
|
|
8
|
-
if (s.
|
|
10
|
+
if (s.trimStart().length === 0) return true;
|
|
9
11
|
return false;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
export function escape(s, cmap) {
|
|
15
|
+
let buffer = '';
|
|
16
|
+
const length = s.length;
|
|
17
|
+
for (let i = 0; i < length; i++) {
|
|
18
|
+
const ch = s.charAt(i);
|
|
19
|
+
const replacement = get(cmap, ch);
|
|
20
|
+
buffer += replacement != null ? String(replacement) : ch;
|
|
21
|
+
}
|
|
22
|
+
return buffer;
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
export function join(sep, coll) {
|
|
13
26
|
if (coll === undefined) {
|
|
14
27
|
coll = sep;
|
|
@@ -32,11 +45,11 @@ export function trim(s) {
|
|
|
32
45
|
}
|
|
33
46
|
|
|
34
47
|
export function triml(s) {
|
|
35
|
-
return s.
|
|
48
|
+
return s.trimStart();
|
|
36
49
|
}
|
|
37
50
|
|
|
38
51
|
export function trimr(s) {
|
|
39
|
-
return s.
|
|
52
|
+
return s.trimEnd();
|
|
40
53
|
}
|
|
41
54
|
|
|
42
55
|
function discardTrailingIfNeeded(limit, v) {
|
|
@@ -162,6 +175,10 @@ export function capitalize(s) {
|
|
|
162
175
|
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
163
176
|
}
|
|
164
177
|
|
|
178
|
+
export function reverse(s) {
|
|
179
|
+
return [...s].reverse().join('');
|
|
180
|
+
}
|
|
181
|
+
|
|
165
182
|
export function includes_QMARK_(s, substr) {
|
|
166
183
|
return s.indexOf(substr) != -1;
|
|
167
184
|
}
|