aontu 0.67.0 → 0.69.0
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/dist/alias.d.ts +12 -1
- package/dist/alias.js +176 -6
- package/dist/alias.js.map +1 -1
- package/dist/aliasname.d.ts +19 -0
- package/dist/aliasname.js +65 -0
- package/dist/aliasname.js.map +1 -0
- package/dist/aontu.d.ts +1 -1
- package/dist/aontu.js +21 -8
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.js +1 -1
- package/dist/aontumodel.js.map +1 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.js +29 -13
- package/dist/cli.js.map +1 -1
- package/dist/ctx.d.ts +1 -0
- package/dist/ctx.js +1 -0
- package/dist/ctx.js.map +1 -1
- package/dist/err.js +18 -1
- package/dist/err.js.map +1 -1
- package/dist/format.js +14 -0
- package/dist/format.js.map +1 -1
- package/dist/helpdoc.js +1 -1
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.js +171 -0
- package/dist/hints.js.map +1 -1
- package/dist/lang.js +325 -38
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +10 -4
- package/dist/lsp.js +116 -7
- package/dist/lsp.js.map +1 -1
- package/dist/site.d.ts +9 -0
- package/dist/site.js +2 -1
- package/dist/site.js.map +1 -1
- package/dist/subsume.js +6 -1
- package/dist/subsume.js.map +1 -1
- package/dist/val/BagVal.d.ts +1 -0
- package/dist/val/BagVal.js +3 -0
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/EmitFuncVal.js +2 -1
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +1 -1
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +2 -1
- package/dist/val/FuncBaseVal.js +25 -1
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/MapVal.js +10 -4
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +2 -1
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +3 -0
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/RecurseVal.d.ts +1 -0
- package/dist/val/RecurseVal.js +7 -3
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.d.ts +1 -0
- package/dist/val/RefVal.js +47 -18
- package/dist/val/RefVal.js.map +1 -1
- package/dist/vet.d.ts +2 -1
- package/dist/vet.js +51 -6
- package/dist/vet.js.map +1 -1
- package/package.json +1 -1
- package/skill/error-codes.md +25 -1
- package/src/alias.ts +214 -6
- package/src/aliasname.ts +95 -0
- package/src/aontu.ts +23 -9
- package/src/aontumodel.ts +1 -1
- package/src/cli.ts +35 -13
- package/src/ctx.ts +4 -1
- package/src/err.ts +19 -1
- package/src/format.ts +14 -0
- package/src/helpdoc.ts +1 -1
- package/src/hints.ts +228 -0
- package/src/lang.ts +370 -33
- package/src/lsp.ts +136 -6
- package/src/site.ts +15 -1
- package/src/subsume.ts +9 -2
- package/src/val/BagVal.ts +4 -0
- package/src/val/EmitFuncVal.ts +3 -2
- package/src/val/FilterFuncVal.ts +2 -2
- package/src/val/FuncBaseVal.ts +30 -1
- package/src/val/MapVal.ts +10 -4
- package/src/val/MatchFuncVal.ts +3 -2
- package/src/val/NilVal.ts +3 -0
- package/src/val/RecurseVal.ts +8 -3
- package/src/val/RefVal.ts +49 -19
- package/src/vet.ts +55 -6
package/dist/lang.js
CHANGED
|
@@ -37,6 +37,8 @@ const DisjunctVal_1 = require("./val/DisjunctVal");
|
|
|
37
37
|
const IntegerVal_1 = require("./val/IntegerVal");
|
|
38
38
|
const ListVal_1 = require("./val/ListVal");
|
|
39
39
|
const MapVal_1 = require("./val/MapVal");
|
|
40
|
+
const Val_1 = require("./val/Val");
|
|
41
|
+
const ctx_1 = require("./ctx");
|
|
40
42
|
const NilVal_1 = require("./val/NilVal");
|
|
41
43
|
const NullVal_1 = require("./val/NullVal");
|
|
42
44
|
const NumberVal_1 = require("./val/NumberVal");
|
|
@@ -93,10 +95,20 @@ const CC_0 = 48;
|
|
|
93
95
|
const CC_d = 100;
|
|
94
96
|
const CC_D = 68;
|
|
95
97
|
const CC_PCT = 37;
|
|
96
|
-
const
|
|
98
|
+
const aliasname_1 = require("./aliasname");
|
|
97
99
|
const CC_EQ = 61;
|
|
98
100
|
const CC_SP = 32;
|
|
99
101
|
const CC_TAB = 9;
|
|
102
|
+
const CC_OB = 123;
|
|
103
|
+
const WS_RE = /\s/;
|
|
104
|
+
let SCOPE_SEQ = 0;
|
|
105
|
+
const MERGE_KEY = aliasname_1.RESERVED_KEY_PREFIX + 'merge';
|
|
106
|
+
const ALIAS_MARK_KEY = aliasname_1.RESERVED_KEY_PREFIX + 'alias';
|
|
107
|
+
const OPTIONAL_MARK_KEY = aliasname_1.RESERVED_KEY_PREFIX + 'optional';
|
|
108
|
+
// `{ %a } = @"f.aon"` is the pair `<head>: <include>`, so the head is
|
|
109
|
+
// one token and the grammar needs nothing new.
|
|
110
|
+
const IMPORT_HEAD_RE = new RegExp('^(' + aliasname_1.ALIAS_SET + ')[ \\t]*=(?!=)');
|
|
111
|
+
const EXPORT_RE = /^export[ \t]*\([ \t]*([^()\s][^()]*?)[ \t]*\)/;
|
|
100
112
|
const CC_9 = 57;
|
|
101
113
|
const CC_A = 65;
|
|
102
114
|
const CC_Z = 90;
|
|
@@ -175,7 +187,7 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
175
187
|
const segs = Array.isArray(t.peg) ? t.peg :
|
|
176
188
|
('string' === typeof t.peg ? [t.peg] : []);
|
|
177
189
|
for (const seg of segs) {
|
|
178
|
-
if ('string' === typeof seg && ALIAS_RE.test(seg)) {
|
|
190
|
+
if ('string' === typeof seg && aliasname_1.ALIAS_RE.test(seg)) {
|
|
179
191
|
return addsite(new NilVal_1.NilVal({ why: 'alias_in_path' }), r, ctx);
|
|
180
192
|
}
|
|
181
193
|
}
|
|
@@ -209,13 +221,67 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
209
221
|
},
|
|
210
222
|
},
|
|
211
223
|
});
|
|
224
|
+
// THE FIXED MATCHER'S CHECK RUNS AT EVERY POSITION: `{` opens a fixed
|
|
225
|
+
// token the text check never sees.
|
|
226
|
+
jsonic.options({
|
|
227
|
+
fixed: {
|
|
228
|
+
check: (lex) => {
|
|
229
|
+
const pnt = lex.pnt;
|
|
230
|
+
const ex = lex.aontu_export;
|
|
231
|
+
// The `(` is the pair's separator, the argument its value.
|
|
232
|
+
if (null != ex && pnt.sI === ex.cl) {
|
|
233
|
+
const cltkn = lex.token('#CL', undefined, '(', pnt);
|
|
234
|
+
pnt.cI += ex.arg - pnt.sI;
|
|
235
|
+
pnt.sI = ex.arg;
|
|
236
|
+
return { done: true, token: cltkn };
|
|
237
|
+
}
|
|
238
|
+
if (null != ex && pnt.sI === ex.arg) {
|
|
239
|
+
delete lex.aontu_export;
|
|
240
|
+
const atkn = lex.token('#TX', ex.src, ex.src, pnt);
|
|
241
|
+
pnt.cI += ex.end - pnt.sI;
|
|
242
|
+
pnt.sI = ex.end;
|
|
243
|
+
return { done: true, token: atkn };
|
|
244
|
+
}
|
|
245
|
+
// THE SHORTHAND IS READ OFF THE SOURCE: a name lexes as its pair.
|
|
246
|
+
const sh = lex.aontu_shorthand;
|
|
247
|
+
if (null != sh && pnt.sI === sh.at) {
|
|
248
|
+
if (1 === sh.stage) {
|
|
249
|
+
sh.stage = 2;
|
|
250
|
+
return { done: true, token: lex.token('#CL', undefined, ':', pnt) };
|
|
251
|
+
}
|
|
252
|
+
delete lex.aontu_shorthand;
|
|
253
|
+
return {
|
|
254
|
+
done: true, token: lex.token('#VL', (r, ctx) => addsite(new RefVal_1.RefVal({ peg: [(0, aliasname_1.aliasScopedKey)(sh.name, srcUrl(ctx))], absolute: true }), r, ctx), sh.name, pnt)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
if (CC_OB === lex.src.charCodeAt(pnt.sI)) {
|
|
258
|
+
const sres = aliasname_1.ALIAS_SHORTHAND_RE.exec(lex.refwd());
|
|
259
|
+
if (null != sres) {
|
|
260
|
+
lex.aontu_shorthand_end = pnt.sI + sres[0].length;
|
|
261
|
+
}
|
|
262
|
+
const hres = IMPORT_HEAD_RE.exec(lex.refwd());
|
|
263
|
+
if (null != hres) {
|
|
264
|
+
const hsrc = hres[1];
|
|
265
|
+
lex.aontu_eq_at = pnt.sI + hres[0].length - 1;
|
|
266
|
+
const htkn = lex.token('#TX', hsrc, hsrc, pnt, {
|
|
267
|
+
aontu_import: (0, aliasname_1.aliasSetItems)(hsrc),
|
|
268
|
+
});
|
|
269
|
+
pnt.sI += hsrc.length;
|
|
270
|
+
pnt.cI += hsrc.length;
|
|
271
|
+
return { done: true, token: htkn };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return undefined;
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
});
|
|
212
278
|
jsonic.options({
|
|
213
279
|
text: {
|
|
214
280
|
check: (lex) => {
|
|
215
281
|
const pnt = lex.pnt;
|
|
216
282
|
const src = lex.src;
|
|
217
283
|
const ares = CC_PCT === src.charCodeAt(pnt.sI) ?
|
|
218
|
-
ALIAS_RE.exec(lex.refwd()) : null;
|
|
284
|
+
aliasname_1.ALIAS_RE.exec(lex.refwd()) : null;
|
|
219
285
|
if (null != ares) {
|
|
220
286
|
const asrc = ares[0];
|
|
221
287
|
let j = pnt.sI + asrc.length;
|
|
@@ -226,11 +292,45 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
226
292
|
if (CC_EQ === src.charCodeAt(j) && CC_EQ !== src.charCodeAt(j + 1)) {
|
|
227
293
|
lex.aontu_eq_at = j;
|
|
228
294
|
}
|
|
229
|
-
|
|
295
|
+
// The name is the KEY; separator and reference follow it.
|
|
296
|
+
const shend = lex.aontu_shorthand_end;
|
|
297
|
+
if (null != shend && pnt.sI < shend) {
|
|
298
|
+
let k = pnt.sI + asrc.length;
|
|
299
|
+
while (k < src.length && WS_RE.test(src[k])) {
|
|
300
|
+
k++;
|
|
301
|
+
}
|
|
302
|
+
const ktkn = lex.token('#TX', asrc.substring(1), asrc, pnt);
|
|
303
|
+
pnt.cI += k - pnt.sI;
|
|
304
|
+
pnt.sI = k;
|
|
305
|
+
lex.aontu_shorthand = { at: k, name: asrc, stage: 1 };
|
|
306
|
+
if (shend - 1 <= k) {
|
|
307
|
+
delete lex.aontu_shorthand_end;
|
|
308
|
+
}
|
|
309
|
+
return { done: true, token: ktkn };
|
|
310
|
+
}
|
|
311
|
+
const atkn = lex.token('#VL', (r, ctx) => addsite(new RefVal_1.RefVal({ peg: [(0, aliasname_1.aliasScopedKey)(asrc, srcUrl(ctx))], absolute: true }), r, ctx), asrc, pnt);
|
|
230
312
|
pnt.sI += asrc.length;
|
|
231
313
|
pnt.cI += asrc.length;
|
|
232
314
|
return { done: true, token: atkn };
|
|
233
315
|
}
|
|
316
|
+
// `export(...)`: the word is the key, spelled unwritably.
|
|
317
|
+
if (CC_e === src.charCodeAt(pnt.sI)) {
|
|
318
|
+
const eres = EXPORT_RE.exec(lex.refwd());
|
|
319
|
+
if (null != eres) {
|
|
320
|
+
const open = eres[0].indexOf('(');
|
|
321
|
+
const arg = eres[0].indexOf(eres[1], open);
|
|
322
|
+
lex.aontu_export = {
|
|
323
|
+
cl: pnt.sI + open,
|
|
324
|
+
arg: pnt.sI + arg,
|
|
325
|
+
end: pnt.sI + eres[0].length,
|
|
326
|
+
src: eres[1],
|
|
327
|
+
};
|
|
328
|
+
const etkn = lex.token('#TX', (0, aliasname_1.exportHoldKey)(), aliasname_1.EXPORT_DECL_NAME, pnt, { aontu_export: true, aontu_export_items: (0, aliasname_1.aliasSetItems)(eres[1]) });
|
|
329
|
+
pnt.sI += aliasname_1.EXPORT_DECL_NAME.length;
|
|
330
|
+
pnt.cI += aliasname_1.EXPORT_DECL_NAME.length;
|
|
331
|
+
return { done: true, token: etkn };
|
|
332
|
+
}
|
|
333
|
+
}
|
|
234
334
|
if (CC_EQ === src.charCodeAt(pnt.sI) && lex.aontu_eq_at === pnt.sI) {
|
|
235
335
|
delete lex.aontu_eq_at;
|
|
236
336
|
const eqtkn = lex.token('#CL', undefined, '=', pnt, { aontu_eq: true });
|
|
@@ -291,6 +391,24 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
291
391
|
v.site.len = ts.len;
|
|
292
392
|
return v;
|
|
293
393
|
};
|
|
394
|
+
// `export` publishes a name; it renames none, and `{%}` is theirs.
|
|
395
|
+
const publishedNames = (items) => undefined === items || 0 === items.length ? undefined :
|
|
396
|
+
items.every((i) => i.local === i.remote) ?
|
|
397
|
+
items.map((i) => i.local) : undefined;
|
|
398
|
+
// A ROOT MAY BE WRAPPED: a file's names are its MAP'S, not open()'s.
|
|
399
|
+
const declaringMap = (val) => {
|
|
400
|
+
let cur = val;
|
|
401
|
+
while (true === cur?.isFunc && 1 === cur.peg?.length) {
|
|
402
|
+
cur = cur.peg[0];
|
|
403
|
+
}
|
|
404
|
+
return cur;
|
|
405
|
+
};
|
|
406
|
+
// The file a value was written in, and so any alias name's scope. A
|
|
407
|
+
// DOCUMENT IS ITS OWN SCOPE too, so a fileless parse is tagged.
|
|
408
|
+
const srcUrl = (ctx) => {
|
|
409
|
+
const url = ctx.meta.multisource && ctx.meta.multisource.path;
|
|
410
|
+
return url ? url : (ctx.meta.aontu_scope ??= '#' + (++SCOPE_SEQ));
|
|
411
|
+
};
|
|
294
412
|
let addsite = (v, r, ctx) => {
|
|
295
413
|
// The source text comes from the SAME token the row and column
|
|
296
414
|
// come from. jsonic has carried it all along; not reading it is
|
|
@@ -301,14 +419,20 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
301
419
|
v.path = r.k ? [...r.k.path] : [];
|
|
302
420
|
return v;
|
|
303
421
|
};
|
|
304
|
-
const isAliasDecl = (ktkn, sep) => null != ktkn && VL === ktkn.tin && ALIAS_RE.test('' + ktkn.src) &&
|
|
422
|
+
const isAliasDecl = (ktkn, sep) => null != ktkn && VL === ktkn.tin && aliasname_1.ALIAS_RE.test('' + ktkn.src) &&
|
|
305
423
|
true === sep?.use?.aontu_eq;
|
|
424
|
+
const keyName = (ktkn) => 'string' === typeof ktkn?.val ? ktkn.val : '' + ktkn?.src;
|
|
306
425
|
const keyRefusalOf = (ktkn, sep) => {
|
|
426
|
+
// THE SENTINEL NAMESPACE IS THE ENGINE'S; it writes `export` here.
|
|
427
|
+
if (keyName(ktkn).startsWith(aliasname_1.RESERVED_KEY_PREFIX) &&
|
|
428
|
+
true !== ktkn.use?.aontu_export) {
|
|
429
|
+
return { why: 'reserved_key' };
|
|
430
|
+
}
|
|
307
431
|
if (null == ktkn || VL !== ktkn.tin) {
|
|
308
432
|
return undefined;
|
|
309
433
|
}
|
|
310
434
|
const kname = '' + ktkn.src;
|
|
311
|
-
if (ALIAS_RE.test(kname)) {
|
|
435
|
+
if (aliasname_1.ALIAS_RE.test(kname)) {
|
|
312
436
|
return isAliasDecl(ktkn, sep) ? undefined : { why: 'alias_colon' };
|
|
313
437
|
}
|
|
314
438
|
const bad = ktkn.use?.aontu_bad;
|
|
@@ -410,18 +534,18 @@ help isolate the syntax error.`,
|
|
|
410
534
|
(prev[type_1.SPREAD] || { o: '&', v: [] });
|
|
411
535
|
prev[type_1.SPREAD].v.push(lm.spread.cj);
|
|
412
536
|
}
|
|
413
|
-
prev
|
|
537
|
+
prev[OPTIONAL_MARK_KEY] = (prev[OPTIONAL_MARK_KEY] || []);
|
|
414
538
|
for (const k of lm.optionalKeys) {
|
|
415
|
-
prev.
|
|
539
|
+
prev[OPTIONAL_MARK_KEY].push(k);
|
|
416
540
|
}
|
|
417
|
-
prev
|
|
541
|
+
prev[ALIAS_MARK_KEY] = (prev[ALIAS_MARK_KEY] || []);
|
|
418
542
|
for (const k of lm.aliasKeys) {
|
|
419
|
-
prev.
|
|
543
|
+
prev[ALIAS_MARK_KEY].push(k);
|
|
420
544
|
}
|
|
421
545
|
return prev;
|
|
422
546
|
}
|
|
423
|
-
prev
|
|
424
|
-
prev.
|
|
547
|
+
prev[MERGE_KEY] = (prev[MERGE_KEY] || []);
|
|
548
|
+
prev[MERGE_KEY].push(curr);
|
|
425
549
|
return prev;
|
|
426
550
|
}
|
|
427
551
|
}
|
|
@@ -554,7 +678,7 @@ help isolate the syntax error.`,
|
|
|
554
678
|
// as the alias reference rather than through the dot rule, and
|
|
555
679
|
// is refused for the same reason.
|
|
556
680
|
if (terms[0] instanceof RefVal_1.RefVal &&
|
|
557
|
-
terms[0].peg.some((seg) => 'string' === typeof seg && ALIAS_RE.test(seg))) {
|
|
681
|
+
terms[0].peg.some((seg) => 'string' === typeof seg && aliasname_1.ALIAS_RE.test(seg))) {
|
|
558
682
|
return addsite(new NilVal_1.NilVal({ why: 'alias_in_path' }), r, ctx);
|
|
559
683
|
}
|
|
560
684
|
if (terms[0] instanceof RefVal_1.RefVal) {
|
|
@@ -702,6 +826,16 @@ help isolate the syntax error.`,
|
|
|
702
826
|
});
|
|
703
827
|
jsonic.rule('val', (rs) => {
|
|
704
828
|
rs
|
|
829
|
+
// Before the core implicit-map alts: a value prefix, not a key.
|
|
830
|
+
.open([
|
|
831
|
+
{
|
|
832
|
+
s: [VL, CL],
|
|
833
|
+
c: (r) => 0 !== r.d && isAliasDecl(r.o0, r.o1),
|
|
834
|
+
p: 'val',
|
|
835
|
+
a: (r) => { r.u.aontu_alias_val = '' + r.o0.src; },
|
|
836
|
+
g: 'aontu-alias-val',
|
|
837
|
+
},
|
|
838
|
+
], { append: false })
|
|
705
839
|
.open([
|
|
706
840
|
{
|
|
707
841
|
s: [CJ, CL], p: 'map', b: 2, n: { pk: 1 },
|
|
@@ -770,6 +904,11 @@ help isolate the syntax error.`,
|
|
|
770
904
|
}
|
|
771
905
|
// else { ERROR? }
|
|
772
906
|
r.node = valnode;
|
|
907
|
+
const aname = r.u.aontu_alias_val;
|
|
908
|
+
if (null != aname && null != valnode) {
|
|
909
|
+
const hoist = (ctx.aontu_alias_hoist ||= []);
|
|
910
|
+
hoist.push({ name: (0, aliasname_1.aliasScopedKey)('' + aname, srcUrl(ctx)), val: valnode });
|
|
911
|
+
}
|
|
773
912
|
return undefined;
|
|
774
913
|
})
|
|
775
914
|
.close([{ s: [CJ, CL], b: 2, g: 'spread,json,more' }]);
|
|
@@ -783,11 +922,24 @@ help isolate the syntax error.`,
|
|
|
783
922
|
])
|
|
784
923
|
.bc((r, ctx) => {
|
|
785
924
|
const optionalKeys = r.u.aontu_optional_keys ?? [];
|
|
786
|
-
const
|
|
925
|
+
const aliasDecls = r.u.aontu_alias_keys ?? [];
|
|
926
|
+
const aliasKeys = [];
|
|
927
|
+
const exportKeys = [];
|
|
787
928
|
let mo = r.node;
|
|
929
|
+
// A REFUSED KEY TAKES NO KEY and is not OPTIONAL: its name is a
|
|
930
|
+
// mark's, and the elision below would put it back.
|
|
931
|
+
for (const kr of (r.u.aontu_key_refusals ?? [])) {
|
|
932
|
+
if ('reserved_key' === kr.why) {
|
|
933
|
+
delete mo[kr.key];
|
|
934
|
+
const oi = optionalKeys.indexOf(kr.key);
|
|
935
|
+
if (-1 !== oi) {
|
|
936
|
+
optionalKeys.splice(oi, 1);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
788
940
|
for (const k in mo) {
|
|
789
|
-
if (null == mo[k] &&
|
|
790
|
-
|
|
941
|
+
if (null == mo[k] && MERGE_KEY !== k &&
|
|
942
|
+
OPTIONAL_MARK_KEY !== k && ALIAS_MARK_KEY !== k) {
|
|
791
943
|
// Pathed at the KEY, not at the enclosing map. addsite takes
|
|
792
944
|
// the rule's path, which here is the map's, so the error
|
|
793
945
|
// would otherwise name the container and leave the reader to
|
|
@@ -811,44 +963,158 @@ help isolate the syntax error.`,
|
|
|
811
963
|
r.node = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
812
964
|
return undefined;
|
|
813
965
|
}
|
|
814
|
-
|
|
966
|
+
const reservedRefusals = [];
|
|
967
|
+
for (const { key, tkn, why, details, url } of (r.u.aontu_key_refusals ?? [])) {
|
|
815
968
|
const en = siteAt(addsite(new NilVal_1.NilVal({ why }), r, ctx), tokenSite(tkn));
|
|
816
969
|
if (null != details) {
|
|
817
970
|
en.details = details;
|
|
818
971
|
}
|
|
819
972
|
en.path = [...(r.k?.path ?? []), key];
|
|
820
|
-
|
|
973
|
+
// A COLON DECLARATION IS REFUSED AND STILL NAMES SOMETHING, so
|
|
974
|
+
// the refusal is held under the key that name would have had
|
|
975
|
+
// and a use of it reports why; not an alias key, so it
|
|
976
|
+
// generates unused.
|
|
977
|
+
if ('alias_colon' === why) {
|
|
978
|
+
delete mo[key];
|
|
979
|
+
mo[(0, aliasname_1.aliasScopedKey)(key, url)] = en;
|
|
980
|
+
}
|
|
981
|
+
// A RESERVED KEY WAITS: its name is where the marks are kept.
|
|
982
|
+
else if ('reserved_key' === why) {
|
|
983
|
+
reservedRefusals.push(en);
|
|
984
|
+
}
|
|
985
|
+
else {
|
|
986
|
+
mo[key] = en;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
// A NAME BELONGS TO THE FILE THAT DECLARED IT. Renamed here and
|
|
990
|
+
// not at the key, so an elided value is still reported by the
|
|
991
|
+
// name the source spells; rebuilt, as key order is resolution.
|
|
992
|
+
const renamed = new Map();
|
|
993
|
+
for (const { name, key } of aliasDecls) {
|
|
994
|
+
renamed.set(name, key);
|
|
995
|
+
if (!aliasKeys.includes(key)) {
|
|
996
|
+
aliasKeys.push(key);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (0 < renamed.size) {
|
|
1000
|
+
const entries = Object.entries(mo);
|
|
1001
|
+
for (const [k] of entries) {
|
|
1002
|
+
delete mo[k];
|
|
1003
|
+
}
|
|
1004
|
+
for (const [k, v] of entries) {
|
|
1005
|
+
const key = renamed.get(k);
|
|
1006
|
+
if (undefined === key) {
|
|
1007
|
+
mo[k] = v;
|
|
1008
|
+
}
|
|
1009
|
+
else {
|
|
1010
|
+
mo[key] = v;
|
|
1011
|
+
(0, Val_1.repathInstance)(v, [...(r.k?.path ?? []), key]);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
// `export` PUBLISHES NAMES AND NOTHING ELSE; a bare name, a key
|
|
1016
|
+
// and the wildcard are refused, and the argument is erased.
|
|
1017
|
+
for (const { items, tkn } of (r.u.aontu_export_decls ?? [])) {
|
|
1018
|
+
delete mo[tkn.val];
|
|
1019
|
+
const names = publishedNames(items);
|
|
1020
|
+
if (undefined === names) {
|
|
1021
|
+
const en = siteAt(addsite(new NilVal_1.NilVal({ why: 'export_arg' }), r, ctx), tokenSite(tkn));
|
|
1022
|
+
en.path = [...(r.k?.path ?? []), aliasname_1.EXPORT_DECL_NAME];
|
|
1023
|
+
mo[aliasname_1.EXPORT_DECL_NAME] = en;
|
|
1024
|
+
}
|
|
1025
|
+
else {
|
|
1026
|
+
exportKeys.push(...names.map((n) => (0, aliasname_1.aliasScopedKey)(n, srcUrl(ctx))));
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
// THE DESTRUCTURE IS ADDITIVE: the values land where the head
|
|
1030
|
+
// stands, each name binds in THIS file's scope, and a file
|
|
1031
|
+
// publishes only what IT declares. A DECLARATION IS THE
|
|
1032
|
+
// DOCUMENT'S, so the names go to the root and the values may
|
|
1033
|
+
// sit under a key.
|
|
1034
|
+
for (const im of (r.u.aontu_import_decls ?? [])) {
|
|
1035
|
+
const hoist = (ctx.aontu_alias_hoist ||= []);
|
|
1036
|
+
const iv = mo[im.key];
|
|
1037
|
+
delete mo[im.key];
|
|
1038
|
+
const dv = declaringMap(iv);
|
|
1039
|
+
const ex = dv.exportKeys ?? [];
|
|
1040
|
+
const ak = dv.aliasKeys ?? [];
|
|
1041
|
+
for (const k of ak) {
|
|
1042
|
+
hoist.push({ name: k, val: dv.peg[k] });
|
|
1043
|
+
delete dv.peg[k];
|
|
1044
|
+
}
|
|
1045
|
+
if (0 < ak.length + ex.length) {
|
|
1046
|
+
dv.aliasKeys = [];
|
|
1047
|
+
dv.exportKeys = [];
|
|
1048
|
+
}
|
|
1049
|
+
(0, Val_1.repathInstance)(iv, [...(r.k?.path ?? [])]);
|
|
1050
|
+
(mo[MERGE_KEY] = mo[MERGE_KEY] || []).push(iv);
|
|
1051
|
+
const binds = 0 === im.names.length ?
|
|
1052
|
+
ex.map((k) => ({ local: (0, aliasname_1.aliasBareName)(k), remote: (0, aliasname_1.aliasBareName)(k) })) : im.names;
|
|
1053
|
+
for (const { local, remote } of binds) {
|
|
1054
|
+
const from = ex.find((k) => (0, aliasname_1.aliasBareName)(k) === remote);
|
|
1055
|
+
let bind;
|
|
1056
|
+
if (undefined === from || !ak.includes(from)) {
|
|
1057
|
+
bind = siteAt(addsite(new NilVal_1.NilVal({ why: 'import_not_exported' }), r, ctx), tokenSite(im.tkn));
|
|
1058
|
+
bind.details = { name: remote };
|
|
1059
|
+
const en = siteAt(addsite(new NilVal_1.NilVal({ why: 'import_not_exported' }), r, ctx), tokenSite(im.tkn));
|
|
1060
|
+
en.details = { name: remote };
|
|
1061
|
+
mo[MERGE_KEY].push(en);
|
|
1062
|
+
}
|
|
1063
|
+
else {
|
|
1064
|
+
bind = addsite(new RefVal_1.RefVal({ peg: [from], absolute: true }), r, ctx);
|
|
1065
|
+
}
|
|
1066
|
+
hoist.push({ name: (0, aliasname_1.aliasScopedKey)(local, im.url), val: bind });
|
|
1067
|
+
}
|
|
821
1068
|
}
|
|
822
1069
|
// Marks carried over from a map include folded in the merge
|
|
823
1070
|
// hook above, applied here where the MapVal is built.
|
|
824
|
-
if (mo
|
|
825
|
-
for (const k of (mo
|
|
1071
|
+
if (mo[OPTIONAL_MARK_KEY] || mo[ALIAS_MARK_KEY]) {
|
|
1072
|
+
for (const k of (mo[OPTIONAL_MARK_KEY] || [])) {
|
|
826
1073
|
if (!optionalKeys.includes(k)) {
|
|
827
1074
|
optionalKeys.push(k);
|
|
828
1075
|
}
|
|
829
1076
|
}
|
|
830
|
-
for (const k of (mo
|
|
1077
|
+
for (const k of (mo[ALIAS_MARK_KEY] || [])) {
|
|
831
1078
|
if (!aliasKeys.includes(k)) {
|
|
832
1079
|
aliasKeys.push(k);
|
|
833
1080
|
}
|
|
834
1081
|
}
|
|
835
|
-
delete mo
|
|
836
|
-
delete mo
|
|
1082
|
+
delete mo[OPTIONAL_MARK_KEY];
|
|
1083
|
+
delete mo[ALIAS_MARK_KEY];
|
|
1084
|
+
}
|
|
1085
|
+
// A value-prefix declaration lands here, at the document root
|
|
1086
|
+
// (ALIASES.0.md), as a copy pathed at its name.
|
|
1087
|
+
if (1 === r.d) {
|
|
1088
|
+
for (const { name, val } of (ctx.aontu_alias_hoist ?? [])) {
|
|
1089
|
+
const acx = new ctx_1.AontuContext({ path: [name] });
|
|
1090
|
+
const copy = val.clone(acx, { path: [name] });
|
|
1091
|
+
(0, Val_1.repathInstance)(copy, [name]);
|
|
1092
|
+
mo[name] = null == mo[name] ? copy :
|
|
1093
|
+
addsite(new ConjunctVal_1.ConjunctVal({ peg: [mo[name], copy] }), r, ctx);
|
|
1094
|
+
if (!aliasKeys.includes(name)) {
|
|
1095
|
+
aliasKeys.push(name);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
837
1098
|
}
|
|
838
1099
|
// Handle defered conjuncts, e.g. `{x:1 @"foo"}`
|
|
839
|
-
|
|
1100
|
+
const deferred = mo[MERGE_KEY];
|
|
1101
|
+
delete mo[MERGE_KEY];
|
|
1102
|
+
const merge = 0 < reservedRefusals.length ?
|
|
1103
|
+
[...(deferred ?? []), ...reservedRefusals] : deferred;
|
|
1104
|
+
if (merge) {
|
|
840
1105
|
let mop = { ...mo };
|
|
841
|
-
delete mop.___merge;
|
|
842
1106
|
let mopv = new MapVal_1.MapVal({ peg: mop });
|
|
843
1107
|
mopv.optionalKeys = optionalKeys;
|
|
844
1108
|
mopv.aliasKeys = aliasKeys;
|
|
1109
|
+
mopv.exportKeys = exportKeys;
|
|
845
1110
|
r.node =
|
|
846
|
-
addsite(new ConjunctVal_1.ConjunctVal({ peg: [mopv, ...
|
|
1111
|
+
addsite(new ConjunctVal_1.ConjunctVal({ peg: [mopv, ...merge] }), r, ctx);
|
|
847
1112
|
}
|
|
848
1113
|
else {
|
|
849
1114
|
r.node = addsite(new MapVal_1.MapVal({ peg: mo }), r, ctx);
|
|
850
1115
|
r.node.optionalKeys = optionalKeys;
|
|
851
1116
|
r.node.aliasKeys = aliasKeys;
|
|
1117
|
+
r.node.exportKeys = exportKeys;
|
|
852
1118
|
}
|
|
853
1119
|
return undefined;
|
|
854
1120
|
})
|
|
@@ -868,7 +1134,7 @@ help isolate the syntax error.`,
|
|
|
868
1134
|
ao[i] = en;
|
|
869
1135
|
}
|
|
870
1136
|
}
|
|
871
|
-
// No
|
|
1137
|
+
// No merge-key arm here: the deferred map.merge that writes it
|
|
872
1138
|
// only ever fires for a `pair` rule, whose parent is always a
|
|
873
1139
|
// `map` rule with a plain-object node — never a list.
|
|
874
1140
|
{
|
|
@@ -944,18 +1210,36 @@ help isolate the syntax error.`,
|
|
|
944
1210
|
r.child.k.key = '&';
|
|
945
1211
|
}
|
|
946
1212
|
})
|
|
947
|
-
.bc((rule) => {
|
|
1213
|
+
.bc((rule, ctx) => {
|
|
948
1214
|
// TRAVERSE PARENTS TO GET PATH
|
|
949
|
-
|
|
1215
|
+
// AN OPTIONAL PAIR OPENS ON ITS `?`: the rule before read the key.
|
|
1216
|
+
const ktkn = true === rule.prev?.u?.aontu_optional ?
|
|
1217
|
+
rule.prev.o0 : rule.o0;
|
|
950
1218
|
const holder = rule.parent;
|
|
951
1219
|
const kr = keyRefusalOf(ktkn, rule.o1);
|
|
952
1220
|
if (null != kr) {
|
|
953
1221
|
holder.u.aontu_key_refusals = (holder.u.aontu_key_refusals || []);
|
|
954
|
-
holder.u.aontu_key_refusals.push({ key:
|
|
1222
|
+
holder.u.aontu_key_refusals.push({ key: keyName(ktkn), tkn: ktkn, url: srcUrl(ctx), ...kr });
|
|
955
1223
|
}
|
|
956
1224
|
else if (isAliasDecl(ktkn, rule.o1)) {
|
|
957
1225
|
holder.u.aontu_alias_keys = (holder.u.aontu_alias_keys || []);
|
|
958
|
-
holder.u.aontu_alias_keys.push(
|
|
1226
|
+
holder.u.aontu_alias_keys.push({
|
|
1227
|
+
name: '' + ktkn.src,
|
|
1228
|
+
key: (0, aliasname_1.aliasScopedKey)('' + ktkn.src, srcUrl(ctx)),
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
else if (true === ktkn?.use?.aontu_export) {
|
|
1232
|
+
holder.u.aontu_export_decls = (holder.u.aontu_export_decls || []);
|
|
1233
|
+
holder.u.aontu_export_decls.push({ items: ktkn.use.aontu_export_items, tkn: ktkn });
|
|
1234
|
+
}
|
|
1235
|
+
else if (null != ktkn?.use?.aontu_import) {
|
|
1236
|
+
holder.u.aontu_import_decls = (holder.u.aontu_import_decls || []);
|
|
1237
|
+
holder.u.aontu_import_decls.push({
|
|
1238
|
+
key: '' + ktkn.src,
|
|
1239
|
+
names: ktkn.use.aontu_import,
|
|
1240
|
+
url: srcUrl(ctx),
|
|
1241
|
+
tkn: ktkn,
|
|
1242
|
+
});
|
|
959
1243
|
}
|
|
960
1244
|
if (rule.u.spread) {
|
|
961
1245
|
rule.node[type_1.SPREAD] =
|
|
@@ -1054,21 +1338,24 @@ help isolate the syntax error.`,
|
|
|
1054
1338
|
v.path = [...(rule.k?.path ?? []),
|
|
1055
1339
|
'' + rule.node.length, key];
|
|
1056
1340
|
}
|
|
1341
|
+
// An element is a value position, so the prefix form applies.
|
|
1342
|
+
if (null == kr && isAliasDecl(ktkn, rule.o1)) {
|
|
1343
|
+
;
|
|
1344
|
+
(ctx.aontu_alias_hoist ||= [])
|
|
1345
|
+
.push({ name: (0, aliasname_1.aliasScopedKey)(key, srcUrl(ctx)), val: v });
|
|
1346
|
+
rule.node.push(v);
|
|
1347
|
+
return undefined;
|
|
1348
|
+
}
|
|
1057
1349
|
const mv = addsite(new MapVal_1.MapVal({ peg: { [key]: v } }), rule, ctx);
|
|
1058
1350
|
// The element's path is the list's plus its index, as any
|
|
1059
1351
|
// element's is (and as the Go port paths it): the map rule's
|
|
1060
1352
|
// "is this the top level" test reads the path, so an element
|
|
1061
1353
|
// of a top-level list must not read as the root.
|
|
1062
1354
|
mv.path = [...(rule.k?.path ?? []), '' + rule.node.length];
|
|
1063
|
-
|
|
1355
|
+
// A REFUSED KEY IS NOT OPTIONAL: the refusal would be dropped.
|
|
1356
|
+
if (true === rule.u.aontu_optional_elem && null == kr) {
|
|
1064
1357
|
mv.optionalKeys = [key];
|
|
1065
1358
|
}
|
|
1066
|
-
// ... and a declaration is a declaration IN the element, which
|
|
1067
|
-
// is where MapVal.unify refuses it: a list element is not the
|
|
1068
|
-
// top level.
|
|
1069
|
-
if (isAliasDecl(ktkn, rule.o1)) {
|
|
1070
|
-
mv.aliasKeys = [key];
|
|
1071
|
-
}
|
|
1072
1359
|
rule.node.push(mv);
|
|
1073
1360
|
}
|
|
1074
1361
|
return undefined;
|