aontu 0.68.0 → 0.70.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/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/hints.js +36 -7
- package/dist/hints.js.map +1 -1
- package/dist/lang.js +289 -35
- 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 +29 -12
- package/dist/val/RefVal.js.map +1 -1
- package/package.json +1 -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/ctx.ts +4 -1
- package/src/err.ts +19 -1
- package/src/format.ts +14 -0
- package/src/hints.ts +40 -7
- package/src/lang.ts +334 -30
- 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 +31 -12
package/dist/lang.js
CHANGED
|
@@ -95,11 +95,20 @@ const CC_0 = 48;
|
|
|
95
95
|
const CC_d = 100;
|
|
96
96
|
const CC_D = 68;
|
|
97
97
|
const CC_PCT = 37;
|
|
98
|
-
|
|
99
|
-
const ALIAS_RE = /^%[A-Za-z_][A-Za-z0-9_]*(?:-[A-Za-z0-9_]+)*/;
|
|
98
|
+
const aliasname_1 = require("./aliasname");
|
|
100
99
|
const CC_EQ = 61;
|
|
101
100
|
const CC_SP = 32;
|
|
102
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]*\)/;
|
|
103
112
|
const CC_9 = 57;
|
|
104
113
|
const CC_A = 65;
|
|
105
114
|
const CC_Z = 90;
|
|
@@ -178,7 +187,7 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
178
187
|
const segs = Array.isArray(t.peg) ? t.peg :
|
|
179
188
|
('string' === typeof t.peg ? [t.peg] : []);
|
|
180
189
|
for (const seg of segs) {
|
|
181
|
-
if ('string' === typeof seg && ALIAS_RE.test(seg)) {
|
|
190
|
+
if ('string' === typeof seg && aliasname_1.ALIAS_RE.test(seg)) {
|
|
182
191
|
return addsite(new NilVal_1.NilVal({ why: 'alias_in_path' }), r, ctx);
|
|
183
192
|
}
|
|
184
193
|
}
|
|
@@ -212,13 +221,67 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
212
221
|
},
|
|
213
222
|
},
|
|
214
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
|
+
});
|
|
215
278
|
jsonic.options({
|
|
216
279
|
text: {
|
|
217
280
|
check: (lex) => {
|
|
218
281
|
const pnt = lex.pnt;
|
|
219
282
|
const src = lex.src;
|
|
220
283
|
const ares = CC_PCT === src.charCodeAt(pnt.sI) ?
|
|
221
|
-
ALIAS_RE.exec(lex.refwd()) : null;
|
|
284
|
+
aliasname_1.ALIAS_RE.exec(lex.refwd()) : null;
|
|
222
285
|
if (null != ares) {
|
|
223
286
|
const asrc = ares[0];
|
|
224
287
|
let j = pnt.sI + asrc.length;
|
|
@@ -229,11 +292,45 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
229
292
|
if (CC_EQ === src.charCodeAt(j) && CC_EQ !== src.charCodeAt(j + 1)) {
|
|
230
293
|
lex.aontu_eq_at = j;
|
|
231
294
|
}
|
|
232
|
-
|
|
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);
|
|
233
312
|
pnt.sI += asrc.length;
|
|
234
313
|
pnt.cI += asrc.length;
|
|
235
314
|
return { done: true, token: atkn };
|
|
236
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
|
+
}
|
|
237
334
|
if (CC_EQ === src.charCodeAt(pnt.sI) && lex.aontu_eq_at === pnt.sI) {
|
|
238
335
|
delete lex.aontu_eq_at;
|
|
239
336
|
const eqtkn = lex.token('#CL', undefined, '=', pnt, { aontu_eq: true });
|
|
@@ -294,6 +391,24 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
294
391
|
v.site.len = ts.len;
|
|
295
392
|
return v;
|
|
296
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
|
+
};
|
|
297
412
|
let addsite = (v, r, ctx) => {
|
|
298
413
|
// The source text comes from the SAME token the row and column
|
|
299
414
|
// come from. jsonic has carried it all along; not reading it is
|
|
@@ -304,14 +419,20 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
304
419
|
v.path = r.k ? [...r.k.path] : [];
|
|
305
420
|
return v;
|
|
306
421
|
};
|
|
307
|
-
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) &&
|
|
308
423
|
true === sep?.use?.aontu_eq;
|
|
424
|
+
const keyName = (ktkn) => 'string' === typeof ktkn?.val ? ktkn.val : '' + ktkn?.src;
|
|
309
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
|
+
}
|
|
310
431
|
if (null == ktkn || VL !== ktkn.tin) {
|
|
311
432
|
return undefined;
|
|
312
433
|
}
|
|
313
434
|
const kname = '' + ktkn.src;
|
|
314
|
-
if (ALIAS_RE.test(kname)) {
|
|
435
|
+
if (aliasname_1.ALIAS_RE.test(kname)) {
|
|
315
436
|
return isAliasDecl(ktkn, sep) ? undefined : { why: 'alias_colon' };
|
|
316
437
|
}
|
|
317
438
|
const bad = ktkn.use?.aontu_bad;
|
|
@@ -413,18 +534,18 @@ help isolate the syntax error.`,
|
|
|
413
534
|
(prev[type_1.SPREAD] || { o: '&', v: [] });
|
|
414
535
|
prev[type_1.SPREAD].v.push(lm.spread.cj);
|
|
415
536
|
}
|
|
416
|
-
prev
|
|
537
|
+
prev[OPTIONAL_MARK_KEY] = (prev[OPTIONAL_MARK_KEY] || []);
|
|
417
538
|
for (const k of lm.optionalKeys) {
|
|
418
|
-
prev.
|
|
539
|
+
prev[OPTIONAL_MARK_KEY].push(k);
|
|
419
540
|
}
|
|
420
|
-
prev
|
|
541
|
+
prev[ALIAS_MARK_KEY] = (prev[ALIAS_MARK_KEY] || []);
|
|
421
542
|
for (const k of lm.aliasKeys) {
|
|
422
|
-
prev.
|
|
543
|
+
prev[ALIAS_MARK_KEY].push(k);
|
|
423
544
|
}
|
|
424
545
|
return prev;
|
|
425
546
|
}
|
|
426
|
-
prev
|
|
427
|
-
prev.
|
|
547
|
+
prev[MERGE_KEY] = (prev[MERGE_KEY] || []);
|
|
548
|
+
prev[MERGE_KEY].push(curr);
|
|
428
549
|
return prev;
|
|
429
550
|
}
|
|
430
551
|
}
|
|
@@ -557,7 +678,7 @@ help isolate the syntax error.`,
|
|
|
557
678
|
// as the alias reference rather than through the dot rule, and
|
|
558
679
|
// is refused for the same reason.
|
|
559
680
|
if (terms[0] instanceof RefVal_1.RefVal &&
|
|
560
|
-
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))) {
|
|
561
682
|
return addsite(new NilVal_1.NilVal({ why: 'alias_in_path' }), r, ctx);
|
|
562
683
|
}
|
|
563
684
|
if (terms[0] instanceof RefVal_1.RefVal) {
|
|
@@ -786,7 +907,7 @@ help isolate the syntax error.`,
|
|
|
786
907
|
const aname = r.u.aontu_alias_val;
|
|
787
908
|
if (null != aname && null != valnode) {
|
|
788
909
|
const hoist = (ctx.aontu_alias_hoist ||= []);
|
|
789
|
-
hoist.push({ name: '' + aname, val: valnode });
|
|
910
|
+
hoist.push({ name: (0, aliasname_1.aliasScopedKey)('' + aname, srcUrl(ctx)), val: valnode });
|
|
790
911
|
}
|
|
791
912
|
return undefined;
|
|
792
913
|
})
|
|
@@ -801,11 +922,24 @@ help isolate the syntax error.`,
|
|
|
801
922
|
])
|
|
802
923
|
.bc((r, ctx) => {
|
|
803
924
|
const optionalKeys = r.u.aontu_optional_keys ?? [];
|
|
804
|
-
const
|
|
925
|
+
const aliasDecls = r.u.aontu_alias_keys ?? [];
|
|
926
|
+
const aliasKeys = [];
|
|
927
|
+
const exportKeys = [];
|
|
805
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
|
+
}
|
|
806
940
|
for (const k in mo) {
|
|
807
|
-
if (null == mo[k] &&
|
|
808
|
-
|
|
941
|
+
if (null == mo[k] && MERGE_KEY !== k &&
|
|
942
|
+
OPTIONAL_MARK_KEY !== k && ALIAS_MARK_KEY !== k) {
|
|
809
943
|
// Pathed at the KEY, not at the enclosing map. addsite takes
|
|
810
944
|
// the rule's path, which here is the map's, so the error
|
|
811
945
|
// would otherwise name the container and leave the reader to
|
|
@@ -829,29 +963,124 @@ help isolate the syntax error.`,
|
|
|
829
963
|
r.node = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
830
964
|
return undefined;
|
|
831
965
|
}
|
|
832
|
-
|
|
966
|
+
const reservedRefusals = [];
|
|
967
|
+
for (const { key, tkn, why, details, url } of (r.u.aontu_key_refusals ?? [])) {
|
|
833
968
|
const en = siteAt(addsite(new NilVal_1.NilVal({ why }), r, ctx), tokenSite(tkn));
|
|
834
969
|
if (null != details) {
|
|
835
970
|
en.details = details;
|
|
836
971
|
}
|
|
837
972
|
en.path = [...(r.k?.path ?? []), key];
|
|
838
|
-
|
|
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
|
+
}
|
|
839
1068
|
}
|
|
840
1069
|
// Marks carried over from a map include folded in the merge
|
|
841
1070
|
// hook above, applied here where the MapVal is built.
|
|
842
|
-
if (mo
|
|
843
|
-
for (const k of (mo
|
|
1071
|
+
if (mo[OPTIONAL_MARK_KEY] || mo[ALIAS_MARK_KEY]) {
|
|
1072
|
+
for (const k of (mo[OPTIONAL_MARK_KEY] || [])) {
|
|
844
1073
|
if (!optionalKeys.includes(k)) {
|
|
845
1074
|
optionalKeys.push(k);
|
|
846
1075
|
}
|
|
847
1076
|
}
|
|
848
|
-
for (const k of (mo
|
|
1077
|
+
for (const k of (mo[ALIAS_MARK_KEY] || [])) {
|
|
849
1078
|
if (!aliasKeys.includes(k)) {
|
|
850
1079
|
aliasKeys.push(k);
|
|
851
1080
|
}
|
|
852
1081
|
}
|
|
853
|
-
delete mo
|
|
854
|
-
delete mo
|
|
1082
|
+
delete mo[OPTIONAL_MARK_KEY];
|
|
1083
|
+
delete mo[ALIAS_MARK_KEY];
|
|
855
1084
|
}
|
|
856
1085
|
// A value-prefix declaration lands here, at the document root
|
|
857
1086
|
// (ALIASES.0.md), as a copy pathed at its name.
|
|
@@ -868,19 +1097,24 @@ help isolate the syntax error.`,
|
|
|
868
1097
|
}
|
|
869
1098
|
}
|
|
870
1099
|
// Handle defered conjuncts, e.g. `{x:1 @"foo"}`
|
|
871
|
-
|
|
1100
|
+
const deferred = mo[MERGE_KEY];
|
|
1101
|
+
delete mo[MERGE_KEY];
|
|
1102
|
+
const merge = 0 < reservedRefusals.length ?
|
|
1103
|
+
[...(deferred ?? []), ...reservedRefusals] : deferred;
|
|
1104
|
+
if (merge) {
|
|
872
1105
|
let mop = { ...mo };
|
|
873
|
-
delete mop.___merge;
|
|
874
1106
|
let mopv = new MapVal_1.MapVal({ peg: mop });
|
|
875
1107
|
mopv.optionalKeys = optionalKeys;
|
|
876
1108
|
mopv.aliasKeys = aliasKeys;
|
|
1109
|
+
mopv.exportKeys = exportKeys;
|
|
877
1110
|
r.node =
|
|
878
|
-
addsite(new ConjunctVal_1.ConjunctVal({ peg: [mopv, ...
|
|
1111
|
+
addsite(new ConjunctVal_1.ConjunctVal({ peg: [mopv, ...merge] }), r, ctx);
|
|
879
1112
|
}
|
|
880
1113
|
else {
|
|
881
1114
|
r.node = addsite(new MapVal_1.MapVal({ peg: mo }), r, ctx);
|
|
882
1115
|
r.node.optionalKeys = optionalKeys;
|
|
883
1116
|
r.node.aliasKeys = aliasKeys;
|
|
1117
|
+
r.node.exportKeys = exportKeys;
|
|
884
1118
|
}
|
|
885
1119
|
return undefined;
|
|
886
1120
|
})
|
|
@@ -900,7 +1134,7 @@ help isolate the syntax error.`,
|
|
|
900
1134
|
ao[i] = en;
|
|
901
1135
|
}
|
|
902
1136
|
}
|
|
903
|
-
// No
|
|
1137
|
+
// No merge-key arm here: the deferred map.merge that writes it
|
|
904
1138
|
// only ever fires for a `pair` rule, whose parent is always a
|
|
905
1139
|
// `map` rule with a plain-object node — never a list.
|
|
906
1140
|
{
|
|
@@ -976,18 +1210,36 @@ help isolate the syntax error.`,
|
|
|
976
1210
|
r.child.k.key = '&';
|
|
977
1211
|
}
|
|
978
1212
|
})
|
|
979
|
-
.bc((rule) => {
|
|
1213
|
+
.bc((rule, ctx) => {
|
|
980
1214
|
// TRAVERSE PARENTS TO GET PATH
|
|
981
|
-
|
|
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;
|
|
982
1218
|
const holder = rule.parent;
|
|
983
1219
|
const kr = keyRefusalOf(ktkn, rule.o1);
|
|
984
1220
|
if (null != kr) {
|
|
985
1221
|
holder.u.aontu_key_refusals = (holder.u.aontu_key_refusals || []);
|
|
986
|
-
holder.u.aontu_key_refusals.push({ key:
|
|
1222
|
+
holder.u.aontu_key_refusals.push({ key: keyName(ktkn), tkn: ktkn, url: srcUrl(ctx), ...kr });
|
|
987
1223
|
}
|
|
988
1224
|
else if (isAliasDecl(ktkn, rule.o1)) {
|
|
989
1225
|
holder.u.aontu_alias_keys = (holder.u.aontu_alias_keys || []);
|
|
990
|
-
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
|
+
});
|
|
991
1243
|
}
|
|
992
1244
|
if (rule.u.spread) {
|
|
993
1245
|
rule.node[type_1.SPREAD] =
|
|
@@ -1089,7 +1341,8 @@ help isolate the syntax error.`,
|
|
|
1089
1341
|
// An element is a value position, so the prefix form applies.
|
|
1090
1342
|
if (null == kr && isAliasDecl(ktkn, rule.o1)) {
|
|
1091
1343
|
;
|
|
1092
|
-
(ctx.aontu_alias_hoist ||= [])
|
|
1344
|
+
(ctx.aontu_alias_hoist ||= [])
|
|
1345
|
+
.push({ name: (0, aliasname_1.aliasScopedKey)(key, srcUrl(ctx)), val: v });
|
|
1093
1346
|
rule.node.push(v);
|
|
1094
1347
|
return undefined;
|
|
1095
1348
|
}
|
|
@@ -1099,7 +1352,8 @@ help isolate the syntax error.`,
|
|
|
1099
1352
|
// "is this the top level" test reads the path, so an element
|
|
1100
1353
|
// of a top-level list must not read as the root.
|
|
1101
1354
|
mv.path = [...(rule.k?.path ?? []), '' + rule.node.length];
|
|
1102
|
-
|
|
1355
|
+
// A REFUSED KEY IS NOT OPTIONAL: the refusal would be dropped.
|
|
1356
|
+
if (true === rule.u.aontu_optional_elem && null == kr) {
|
|
1103
1357
|
mv.optionalKeys = [key];
|
|
1104
1358
|
}
|
|
1105
1359
|
rule.node.push(mv);
|