aontu 0.62.0 → 0.63.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 +1 -1
- package/dist/agentsmd.js +0 -27
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.js +0 -92
- package/dist/allow.js.map +1 -1
- package/dist/aontu.d.ts +1 -1
- package/dist/aontu.js +1 -79
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.d.ts +4 -0
- package/dist/aontumodel.js +33 -0
- package/dist/aontumodel.js.map +1 -0
- package/dist/cli.js +101 -620
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +0 -48
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js +0 -32
- package/dist/diff.js.map +1 -1
- package/dist/err.js +0 -40
- package/dist/err.js.map +1 -1
- package/dist/escape.js +0 -45
- package/dist/escape.js.map +1 -1
- package/dist/exactjson.d.ts +0 -35
- package/dist/exactjson.js +0 -131
- package/dist/exactjson.js.map +1 -1
- package/dist/format.js +13 -203
- package/dist/format.js.map +1 -1
- package/dist/grammar.d.ts +9 -0
- package/dist/grammar.js +54 -0
- package/dist/grammar.js.map +1 -0
- package/dist/graph.js +0 -26
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +0 -82
- package/dist/hcanon.js.map +1 -1
- package/dist/helpdoc.js +1 -1
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +54 -55
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +0 -114
- package/dist/jsonschema.js.map +1 -1
- package/dist/keyorder.d.ts +0 -7
- package/dist/keyorder.js +0 -41
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +17 -915
- package/dist/lang.js.map +1 -1
- package/dist/lower.js +11 -61
- package/dist/lower.js.map +1 -1
- package/dist/lsp-server.js +0 -16
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +12 -159
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +0 -26
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +0 -113
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +0 -130
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +0 -162
- package/dist/mod.js.map +1 -1
- package/dist/patch.js +0 -217
- package/dist/patch.js.map +1 -1
- package/dist/provenance.js +0 -140
- package/dist/provenance.js.map +1 -1
- package/dist/query.js +0 -75
- package/dist/query.js.map +1 -1
- package/dist/reach.js +0 -43
- package/dist/reach.js.map +1 -1
- package/dist/relation.js +0 -61
- package/dist/relation.js.map +1 -1
- package/dist/render.js +20 -135
- package/dist/render.js.map +1 -1
- package/dist/report-sarif.d.ts +0 -11
- package/dist/report-sarif.js +0 -28
- package/dist/report-sarif.js.map +1 -1
- package/dist/sig.js +0 -35
- package/dist/sig.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/siggate.js +0 -4
- package/dist/siggate.js.map +1 -1
- package/dist/site.js +3 -29
- package/dist/site.js.map +1 -1
- package/dist/subsume.d.ts +0 -10
- package/dist/subsume.js +0 -137
- package/dist/subsume.js.map +1 -1
- package/dist/template.d.ts +2 -1
- package/dist/template.js +58 -138
- package/dist/template.js.map +1 -1
- package/dist/trim.js +0 -41
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.js +12 -242
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +0 -22
- package/dist/utility.js.map +1 -1
- package/dist/val/AbnfFuncVal.d.ts +18 -0
- package/dist/val/AbnfFuncVal.js +132 -0
- package/dist/val/AbnfFuncVal.js.map +1 -0
- package/dist/val/AbsentVal.d.ts +11 -0
- package/dist/val/AbsentVal.js +30 -0
- package/dist/val/AbsentVal.js.map +1 -0
- package/dist/val/AggFuncVal.d.ts +10 -1
- package/dist/val/AggFuncVal.js +104 -116
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/ArithFuncVal.js +0 -12
- package/dist/val/ArithFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -78
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +0 -16
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +0 -16
- package/dist/val/BigIntegerVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +0 -9
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/CmpFuncVal.js +2 -59
- package/dist/val/CmpFuncVal.js.map +1 -1
- package/dist/val/ConjunctVal.js +0 -29
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +0 -500
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.js +0 -2
- package/dist/val/ContainerKindVal.js.map +1 -1
- package/dist/val/CopyFuncVal.js +0 -3
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.js +0 -179
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +0 -152
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.js +0 -3
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +1 -1
- package/dist/val/EmitFuncVal.js +6 -119
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/ExpectVal.js +0 -62
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +0 -25
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +7 -127
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.js +0 -15
- package/dist/val/GraphAtomVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +0 -13
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.js +0 -61
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +0 -20
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.js +0 -46
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +0 -57
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +0 -11
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +0 -151
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +0 -27
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
- package/dist/val/MaybeFuncVal.js +50 -0
- package/dist/val/MaybeFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js +0 -18
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +0 -60
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.js +8 -42
- package/dist/val/NomFuncVal.js.map +1 -1
- package/dist/val/NumberVal.js +0 -15
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -0
- package/dist/val/OpBaseVal.js +3 -15
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +0 -34
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +0 -6
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.js +0 -41
- package/dist/val/PathVal.js.map +1 -1
- package/dist/val/PlaceVal.js +0 -25
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +1 -7
- package/dist/val/PlusOpVal.js +13 -74
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js +0 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.js +0 -167
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.js +0 -55
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.js +0 -282
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +0 -232
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +0 -49
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +0 -11
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StrFuncVal.js +0 -18
- package/dist/val/StrFuncVal.js.map +1 -1
- package/dist/val/SuperFuncVal.js +0 -32
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +0 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TranslateFuncVal.js +1 -3
- package/dist/val/TranslateFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js +0 -11
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -0
- package/dist/val/Val.js +2 -133
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +0 -12
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.js +0 -37
- package/dist/val/arith.js.map +1 -1
- package/dist/val/caserange.js +0 -61
- package/dist/val/caserange.js.map +1 -1
- package/dist/val/members.js +0 -6
- package/dist/val/members.js.map +1 -1
- package/dist/val/numcmp.js +0 -11
- package/dist/val/numcmp.js.map +1 -1
- package/dist/val/numkind.js +0 -145
- package/dist/val/numkind.js.map +1 -1
- package/dist/val/valutil.js +0 -16
- package/dist/val/valutil.js.map +1 -1
- package/dist/vet.js +0 -461
- package/dist/vet.js.map +1 -1
- package/dist/view.js +0 -414
- package/dist/view.js.map +1 -1
- package/dist/walk.js +0 -41
- package/dist/walk.js.map +1 -1
- package/grammar/aontu.abnf +8 -6
- package/grammar/aontu.gbnf +4 -4
- package/grammar/aontu.lark +4 -4
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/src/agentsmd.ts +0 -35
- package/src/alias.ts +0 -39
- package/src/allow.ts +1 -96
- package/src/aontu.ts +3 -110
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +113 -682
- package/src/ctx.ts +0 -103
- package/src/diff.ts +0 -40
- package/src/err.ts +0 -40
- package/src/escape.ts +0 -46
- package/src/exactjson.ts +0 -131
- package/src/format.ts +14 -257
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +1 -1
- package/src/hints.ts +66 -57
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +19 -931
- package/src/lower.ts +12 -62
- package/src/lsp-server.ts +0 -16
- package/src/lsp.ts +12 -180
- package/src/mcp-server.ts +0 -31
- package/src/mcp.ts +0 -130
- package/src/mod-tool.ts +0 -158
- package/src/mod.ts +0 -178
- package/src/patch.ts +0 -232
- package/src/provenance.ts +0 -183
- package/src/query.ts +0 -84
- package/src/reach.ts +0 -53
- package/src/relation.ts +0 -84
- package/src/render.ts +20 -172
- package/src/report-sarif.ts +0 -48
- package/src/sig.ts +0 -35
- package/src/sigdecl.ts +1 -1
- package/src/siggate.ts +0 -30
- package/src/site.ts +3 -29
- package/src/subsume.ts +1 -161
- package/src/template.ts +69 -140
- package/src/trim.ts +0 -53
- package/src/type.ts +2 -45
- package/src/unify.ts +13 -251
- package/src/utility.ts +0 -31
- package/src/val/AbnfFuncVal.ts +181 -0
- package/src/val/AbsentVal.ts +54 -0
- package/src/val/AggFuncVal.ts +152 -188
- package/src/val/ArithFuncVal.ts +0 -20
- package/src/val/BagVal.ts +1 -78
- package/src/val/BigDecimalVal.ts +0 -16
- package/src/val/BigIntegerVal.ts +0 -16
- package/src/val/CloseFuncVal.ts +0 -9
- package/src/val/CmpFuncVal.ts +4 -166
- package/src/val/ConjunctVal.ts +0 -33
- package/src/val/ConstraintVal.ts +2 -537
- package/src/val/ContainerKindVal.ts +0 -18
- package/src/val/CopyFuncVal.ts +0 -5
- package/src/val/Decimal.ts +1 -185
- package/src/val/DeprecateFuncVal.ts +0 -10
- package/src/val/DisjunctVal.ts +0 -157
- package/src/val/EachFuncVal.ts +0 -40
- package/src/val/EmitFuncVal.ts +8 -208
- package/src/val/ExpectVal.ts +0 -62
- package/src/val/FilterFuncVal.ts +0 -55
- package/src/val/FuncBaseVal.ts +9 -130
- package/src/val/GraphAtomVal.ts +0 -42
- package/src/val/HideFuncVal.ts +0 -15
- package/src/val/IntegerVal.ts +0 -61
- package/src/val/JunctionVal.ts +0 -20
- package/src/val/KeyFuncVal.ts +0 -48
- package/src/val/ListVal.ts +0 -59
- package/src/val/LowerFuncVal.ts +0 -12
- package/src/val/MapVal.ts +0 -151
- package/src/val/MatchFuncVal.ts +0 -59
- package/src/val/MaybeFuncVal.ts +86 -0
- package/src/val/MoveFuncVal.ts +0 -20
- package/src/val/NilVal.ts +0 -60
- package/src/val/NomFuncVal.ts +8 -95
- package/src/val/NumberVal.ts +0 -16
- package/src/val/OpBaseVal.ts +4 -17
- package/src/val/PackFuncVal.ts +0 -63
- package/src/val/PathFuncVal.ts +0 -32
- package/src/val/PathVal.ts +0 -66
- package/src/val/PlaceVal.ts +0 -45
- package/src/val/PlusOpVal.ts +18 -75
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +0 -179
- package/src/val/RecurseVal.ts +0 -81
- package/src/val/RefVal.ts +1 -285
- package/src/val/ReferFuncVal.ts +0 -255
- package/src/val/ScalarKindVal.ts +0 -50
- package/src/val/ScalarVal.ts +0 -12
- package/src/val/StrFuncVal.ts +0 -44
- package/src/val/SuperFuncVal.ts +0 -42
- package/src/val/TopVal.ts +0 -1
- package/src/val/TranslateFuncVal.ts +1 -51
- package/src/val/UpperFuncVal.ts +0 -12
- package/src/val/Val.ts +3 -192
- package/src/val/VarVal.ts +0 -15
- package/src/val/arith.ts +0 -92
- package/src/val/caserange.ts +0 -62
- package/src/val/members.ts +0 -23
- package/src/val/numcmp.ts +1 -27
- package/src/val/numkind.ts +0 -149
- package/src/val/valutil.ts +0 -16
- package/src/vet.ts +1 -582
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -672
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/dist/val/NamerFuncVal.d.ts +0 -12
- package/dist/val/NamerFuncVal.js +0 -176
- package/dist/val/NamerFuncVal.js.map +0 -1
- package/src/std.ts +0 -683
package/src/render.ts
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
// THE RENDERER (docs/design/RENDER.0.md; docs/capability-review/
|
|
5
|
-
// g9-transformation.md §3). `render` evaluates a document, takes the
|
|
6
|
-
// value at `--at` (the root by default), vets it against the bundled
|
|
7
|
-
// `aontu:code` vocabulary, and folds `code.units` into bytes;
|
|
8
|
-
// `renderValue` is the fold alone, over `generate()` output. The fold
|
|
9
|
-
// is pure and total: it never touches the Val tree, never reads or
|
|
10
|
-
// writes a file, never sorts and never iterates a map, and every piece
|
|
11
|
-
// of a fragment carries its own depth (`at`), so the renderer owns
|
|
12
|
-
// every prefix and no piece nests another (the second amendment's
|
|
13
|
-
// fragment algebra, RENDER.0.md D2 and D6).
|
|
14
|
-
//
|
|
15
|
-
// WHAT THIS PHASE RENDERS (RENDER.0.md P3): fragments -- a line, a
|
|
16
|
-
// blank run, a raw block, a bare string piece, a reference inline --
|
|
17
|
-
// and the `text` escape, under a profile that knows its language. The
|
|
18
|
-
// one bundled profile is `aontu:lang/text`, which every fragment-only
|
|
19
|
-
// unit falls back to; a declaration (`record`, `enum`, ...) needs a
|
|
20
|
-
// LOWERING, which P5 brings with the TypeScript and Go profiles, and
|
|
21
|
-
// until then is `render_profile`.
|
|
22
|
-
|
|
23
4
|
import { Aontu } from './aontu'
|
|
24
5
|
import { vet, failureFinding, anchorAt } from './vet'
|
|
25
6
|
import type { VetFinding } from './vet'
|
|
@@ -42,12 +23,6 @@ export type RenderUnit = {
|
|
|
42
23
|
text: string
|
|
43
24
|
}
|
|
44
25
|
|
|
45
|
-
// THE THREE LOSS TIERS (RENDER.0.md D7). Tier 1 is a check the target's
|
|
46
|
-
// type system cannot enforce (the declaration lowering's, P5); tier 2
|
|
47
|
-
// a fragment -- structured, re-indentable, terminator-checked, saying
|
|
48
|
-
// nothing about target syntax; tier 3 an opaque escape, a `text`
|
|
49
|
-
// declaration or a `raw` piece. `strict` refuses tier 3 and only
|
|
50
|
-
// tier 3.
|
|
51
26
|
export type RenderLoss = {
|
|
52
27
|
unit: string
|
|
53
28
|
path: string
|
|
@@ -56,12 +31,6 @@ export type RenderLoss = {
|
|
|
56
31
|
reason: string
|
|
57
32
|
}
|
|
58
33
|
|
|
59
|
-
// ONE PIECE'S PROVENANCE (RENDER.0.md D9, D11; P7). A dispatch stamps
|
|
60
|
-
// every piece it emits with the node it matched and the rule it took,
|
|
61
|
-
// and the fold reads the stamps back off the instance: `piece` is the
|
|
62
|
-
// piece's own path there, `unit` the unit it landed in, `node` the
|
|
63
|
-
// model address the rule matched, and `rule` the rule's address --
|
|
64
|
-
// its table's, then `#`, then its index in that table.
|
|
65
34
|
export type RenderTrace = {
|
|
66
35
|
unit: string
|
|
67
36
|
piece: string
|
|
@@ -69,8 +38,6 @@ export type RenderTrace = {
|
|
|
69
38
|
rule: string
|
|
70
39
|
}
|
|
71
40
|
|
|
72
|
-
// THE COVERAGE REPORT (P7; G9 §6, "coverage cuts both ways"). Two
|
|
73
|
-
// lists, and both are set computations over what the run recorded.
|
|
74
41
|
export type RenderCoverage = {
|
|
75
42
|
// Every model path a reference resolved to, in walk order: what the
|
|
76
43
|
// render READ.
|
|
@@ -78,27 +45,15 @@ export type RenderCoverage = {
|
|
|
78
45
|
// Dead model: the SHALLOWEST model paths no read reached. A path
|
|
79
46
|
// whose subtree holds a read is not named; its unread children are.
|
|
80
47
|
dead: string[]
|
|
81
|
-
// A silent hole: a rendered declaration no rule produced. In a
|
|
82
|
-
// document with no rule table that is every declaration, which is
|
|
83
|
-
// the true statement about it -- the rule layer governs none of this
|
|
84
|
-
// output.
|
|
85
48
|
unruled: { unit: string, path: string }[]
|
|
86
49
|
}
|
|
87
50
|
|
|
88
51
|
export type RenderReport = {
|
|
89
52
|
verdict: RenderVerdict
|
|
90
|
-
// In `units[]` order. Empty on `error`.
|
|
91
53
|
units: RenderUnit[]
|
|
92
54
|
// Per unit and path. Empty on `error`.
|
|
93
55
|
lossy: RenderLoss[]
|
|
94
|
-
// On `error` only, in vet's finding shape: the document did not
|
|
95
|
-
// stand up, the instance is not `aontu:code`, or a unit could not be
|
|
96
|
-
// rendered (`render_*`).
|
|
97
56
|
errors?: VetFinding[]
|
|
98
|
-
// The dispatch trace, under `trace` or `coverage` (P7), in document
|
|
99
|
-
// order. Absent when it is empty, on `error`, and from
|
|
100
|
-
// `renderValue`, which folds an instance the recorder never watched
|
|
101
|
-
// being built.
|
|
102
57
|
trace?: RenderTrace[]
|
|
103
58
|
// The coverage report, under `coverage` (P7).
|
|
104
59
|
coverage?: RenderCoverage
|
|
@@ -111,31 +66,21 @@ export type RenderOptions = IncludeOptions & {
|
|
|
111
66
|
// Where the document CAME FROM, so a relative `@"file"` load inside
|
|
112
67
|
// it resolves from its own directory.
|
|
113
68
|
path?: string
|
|
114
|
-
// Profiles supplied by the caller, each an evaluated profile map
|
|
115
|
-
// (`{lang, indent, ...}`), matched to a unit by `lang` before the
|
|
116
|
-
// bundled set is asked (RENDER.0.md D5, step 1).
|
|
117
69
|
profiles?: any[]
|
|
118
70
|
// Render only the unit at this path.
|
|
119
71
|
unit?: string
|
|
120
|
-
// Refuse tier-3 loss: the opaque escapes.
|
|
121
72
|
strict?: boolean
|
|
122
|
-
// RECORD THE DISPATCH TRACE (P7). Off by default: an instrumented
|
|
123
|
-
// run stamps every value a reference resolves and every piece a rule
|
|
124
|
-
// emits, and an ordinary one pays one property load per meet.
|
|
125
73
|
trace?: boolean
|
|
126
74
|
// Compute the coverage report, which needs the trace and turns it on.
|
|
127
75
|
coverage?: boolean
|
|
128
|
-
// Measure coverage under this path only, instead of the document
|
|
129
|
-
// root (RENDER.0.md X-3). The narrower measure a document with its
|
|
130
|
-
// model under one key wants.
|
|
131
76
|
coverageAt?: string
|
|
132
77
|
}
|
|
133
78
|
|
|
134
79
|
|
|
135
80
|
const VOCABULARY = '@"aontu:code"'
|
|
136
|
-
// The bundled profiles, by lang: aontu:lang/<lang>.
|
|
137
|
-
const BUNDLED_LANGS = ['go', 'text', 'typescript']
|
|
138
|
-
const PROFILE_VOCABULARY = '@"aontu:
|
|
81
|
+
// The bundled profiles, by lang: aontu:render/lang/<lang>.
|
|
82
|
+
const BUNDLED_LANGS = ['go', 'markdown', 'text', 'typescript']
|
|
83
|
+
const PROFILE_VOCABULARY = '@"aontu:render"'
|
|
139
84
|
|
|
140
85
|
|
|
141
86
|
function finding(
|
|
@@ -150,29 +95,10 @@ function errorReport(errors: VetFinding[]): RenderReport {
|
|
|
150
95
|
}
|
|
151
96
|
|
|
152
97
|
|
|
153
|
-
// The verb's evaluation, before the fold (RENDER.0.md D1): evaluate,
|
|
154
|
-
// anchor, vet the anchored value against the vocabulary as `aontu vet`
|
|
155
|
-
// would, and generate the MEET of the two -- so the vocabulary's
|
|
156
|
-
// defaults (`at: 0`, `n: 1`, `reindent: true`) are in the instance the
|
|
157
|
-
// fold reads, whether or not the document included the vocabulary
|
|
158
|
-
// itself. THE VET AND THE MEET READ THE SETTLED VALUE, re-sourced
|
|
159
|
-
// through its hash form (valid source that evaluates to the same
|
|
160
|
-
// value), not the document's text: a fragment's lines are what a
|
|
161
|
-
// transform COMPUTED -- an `emit`, a `join` -- and the vocabulary's
|
|
162
|
-
// alternatives are tried against values, not against calls that are
|
|
163
|
-
// still waiting to fire. A finding from that vet therefore addresses
|
|
164
|
-
// the instance by path, which is the addressing every render finding
|
|
165
|
-
// uses (G9 §3); a document that does not stand up at all is reported
|
|
166
|
-
// with its own sites, before any of this.
|
|
167
98
|
export function render(src: string, options?: RenderOptions): RenderReport {
|
|
168
99
|
const opts = options ?? {}
|
|
169
100
|
const aontu = new Aontu(includeOpts(opts))
|
|
170
101
|
|
|
171
|
-
// THE RECORDER (P7), on for a run that was asked for a trace or a
|
|
172
|
-
// coverage report and off for every other. Its presence is the one
|
|
173
|
-
// switch: the read set fills as references resolve, and the two
|
|
174
|
-
// riders that carry a read address and a dispatch stamp are written
|
|
175
|
-
// only while it is there.
|
|
176
102
|
const rec = true === opts.trace || true === opts.coverage
|
|
177
103
|
const reads = rec ? new Set<string>() : undefined
|
|
178
104
|
|
|
@@ -198,40 +124,20 @@ export function render(src: string, options?: RenderOptions): RenderReport {
|
|
|
198
124
|
node = found
|
|
199
125
|
}
|
|
200
126
|
|
|
201
|
-
// UNDER NO CALLER CAPABILITY, here and in the meet below: the
|
|
202
|
-
// vocabulary is the engine's own and the instance is a canon, which
|
|
203
|
-
// includes nothing, so the caller's include capability -- which
|
|
204
|
-
// governs the DOCUMENT -- has nothing to govern here, and `none`
|
|
205
|
-
// must not deny the renderer its own schema.
|
|
206
127
|
const value = hcanon(node)
|
|
207
128
|
const report = vet(VOCABULARY, value)
|
|
208
129
|
if ('valid' !== report.verdict) {
|
|
209
130
|
return errorReport(report.findings)
|
|
210
131
|
}
|
|
211
132
|
|
|
212
|
-
// The meet, keyed: the vocabulary's root holds `aontu.Code`, and so
|
|
213
|
-
// does the instance's (a value the vet admitted is a map), and a
|
|
214
|
-
// document with no `code` at all is the vocabulary's own empty
|
|
215
|
-
// instance. The key is namespaced (ADR-029), so the reach is two deep.
|
|
216
133
|
const codeVal: any = node.peg.aontu?.peg?.Code
|
|
217
134
|
const instance = new Aontu().generate(
|
|
218
135
|
VOCABULARY + (undefined === codeVal ? '' : '\naontu: Code: ' + hcanon(codeVal)))
|
|
219
136
|
const folded = renderValue(instance, opts)
|
|
220
137
|
|
|
221
|
-
// THE TWO REPORTS ARE JOINED TO THE FOLD BY PATH (P7), which is what
|
|
222
|
-
// lets the fold stay the pure total function D6 asks for: the
|
|
223
|
-
// dispatch stamps ride the VALUE, the instance the fold reads is
|
|
224
|
-
// that value re-sourced through its hash form, and a piece is at the
|
|
225
|
-
// same path in both. Nothing to report on `error`: there are no
|
|
226
|
-
// units to attribute pieces to.
|
|
227
138
|
if (rec && 'error' !== folded.verdict) {
|
|
228
139
|
const marks = emitted(node)
|
|
229
140
|
const trace = traceOf(marks, instance, folded.units)
|
|
230
|
-
// AN EMPTY TRACE IS NO TRACE, in both ports: Go omits an empty
|
|
231
|
-
// slice, and a report shape that differed by port would be the one
|
|
232
|
-
// thing the shared rows exist to refuse. A run that emitted no
|
|
233
|
-
// piece has nothing to attribute, and the coverage report says so
|
|
234
|
-
// in its own words.
|
|
235
141
|
if (0 < trace.length) {
|
|
236
142
|
folded.trace = trace
|
|
237
143
|
}
|
|
@@ -268,10 +174,6 @@ function walkVals(root: any, fn: (v: any, path: string[]) => boolean): void {
|
|
|
268
174
|
}
|
|
269
175
|
else if (true === v.isMap && null != v.peg) {
|
|
270
176
|
for (const k of Object.keys(v.peg).sort(cmpCodePoint)) {
|
|
271
|
-
// AN ALIAS DECLARATION IS NOT A MEMBER, here for the reason
|
|
272
|
-
// every fold has it (./val/members.ts): `%wire = …` holds a
|
|
273
|
-
// value the document never generates, so it is neither a piece
|
|
274
|
-
// to trace nor model that could be called dead.
|
|
275
177
|
if (!v.aliasKeys.includes(k)) {
|
|
276
178
|
walk(v.peg[k], [...path, k])
|
|
277
179
|
}
|
|
@@ -303,13 +205,6 @@ function emitted(node: any): { path: string, mark: any }[] {
|
|
|
303
205
|
}
|
|
304
206
|
|
|
305
207
|
|
|
306
|
-
// The trace: one entry per stamped piece that a RENDERED unit holds. A
|
|
307
|
-
// piece is IN the unit whose path prefixes its own, which is the whole
|
|
308
|
-
// of the question -- no path is parsed, and a stamp that lies under no
|
|
309
|
-
// unit at all (a rule set held under a key of its own, and referred to
|
|
310
|
-
// from a unit) simply matches nothing. A unit the run did not render
|
|
311
|
-
// (`--unit` names one) has no bytes for a piece of it to be in, so it
|
|
312
|
-
// is not among the prefixes either.
|
|
313
208
|
function traceOf(marks: { path: string, mark: any }[], instance: any,
|
|
314
209
|
units: RenderUnit[]): RenderTrace[] {
|
|
315
210
|
const pre: { at: string, path: string }[] = []
|
|
@@ -341,10 +236,6 @@ function ancestors(a: string): string[] {
|
|
|
341
236
|
}
|
|
342
237
|
|
|
343
238
|
|
|
344
|
-
// Is the value at `a` covered by the set -- the address itself in it,
|
|
345
|
-
// or an address above it? An address ABOVE it covers the whole subtree:
|
|
346
|
-
// a reference that read `$.schema` read everything under it, and a rule
|
|
347
|
-
// that emitted a unit emitted every declaration in it.
|
|
348
239
|
function covered(set: Set<string>, a: string): boolean {
|
|
349
240
|
if (set.has(a)) {
|
|
350
241
|
return true
|
|
@@ -358,15 +249,6 @@ function covered(set: Set<string>, a: string): boolean {
|
|
|
358
249
|
}
|
|
359
250
|
|
|
360
251
|
|
|
361
|
-
// THE COVERAGE REPORT (P7). Dead model is measured over the DOCUMENT
|
|
362
|
-
// ROOT, or under `coverageAt` when a document keeps its model under one
|
|
363
|
-
// key (X-3, decided here): the read set is absolute, so a narrower
|
|
364
|
-
// measure is a narrower walk, not a different origin. The render's own
|
|
365
|
-
// output -- the `aontu` namespace under the anchor -- is not model and
|
|
366
|
-
// is never walked into: nothing reads it, so every document would
|
|
367
|
-
// otherwise report it dead. The whole NAMESPACE is excluded, not just
|
|
368
|
-
// `aontu.Code` (ADR-029): everything under it is language-supplied, so
|
|
369
|
-
// an included vocabulary is not dead model either.
|
|
370
252
|
function coverOf(root: any, node: any, reads: Set<string>,
|
|
371
253
|
opts: RenderOptions, marks: { path: string, mark: any }[], instance: any,
|
|
372
254
|
units: RenderUnit[]): RenderCoverage | undefined {
|
|
@@ -386,8 +268,6 @@ function coverOf(root: any, node: any, reads: Set<string>,
|
|
|
386
268
|
base = found.path
|
|
387
269
|
}
|
|
388
270
|
|
|
389
|
-
// The two questions asked of the read set, as sets: is this address
|
|
390
|
-
// read (or under one that is), and does a read lie BELOW it?
|
|
391
271
|
const above = new Set<string>(reads)
|
|
392
272
|
const below = new Set<string>()
|
|
393
273
|
for (const r of reads) {
|
|
@@ -402,11 +282,6 @@ function coverOf(root: any, node: any, reads: Set<string>,
|
|
|
402
282
|
if (a === codeAddr || covered(above, a)) {
|
|
403
283
|
return false
|
|
404
284
|
}
|
|
405
|
-
// THE ROOT OF THE MEASURE IS NEVER ITSELF DEAD MODEL, and is
|
|
406
|
-
// descended into whatever the read set holds. A document that is
|
|
407
|
-
// only a transform reads nothing above its own model, and naming
|
|
408
|
-
// the root there would report the whole document dead while its
|
|
409
|
-
// one live subtree sat inside it.
|
|
410
285
|
if (below.has(a) || 0 === path.length) {
|
|
411
286
|
return true
|
|
412
287
|
}
|
|
@@ -446,25 +321,19 @@ function coverOf(root: any, node: any, reads: Set<string>,
|
|
|
446
321
|
// whose declarations are fragments and text escapes only.
|
|
447
322
|
const bundled: Record<string, any> = {}
|
|
448
323
|
|
|
449
|
-
// A bundled profile, evaluated once: the meet of aontu:lang/<lang>
|
|
324
|
+
// A bundled profile, evaluated once: the meet of aontu:render/lang/<lang>
|
|
450
325
|
// with the vocabulary, so its defaults are in it.
|
|
451
326
|
function bundledProfile(lang: string): any {
|
|
452
327
|
if (!BUNDLED_LANGS.includes(lang)) {
|
|
453
328
|
return undefined
|
|
454
329
|
}
|
|
455
330
|
if (undefined === bundled[lang]) {
|
|
456
|
-
bundled[lang] = new Aontu().generate('@"aontu:lang/' + lang + '"').aontu.
|
|
331
|
+
bundled[lang] = new Aontu().generate('@"aontu:render/lang/' + lang + '"').aontu.render.Lang
|
|
457
332
|
}
|
|
458
333
|
return bundled[lang]
|
|
459
334
|
}
|
|
460
335
|
|
|
461
336
|
|
|
462
|
-
// PROFILE SELECTION, per unit (RENDER.0.md D5): a caller-supplied
|
|
463
|
-
// profile whose `lang` is the unit's; else the bundled profile of that
|
|
464
|
-
// `lang`; else `aontu:lang/text`, if and only if every declaration in
|
|
465
|
-
// the unit is a fragment or a text escape; else nothing, which the
|
|
466
|
-
// caller reports as `render_profile`. The unit's inline `profile` is
|
|
467
|
-
// merged over whichever base was found.
|
|
468
337
|
function profileFor(lang: string, given: any[] | undefined, fragOnly: boolean): any {
|
|
469
338
|
const supplied = (given ?? []).find((p: any) => p?.lang === lang)
|
|
470
339
|
if (undefined !== supplied) {
|
|
@@ -496,16 +365,6 @@ function mergeProfile(base: any, over: any): any {
|
|
|
496
365
|
}
|
|
497
366
|
|
|
498
367
|
|
|
499
|
-
// THE FOLD (RENDER.0.md D6). `pad(at)` is `indent.unit` repeated
|
|
500
|
-
// `indent.width × at` times; a line is `pad + text + LF`, and an empty
|
|
501
|
-
// text emits no pad; a blank is its terminators alone; a raw block's
|
|
502
|
-
// lines each get the pad unless `reindent: false`, which emits them
|
|
503
|
-
// at column 0 verbatim -- and common leading indentation is never
|
|
504
|
-
// stripped. A reference inline is its name, verbatim (a
|
|
505
|
-
// declaration-capable profile puts it through its identifier rules,
|
|
506
|
-
// P5). Nothing is trimmed (D3): the text is the transform's.
|
|
507
|
-
// A profile with no indent -- a caller-supplied map the vocabulary
|
|
508
|
-
// never filled -- takes the vocabulary's own default, two spaces.
|
|
509
368
|
function pad(profile: any, at: number): string {
|
|
510
369
|
const indent = profile.indent ?? { unit: ' ', width: 2 }
|
|
511
370
|
return (indent.unit ?? ' ').repeat((indent.width ?? 2) * at)
|
|
@@ -532,7 +391,7 @@ function foldPiece(
|
|
|
532
391
|
return line(profile, 0, piece)
|
|
533
392
|
}
|
|
534
393
|
if ('line' === piece.k) {
|
|
535
|
-
return line(profile, piece.at ?? 0, piece.
|
|
394
|
+
return line(profile, piece.at ?? 0, piece.n.map((p: any) => inline(p, ctx)).join(''))
|
|
536
395
|
}
|
|
537
396
|
if ('blank' === piece.k) {
|
|
538
397
|
return '\n'.repeat(piece.n ?? 1)
|
|
@@ -551,13 +410,6 @@ function foldPiece(
|
|
|
551
410
|
}
|
|
552
411
|
|
|
553
412
|
|
|
554
|
-
// A PROFILE DOCUMENT (RENDER.0.md D5), evaluated the way `render`
|
|
555
|
-
// evaluates its own: under the caller's include options, then vetted
|
|
556
|
-
// against aontu:profile as a settled value and met with that vocabulary
|
|
557
|
-
// so its defaults (`indent.width: 2`, ...) are in it. The answer is the
|
|
558
|
-
// `profile` map the fold reads -- what `--profile <file>` hands to
|
|
559
|
-
// RenderOptions.profiles -- or the findings that refused the document:
|
|
560
|
-
// one that does not stand up, or one the vocabulary rejects.
|
|
561
413
|
export function renderProfile(src: string, options?: RenderOptions):
|
|
562
414
|
{ profile?: any, errors?: VetFinding[] } {
|
|
563
415
|
const opts = options ?? {}
|
|
@@ -574,9 +426,9 @@ export function renderProfile(src: string, options?: RenderOptions):
|
|
|
574
426
|
// The meet, keyed as render's is: the vocabulary requires `profile`,
|
|
575
427
|
// so a value the vet admitted has one.
|
|
576
428
|
const instance = new Aontu().generate(
|
|
577
|
-
PROFILE_VOCABULARY + '\naontu:
|
|
578
|
-
hcanon(root.peg.aontu.peg.
|
|
579
|
-
return { profile: instance.aontu.
|
|
429
|
+
PROFILE_VOCABULARY + '\naontu: render: Lang: ' +
|
|
430
|
+
hcanon(root.peg.aontu.peg.render.peg.Lang))
|
|
431
|
+
return { profile: instance.aontu.render.Lang }
|
|
580
432
|
}
|
|
581
433
|
|
|
582
434
|
|
|
@@ -589,10 +441,6 @@ function unitList(instance: any): any[] {
|
|
|
589
441
|
}
|
|
590
442
|
|
|
591
443
|
|
|
592
|
-
// The fold alone, over `generate()` output: the instance is
|
|
593
|
-
// `{code: {units: [...]}}` as the vocabulary shapes it, with its
|
|
594
|
-
// defaults filled -- which is what `render` hands over, and what a
|
|
595
|
-
// caller of this function is responsible for.
|
|
596
444
|
export function renderValue(instance: any, options?: RenderOptions): RenderReport {
|
|
597
445
|
const opts = options ?? {}
|
|
598
446
|
const errors: VetFinding[] = []
|
|
@@ -638,15 +486,11 @@ export function renderValue(instance: any, options?: RenderOptions): RenderRepor
|
|
|
638
486
|
if (undefined === base) {
|
|
639
487
|
errors.push(finding('render_profile', 'parse', upath + '.lang',
|
|
640
488
|
'no profile renders ' + lang + ': a declaration needs a lowering, and ' +
|
|
641
|
-
'only fragments and text escapes render under aontu:lang/text.'))
|
|
489
|
+
'only fragments and text escapes render under aontu:render/lang/text.'))
|
|
642
490
|
return
|
|
643
491
|
}
|
|
644
492
|
const profile = null == unit.profile ? base : mergeProfile(base, unit.profile)
|
|
645
493
|
|
|
646
|
-
// THE LOWERING (D5, P5), when the profile names one: the unit's
|
|
647
|
-
// header -- banner, package clause, imports -- and each declaration
|
|
648
|
-
// as pieces the fold takes, a blank line between two lowered
|
|
649
|
-
// declarations. A fragment or a text escape owns its own blanks.
|
|
650
494
|
const family: string | undefined = profile.lowering
|
|
651
495
|
const ctx: LowerCtx | undefined = undefined === family ? undefined
|
|
652
496
|
: { profile, family, unit: path, lossy }
|
|
@@ -666,12 +510,16 @@ export function renderValue(instance: any, options?: RenderOptions): RenderRepor
|
|
|
666
510
|
const dpath = upath + '.decls.' + j
|
|
667
511
|
if ('frag' === decl.k) {
|
|
668
512
|
lowered = false
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
513
|
+
// Lossy only against a language whose DECLARATIONS could have
|
|
514
|
+
// been lowered instead: a fragment is all the others have.
|
|
515
|
+
if (null != profile.lowering) {
|
|
516
|
+
lossy.push({
|
|
517
|
+
unit: path, path: dpath, tier: 2, construct: 'frag',
|
|
518
|
+
reason: 'a fragment says nothing about ' + lang + ' syntax',
|
|
519
|
+
})
|
|
520
|
+
}
|
|
521
|
+
decl.n.forEach((piece: any, n: number) => {
|
|
522
|
+
text += foldPiece(piece, profile, path, dpath + '.n.' + n, lossy, ctx)
|
|
675
523
|
})
|
|
676
524
|
}
|
|
677
525
|
else if ('text' === decl.k) {
|
package/src/report-sarif.ts
CHANGED
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// SARIF rendering for a vet report (G2 phase 5,
|
|
4
|
-
// docs/capability-review/g2-validation-verb.md).
|
|
5
|
-
//
|
|
6
|
-
// A MINIMAL SARIF 2.1.0 profile, and deliberately nothing more: one
|
|
7
|
-
// run, one `result` per finding, the finding's first site as the
|
|
8
|
-
// primary location, its remaining sites under `relatedLocations`, and
|
|
9
|
-
// the whole finding object embedded in `properties` so a SARIF consumer
|
|
10
|
-
// still holds the native contract. No fixes, no code flows, no
|
|
11
|
-
// baselines — the JSON report is the native contract, SARIF is the
|
|
12
|
-
// interchange skin CI systems already ingest (GitHub code scanning
|
|
13
|
-
// uploads, PR annotation).
|
|
14
|
-
//
|
|
15
|
-
// This is library API, not CLI plumbing, for the same reason the vet
|
|
16
|
-
// engine is: an embedder (and G7's MCP server later) must be able to
|
|
17
|
-
// emit the interchange form without shelling out. The Go twin is
|
|
18
|
-
// go/report_sarif.go, and the two are held to byte parity over the
|
|
19
|
-
// shared fixture pair in test/spec/files/vet-sarif/ — with the message
|
|
20
|
-
// text and producer version redacted, exactly as test/spec/vet.tsv
|
|
21
|
-
// carves the message out of its goldens, because prose and the two
|
|
22
|
-
// independent version series are deliberately not in cross-port parity.
|
|
23
3
|
|
|
24
4
|
import type { VetReport, VetFinding, VetSite } from './vet'
|
|
25
5
|
|
|
@@ -37,13 +17,6 @@ const SARIF_LEVEL: Record<string, string> = {
|
|
|
37
17
|
}
|
|
38
18
|
|
|
39
19
|
|
|
40
|
-
// A site's file is a filesystem path, and a SARIF artifactLocation.uri
|
|
41
|
-
// is a URI reference: `#`, `%`, spaces and every other URI-significant
|
|
42
|
-
// character must be percent-encoded or a consumer parses the path as
|
|
43
|
-
// something else (text after `#` becomes a fragment). Encoded BY BYTE
|
|
44
|
-
// over UTF-8, with RFC 3986's unreserved and path characters kept
|
|
45
|
-
// literal, so the Go twin produces identical bytes from an identical
|
|
46
|
-
// loop (go/report_sarif.go sarifURI).
|
|
47
20
|
function sarifUri(path: string): string {
|
|
48
21
|
const bytes = Buffer.from(path, 'utf8')
|
|
49
22
|
let out = ''
|
|
@@ -75,11 +48,6 @@ function sarifLocation(site: VetSite): any {
|
|
|
75
48
|
|
|
76
49
|
|
|
77
50
|
function sarifResult(finding: VetFinding): any {
|
|
78
|
-
// The engine orders sites data-first (the thing to fix), so the first
|
|
79
|
-
// site is the primary location and the rest are related — which for a
|
|
80
|
-
// two-site conflict puts the schema's declaration under
|
|
81
|
-
// `relatedLocations`, exactly where a code-scanning UI shows "the
|
|
82
|
-
// other side".
|
|
83
51
|
const result: any = {
|
|
84
52
|
level: SARIF_LEVEL[finding.severity],
|
|
85
53
|
locations: [sarifLocation(finding.sites[0])],
|
|
@@ -95,26 +63,10 @@ function sarifResult(finding: VetFinding): any {
|
|
|
95
63
|
}
|
|
96
64
|
|
|
97
65
|
|
|
98
|
-
/**
|
|
99
|
-
* Render a vet report as SARIF 2.1.0 text (a minimal profile: one run,
|
|
100
|
-
* one result per finding, the finding embedded in `properties`).
|
|
101
|
-
*
|
|
102
|
-
* @param report A report from `vet()`.
|
|
103
|
-
* @param version The producer version for `tool.driver.version` —
|
|
104
|
-
* the CLI passes its package version; the two ports'
|
|
105
|
-
* version series are independent by design.
|
|
106
|
-
* @returns The SARIF JSON text, indented two spaces, keys in
|
|
107
|
-
* the canonical emitter's sorted order.
|
|
108
|
-
*/
|
|
109
66
|
function sarifReport(report: VetReport, version: string): string {
|
|
110
67
|
return exactJSON({
|
|
111
68
|
$schema: 'https://json.schemastore.org/sarif-2.1.0.json',
|
|
112
69
|
runs: [{
|
|
113
|
-
// An `error` verdict means the run could not be set up (an
|
|
114
|
-
// unusable schema): zero findings from a FAILED run must not
|
|
115
|
-
// read like zero findings from a clean one, so the failure is
|
|
116
|
-
// carried in SARIF's own invocation metadata rather than by an
|
|
117
|
-
// indistinguishable empty result list.
|
|
118
70
|
invocations: [{
|
|
119
71
|
executionSuccessful: 'error' !== report.verdict,
|
|
120
72
|
}],
|
package/src/sig.ts
CHANGED
|
@@ -1,29 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2021-2026 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// THE SIGNATURE REGISTRY (docs/design/SIGNATURES.0.md). The call
|
|
4
|
-
// surface of the built-in functions is DECLARED, in the signature
|
|
5
|
-
// syntax itself, in test/spec/signature.tsv; this module is the
|
|
6
|
-
// TypeScript half of the pair that reads it. The declaration text is
|
|
7
|
-
// inlined at build time (ts/src/sigdecl.ts, `make sig`) and parsed at
|
|
8
|
-
// initialisation by the signature grammar -- a custom tabnas grammar,
|
|
9
|
-
// the same engine the aontu grammar itself is built on -- into the
|
|
10
|
-
// registry the runtime signature checker, the error-message builder,
|
|
11
|
-
// the docs table and the LSP all consume. Neither port authors a
|
|
12
|
-
// table: go/sig.go parses the same text with the same grammar, and
|
|
13
|
-
// the shared suite round-trips every line (render(parse(line)) is the
|
|
14
|
-
// line) so the two parsers cannot drift.
|
|
15
|
-
//
|
|
16
|
-
// line = name '(' [ arg {',' arg} ] ')' ':' type
|
|
17
|
-
// arg = [mode] name ['?'] ':' type
|
|
18
|
-
// | '...' name ':' ( type | '(' [mode] type {',' [mode] type} ')' )
|
|
19
|
-
// type = word {'|' word}
|
|
20
|
-
// mode = 'capture' | 'template' | 'trial' | 'projector' | 'text'
|
|
21
|
-
//
|
|
22
|
-
// `value` mode is unmarked; the five marked modes are the vocabulary
|
|
23
|
-
// plain pseudo-TypeScript cannot say (a captured spelling is not a
|
|
24
|
-
// string value). The grammar is line-oriented: the loader strips
|
|
25
|
-
// comment and blank lines and parses each declaration line alone, so
|
|
26
|
-
// the grammar never sees line structure.
|
|
27
3
|
|
|
28
4
|
import { Tabnas } from '@tabnas/parser'
|
|
29
5
|
|
|
@@ -59,11 +35,6 @@ const ARG_MODES: Record<string, boolean> = {
|
|
|
59
35
|
}
|
|
60
36
|
|
|
61
37
|
|
|
62
|
-
// The signature grammar, as a tabnas grammar plugin. Rules: sig (the
|
|
63
|
-
// line) -> args -> arg -> argtype -> type | group -> gmember. Alts
|
|
64
|
-
// match at most two tokens, the engine's shape; lists loop the
|
|
65
|
-
// json-grammar way (the element rule replaces itself on ',' and
|
|
66
|
-
// backtracks the closer for its parent to consume).
|
|
67
38
|
function sigGrammar(tn: any) {
|
|
68
39
|
tn.options({
|
|
69
40
|
fixed: {
|
|
@@ -326,12 +297,6 @@ export type {
|
|
|
326
297
|
FuncSig,
|
|
327
298
|
}
|
|
328
299
|
|
|
329
|
-
// The parsed registry, built once from the inlined declaration -- the
|
|
330
|
-
// one source every consumer (the arity tables, the runtime gate, the
|
|
331
|
-
// hints, the docs table, the LSP) reads. A parse failure here throws
|
|
332
|
-
// at module load: the inlined text is repository content whose parse
|
|
333
|
-
// the round-trip suite gates, so a failure is a build defect, not a
|
|
334
|
-
// runtime condition. Twin: funcSig in go/sig.go.
|
|
335
300
|
const funcSig: Record<string, FuncSig> =
|
|
336
301
|
parseSigText(SIGDECL) /* node:coverage ignore next 9 */
|
|
337
302
|
|
package/src/sigdecl.ts
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
// this copy is identical with the shared file.
|
|
7
7
|
|
|
8
8
|
const SIGDECL: string =
|
|
9
|
-
"# The call surface: one declaration line per built-in function\n# (docs/design/SIGNATURES.0.md). THIS FILE IS THE SOURCE — both ports\n# carry a build-time-inlined copy (ts/src/sigdecl.ts, go/sigdecl.txt;\n# `make sig` regenerates both, and each port's suite asserts its copy\n# is byte-identical with this file) and parse it at initialisation\n# with the signature grammar, a tabnas grammar (ts/src/sig.ts,\n# go/sig.go). The suites also round-trip every line:\n# render(parse(line)) must be the line exactly, in both ports.\n#\n# The syntax (rendered TypeScript-ish, honest about argument MODES):\n# line = name '(' [ arg {',' arg} ] ')' ':' type\n# arg = [mode] name ['?'] ':' type\n# | '...' name ':' '(' [mode] type {',' [mode] type} ')'\n# type = word {'|' word}\n# mode = 'capture' | 'template' | 'trial' | 'projector' | 'text'\n# `value` mode is unmarked. `constraint` is the result word for\n# residuals whose meet depends on the peer; `any` is the honest type\n# where a function is a wrapper.\nupper(s: string|number, start?: integer|biginteger, len?: integer|biginteger) : string\nlower(s: string|number, start?: integer|biginteger, len?: integer|biginteger) : string\ncopy(v: any) : any\npref(v: any) : any\nsuper(t: any) : any\ntype(t: any) : any\nhide(v: any) : any\nclose(m: any) : any\nopen(m: any) : any\nmove(v: any) : any\npath(capture p?: path) : path\nmap() : map\nlist() : list\nmin(n: number|string) : constraint\nmax(n: number|string) : constraint\nabove(n: number|string) : constraint\nbelow(n: number|string) : constraint\nre(text p: string) : constraint\nlength(n: number|constraint) : constraint\nkey(up?: integer|biginteger) : string\nunique(projector k?: string) : constraint\nneq(...vals: number|string) : constraint\nmust(trial c: any, text msg: string) : constraint\ndeprecate(v: any, r?: map) : any\nacyclic() : constraint\ninverse(projector k: string) : constraint\nrefer(template t?: any) : constraint\nrel(template t?: any) : constraint\npack(d: map|list, template t: any) : map\neach(d: map|list, template t: any) : list\nfilter(d: map|list, trial c: any) : map|list\nmatch(s: any, ...pr: (trial any, any), dflt?: any) : any\nadd(a: number, b: number) : number\nsub(a: number, b: number) : number\nmul(a: number, b: number) : number\ndiv(a: number, b: number) : number\nmod(a: number, b: number) : number\nrem(a: number, b: number) : number\nsum(d: map|list) : number\nleast(d: map|list) : number\ngreatest(d: map|list) : number\npick(d: map|list, projector k: string|integer) : any\njoin(d: map|list, sep?: string) : string\nesc(s: string, variant?: string) : string\nusc(s: string, variant?: string) : string\nrep(s: string, text p: string, text sub: string) : string\nsplit(s: string, sep: string|constraint) : list\nemit(s: map|list, template t: map|list) : list\n"
|
|
9
|
+
"# The call surface: one declaration line per built-in function\n# (docs/design/SIGNATURES.0.md). THIS FILE IS THE SOURCE — both ports\n# carry a build-time-inlined copy (ts/src/sigdecl.ts, go/sigdecl.txt;\n# `make sig` regenerates both, and each port's suite asserts its copy\n# is byte-identical with this file) and parse it at initialisation\n# with the signature grammar, a tabnas grammar (ts/src/sig.ts,\n# go/sig.go). The suites also round-trip every line:\n# render(parse(line)) must be the line exactly, in both ports.\n#\n# The syntax (rendered TypeScript-ish, honest about argument MODES):\n# line = name '(' [ arg {',' arg} ] ')' ':' type\n# arg = [mode] name ['?'] ':' type\n# | '...' name ':' '(' [mode] type {',' [mode] type} ')'\n# type = word {'|' word}\n# mode = 'capture' | 'template' | 'trial' | 'projector' | 'text'\n# `value` mode is unmarked. `constraint` is the result word for\n# residuals whose meet depends on the peer; `any` is the honest type\n# where a function is a wrapper.\nupper(s: string|number, start?: integer|biginteger, len?: integer|biginteger) : string\nlower(s: string|number, start?: integer|biginteger, len?: integer|biginteger) : string\ncopy(v: any) : any\npref(v: any) : any\nsuper(t: any) : any\ntype(t: any) : any\nhide(v: any) : any\nmaybe(v: any) : any\nclose(m: any) : any\nopen(m: any) : any\nmove(v: any) : any\npath(capture p?: path) : path\nmap() : map\nlist() : list\nmin(n: number|string) : constraint\nmax(n: number|string) : constraint\nabove(n: number|string) : constraint\nbelow(n: number|string) : constraint\nre(text p: string) : constraint\nlength(n: number|constraint) : constraint\nkey(up?: integer|biginteger) : string\nunique(projector k?: string) : constraint\nneq(...vals: number|string) : constraint\nmust(trial c: any, text msg: string) : constraint\ndeprecate(v: any, r?: map) : any\nacyclic() : constraint\ninverse(projector k: string) : constraint\nrefer(template t?: any) : constraint\nrel(template t?: any) : constraint\npack(d: map|list, template t: any) : map\neach(d: map|list, template t: any) : list\nfilter(d: map|list, trial c: any) : map|list\nmatch(s: any, ...pr: (trial any, any), dflt?: any) : any\nadd(a: number, b: number) : number\nsub(a: number, b: number) : number\nmul(a: number, b: number) : number\ndiv(a: number, b: number) : number\nmod(a: number, b: number) : number\nrem(a: number, b: number) : number\nsum(d: map|list) : number\nleast(d: map|list) : number\ngreatest(d: map|list) : number\npick(d: map|list, projector k: string|integer) : any\nsort(d: map|list, projector k?: string|integer, dir?: string) : list\njoin(d: map|list, sep?: string) : string\nesc(s: string, variant?: string) : string\nusc(s: string, variant?: string) : string\nrep(s: string, text p: string, text sub: string) : string\nsplit(s: string, sep: string|constraint) : list\nemit(s: map|list, template t: map|list) : list\nabnf(g: string) : string\nparse(g: string, v?: string) : map|list|constraint\nnom(name: string, style?: string|list, acronyms?: list) : string|map\ntranslate(s: string, from: string, to?: string) : string\nproject(spec?: string|map, children?: list) : map\nfolder(spec: string|map, children?: list) : map\nfile(spec: string|map, children?: list) : map\ncontent(spec: string|map) : map\nline(spec: string|map) : map\nfragment(spec: string|map, children?: list) : map\nslot(spec: string|map, children?: list) : map\ninject(spec: string|map, children?: list) : map\ncopyfiles(spec: string|map) : map\nlistitems(spec: map, children?: list) : map\n"
|
|
10
10
|
|
|
11
11
|
export { SIGDECL }
|
package/src/siggate.ts
CHANGED
|
@@ -1,31 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2021-2026 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// THE RUNTIME SIGNATURE CHECKER (docs/design/SIGNATURES.0.md). One
|
|
4
|
-
// argument gate, run by the shared function machinery
|
|
5
|
-
// (FuncBaseVal.unify) just before a call resolves, when its arguments
|
|
6
|
-
// are driven: for each VALUE-mode argument whose declared type is
|
|
7
|
-
// scalar-kind words, the driven Val must be a concrete scalar of an
|
|
8
|
-
// admitted kind. A failure refuses as `func_arg`, whose hint renders
|
|
9
|
-
// the signature line and names the offending argument -- the
|
|
10
|
-
// error-message builder the registry exists for.
|
|
11
|
-
//
|
|
12
|
-
// The gate owns exactly the argument-shape refusals that were bare
|
|
13
|
-
// `invalid-arg` at the call: the case family's operand, the
|
|
14
|
-
// arithmetic operands, join's separator, pick's key. Everything with
|
|
15
|
-
// more meaning than a shape mismatch keeps its own code: the bag
|
|
16
|
-
// arguments (`pack_data`, `each_data`, `filter_data`,
|
|
17
|
-
// `aggregate_data` -- container words are not gate words), the
|
|
18
|
-
// constraint atoms (not on this path at all -- their refusals ride
|
|
19
|
-
// the residual), `key()` (whose level meaning `key_level` names, and
|
|
20
|
-
// which is skipped here for that reason), and the capture, template,
|
|
21
|
-
// trial, projector and text modes, none of which are read as values.
|
|
22
|
-
//
|
|
23
|
-
// What the gate refuses it must POSITIVELY identify: a concrete
|
|
24
|
-
// scalar of a wrong kind, a map, a list, or a scalar KIND marker
|
|
25
|
-
// where a value belongs. Anything else -- a preference, a residual, a
|
|
26
|
-
// disjunct -- passes through to the builtin's own logic, which is
|
|
27
|
-
// what keeps arith's unpref reading and join's deferral working.
|
|
28
|
-
// Twin: sigRefuse in go/siggate.go.
|
|
29
3
|
|
|
30
4
|
import type { Val } from './type'
|
|
31
5
|
import { AontuContext } from './ctx'
|
|
@@ -44,10 +18,6 @@ import {
|
|
|
44
18
|
} from './val/ScalarKindVal'
|
|
45
19
|
|
|
46
20
|
|
|
47
|
-
// The scalar-kind words the gate enforces, each to its lattice
|
|
48
|
-
// marker. A declared type is gate-checkable only when EVERY union
|
|
49
|
-
// word is here: `any`, `constraint`, and the container words leave
|
|
50
|
-
// the argument to the builtin.
|
|
51
21
|
const SIG_KIND = new Map<string, any>([
|
|
52
22
|
['string', String],
|
|
53
23
|
['number', Number],
|
package/src/site.ts
CHANGED
|
@@ -10,35 +10,9 @@ type SiteSpec = {
|
|
|
10
10
|
row?: number, col?: number, url?: string, len?: number, src?: string,
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// THE EXTENT IS NOT OPTIONAL DETAIL — it is what makes a site safe to
|
|
17
|
-
// edit. Without it the only length available is the CANON, and canon is
|
|
18
|
-
// not source text: `port: 0x1F` has canon `31`, so replacing
|
|
19
|
-
// `(col, canon.length)` writes `port: 5x1F` and corrupts the document.
|
|
20
|
-
// The parser knew the extent all along — the token carries `len` and
|
|
21
|
-
// `src` beside the `rI`/`cI` this already read — and dropping it was
|
|
22
|
-
// the whole defect (status report 2026-08-21, §5).
|
|
23
|
-
//
|
|
24
|
-
// WHAT THE EXTENT COVERS is the TOKEN THE SITE POINTS AT, which is the
|
|
25
|
-
// same thing row and col have always pointed at:
|
|
26
|
-
//
|
|
27
|
-
// 0x1F a scalar literal len 4 the whole literal
|
|
28
|
-
// "hi there" a string len 10 quotes included
|
|
29
|
-
// {x:1} a map len 1 the opening brace
|
|
30
|
-
// min(3) a constraint len 3 the name, not the call
|
|
31
|
-
//
|
|
32
|
-
// So for a SCALAR — which is what a repair edits, and what `set` and
|
|
33
|
-
// the manual fallback rewrite — `(col, len)` is exactly the span to
|
|
34
|
-
// replace. For a container it under-reaches to the opening delimiter,
|
|
35
|
-
// which is safe in the direction that matters: a highlight that is too
|
|
36
|
-
// short is a cosmetic flaw, while canon.length on a map over-reaches
|
|
37
|
-
// across lines into text the value never occupied.
|
|
38
|
-
//
|
|
39
|
-
// -1 and '' mean UNKNOWN, the same convention row and col already use:
|
|
40
|
-
// a value minted by unification rather than written by a document has
|
|
41
|
-
// no site, and must not be edited as though it had one.
|
|
13
|
+
// row, col and len -1, url and src empty, mean UNKNOWN: a value the
|
|
14
|
+
// engine minted rather than read has no site, and must not be edited
|
|
15
|
+
// as though it had one.
|
|
42
16
|
class Site {
|
|
43
17
|
row: number
|
|
44
18
|
col: number
|