aontu 0.57.0 → 0.59.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/README.md +2 -2
- package/dist/agentsmd.js +1 -1
- package/dist/alias.d.ts +3 -0
- package/dist/alias.js +59 -0
- package/dist/alias.js.map +1 -0
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +12 -3
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +486 -4
- package/dist/cli.js.map +1 -1
- package/dist/ctx.d.ts +4 -0
- package/dist/ctx.js +3 -0
- package/dist/ctx.js.map +1 -1
- package/dist/err.js +6 -3
- package/dist/err.js.map +1 -1
- package/dist/format.js +8 -2
- package/dist/format.js.map +1 -1
- package/dist/hints.js +40 -9
- package/dist/hints.js.map +1 -1
- package/dist/lang.js +409 -58
- package/dist/lang.js.map +1 -1
- package/dist/lower.d.ts +20 -0
- package/dist/lower.js +575 -0
- package/dist/lower.js.map +1 -0
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +1 -1
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +1 -1
- package/dist/mcp.d.ts +1 -0
- package/dist/mcp.js +40 -3
- package/dist/mcp.js.map +1 -1
- package/dist/render.d.ts +53 -0
- package/dist/render.js +542 -0
- package/dist/render.js.map +1 -0
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/std.d.ts +2 -0
- package/dist/std.js +498 -2
- package/dist/std.js.map +1 -1
- package/dist/template.d.ts +5 -0
- package/dist/template.js +257 -0
- package/dist/template.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.d.ts +2 -0
- package/dist/type.js.map +1 -1
- package/dist/unify.js +43 -0
- package/dist/unify.js.map +1 -1
- package/dist/val/AggFuncVal.d.ts +1 -1
- package/dist/val/AggFuncVal.js +10 -21
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -1
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +1 -1
- package/dist/val/DisjunctVal.js +33 -2
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.d.ts +1 -1
- package/dist/val/EachFuncVal.js +8 -13
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +23 -4
- package/dist/val/EmitFuncVal.js +298 -28
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +8 -4
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FormFuncVal.d.ts +14 -0
- package/dist/val/FormFuncVal.js +55 -0
- package/dist/val/FormFuncVal.js.map +1 -0
- package/dist/val/FuncBaseVal.js +36 -13
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/ListVal.js +9 -1
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/MapVal.d.ts +2 -1
- package/dist/val/MapVal.js +2 -1
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/PackFuncVal.d.ts +1 -1
- package/dist/val/PackFuncVal.js +22 -18
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PlaceVal.js +7 -2
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/RefVal.d.ts +3 -0
- package/dist/val/RefVal.js +181 -18
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/Val.d.ts +8 -1
- package/dist/val/Val.js +39 -1
- package/dist/val/Val.js.map +1 -1
- package/dist/val/members.d.ts +9 -0
- package/dist/val/members.js +52 -0
- package/dist/val/members.js.map +1 -0
- package/grammar/aontu.abnf +1 -1
- package/grammar/aontu.gbnf +1 -1
- package/grammar/aontu.lark +1 -1
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +4 -4
- package/skill/error-codes.md +1 -1
- package/skill/examples.md +1 -1
- package/skill/grammar-card.md +1 -1
- package/src/agentsmd.ts +1 -1
- package/src/alias.ts +112 -0
- package/src/aontu.ts +20 -2
- package/src/cli.ts +528 -4
- package/src/ctx.ts +18 -0
- package/src/err.ts +6 -3
- package/src/format.ts +12 -2
- package/src/hints.ts +47 -9
- package/src/lang.ts +453 -63
- package/src/lower.ts +636 -0
- package/src/lsp.ts +1 -1
- package/src/mcp-server.ts +1 -1
- package/src/mcp.ts +43 -4
- package/src/render.ts +727 -0
- package/src/sigdecl.ts +1 -1
- package/src/std.ts +506 -1
- package/src/template.ts +291 -0
- package/src/type.ts +10 -1
- package/src/unify.ts +47 -0
- package/src/val/AggFuncVal.ts +10 -21
- package/src/val/BagVal.ts +1 -1
- package/src/val/ConstraintVal.ts +1 -1
- package/src/val/DisjunctVal.ts +33 -2
- package/src/val/EachFuncVal.ts +8 -16
- package/src/val/EmitFuncVal.ts +376 -39
- package/src/val/FilterFuncVal.ts +11 -4
- package/src/val/FormFuncVal.ts +119 -0
- package/src/val/FuncBaseVal.ts +36 -13
- package/src/val/ListVal.ts +9 -1
- package/src/val/MapVal.ts +3 -2
- package/src/val/PackFuncVal.ts +23 -19
- package/src/val/PlaceVal.ts +7 -2
- package/src/val/RefVal.ts +193 -20
- package/src/val/Val.ts +75 -4
- package/src/val/members.ts +86 -0
package/src/lang.ts
CHANGED
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
makeJsonicProcessor,
|
|
72
72
|
} from '@tabnas/multisource/processor/jsonic'
|
|
73
73
|
|
|
74
|
-
import { STD_SOURCES } from './std'
|
|
74
|
+
import { STD_SOURCES, AONTU_SCHEME, AONTU_MODELS } from './std'
|
|
75
75
|
import {
|
|
76
76
|
parseModuleRef, resolveModule, modCacheDir, MODULE_REFUSAL_CODES,
|
|
77
77
|
} from './mod'
|
|
@@ -143,6 +143,7 @@ import { ReferFuncVal, RelFuncVal } from './val/ReferFuncVal'
|
|
|
143
143
|
import { AcyclicFuncVal, InverseFuncVal } from './val/GraphAtomVal'
|
|
144
144
|
import { PackFuncVal } from './val/PackFuncVal'
|
|
145
145
|
import { EachFuncVal } from './val/EachFuncVal'
|
|
146
|
+
import { FormFuncVal } from './val/FormFuncVal'
|
|
146
147
|
import { FilterFuncVal } from './val/FilterFuncVal'
|
|
147
148
|
import { MatchFuncVal } from './val/MatchFuncVal'
|
|
148
149
|
import { EmitFuncVal } from './val/EmitFuncVal'
|
|
@@ -221,11 +222,123 @@ const CC_D = 68
|
|
|
221
222
|
|
|
222
223
|
// THE ALIAS SIGIL. `%` is part of an alias's name, so the name is one
|
|
223
224
|
// lexeme wherever it appears and its meaning is decided by position:
|
|
224
|
-
// a BINDING in key position (`%uint8
|
|
225
|
+
// a BINDING in key position (`%uint8 = …` declares), a USE in value
|
|
225
226
|
// position (`listen: %uint8` refers). docs/design/ALIASES.0.md §4.
|
|
226
227
|
const CC_PCT = 37
|
|
227
228
|
const ALIAS_RE = /^%[A-Za-z_][A-Za-z0-9_]*/
|
|
228
229
|
|
|
230
|
+
// THE DECLARATION OPERATOR. `%name = value` declares; the `=` is the
|
|
231
|
+
// pair's separator, lexed as the colon token so the declaration then
|
|
232
|
+
// parses as a pair whose key is the alias name (ALIASES.0.md X-1, as
|
|
233
|
+
// settled 2026-09-05). `=` is syntax ONLY there: anywhere else it is
|
|
234
|
+
// punctuation outside its syntax, and the bare-text scan below refuses
|
|
235
|
+
// it (`foo = 1`, `a: x=y`).
|
|
236
|
+
const CC_EQ = 61
|
|
237
|
+
const CC_SP = 32
|
|
238
|
+
const CC_TAB = 9
|
|
239
|
+
|
|
240
|
+
// THE BARE-TEXT RULE. A bare string holds letters, digits, `-` and `_`,
|
|
241
|
+
// and nothing else. Every other punctuation character is either SYNTAX,
|
|
242
|
+
// where the grammar gives it a meaning, or an ERROR where it does not
|
|
243
|
+
// -- never silently part of a string. `x=y`, `6/2`, `50%` and `>10`
|
|
244
|
+
// were all bare strings once, each a well-formed wrong document, and
|
|
245
|
+
// each is refused now, naming the character (bare_punct).
|
|
246
|
+
//
|
|
247
|
+
// scanBareRun classifies each character of a run three ways, in this
|
|
248
|
+
// order: TEXT continues the run; an ENDER stops it; anything else is
|
|
249
|
+
// BAD. The ender set is the lexer's own -- space, line, fixed tokens,
|
|
250
|
+
// comment starters -- read from the config its text matcher was built
|
|
251
|
+
// from, so it cannot drift from the grammar. A bad run is still scanned
|
|
252
|
+
// to its ender, so the refusal claims the whole spelling and the lexer
|
|
253
|
+
// never reads the tail of it as syntax.
|
|
254
|
+
//
|
|
255
|
+
// `-` is text wherever the scan sees it. A run never STARTS on one:
|
|
256
|
+
// `-` is the sign of a number and the negation prefix, a fixed token
|
|
257
|
+
// the fixed matcher claims before either scanning stage can run, so
|
|
258
|
+
// `a:-1` is the negation of 1 and `a:6-2` the string. The `+` of an
|
|
259
|
+
// exponent (`1e+2`) is admitted only by the NUMBER stage's scan, the
|
|
260
|
+
// one stage that can make a number of it. Mirrors scanBareRun in
|
|
261
|
+
// go/lang.go, decision for decision.
|
|
262
|
+
const CC_9 = 57
|
|
263
|
+
const CC_A = 65
|
|
264
|
+
const CC_Z = 90
|
|
265
|
+
const CC_a = 97
|
|
266
|
+
const CC_z = 122
|
|
267
|
+
const CC_E = 69
|
|
268
|
+
const CC_e = 101
|
|
269
|
+
const CC_US = 95
|
|
270
|
+
const CC_MINUS = 45
|
|
271
|
+
const CC_PLUS = 43
|
|
272
|
+
|
|
273
|
+
// Beyond ASCII a letter, a digit or a combining mark is text (`café`);
|
|
274
|
+
// a dash, a symbol or a space of any other kind is not.
|
|
275
|
+
const UNICODE_TEXT_RE = /^[\p{L}\p{N}\p{M}]$/u
|
|
276
|
+
|
|
277
|
+
function textChar(c: number): boolean {
|
|
278
|
+
return (CC_0 <= c && c <= CC_9) ||
|
|
279
|
+
(CC_a <= c && c <= CC_z) ||
|
|
280
|
+
(CC_A <= c && c <= CC_Z) ||
|
|
281
|
+
CC_US === c ||
|
|
282
|
+
CC_MINUS === c ||
|
|
283
|
+
(127 < c && UNICODE_TEXT_RE.test(String.fromCodePoint(c)))
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// The lexer's text ender, at i. The regexp is the text matcher's own
|
|
287
|
+
// ender alternation (cfg.rePart.ender) made sticky, built once per
|
|
288
|
+
// config and cached on it.
|
|
289
|
+
function enderAt(cfg: any, src: string, i: number): boolean {
|
|
290
|
+
let re: RegExp = cfg.aontu_ender_re
|
|
291
|
+
if (null == re) {
|
|
292
|
+
re = cfg.aontu_ender_re = new RegExp(cfg.rePart.ender.join(''), 'y')
|
|
293
|
+
}
|
|
294
|
+
re.lastIndex = i
|
|
295
|
+
return re.test(src)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Where the run ends, the index of its first BAD character (-1 when the
|
|
299
|
+
// run is clean) and that character.
|
|
300
|
+
type BareRun = { end: number, bad: number, ch: string }
|
|
301
|
+
|
|
302
|
+
function scanBareRun(cfg: any, src: string, start: number, expo: boolean): BareRun {
|
|
303
|
+
let i = start
|
|
304
|
+
let bad = -1
|
|
305
|
+
let ch = ''
|
|
306
|
+
while (i < src.length) {
|
|
307
|
+
const c = src.codePointAt(i) as number
|
|
308
|
+
const w = 0xffff < c ? 2 : 1
|
|
309
|
+
if (textChar(c)) {
|
|
310
|
+
i += w
|
|
311
|
+
continue
|
|
312
|
+
}
|
|
313
|
+
if (expo && CC_PLUS === c && start < i) {
|
|
314
|
+
const p = src.charCodeAt(i - 1)
|
|
315
|
+
const n = src.charCodeAt(i + 1)
|
|
316
|
+
if ((CC_e === p || CC_E === p) && CC_0 <= n && n <= CC_9) {
|
|
317
|
+
i += 1
|
|
318
|
+
continue
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (enderAt(cfg, src, i)) {
|
|
322
|
+
break
|
|
323
|
+
}
|
|
324
|
+
if (-1 === bad) {
|
|
325
|
+
bad = i
|
|
326
|
+
ch = String.fromCodePoint(c)
|
|
327
|
+
}
|
|
328
|
+
i += w
|
|
329
|
+
}
|
|
330
|
+
return { end: i, bad, ch }
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// A run the number matcher may lex: its own number grammar, less the
|
|
334
|
+
// fraction -- `.` is a fixed token, so a run never holds one, and the
|
|
335
|
+
// matcher reads it past the run by itself (`1.5` is the run `1`).
|
|
336
|
+
const NUMBER_RUN_RE =
|
|
337
|
+
/^[-+]?(?:0(?:[xX][0-9a-fA-F_]+|[oO][0-7_]+|[bB][01_]+)|[0-9][0-9_]*(?:[eE][-+]?[0-9][0-9_]*)?)$/
|
|
338
|
+
|
|
339
|
+
// The number matcher's hook result where the run is not its to lex.
|
|
340
|
+
const NOT_A_NUMBER = { done: true, token: undefined }
|
|
341
|
+
|
|
229
342
|
let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
230
343
|
|
|
231
344
|
jsonic.use(asPlugin(Path))
|
|
@@ -306,6 +419,35 @@ let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
|
306
419
|
// matched case-insensitively so the rule does not depend on which
|
|
307
420
|
// prefix spellings the engine accepts.
|
|
308
421
|
exclude: /__|^[-+]?0[xXoObB]_|_$/,
|
|
422
|
+
|
|
423
|
+
// THE NUMBER STAGE OF THE BARE-TEXT RULE. The matcher runs before
|
|
424
|
+
// the text matcher and reads a number up to the next ender -- and
|
|
425
|
+
// `-` is an ender, being the negation prefix's fixed token, so it
|
|
426
|
+
// would take the `2026` of `2026-09-05` and leave `-09-05` to the
|
|
427
|
+
// grammar. The hook scans the whole run first and declines for
|
|
428
|
+
// the matcher wherever the run is not its to lex: a run with a
|
|
429
|
+
// bad character (the text stage refuses it), a run that is not a
|
|
430
|
+
// number at all (`2026-09-05`, `6-2` are text). Twin of tsNumCheck
|
|
431
|
+
// in go/lang.go.
|
|
432
|
+
check: (lex: any) => {
|
|
433
|
+
const pnt = lex.pnt
|
|
434
|
+
const src = lex.src
|
|
435
|
+
// The hook makes the matcher a candidate at every position, so
|
|
436
|
+
// the common case -- a run no number can open -- declines for it
|
|
437
|
+
// in one char read. A DIGIT opens a number here and nothing
|
|
438
|
+
// else: the sign and the dot open the matcher's own grammar, but
|
|
439
|
+
// they are fixed tokens (the prefix operators and member
|
|
440
|
+
// access), claimed before this hook can run.
|
|
441
|
+
const c = src.charCodeAt(pnt.sI)
|
|
442
|
+
if (!(CC_0 <= c && c <= CC_9)) {
|
|
443
|
+
return NOT_A_NUMBER
|
|
444
|
+
}
|
|
445
|
+
const run = scanBareRun(lex.cfg, src, pnt.sI, true)
|
|
446
|
+
if (-1 !== run.bad || !NUMBER_RUN_RE.test(src.slice(pnt.sI, run.end))) {
|
|
447
|
+
return NOT_A_NUMBER
|
|
448
|
+
}
|
|
449
|
+
return undefined
|
|
450
|
+
},
|
|
309
451
|
},
|
|
310
452
|
})
|
|
311
453
|
|
|
@@ -360,12 +502,27 @@ let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
|
360
502
|
// the token's source text (`0d1: 5` yields the key `0d1`), so a
|
|
361
503
|
// declaration reads as the key `%uint8`, while a value position
|
|
362
504
|
// calls the function below and gets the reference.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
505
|
+
// A `%` that opens no name (`%`, `%1`, `50%`) falls through to
|
|
506
|
+
// the bare-text scan below, which refuses it.
|
|
507
|
+
const ares = CC_PCT === src.charCodeAt(pnt.sI) ?
|
|
508
|
+
ALIAS_RE.exec(lex.refwd()) : null
|
|
509
|
+
if (null != ares) {
|
|
368
510
|
const asrc = ares[0]
|
|
511
|
+
|
|
512
|
+
// A lone `=` after the name, across horizontal space only, is
|
|
513
|
+
// the declaration operator. Decided HERE, where the name is
|
|
514
|
+
// claimed, and only its position is kept: the very next text
|
|
515
|
+
// position is that `=`, since nothing but space sits between,
|
|
516
|
+
// so the mark cannot outlive its one use. `==` is not it.
|
|
517
|
+
let j = pnt.sI + asrc.length
|
|
518
|
+
while (j < src.length &&
|
|
519
|
+
(CC_SP === src.charCodeAt(j) || CC_TAB === src.charCodeAt(j))) {
|
|
520
|
+
j++
|
|
521
|
+
}
|
|
522
|
+
if (CC_EQ === src.charCodeAt(j) && CC_EQ !== src.charCodeAt(j + 1)) {
|
|
523
|
+
lex.aontu_eq_at = j
|
|
524
|
+
}
|
|
525
|
+
|
|
369
526
|
const atkn = lex.token(
|
|
370
527
|
'#VL',
|
|
371
528
|
// AN ALIAS REFERENCE IS A PATH REFERENCE. `%uint8` is
|
|
@@ -384,63 +541,165 @@ let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
|
384
541
|
return { done: true, token: atkn }
|
|
385
542
|
}
|
|
386
543
|
|
|
387
|
-
|
|
388
|
-
|
|
544
|
+
// The `=` the alias arm above marked: the separator of a
|
|
545
|
+
// declaration, as a colon token whose source is `=`. The pair rule
|
|
546
|
+
// is then the pair rule, and the formatter writes the spelling it
|
|
547
|
+
// read. Marked in `use` so the pair rule can tell it from a colon,
|
|
548
|
+
// which no longer declares.
|
|
549
|
+
if (CC_EQ === src.charCodeAt(pnt.sI) && lex.aontu_eq_at === pnt.sI) {
|
|
550
|
+
delete lex.aontu_eq_at
|
|
551
|
+
const eqtkn = lex.token('#CL', undefined, '=', pnt, { aontu_eq: true })
|
|
552
|
+
pnt.sI += 1
|
|
553
|
+
pnt.cI += 1
|
|
554
|
+
return { done: true, token: eqtkn }
|
|
389
555
|
}
|
|
390
|
-
|
|
391
|
-
if (
|
|
392
|
-
|
|
556
|
+
|
|
557
|
+
if (CC_0 === src.charCodeAt(pnt.sI)) {
|
|
558
|
+
const c1 = src.charCodeAt(pnt.sI + 1)
|
|
559
|
+
if (CC_d === c1 || CC_D === c1) {
|
|
560
|
+
// BIG_LITERAL_RE is `^`-anchored and read against the
|
|
561
|
+
// forward source (memoized per position by refwd), which is
|
|
562
|
+
// what lets it claim the `.` of `0d1.5`. A `0d` run it does
|
|
563
|
+
// not match falls through to the bare-text scan below.
|
|
564
|
+
const res = BIG_LITERAL_RE.exec(lex.refwd())
|
|
565
|
+
if (null != res) {
|
|
566
|
+
const msrc = res[0]
|
|
567
|
+
// The token value is a FUNCTION so Val construction
|
|
568
|
+
// happens at parse time, where the rule and context needed
|
|
569
|
+
// for the site exist (jsonic calls a #VL token's function
|
|
570
|
+
// value with them). A `0d` literal never spans a line, so
|
|
571
|
+
// only the source and column positions advance.
|
|
572
|
+
const tkn = lex.token(
|
|
573
|
+
'#VL',
|
|
574
|
+
(r: Rule, ctx: JsonicContext) => addsite(bigVal(res), r, ctx),
|
|
575
|
+
msrc,
|
|
576
|
+
pnt)
|
|
577
|
+
pnt.sI += msrc.length
|
|
578
|
+
pnt.cI += msrc.length
|
|
579
|
+
return { done: true, token: tkn }
|
|
580
|
+
}
|
|
581
|
+
}
|
|
393
582
|
}
|
|
394
583
|
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
584
|
+
// THE BARE-TEXT RULE (scanBareRun). Last, so that a name, a
|
|
585
|
+
// declaration operator and an exact literal are read before a
|
|
586
|
+
// run is judged as text.
|
|
587
|
+
// The run is never empty: every ender is a token an earlier
|
|
588
|
+
// matcher claims, so the text stage only opens on a character
|
|
589
|
+
// the scan classifies as text or as bad.
|
|
590
|
+
const run = scanBareRun(lex.cfg, src, pnt.sI, false)
|
|
591
|
+
const msrc = src.slice(pnt.sI, run.end)
|
|
592
|
+
|
|
593
|
+
if (-1 !== run.bad) {
|
|
594
|
+
// BAD: the run is refused whole, sited at the character (the
|
|
595
|
+
// mark in `use` is what tokenSite reads). As a VALUE the
|
|
596
|
+
// token's function builds the refusal at the parse, where the
|
|
597
|
+
// rule carries the position. As a KEY the token is read for
|
|
598
|
+
// its source alone, so the mark is what the pair and elem
|
|
599
|
+
// rules read to write the refusal where the map is built.
|
|
600
|
+
const ch = run.ch
|
|
601
|
+
const tkn = lex.token(
|
|
602
|
+
'#VL',
|
|
603
|
+
(r: Rule, ctx: JsonicContext) => {
|
|
604
|
+
const nv: any = addsite(new NilVal({ why: 'bare_punct' }), r, ctx)
|
|
605
|
+
nv.details = { char: ch, text: msrc }
|
|
606
|
+
return nv
|
|
607
|
+
},
|
|
608
|
+
msrc,
|
|
609
|
+
pnt,
|
|
610
|
+
{ aontu_bad: ch })
|
|
611
|
+
pnt.sI += msrc.length
|
|
612
|
+
pnt.cI += msrc.length
|
|
613
|
+
return { done: true, token: tkn }
|
|
401
614
|
}
|
|
402
615
|
|
|
403
|
-
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
//
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return { done: true, token: tkn }
|
|
616
|
+
// CLEAN, with a `-` past its start (`team-payments`,
|
|
617
|
+
// `2026-09-05`): claimed here as one text token, because the
|
|
618
|
+
// default matcher's ender set would carve the run at the `-`.
|
|
619
|
+
// Any other clean run is the default matcher's, which also reads
|
|
620
|
+
// the value keywords and the `_` hole.
|
|
621
|
+
if (-1 !== msrc.indexOf('-')) {
|
|
622
|
+
const tkn = lex.token('#TX', msrc, msrc, pnt)
|
|
623
|
+
pnt.sI += msrc.length
|
|
624
|
+
pnt.cI += msrc.length
|
|
625
|
+
return { done: true, token: tkn }
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return undefined
|
|
417
629
|
},
|
|
418
630
|
},
|
|
419
631
|
})
|
|
420
632
|
|
|
421
633
|
// TODO: refactor Val constructor
|
|
422
634
|
// let addsite = (v: Val, p: string[]) => (v.path = [...(p || [])], v)
|
|
423
|
-
|
|
635
|
+
// WHERE A TOKEN SITES A VALUE: the token's own position and text --
|
|
636
|
+
// except for a token the bare-text rule marked (`aontu_bad`), which
|
|
637
|
+
// sites at the offending CHARACTER. Its column is the character's
|
|
638
|
+
// first occurrence in the run (every character before it is text,
|
|
639
|
+
// and it is not), and its text is the character alone. Read here and
|
|
640
|
+
// nowhere else, so a value sited from such a token lands on the
|
|
641
|
+
// character however many times the parse re-sites it.
|
|
642
|
+
//
|
|
643
|
+
// A TOKEN WITH NO TEXT IS NO SPAN, in both ports, and the extent is
|
|
644
|
+
// DERIVED from the text rather than read from the token's own `len`
|
|
645
|
+
// — so the Go twin, whose token has no len field, computes the
|
|
646
|
+
// identical number with utf16Len and nothing has to be kept in step.
|
|
647
|
+
type TokenSite = { row: number, col: number, src: string, len: number }
|
|
648
|
+
const NO_SITE: TokenSite = { row: -1, col: -1, src: '', len: -1 }
|
|
649
|
+
const tokenSite = (tkn: any): TokenSite => {
|
|
650
|
+
const src: string = tkn.src
|
|
651
|
+
const bad = tkn.use?.aontu_bad
|
|
652
|
+
if (null != bad) {
|
|
653
|
+
const ch = '' + bad
|
|
654
|
+
return { row: tkn.rI, col: tkn.cI + src.indexOf(ch), src: ch, len: ch.length }
|
|
655
|
+
}
|
|
656
|
+
return { row: tkn.rI, col: tkn.cI, src, len: '' === src ? -1 : src.length }
|
|
657
|
+
}
|
|
658
|
+
const siteAt = (v: Val, ts: TokenSite): Val => {
|
|
659
|
+
v.site.row = ts.row
|
|
660
|
+
v.site.col = ts.col
|
|
661
|
+
v.site.src = ts.src
|
|
662
|
+
v.site.len = ts.len
|
|
663
|
+
return v
|
|
664
|
+
}
|
|
424
665
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
v.site.url = ctx.meta.multisource ? ctx.meta.multisource.path : ''
|
|
428
|
-
// The source text, from the SAME token the row and column above
|
|
666
|
+
let addsite = (v: Val, r: Rule, ctx: JsonicContext) => {
|
|
667
|
+
// The source text comes from the SAME token the row and column
|
|
429
668
|
// come from. jsonic has carried it all along; not reading it is
|
|
430
669
|
// what left a site uneditable (ts/src/site.ts).
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
// DERIVED from the text rather than read from the token's own `len`
|
|
434
|
-
// — so the Go twin, whose token has no len field, computes the
|
|
435
|
-
// identical number with utf16Len and nothing has to be kept in step.
|
|
436
|
-
v.site.src = null == r.o0 ? '' : r.o0.src
|
|
437
|
-
v.site.len = '' === v.site.src ? -1 : v.site.src.length
|
|
670
|
+
siteAt(v, null == r.o0 ? NO_SITE : tokenSite(r.o0))
|
|
671
|
+
v.site.url = ctx.meta.multisource ? ctx.meta.multisource.path : ''
|
|
438
672
|
// A keyed rule always carries a path array; a keyless one has none.
|
|
439
673
|
v.path = r.k ? [...r.k.path] : []
|
|
440
674
|
|
|
441
675
|
return v
|
|
442
676
|
}
|
|
443
677
|
|
|
678
|
+
// THE KEY REFUSALS a pair may carry, decided from its key TOKEN --
|
|
679
|
+
// never from the key text alone, since a quoted `"%a"` or `"x=y"` is
|
|
680
|
+
// an ordinary key: a declaration spelled with a colon (alias_colon),
|
|
681
|
+
// and a key the bare-text rule refuses (bare_punct). Undefined for an
|
|
682
|
+
// ordinary key, and for a declaration (`%a = 1`), which is a binding
|
|
683
|
+
// (isAliasDecl), not a refusal. Asked FIRST by the pair rule and by
|
|
684
|
+
// the elem rule, before the declaration is, so a pair in list
|
|
685
|
+
// position is held to the map's rules.
|
|
686
|
+
const isAliasDecl = (ktkn: any, sep: any): boolean =>
|
|
687
|
+
null != ktkn && VL === ktkn.tin && ALIAS_RE.test('' + ktkn.src) &&
|
|
688
|
+
true === sep?.use?.aontu_eq
|
|
689
|
+
const keyRefusalOf = (ktkn: any, sep: any):
|
|
690
|
+
{ why: string, details?: Record<string, any> } | undefined => {
|
|
691
|
+
if (null == ktkn || VL !== ktkn.tin) {
|
|
692
|
+
return undefined
|
|
693
|
+
}
|
|
694
|
+
const kname = '' + ktkn.src
|
|
695
|
+
if (ALIAS_RE.test(kname)) {
|
|
696
|
+
return isAliasDecl(ktkn, sep) ? undefined : { why: 'alias_colon' }
|
|
697
|
+
}
|
|
698
|
+
const bad = ktkn.use?.aontu_bad
|
|
699
|
+
return null == bad ? undefined :
|
|
700
|
+
{ why: 'bare_punct', details: { char: '' + bad, text: kname } }
|
|
701
|
+
}
|
|
702
|
+
|
|
444
703
|
|
|
445
704
|
jsonic.options({
|
|
446
705
|
hint: {
|
|
@@ -548,6 +807,38 @@ help isolate the syntax error.`,
|
|
|
548
807
|
// Handle defered conjuncts, where MapVal does not yet
|
|
549
808
|
// exist, by creating ConjunctVal later.
|
|
550
809
|
else {
|
|
810
|
+
// AN INCLUDE UNIFIES IN PLACE. multisource calls this hook at
|
|
811
|
+
// the `@`'s own source position, so `prev` holds exactly the
|
|
812
|
+
// pairs written BEFORE it. Folding the loaded map's keys in
|
|
813
|
+
// here -- host-so-far first, arriving value second -- is what
|
|
814
|
+
// inlining the loaded bytes at the `@` does, and mirrors
|
|
815
|
+
// go/lang.go's Map.Merge, which multisource-go drives one key
|
|
816
|
+
// at a time. A non-map load has no keys to fold and stays a
|
|
817
|
+
// deferred conjunct arm.
|
|
818
|
+
if (true === (cval as any)?.isMap) {
|
|
819
|
+
const lm: any = cval
|
|
820
|
+
for (const k of Object.keys(lm.peg)) {
|
|
821
|
+
const own = (prev as any)[k]
|
|
822
|
+
;(prev as any)[k] = (null == own) ? lm.peg[k] :
|
|
823
|
+
(own?.isVal
|
|
824
|
+
? new ConjunctVal({ peg: [own, lm.peg[k]] })
|
|
825
|
+
: lm.peg[k])
|
|
826
|
+
}
|
|
827
|
+
// The loaded map's spread joins THIS map's spread list at
|
|
828
|
+
// the `@`'s position: the parse pushes each `&:` onto the
|
|
829
|
+
// node as it is read, so `prev[SPREAD].v` already holds the
|
|
830
|
+
// spreads written before the `@` and nothing after it.
|
|
831
|
+
if (null != lm.spread?.cj) {
|
|
832
|
+
;(prev as any)[SPREAD] =
|
|
833
|
+
((prev as any)[SPREAD] || { o: '&', v: [] })
|
|
834
|
+
;(prev as any)[SPREAD].v.push(lm.spread.cj)
|
|
835
|
+
}
|
|
836
|
+
prev.___optional = (prev.___optional || [])
|
|
837
|
+
for (const k of lm.optionalKeys) { prev.___optional.push(k) }
|
|
838
|
+
prev.___alias = (prev.___alias || [])
|
|
839
|
+
for (const k of lm.aliasKeys) { prev.___alias.push(k) }
|
|
840
|
+
return prev
|
|
841
|
+
}
|
|
551
842
|
prev.___merge = (prev.___merge || [])
|
|
552
843
|
prev.___merge.push(curr)
|
|
553
844
|
return prev
|
|
@@ -632,6 +923,14 @@ help isolate the syntax error.`,
|
|
|
632
923
|
pack: PackFuncVal,
|
|
633
924
|
each: EachFuncVal,
|
|
634
925
|
|
|
926
|
+
// RENDER P6: the order-preserving map. `form` makes one list
|
|
927
|
+
// element per child of its data, being the template with `_`
|
|
928
|
+
// bound to the source child -- a construction, where `each` is a
|
|
929
|
+
// bound (G9 §4). It exists because `pick(pack(...))` re-sorts to
|
|
930
|
+
// code-point order, and a struct's fields or a file's imports
|
|
931
|
+
// are the model's order or they are wrong.
|
|
932
|
+
form: FormFuncVal,
|
|
933
|
+
|
|
635
934
|
// G8 phase 2: selection. `filter` keeps the children of a bag that
|
|
636
935
|
// unify with a condition; `match` picks the first arm whose
|
|
637
936
|
// pattern the scrutinee unifies with. Both select by
|
|
@@ -1129,17 +1428,8 @@ help isolate the syntax error.`,
|
|
|
1129
1428
|
}
|
|
1130
1429
|
|
|
1131
1430
|
if (null != valnode && 'object' === typeof valnode && valnode.site) {
|
|
1132
|
-
|
|
1133
|
-
valnode.site.row = st.rI
|
|
1134
|
-
valnode.site.col = st.cI
|
|
1431
|
+
siteAt(valnode, tokenSite(r.o0))
|
|
1135
1432
|
valnode.site.url = ctx.meta.multisource && ctx.meta.multisource.path
|
|
1136
|
-
// No `?? ''` and no empty-text arm here: this branch runs only
|
|
1137
|
-
// for a rule that HAS an open token, and a token that opens a
|
|
1138
|
-
// value always carries text — the coverage gate refuses both
|
|
1139
|
-
// guards as dead. The unset case is the one above, where r.o0
|
|
1140
|
-
// itself can be absent.
|
|
1141
|
-
valnode.site.src = st.src
|
|
1142
|
-
valnode.site.len = st.src.length
|
|
1143
1433
|
}
|
|
1144
1434
|
// else { ERROR? }
|
|
1145
1435
|
|
|
@@ -1178,7 +1468,8 @@ help isolate the syntax error.`,
|
|
|
1178
1468
|
// nested pair, which the val rule does produce -- and neither is
|
|
1179
1469
|
// a trailing comma.
|
|
1180
1470
|
for (const k in mo) {
|
|
1181
|
-
if (null == mo[k] && '___merge' !== k
|
|
1471
|
+
if (null == mo[k] && '___merge' !== k &&
|
|
1472
|
+
'___optional' !== k && '___alias' !== k) {
|
|
1182
1473
|
// Pathed at the KEY, not at the enclosing map. addsite takes
|
|
1183
1474
|
// the rule's path, which here is the map's, so the error
|
|
1184
1475
|
// would otherwise name the container and leave the reader to
|
|
@@ -1223,6 +1514,35 @@ help isolate the syntax error.`,
|
|
|
1223
1514
|
return undefined
|
|
1224
1515
|
}
|
|
1225
1516
|
|
|
1517
|
+
// A KEY REFUSAL (the pair rule records them: a declaration
|
|
1518
|
+
// spelled with a colon, a key the bare-text rule refuses) becomes
|
|
1519
|
+
// the refusal, in place of whatever followed the colon and sited
|
|
1520
|
+
// at the KEY rather than at the map -- at the offending character
|
|
1521
|
+
// of it, where there is one -- so the frame points at the
|
|
1522
|
+
// spelling to change.
|
|
1523
|
+
for (const { key, tkn, why, details } of
|
|
1524
|
+
(r.u.aontu_key_refusals ?? []) as any[]) {
|
|
1525
|
+
const en: any = siteAt(addsite(new NilVal({ why }), r, ctx), tokenSite(tkn))
|
|
1526
|
+
if (null != details) {
|
|
1527
|
+
en.details = details
|
|
1528
|
+
}
|
|
1529
|
+
en.path = [...(r.k?.path ?? []), key]
|
|
1530
|
+
mo[key] = en
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
// Marks carried over from a map include folded in the merge
|
|
1534
|
+
// hook above, applied here where the MapVal is built.
|
|
1535
|
+
if (mo.___optional || mo.___alias) {
|
|
1536
|
+
for (const k of (mo.___optional || [])) {
|
|
1537
|
+
if (!optionalKeys.includes(k)) { optionalKeys.push(k) }
|
|
1538
|
+
}
|
|
1539
|
+
for (const k of (mo.___alias || [])) {
|
|
1540
|
+
if (!aliasKeys.includes(k)) { aliasKeys.push(k) }
|
|
1541
|
+
}
|
|
1542
|
+
delete mo.___optional
|
|
1543
|
+
delete mo.___alias
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1226
1546
|
// Handle defered conjuncts, e.g. `{x:1 @"foo"}`
|
|
1227
1547
|
if (mo.___merge) {
|
|
1228
1548
|
let mop = { ...mo }
|
|
@@ -1403,10 +1723,21 @@ help isolate the syntax error.`,
|
|
|
1403
1723
|
// Being a property of the map is also what carries it through a
|
|
1404
1724
|
// meet, the way optional keys are carried.
|
|
1405
1725
|
const ktkn: any = rule.o0
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1726
|
+
const holder: any = rule.parent
|
|
1727
|
+
const kr = keyRefusalOf(ktkn, rule.o1)
|
|
1728
|
+
if (null != kr) {
|
|
1729
|
+
// A KEY REFUSAL (keyRefusalOf) is written where the map is
|
|
1730
|
+
// built, in the value's place and sited at the key, so the
|
|
1731
|
+
// frame points at the spelling to change. A declaration
|
|
1732
|
+
// spelled with a colon is refused rather than read as the
|
|
1733
|
+
// ordinary key `%foo` the text would otherwise become -- a
|
|
1734
|
+
// document written for the old form would then generate a
|
|
1735
|
+
// "%foo" field and every `%foo` use would resolve to nothing,
|
|
1736
|
+
// and neither says why.
|
|
1737
|
+
holder.u.aontu_key_refusals = (holder.u.aontu_key_refusals || [])
|
|
1738
|
+
holder.u.aontu_key_refusals.push({ key: '' + ktkn.src, tkn: ktkn, ...kr })
|
|
1739
|
+
}
|
|
1740
|
+
else if (isAliasDecl(ktkn, rule.o1)) {
|
|
1410
1741
|
// Always recorded here; whether the map is ALLOWED to carry
|
|
1411
1742
|
// declarations is decided on the VALUE (MapVal.unify), not at
|
|
1412
1743
|
// the parse. The parse cannot see it: an INCLUDED file's
|
|
@@ -1414,7 +1745,7 @@ help isolate the syntax error.`,
|
|
|
1414
1745
|
// once the loaded map is placed does it become apparent that
|
|
1415
1746
|
// root is not the document's.
|
|
1416
1747
|
holder.u.aontu_alias_keys = (holder.u.aontu_alias_keys || [])
|
|
1417
|
-
holder.u.aontu_alias_keys.push(
|
|
1748
|
+
holder.u.aontu_alias_keys.push('' + ktkn.src)
|
|
1418
1749
|
}
|
|
1419
1750
|
|
|
1420
1751
|
if (rule.u.spread) {
|
|
@@ -1583,20 +1914,48 @@ help isolate the syntax error.`,
|
|
|
1583
1914
|
// mistake, not an empty value.
|
|
1584
1915
|
if (true === rule.u.pair) {
|
|
1585
1916
|
const key = '' + rule.u.key
|
|
1917
|
+
// The key TOKEN: the optional spelling's sits on the elem rule
|
|
1918
|
+
// before this one (`[x?: 1]` is two elem rules).
|
|
1919
|
+
const ktkn: any = true === rule.u.aontu_optional_elem ?
|
|
1920
|
+
rule.prev.o0 : rule.o0
|
|
1586
1921
|
let v: any = rule.child.node
|
|
1922
|
+
const kr = keyRefusalOf(ktkn, rule.o1)
|
|
1587
1923
|
if (null == v) {
|
|
1588
1924
|
v = addsite(new NilVal({ why: 'elided_value' }), rule, ctx)
|
|
1589
1925
|
v.path = [...(rule.k?.path ?? []),
|
|
1590
1926
|
'' + rule.node.length, key]
|
|
1591
1927
|
}
|
|
1928
|
+
// THE KEY IS HELD TO THE MAP'S RULES: a key the map rule would
|
|
1929
|
+
// refuse (a colon declaration, a bare-text refusal) is refused
|
|
1930
|
+
// here too, in the value's place and sited at the key, rather
|
|
1931
|
+
// than generated as the element `[{"x=y": 1}]`.
|
|
1932
|
+
else if (null != kr) {
|
|
1933
|
+
v = siteAt(addsite(new NilVal({ why: kr.why }), rule, ctx), tokenSite(ktkn))
|
|
1934
|
+
if (null != kr.details) {
|
|
1935
|
+
v.details = kr.details
|
|
1936
|
+
}
|
|
1937
|
+
v.path = [...(rule.k?.path ?? []),
|
|
1938
|
+
'' + rule.node.length, key]
|
|
1939
|
+
}
|
|
1592
1940
|
const mv: any = addsite(
|
|
1593
1941
|
new MapVal({ peg: { [key]: v } }), rule, ctx)
|
|
1942
|
+
// The element's path is the list's plus its index, as any
|
|
1943
|
+
// element's is (and as the Go port paths it): the map rule's
|
|
1944
|
+
// "is this the top level" test reads the path, so an element
|
|
1945
|
+
// of a top-level list must not read as the root.
|
|
1946
|
+
mv.path = [...(rule.k?.path ?? []), '' + rule.node.length]
|
|
1594
1947
|
// `[a?: 1]` is `[{a?: 1}]`: the key is optional IN the
|
|
1595
1948
|
// element, so the two spellings stay one rule apart rather
|
|
1596
1949
|
// than two behaviours apart.
|
|
1597
1950
|
if (true === rule.u.aontu_optional_elem) {
|
|
1598
1951
|
mv.optionalKeys = [key]
|
|
1599
1952
|
}
|
|
1953
|
+
// ... and a declaration is a declaration IN the element, which
|
|
1954
|
+
// is where MapVal.unify refuses it: a list element is not the
|
|
1955
|
+
// top level.
|
|
1956
|
+
if (isAliasDecl(ktkn, rule.o1)) {
|
|
1957
|
+
mv.aliasKeys = [key]
|
|
1958
|
+
}
|
|
1600
1959
|
rule.node.push(mv)
|
|
1601
1960
|
}
|
|
1602
1961
|
|
|
@@ -1976,6 +2335,18 @@ function makeModelResolver(options: any) {
|
|
|
1976
2335
|
throw err
|
|
1977
2336
|
}
|
|
1978
2337
|
|
|
2338
|
+
// A LANGUAGE-SUPPLIED MODEL THAT DOES NOT EXIST THROWS, as a denial
|
|
2339
|
+
// does and for the same bare-member reason, with the not-found code
|
|
2340
|
+
// the include machinery already uses and a message that names the
|
|
2341
|
+
// set: a typo in an `aontu:` name must not go looking on disk.
|
|
2342
|
+
const modelNotFound = (path: string): never => {
|
|
2343
|
+
const err: any = new Error(
|
|
2344
|
+
'source not found: ' + path +
|
|
2345
|
+
' (the language-supplied models are ' + AONTU_MODELS.join(', ') + ')')
|
|
2346
|
+
err.code = 'multisource_not_found'
|
|
2347
|
+
throw err
|
|
2348
|
+
}
|
|
2349
|
+
|
|
1979
2350
|
// The gate every leg that RESOLVES A NAME passes through. The std and
|
|
1980
2351
|
// module legs do not: both state `kind: 'aon'` because what they
|
|
1981
2352
|
// serve is Aontu source by construction, not by its spelling.
|
|
@@ -2050,6 +2421,24 @@ function makeModelResolver(options: any) {
|
|
|
2050
2421
|
deny(path)
|
|
2051
2422
|
}
|
|
2052
2423
|
|
|
2424
|
+
// THE LANGUAGE-SUPPLIED MODELS (docs/design/MODELS.0.md D1): an
|
|
2425
|
+
// `aontu:` name resolves from the engine's own table and nowhere
|
|
2426
|
+
// else -- the memory, module, file and package legs are never
|
|
2427
|
+
// asked, so nothing on disk can shadow one and a typo is refused
|
|
2428
|
+
// here, naming the set, rather than searched for. Available under
|
|
2429
|
+
// every capability but `none`, checked just above, like the std
|
|
2430
|
+
// names below. A path that is not a string (`a: @1`) is not a name
|
|
2431
|
+
// at all: it falls through to the legs below and is not found there,
|
|
2432
|
+
// as it always was.
|
|
2433
|
+
if ('string' === typeof path && path.startsWith(AONTU_SCHEME)) {
|
|
2434
|
+
const model = STD_SOURCES[path]
|
|
2435
|
+
if (null == model) {
|
|
2436
|
+
modelNotFound(path)
|
|
2437
|
+
}
|
|
2438
|
+
record(ctx, path, 'std')
|
|
2439
|
+
return { found: true, path, full: path, kind: 'aon', src: model, search: [] }
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2053
2442
|
// THE BUNDLED VOCABULARY (G4 phase 4, ts/src/std.ts): served from
|
|
2054
2443
|
// the engine itself, so it needs neither the filesystem nor package
|
|
2055
2444
|
// resolution and is available under every capability but `none` —
|
|
@@ -2296,7 +2685,7 @@ function opCharHint(src: string): string {
|
|
|
2296
2685
|
q = c
|
|
2297
2686
|
}
|
|
2298
2687
|
else if ('<' === c || '>' === c) {
|
|
2299
|
-
return '\nThe > and < characters are not
|
|
2688
|
+
return '\nThe > and < characters are not aontu operators: write the ' +
|
|
2300
2689
|
'bound functions min(x), max(x), above(x), below(x) instead.'
|
|
2301
2690
|
}
|
|
2302
2691
|
}
|
|
@@ -2446,9 +2835,10 @@ class Lang {
|
|
|
2446
2835
|
}
|
|
2447
2836
|
catch (e: any) {
|
|
2448
2837
|
if ('include_denied' === e?.code || 'include_extension' === e?.code ||
|
|
2449
|
-
MODULE_REFUSAL_CODES.has(e?.code)) {
|
|
2838
|
+
'multisource_not_found' === e?.code || MODULE_REFUSAL_CODES.has(e?.code)) {
|
|
2450
2839
|
// A denied include (G5), an include whose extension is not read
|
|
2451
|
-
// as Aontu source (ADR-012, INCLUDE_KINDS),
|
|
2840
|
+
// as Aontu source (ADR-012, INCLUDE_KINDS), an `aontu:` name the
|
|
2841
|
+
// engine does not serve (MODELS.0.md D1), and a module that is
|
|
2452
2842
|
// missing, fails its pin, or names a path that escapes its store
|
|
2453
2843
|
// (G6 phase 2) are refused the same way, for the same reason: the
|
|
2454
2844
|
// resolver THROWS so a bare-member include cannot vanish in the
|