squint-cljs 0.14.199 → 0.14.201
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 +113 -113
- package/lib/cljs.pprint.js +258 -258
- package/lib/compiler.js +1318 -1279
- package/lib/compiler.node.js +45 -40
- package/lib/compiler.sci.js +1267 -1263
- 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 -120
- package/src/squint/multi.js +63 -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,10 @@ 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
|
-
const
|
|
211
|
+
const m = fieldMap(h[field]);
|
|
212
|
+
const key = findKeyByEquiv(m, tag);
|
|
159
213
|
if (key === undefined) return null;
|
|
160
|
-
const s =
|
|
214
|
+
const s = m.get(key);
|
|
161
215
|
return s && s.size ? new Set(s) : null;
|
|
162
216
|
}
|
|
163
217
|
export function parents(a, b) { return hAnd(a, b, 'parents'); }
|
|
@@ -220,7 +274,8 @@ class MultiFn {
|
|
|
220
274
|
this.resetCache();
|
|
221
275
|
}
|
|
222
276
|
findBest(val) {
|
|
223
|
-
|
|
277
|
+
// an atom-held hierarchy can hold the plain-map rep
|
|
278
|
+
const h = toHierarchy(this.hierarchy.deref());
|
|
224
279
|
let best = null;
|
|
225
280
|
for (const [dv, fn] of this.methodTable) {
|
|
226
281
|
if (_isa(h, val, dv)) {
|
|
@@ -279,7 +334,7 @@ export function defmulti(name, dispatchFn, opts) {
|
|
|
279
334
|
let hierarchy;
|
|
280
335
|
if (opts.hierarchy == null) hierarchy = { deref: gh };
|
|
281
336
|
else if (typeof opts.hierarchy.deref === 'function') hierarchy = opts.hierarchy;
|
|
282
|
-
else { const h = opts.hierarchy; hierarchy = { deref: () => h }; }
|
|
337
|
+
else { const h = toHierarchy(opts.hierarchy); hierarchy = { deref: () => h }; }
|
|
283
338
|
const mf = new MultiFn(name, dispatchFn, defaultVal, hierarchy);
|
|
284
339
|
const call = function (...args) { return mf.invoke(args); };
|
|
285
340
|
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
|
}
|