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/dist/lang.js
CHANGED
|
@@ -2,18 +2,9 @@
|
|
|
2
2
|
/* Copyright (c) 2021-2025 Richard Rodger, MIT License */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.Site = exports.Lang = void 0;
|
|
5
|
-
// import { performance } from 'node:perf_hooks'
|
|
6
|
-
// Named imports, not `import * as`: the namespace form makes tsc emit
|
|
7
|
-
// the __importStar downlevel helper, whose branches no supported Node
|
|
8
|
-
// takes (the same rule cli.ts records). Aliased because `Path` is
|
|
9
|
-
// already the @tabnas/path plugin below.
|
|
10
5
|
const node_fs_1 = require("node:fs");
|
|
11
6
|
const node_path_1 = require("node:path");
|
|
12
7
|
const jsonic_1 = require("@tabnas/jsonic");
|
|
13
|
-
// THE CONFIG-FORMAT READERS (ADR-012). Each is a jsonic plugin for one
|
|
14
|
-
// format, so an included `.toml` or `.yaml` is parsed by a real parser
|
|
15
|
-
// for that format rather than guessed at by this one. `@tabnas/json` is
|
|
16
|
-
// the strict RFC 8259 reader, used for `.json` and `.jsonld`.
|
|
17
8
|
const sig_1 = require("./sig");
|
|
18
9
|
const json_1 = require("@tabnas/json");
|
|
19
10
|
const toml_1 = require("@tabnas/toml");
|
|
@@ -23,18 +14,11 @@ const yaml_1 = require("@tabnas/yaml");
|
|
|
23
14
|
const ini_1 = require("@tabnas/ini");
|
|
24
15
|
const debug_1 = require("@tabnas/debug");
|
|
25
16
|
const multisource_1 = require("@tabnas/multisource");
|
|
26
|
-
// TODO: @tabnas/multisource should support virtual fs
|
|
27
17
|
const file_1 = require("@tabnas/multisource/resolver/file");
|
|
28
18
|
const pkg_1 = require("@tabnas/multisource/resolver/pkg");
|
|
29
19
|
const mem_1 = require("@tabnas/multisource/resolver/mem");
|
|
30
|
-
// The Aontu-source processor, TAKEN RATHER THAN ALIASED. The obvious
|
|
31
|
-
// spelling is the alias `aon: 'jsonic'`, which multisource resolves
|
|
32
|
-
// through its own processor map -- but `jsonic` is a FORMAT NAME in
|
|
33
|
-
// the include table now, so that alias resolved to the plain-jsonic
|
|
34
|
-
// DATA reader and every `.aon` include was suddenly parsed without the
|
|
35
|
-
// language in it. Naming the function leaves nothing to collide with.
|
|
36
20
|
const jsonic_2 = require("@tabnas/multisource/processor/jsonic");
|
|
37
|
-
const
|
|
21
|
+
const aontumodel_1 = require("./aontumodel");
|
|
38
22
|
const mod_1 = require("./mod");
|
|
39
23
|
const expr_1 = require("@tabnas/expr");
|
|
40
24
|
const path_1 = require("@tabnas/path");
|
|
@@ -67,11 +51,13 @@ const CopyFuncVal_1 = require("./val/CopyFuncVal");
|
|
|
67
51
|
const KeyFuncVal_1 = require("./val/KeyFuncVal");
|
|
68
52
|
const TypeFuncVal_1 = require("./val/TypeFuncVal");
|
|
69
53
|
const HideFuncVal_1 = require("./val/HideFuncVal");
|
|
54
|
+
const AbnfFuncVal_1 = require("./val/AbnfFuncVal");
|
|
70
55
|
const DeprecateFuncVal_1 = require("./val/DeprecateFuncVal");
|
|
71
56
|
const ReferFuncVal_1 = require("./val/ReferFuncVal");
|
|
72
57
|
const GraphAtomVal_1 = require("./val/GraphAtomVal");
|
|
73
58
|
const PackFuncVal_1 = require("./val/PackFuncVal");
|
|
74
59
|
const CmpFuncVal_1 = require("./val/CmpFuncVal");
|
|
60
|
+
const MaybeFuncVal_1 = require("./val/MaybeFuncVal");
|
|
75
61
|
const NomFuncVal_1 = require("./val/NomFuncVal");
|
|
76
62
|
const TranslateFuncVal_1 = require("./val/TranslateFuncVal");
|
|
77
63
|
const EachFuncVal_1 = require("./val/EachFuncVal");
|
|
@@ -91,32 +77,11 @@ const OpenFuncVal_1 = require("./val/OpenFuncVal");
|
|
|
91
77
|
const SuperFuncVal_1 = require("./val/SuperFuncVal");
|
|
92
78
|
const ConstraintVal_1 = require("./val/ConstraintVal");
|
|
93
79
|
const asPlugin = (p) => p;
|
|
94
|
-
// Build the Val for a matched `0d` literal (see the `0d` value matcher
|
|
95
|
-
// below). Leaf by source: digits only is a biginteger, a `.` or an
|
|
96
|
-
// exponent makes it a bigdecimal.
|
|
97
|
-
//
|
|
98
|
-
// A literal over the D6 exactness budget becomes a LOCATED ERROR here
|
|
99
|
-
// and not a rounded or expanded value: `0d1e1000000000` has a one-digit
|
|
100
|
-
// coefficient, so only the scale bound catches it, and it is caught at
|
|
101
|
-
// parse -- before plain-form rendering would try to materialise a
|
|
102
|
-
// gigabyte of zeros.
|
|
103
|
-
// The source text of a negated exact literal. `-` is a prefix OPERATOR,
|
|
104
|
-
// not part of the literal, so the text has to be rebuilt here to keep
|
|
105
|
-
// `src` meaning "how this value is spelled" (see bigVal).
|
|
106
80
|
function negsrc(src) {
|
|
107
|
-
// src is never empty here: it is a BIG_LITERAL_RE match (at minimum
|
|
108
|
-
// the two chars `0d`) or an already-negated spelling. Computed exact
|
|
109
|
-
// values do carry src '', but they are built at unify time, long
|
|
110
|
-
// after this parse-time opmap.
|
|
111
81
|
return src.startsWith('-') ? src.slice(1) : '-' + src;
|
|
112
82
|
}
|
|
113
83
|
function bigVal(res) {
|
|
114
84
|
const lit = (0, Decimal_1.readBigLiteral)(res);
|
|
115
|
-
// `src` is the literal's own text, and it is not decoration: a path
|
|
116
|
-
// segment is spelled text, so `$.a.0d1` must address the key `0d1` --
|
|
117
|
-
// the same key `a:{0d1:7}` creates -- rather than the number 1. See
|
|
118
|
-
// RefVal.append. Without it the segment was empty and the reference
|
|
119
|
-
// silently resolved to its own container.
|
|
120
85
|
const src = res[0];
|
|
121
86
|
return 'biginteger' === lit.leaf ? new BigIntegerVal_1.BigIntegerVal({ peg: lit.int, src }) :
|
|
122
87
|
'bigdecimal' === lit.leaf ? new BigDecimalVal_1.BigDecimalVal({ peg: lit.dec, src }) :
|
|
@@ -126,43 +91,11 @@ function bigVal(res) {
|
|
|
126
91
|
const CC_0 = 48;
|
|
127
92
|
const CC_d = 100;
|
|
128
93
|
const CC_D = 68;
|
|
129
|
-
// THE ALIAS SIGIL. `%` is part of an alias's name, so the name is one
|
|
130
|
-
// lexeme wherever it appears and its meaning is decided by position:
|
|
131
|
-
// a BINDING in key position (`%uint8 = …` declares), a USE in value
|
|
132
|
-
// position (`listen: %uint8` refers). docs/design/ALIASES.0.md §4.
|
|
133
94
|
const CC_PCT = 37;
|
|
134
95
|
const ALIAS_RE = /^%[A-Za-z_][A-Za-z0-9_]*/;
|
|
135
|
-
// THE DECLARATION OPERATOR. `%name = value` declares; the `=` is the
|
|
136
|
-
// pair's separator, lexed as the colon token so the declaration then
|
|
137
|
-
// parses as a pair whose key is the alias name (ALIASES.0.md X-1, as
|
|
138
|
-
// settled 2026-09-05). `=` is syntax ONLY there: anywhere else it is
|
|
139
|
-
// punctuation outside its syntax, and the bare-text scan below refuses
|
|
140
|
-
// it (`foo = 1`, `a: x=y`).
|
|
141
96
|
const CC_EQ = 61;
|
|
142
97
|
const CC_SP = 32;
|
|
143
98
|
const CC_TAB = 9;
|
|
144
|
-
// THE BARE-TEXT RULE. A bare string holds letters, digits, `-` and `_`,
|
|
145
|
-
// and nothing else. Every other punctuation character is either SYNTAX,
|
|
146
|
-
// where the grammar gives it a meaning, or an ERROR where it does not
|
|
147
|
-
// -- never silently part of a string. `x=y`, `6/2`, `50%` and `>10`
|
|
148
|
-
// were all bare strings once, each a well-formed wrong document, and
|
|
149
|
-
// each is refused now, naming the character (bare_punct).
|
|
150
|
-
//
|
|
151
|
-
// scanBareRun classifies each character of a run three ways, in this
|
|
152
|
-
// order: TEXT continues the run; an ENDER stops it; anything else is
|
|
153
|
-
// BAD. The ender set is the lexer's own -- space, line, fixed tokens,
|
|
154
|
-
// comment starters -- read from the config its text matcher was built
|
|
155
|
-
// from, so it cannot drift from the grammar. A bad run is still scanned
|
|
156
|
-
// to its ender, so the refusal claims the whole spelling and the lexer
|
|
157
|
-
// never reads the tail of it as syntax.
|
|
158
|
-
//
|
|
159
|
-
// `-` is text wherever the scan sees it. A run never STARTS on one:
|
|
160
|
-
// `-` is the sign of a number and the negation prefix, a fixed token
|
|
161
|
-
// the fixed matcher claims before either scanning stage can run, so
|
|
162
|
-
// `a:-1` is the negation of 1 and `a:6-2` the string. The `+` of an
|
|
163
|
-
// exponent (`1e+2`) is admitted only by the NUMBER stage's scan, the
|
|
164
|
-
// one stage that can make a number of it. Mirrors scanBareRun in
|
|
165
|
-
// go/lang.go, decision for decision.
|
|
166
99
|
const CC_9 = 57;
|
|
167
100
|
const CC_A = 65;
|
|
168
101
|
const CC_Z = 90;
|
|
@@ -233,34 +166,10 @@ const NUMBER_RUN_RE = /^[-+]?(?:0(?:[xX][0-9a-fA-F_]+|[oO][0-7_]+|[bB][01_]+)|[0
|
|
|
233
166
|
const NOT_A_NUMBER = { done: true, token: undefined };
|
|
234
167
|
let AontuJsonic = function AontuLang(jsonic) {
|
|
235
168
|
jsonic.use(asPlugin(path_1.Path));
|
|
236
|
-
// Only # line comments are valid Aontu syntax (see
|
|
237
|
-
// docs/reference-language.md; go/lang.go sets the same). Clear the
|
|
238
|
-
// underlying jsonic comment markers entirely, then define # directly,
|
|
239
|
-
// so the comment set is hash-only regardless of those defaults.
|
|
240
169
|
let dotRef = (r, ctx, terms, prefix) => {
|
|
241
170
|
terms = dropUnfilled(terms);
|
|
242
171
|
if (0 === terms.length)
|
|
243
172
|
return incompleteNil(r, ctx);
|
|
244
|
-
// AN ALIAS IS NOT A PATH SEGMENT. `$.%foo` is refused: the alias
|
|
245
|
-
// namespace and the path namespace are disjoint, and an alias is
|
|
246
|
-
// reached by writing `%foo` and only that.
|
|
247
|
-
//
|
|
248
|
-
// The engine spells an alias reference AS a root reference to the
|
|
249
|
-
// declaration -- which is what gives it order independence and a
|
|
250
|
-
// cycle check shared with paths -- but that is an implementation of
|
|
251
|
-
// the name, not a second way to write it. Left writable, the two
|
|
252
|
-
// spellings would drift apart the moment aliases stop being
|
|
253
|
-
// file-shaped, and `$.%b` inside an included file would reach the
|
|
254
|
-
// INCLUDER's `%b` rather than its own, which is exactly the
|
|
255
|
-
// cross-file capture the sigil exists to prevent.
|
|
256
|
-
// `%foo` lexes to the reference itself, so in `$.%foo` it arrives
|
|
257
|
-
// as a TERM rather than as a string segment -- both shapes are
|
|
258
|
-
// checked, since a quoted `$."%foo"` would arrive as the string.
|
|
259
|
-
// Terms here are always Vals -- dropUnfilled has removed the
|
|
260
|
-
// nulls, and the dot rules never hand over a raw string -- so the
|
|
261
|
-
// shapes are exactly three: a RefVal (peg is the segment array), a
|
|
262
|
-
// StringVal (peg is the segment), and anything else (a numeric or
|
|
263
|
-
// exact segment, which cannot be an alias name).
|
|
264
173
|
for (const t of terms) {
|
|
265
174
|
const segs = Array.isArray(t.peg) ? t.peg :
|
|
266
175
|
('string' === typeof t.peg ? [t.peg] : []);
|
|
@@ -281,48 +190,12 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
281
190
|
},
|
|
282
191
|
},
|
|
283
192
|
});
|
|
284
|
-
// Digit separators are legal only as a SINGLE separator BETWEEN
|
|
285
|
-
// digits (the rule test/spec/engine-parity.tsv records as the engine's
|
|
286
|
-
// adjudication; pinned by the sep-* rows in
|
|
287
|
-
// test/spec/number-model.tsv). The engine's number matcher
|
|
288
|
-
// enforces most of that already — `1_`, `_1`, `1_.5`, `1._5`, `1e_2`,
|
|
289
|
-
// `1e2_` all fall through to text — but two gaps remain: a REPEATED
|
|
290
|
-
// separator (`1__0` lexed as 10) and a separator at the edge of a
|
|
291
|
-
// base-prefixed digit run (`0x_ff`, `0xff_` lexed as 255). Both
|
|
292
|
-
// silently accept a typo as a different number, so aontu declines the
|
|
293
|
-
// whole run instead and it lexes as text ("1__0"), exactly as `1_`
|
|
294
|
-
// already does.
|
|
295
|
-
//
|
|
296
|
-
// `number.exclude` is tested against the matched number source and,
|
|
297
|
-
// when it matches, makes the matcher decline the entire span. Kept in
|
|
298
|
-
// lock-step with sepInvalid in go/lang.go, which is wired to the
|
|
299
|
-
// equivalent `Number.Exclude` hook (and to the Check hook, which
|
|
300
|
-
// constructs big base-prefixed tokens itself and so bypasses Exclude).
|
|
301
193
|
jsonic.options({
|
|
302
194
|
number: {
|
|
303
|
-
// `__` repeated separator; `0x_`/`0o_`/`0b_` separator opening a
|
|
304
|
-
// base-prefixed run; `_` closing any run. The prefix letter is
|
|
305
|
-
// matched case-insensitively so the rule does not depend on which
|
|
306
|
-
// prefix spellings the engine accepts.
|
|
307
195
|
exclude: /__|^[-+]?0[xXoObB]_|_$/,
|
|
308
|
-
// THE NUMBER STAGE OF THE BARE-TEXT RULE. The matcher runs before
|
|
309
|
-
// the text matcher and reads a number up to the next ender -- and
|
|
310
|
-
// `-` is an ender, being the negation prefix's fixed token, so it
|
|
311
|
-
// would take the `2026` of `2026-09-05` and leave `-09-05` to the
|
|
312
|
-
// grammar. The hook scans the whole run first and declines for
|
|
313
|
-
// the matcher wherever the run is not its to lex: a run with a
|
|
314
|
-
// bad character (the text stage refuses it), a run that is not a
|
|
315
|
-
// number at all (`2026-09-05`, `6-2` are text). Twin of tsNumCheck
|
|
316
|
-
// in go/lang.go.
|
|
317
196
|
check: (lex) => {
|
|
318
197
|
const pnt = lex.pnt;
|
|
319
198
|
const src = lex.src;
|
|
320
|
-
// The hook makes the matcher a candidate at every position, so
|
|
321
|
-
// the common case -- a run no number can open -- declines for it
|
|
322
|
-
// in one char read. A DIGIT opens a number here and nothing
|
|
323
|
-
// else: the sign and the dot open the matcher's own grammar, but
|
|
324
|
-
// they are fixed tokens (the prefix operators and member
|
|
325
|
-
// access), claimed before this hook can run.
|
|
326
199
|
const c = src.charCodeAt(pnt.sI);
|
|
327
200
|
if (!(CC_0 <= c && c <= CC_9)) {
|
|
328
201
|
return NOT_A_NUMBER;
|
|
@@ -335,67 +208,15 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
335
208
|
},
|
|
336
209
|
},
|
|
337
210
|
});
|
|
338
|
-
// D3 -- the `0d` literal, the only route to the exact leaves
|
|
339
|
-
// (biginteger and bigdecimal). See BIG_LITERAL_RE for the grammar and
|
|
340
|
-
// the leaf-by-source rule.
|
|
341
|
-
//
|
|
342
|
-
// The literal is claimed by the TEXT MATCHER'S CHECK HOOK (the sibling
|
|
343
|
-
// of the `Number.Check` hook the Go port already uses for big
|
|
344
|
-
// base-prefixed literals), not by a `value.def` entry, because a `0d`
|
|
345
|
-
// run may contain a `.` and the two claim source differently:
|
|
346
|
-
//
|
|
347
|
-
// - A value def -- even a consuming one, matched against the full
|
|
348
|
-
// forward source -- is applied INSIDE the text matcher, AFTER its
|
|
349
|
-
// ender regexp has already carved the run at the `.`. The def
|
|
350
|
-
// claims `0d1.5` whole, but the matcher then still emits the
|
|
351
|
-
// ender's `.` as a fixed token, so `x:0d1.5` lexed as the
|
|
352
|
-
// bigdecimal FOLLOWED BY a dangling member-access dot (a path
|
|
353
|
-
// cycle). Verified, not theorised.
|
|
354
|
-
// - The check hook runs BEFORE that ender regexp and returns the
|
|
355
|
-
// token outright, so the run is claimed whole and nothing else is
|
|
356
|
-
// emitted.
|
|
357
|
-
//
|
|
358
|
-
// A `match.value` matcher (which runs ahead of every other matcher)
|
|
359
|
-
// also claims it correctly, but it is a candidate at EVERY lex
|
|
360
|
-
// position and materializes the forward source there: ~8% on a
|
|
361
|
-
// text-heavy document, for a syntax almost none of them use. The check
|
|
362
|
-
// hook only runs where the text matcher already runs, and measures at
|
|
363
|
-
// parity with not having it.
|
|
364
|
-
//
|
|
365
|
-
// The number matcher never sees these runs at all: it declines `0d…`
|
|
366
|
-
// outright, since `d` is not an ender.
|
|
367
211
|
jsonic.options({
|
|
368
212
|
text: {
|
|
369
213
|
check: (lex) => {
|
|
370
|
-
// Guard first, on char codes: this hook runs at every text
|
|
371
|
-
// position, and the common case (any run that cannot be a `0d`
|
|
372
|
-
// literal or an alias) must cost two char reads and no
|
|
373
|
-
// allocation.
|
|
374
214
|
const pnt = lex.pnt;
|
|
375
215
|
const src = lex.src;
|
|
376
|
-
// AN ALIAS NAME IS CLAIMED WHOLE, for the same reason the `0d`
|
|
377
|
-
// run below is: the text matcher's ender regexp would otherwise
|
|
378
|
-
// carve `%uint8` at the `%` and emit the sigil as its own token,
|
|
379
|
-
// leaving a bare `uint8` behind -- which is exactly the capture
|
|
380
|
-
// the sigil exists to prevent. Claiming it here, before that
|
|
381
|
-
// ender runs, keeps the name one lexeme.
|
|
382
|
-
//
|
|
383
|
-
// The token's SOURCE is the whole `%name`, which is what makes
|
|
384
|
-
// the same lexeme work in both positions: jsonic keys a pair by
|
|
385
|
-
// the token's source text (`0d1: 5` yields the key `0d1`), so a
|
|
386
|
-
// declaration reads as the key `%uint8`, while a value position
|
|
387
|
-
// calls the function below and gets the reference.
|
|
388
|
-
// A `%` that opens no name (`%`, `%1`, `50%`) falls through to
|
|
389
|
-
// the bare-text scan below, which refuses it.
|
|
390
216
|
const ares = CC_PCT === src.charCodeAt(pnt.sI) ?
|
|
391
217
|
ALIAS_RE.exec(lex.refwd()) : null;
|
|
392
218
|
if (null != ares) {
|
|
393
219
|
const asrc = ares[0];
|
|
394
|
-
// A lone `=` after the name, across horizontal space only, is
|
|
395
|
-
// the declaration operator. Decided HERE, where the name is
|
|
396
|
-
// claimed, and only its position is kept: the very next text
|
|
397
|
-
// position is that `=`, since nothing but space sits between,
|
|
398
|
-
// so the mark cannot outlive its one use. `==` is not it.
|
|
399
220
|
let j = pnt.sI + asrc.length;
|
|
400
221
|
while (j < src.length &&
|
|
401
222
|
(CC_SP === src.charCodeAt(j) || CC_TAB === src.charCodeAt(j))) {
|
|
@@ -404,24 +225,11 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
404
225
|
if (CC_EQ === src.charCodeAt(j) && CC_EQ !== src.charCodeAt(j + 1)) {
|
|
405
226
|
lex.aontu_eq_at = j;
|
|
406
227
|
}
|
|
407
|
-
const atkn = lex.token('#VL',
|
|
408
|
-
// AN ALIAS REFERENCE IS A PATH REFERENCE. `%uint8` is
|
|
409
|
-
// `$.%uint8`: root-absolute, one segment, spelled with the
|
|
410
|
-
// sigil the declaration is spelled with. Everything the
|
|
411
|
-
// design asks of it -- order independence, alias-of-alias,
|
|
412
|
-
// redeclaration unifying, cycle refusal spanning both
|
|
413
|
-
// namespaces -- is then the reference machinery already in
|
|
414
|
-
// the language, not a second resolver beside it.
|
|
415
|
-
(r, ctx) => addsite(new RefVal_1.RefVal({ peg: [asrc], absolute: true }), r, ctx), asrc, pnt);
|
|
228
|
+
const atkn = lex.token('#VL', (r, ctx) => addsite(new RefVal_1.RefVal({ peg: [asrc], absolute: true }), r, ctx), asrc, pnt);
|
|
416
229
|
pnt.sI += asrc.length;
|
|
417
230
|
pnt.cI += asrc.length;
|
|
418
231
|
return { done: true, token: atkn };
|
|
419
232
|
}
|
|
420
|
-
// The `=` the alias arm above marked: the separator of a
|
|
421
|
-
// declaration, as a colon token whose source is `=`. The pair rule
|
|
422
|
-
// is then the pair rule, and the formatter writes the spelling it
|
|
423
|
-
// read. Marked in `use` so the pair rule can tell it from a colon,
|
|
424
|
-
// which no longer declares.
|
|
425
233
|
if (CC_EQ === src.charCodeAt(pnt.sI) && lex.aontu_eq_at === pnt.sI) {
|
|
426
234
|
delete lex.aontu_eq_at;
|
|
427
235
|
const eqtkn = lex.token('#CL', undefined, '=', pnt, { aontu_eq: true });
|
|
@@ -432,18 +240,9 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
432
240
|
if (CC_0 === src.charCodeAt(pnt.sI)) {
|
|
433
241
|
const c1 = src.charCodeAt(pnt.sI + 1);
|
|
434
242
|
if (CC_d === c1 || CC_D === c1) {
|
|
435
|
-
// BIG_LITERAL_RE is `^`-anchored and read against the
|
|
436
|
-
// forward source (memoized per position by refwd), which is
|
|
437
|
-
// what lets it claim the `.` of `0d1.5`. A `0d` run it does
|
|
438
|
-
// not match falls through to the bare-text scan below.
|
|
439
243
|
const res = Decimal_1.BIG_LITERAL_RE.exec(lex.refwd());
|
|
440
244
|
if (null != res) {
|
|
441
245
|
const msrc = res[0];
|
|
442
|
-
// The token value is a FUNCTION so Val construction
|
|
443
|
-
// happens at parse time, where the rule and context needed
|
|
444
|
-
// for the site exist (jsonic calls a #VL token's function
|
|
445
|
-
// value with them). A `0d` literal never spans a line, so
|
|
446
|
-
// only the source and column positions advance.
|
|
447
246
|
const tkn = lex.token('#VL', (r, ctx) => addsite(bigVal(res), r, ctx), msrc, pnt);
|
|
448
247
|
pnt.sI += msrc.length;
|
|
449
248
|
pnt.cI += msrc.length;
|
|
@@ -451,21 +250,9 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
451
250
|
}
|
|
452
251
|
}
|
|
453
252
|
}
|
|
454
|
-
// THE BARE-TEXT RULE (scanBareRun). Last, so that a name, a
|
|
455
|
-
// declaration operator and an exact literal are read before a
|
|
456
|
-
// run is judged as text.
|
|
457
|
-
// The run is never empty: every ender is a token an earlier
|
|
458
|
-
// matcher claims, so the text stage only opens on a character
|
|
459
|
-
// the scan classifies as text or as bad.
|
|
460
253
|
const run = scanBareRun(lex.cfg, src, pnt.sI, false);
|
|
461
254
|
const msrc = src.slice(pnt.sI, run.end);
|
|
462
255
|
if (-1 !== run.bad) {
|
|
463
|
-
// BAD: the run is refused whole, sited at the character (the
|
|
464
|
-
// mark in `use` is what tokenSite reads). As a VALUE the
|
|
465
|
-
// token's function builds the refusal at the parse, where the
|
|
466
|
-
// rule carries the position. As a KEY the token is read for
|
|
467
|
-
// its source alone, so the mark is what the pair and elem
|
|
468
|
-
// rules read to write the refusal where the map is built.
|
|
469
256
|
const ch = run.ch;
|
|
470
257
|
const tkn = lex.token('#VL', (r, ctx) => {
|
|
471
258
|
const nv = addsite(new NilVal_1.NilVal({ why: 'bare_punct' }), r, ctx);
|
|
@@ -476,11 +263,6 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
476
263
|
pnt.cI += msrc.length;
|
|
477
264
|
return { done: true, token: tkn };
|
|
478
265
|
}
|
|
479
|
-
// CLEAN, with a `-` past its start (`team-payments`,
|
|
480
|
-
// `2026-09-05`): claimed here as one text token, because the
|
|
481
|
-
// default matcher's ender set would carve the run at the `-`.
|
|
482
|
-
// Any other clean run is the default matcher's, which also reads
|
|
483
|
-
// the value keywords and the `_` hole.
|
|
484
266
|
if (-1 !== msrc.indexOf('-')) {
|
|
485
267
|
const tkn = lex.token('#TX', msrc, msrc, pnt);
|
|
486
268
|
pnt.sI += msrc.length;
|
|
@@ -518,14 +300,6 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
518
300
|
v.path = r.k ? [...r.k.path] : [];
|
|
519
301
|
return v;
|
|
520
302
|
};
|
|
521
|
-
// THE KEY REFUSALS a pair may carry, decided from its key TOKEN --
|
|
522
|
-
// never from the key text alone, since a quoted `"%a"` or `"x=y"` is
|
|
523
|
-
// an ordinary key: a declaration spelled with a colon (alias_colon),
|
|
524
|
-
// and a key the bare-text rule refuses (bare_punct). Undefined for an
|
|
525
|
-
// ordinary key, and for a declaration (`%a = 1`), which is a binding
|
|
526
|
-
// (isAliasDecl), not a refusal. Asked FIRST by the pair rule and by
|
|
527
|
-
// the elem rule, before the declaration is, so a pair in list
|
|
528
|
-
// position is held to the map's rules.
|
|
529
303
|
const isAliasDecl = (ktkn, sep) => null != ktkn && VL === ktkn.tin && ALIAS_RE.test('' + ktkn.src) &&
|
|
530
304
|
true === sep?.use?.aontu_eq;
|
|
531
305
|
const keyRefusalOf = (ktkn, sep) => {
|
|
@@ -564,10 +338,6 @@ help isolate the syntax error.`,
|
|
|
564
338
|
},
|
|
565
339
|
value: {
|
|
566
340
|
def: {
|
|
567
|
-
// NOTE: specify with functions as jsonic/deep will
|
|
568
|
-
// remove class prototype as options are assumed plain
|
|
569
|
-
// (except for functions).
|
|
570
|
-
// TODO: jsonic should be able to pass context into these
|
|
571
341
|
'string': {
|
|
572
342
|
val: (r, ctx) => addsite(new ScalarKindVal_1.ScalarKindVal({ peg: String }), r, ctx)
|
|
573
343
|
},
|
|
@@ -583,8 +353,6 @@ help isolate the syntax error.`,
|
|
|
583
353
|
'float': {
|
|
584
354
|
val: (r, ctx) => addsite(new ScalarKindVal_1.ScalarKindVal({ peg: ScalarKindVal_1.Float }), r, ctx)
|
|
585
355
|
},
|
|
586
|
-
// The two exact leaves. Their keywords are the marker class
|
|
587
|
-
// names lowercased, which is also how ScalarKindVal canons them.
|
|
588
356
|
'biginteger': {
|
|
589
357
|
val: (r, ctx) => addsite(new ScalarKindVal_1.ScalarKindVal({ peg: ScalarKindVal_1.BigInteger }), r, ctx)
|
|
590
358
|
},
|
|
@@ -597,7 +365,6 @@ help isolate the syntax error.`,
|
|
|
597
365
|
'nil': {
|
|
598
366
|
val: (r, ctx) => addsite(new NilVal_1.NilVal({ why: 'literal_nil' }), r, ctx)
|
|
599
367
|
},
|
|
600
|
-
// TODO: FIX: need a TOP instance to hold path
|
|
601
368
|
'top': { val: () => (0, top_1.top)() },
|
|
602
369
|
// G8 phase 3: the placeholder. A BARE `_` is the hole; `"_"`
|
|
603
370
|
// quoted, and any longer bare word containing it, stay text.
|
|
@@ -612,7 +379,6 @@ help isolate the syntax error.`,
|
|
|
612
379
|
let pval = prev;
|
|
613
380
|
let cval = curr;
|
|
614
381
|
if (pval?.isVal && cval?.isVal) {
|
|
615
|
-
// TODO: test multi element conjuncts work
|
|
616
382
|
if (pval.isConjunct && cval.isConjunct) {
|
|
617
383
|
pval.append(cval);
|
|
618
384
|
return pval;
|
|
@@ -628,14 +394,6 @@ help isolate the syntax error.`,
|
|
|
628
394
|
// Handle defered conjuncts, where MapVal does not yet
|
|
629
395
|
// exist, by creating ConjunctVal later.
|
|
630
396
|
else {
|
|
631
|
-
// AN INCLUDE UNIFIES IN PLACE. multisource calls this hook at
|
|
632
|
-
// the `@`'s own source position, so `prev` holds exactly the
|
|
633
|
-
// pairs written BEFORE it. Folding the loaded map's keys in
|
|
634
|
-
// here -- host-so-far first, arriving value second -- is what
|
|
635
|
-
// inlining the loaded bytes at the `@` does, and mirrors
|
|
636
|
-
// go/lang.go's Map.Merge, which multisource-go drives one key
|
|
637
|
-
// at a time. A non-map load has no keys to fold and stays a
|
|
638
|
-
// deferred conjunct arm.
|
|
639
397
|
if (true === cval?.isMap) {
|
|
640
398
|
const lm = cval;
|
|
641
399
|
for (const k of Object.keys(lm.peg)) {
|
|
@@ -645,10 +403,6 @@ help isolate the syntax error.`,
|
|
|
645
403
|
? new ConjunctVal_1.ConjunctVal({ peg: [own, lm.peg[k]] })
|
|
646
404
|
: lm.peg[k]);
|
|
647
405
|
}
|
|
648
|
-
// The loaded map's spread joins THIS map's spread list at
|
|
649
|
-
// the `@`'s position: the parse pushes each `&:` onto the
|
|
650
|
-
// node as it is read, so `prev[SPREAD].v` already holds the
|
|
651
|
-
// spreads written before the `@` and nothing after it.
|
|
652
406
|
if (null != lm.spread?.cj) {
|
|
653
407
|
;
|
|
654
408
|
prev[type_1.SPREAD] =
|
|
@@ -682,20 +436,11 @@ help isolate the syntax error.`,
|
|
|
682
436
|
move: MoveFuncVal_1.MoveFuncVal,
|
|
683
437
|
path: PathFuncVal_1.PathFuncVal,
|
|
684
438
|
pref: PrefFuncVal_1.PrefFuncVal,
|
|
685
|
-
// First-class paths and the container kinds
|
|
686
|
-
// (docs/design/PATHS.0.md). `path(p)` CAPTURES a path as a value;
|
|
687
|
-
// `path()`, `map()` and `list()` are kinds -- the vacuous
|
|
688
|
-
// constructor call admits its values and defaults to nothing,
|
|
689
|
-
// where the container LITERALS `{}`/`[]` default to empty.
|
|
690
439
|
map: ContainerKindVal_1.MapFuncVal,
|
|
691
440
|
list: ContainerKindVal_1.ListFuncVal,
|
|
692
441
|
close: CloseFuncVal_1.CloseFuncVal,
|
|
693
442
|
open: OpenFuncVal_1.OpenFuncVal,
|
|
694
443
|
super: SuperFuncVal_1.SuperFuncVal,
|
|
695
|
-
// The constraint algebra's Band A atoms (G1 phase 1;
|
|
696
|
-
// docs/reference-language.md, "The constraint algebra"): bounds
|
|
697
|
-
// and exclusion enter through the function registry — the
|
|
698
|
-
// established extension point — with zero grammar change.
|
|
699
444
|
min: ConstraintVal_1.MinConstraintVal,
|
|
700
445
|
max: ConstraintVal_1.MaxConstraintVal,
|
|
701
446
|
above: ConstraintVal_1.AboveConstraintVal,
|
|
@@ -704,25 +449,15 @@ help isolate the syntax error.`,
|
|
|
704
449
|
// G1 phase 2: pattern membership, over the portable subset both
|
|
705
450
|
// host regex engines agree on (nonPortableRe in ConstraintVal.ts).
|
|
706
451
|
re: ConstraintVal_1.ReConstraintVal,
|
|
707
|
-
// G1 phase 3: the sizing atoms. Both are properties of a CONTAINER
|
|
708
|
-
// (or, for length, of a string) rather than comparisons against a
|
|
709
|
-
// value, which is why `unique` is the one built-in taking no
|
|
710
|
-
// argument at all.
|
|
711
452
|
length: ConstraintVal_1.LengthConstraintVal,
|
|
712
453
|
unique: ConstraintVal_1.UniqueConstraintVal,
|
|
713
|
-
// G1 phase 5: Band B. `must` is the one atom the algebra does not
|
|
714
|
-
// reason about -- it is checked against the finished value and
|
|
715
|
-
// reported with the author's own message, never simplified and
|
|
716
|
-
// never consulted for emptiness or subsumption.
|
|
717
454
|
must: ConstraintVal_1.MustConstraintVal,
|
|
455
|
+
abnf: AbnfFuncVal_1.AbnfFuncVal,
|
|
456
|
+
parse: AbnfFuncVal_1.ParseFuncVal,
|
|
718
457
|
// G3 phase 4: the deprecation mark. Unification-transparent; the
|
|
719
458
|
// record rides the result (Val.deprecation) and canon renders the
|
|
720
459
|
// call back (canonRiders).
|
|
721
460
|
deprecate: DeprecateFuncVal_1.DeprecateFuncVal,
|
|
722
|
-
// G4 phase 2: the checked, typed, LINK-shaped reference. A
|
|
723
|
-
// constraint on a string field: the string must be a TREE ADDRESS
|
|
724
|
-
// (`$.a.b` or `.b`), the address must resolve, and the optional
|
|
725
|
-
// argument flows INTO the target. The field keeps the string.
|
|
726
461
|
refer: ReferFuncVal_1.ReferFuncVal,
|
|
727
462
|
rel: ReferFuncVal_1.RelFuncVal,
|
|
728
463
|
// RELATIONS P2 (docs/design/RELATIONS.0.md §3.3): the graph
|
|
@@ -730,112 +465,32 @@ help isolate the syntax error.`,
|
|
|
730
465
|
// govern. Lattice-inert; the verdict lands at generation.
|
|
731
466
|
acyclic: GraphAtomVal_1.AcyclicFuncVal,
|
|
732
467
|
inverse: GraphAtomVal_1.InverseFuncVal,
|
|
733
|
-
// G8 phase 1: generation to KEYED CHILDREN. `pack` makes one keyed
|
|
734
|
-
// child per child of its data, cloning its template per
|
|
735
|
-
// destination exactly as a spread does, and waits for the model to
|
|
736
|
-
// settle before it fires (the staging rule, G8 phase 0).
|
|
737
468
|
pack: PackFuncVal_1.PackFuncVal,
|
|
738
|
-
// RENDER P6: the order-preserving map, and generation to a LIST.
|
|
739
|
-
// `each` makes one list element per child of its data, being the
|
|
740
|
-
// template with `_` bound to the source child. It exists because
|
|
741
|
-
// `pick(pack(...))` re-sorts to code-point order, and a struct's
|
|
742
|
-
// fields or a file's imports are the model's order or they are
|
|
743
|
-
// wrong.
|
|
744
|
-
//
|
|
745
|
-
// Mentioning the hole makes it a BOUND instead: `each(d, _ & t)`
|
|
746
|
-
// meets each child with `t`, and `each(d, _)` is a bag's members
|
|
747
|
-
// as a list. That is what the retired meet-only `each` spelled
|
|
748
|
-
// (ADR-026), and why this one could take the name (ADR-027).
|
|
749
469
|
each: EachFuncVal_1.EachFuncVal,
|
|
750
|
-
// G8 phase 2: selection. `filter` keeps the children of a bag that
|
|
751
|
-
// unify with a condition; `match` picks the first arm whose
|
|
752
|
-
// pattern the scrutinee unifies with. Both select by
|
|
753
|
-
// UNIFIABILITY, tried in trial mode, so neither adds a predicate
|
|
754
|
-
// language to the one the lattice already is.
|
|
755
470
|
filter: FilterFuncVal_1.FilterFuncVal,
|
|
756
471
|
match: MatchFuncVal_1.MatchFuncVal,
|
|
757
|
-
// The arithmetic family (the review's finding I). Maths beyond `+`
|
|
758
|
-
// arrives as FUNCTIONS — `-` `*` `/` `%` stay reserved — and the
|
|
759
|
-
// family is numeric where the operator is polymorphic, which is
|
|
760
|
-
// what makes `add` more than a second spelling of `+`: it refuses
|
|
761
|
-
// the string concatenation that silently answers `"500m" + "500m"`.
|
|
762
|
-
// Every rule they obey is in ts/src/val/arith.ts.
|
|
763
472
|
add: ArithFuncVal_1.AddFuncVal,
|
|
764
473
|
sub: ArithFuncVal_1.SubFuncVal,
|
|
765
474
|
mul: ArithFuncVal_1.MulFuncVal,
|
|
766
475
|
div: ArithFuncVal_1.DivFuncVal,
|
|
767
476
|
mod: ArithFuncVal_1.ModFuncVal,
|
|
768
477
|
rem: ArithFuncVal_1.RemFuncVal,
|
|
769
|
-
// Aggregation over a finite, settled bag (the review's finding I).
|
|
770
|
-
// `least` and `greatest` rather than min and max, which are already
|
|
771
|
-
// the atoms for a lower and an upper BOUND -- an aggregate over a
|
|
772
|
-
// set and a bound on a value must not share a spelling.
|
|
773
478
|
sum: AggFuncVal_1.SumFuncVal,
|
|
774
479
|
least: AggFuncVal_1.LeastFuncVal,
|
|
775
480
|
greatest: AggFuncVal_1.GreatestFuncVal,
|
|
776
|
-
|
|
777
|
-
// RECORDS: `sum(pick($.lines, amountCents))`. Not a clever `each`
|
|
778
|
-
// template -- `each(d, _ & t)` MEETS each child, and a meet cannot
|
|
779
|
-
// select.
|
|
481
|
+
maybe: MaybeFuncVal_1.MaybeFuncVal,
|
|
780
482
|
pick: AggFuncVal_1.PickFuncVal,
|
|
781
|
-
|
|
782
|
-
// folds with `+`, so it inherits the one number-to-text rule and
|
|
783
|
-
// the language does not grow a second. It is the primitive that
|
|
784
|
-
// turns a bag of computed lines into a file.
|
|
483
|
+
sort: AggFuncVal_1.SortFuncVal,
|
|
785
484
|
join: AggFuncVal_1.JoinFuncVal,
|
|
786
|
-
// G9 phase 6: apply-templates. One flat list of pieces from a
|
|
787
|
-
// selection and a RULE TABLE -- for each node, the first template
|
|
788
|
-
// whose `match` it unifies with, its `body` instantiated at that
|
|
789
|
-
// node. The dispatch is the engine's because a body referenced by
|
|
790
|
-
// path resolves its references at the definition site, and the
|
|
791
|
-
// relative resolution that does exist is a dot count that does not
|
|
792
|
-
// survive a second dispatch (docs/design/EMIT.0.md).
|
|
793
485
|
emit: EmitFuncVal_1.EmitFuncVal,
|
|
794
|
-
// G9 phase 6: the string builtins the rule layer needs. `esc`
|
|
795
|
-
// makes a value safe inside a literal and `usc` reads it back;
|
|
796
|
-
// `rep` and `split` derive names from model data. All four are
|
|
797
|
-
// ordinary string functions -- they know nothing about generation,
|
|
798
|
-
// which is why they can land before the renderer does.
|
|
799
486
|
esc: StrFuncVal_1.EscFuncVal,
|
|
800
487
|
usc: StrFuncVal_1.UscFuncVal,
|
|
801
488
|
rep: StrFuncVal_1.RepFuncVal,
|
|
802
489
|
split: StrFuncVal_1.SplitFuncVal,
|
|
803
|
-
// THE COMPONENT PRIMITIVES -- SPIKE (ts/src/val/CmpFuncVal.ts,
|
|
804
|
-
// docs/design/JOSTRACA.0.md). jostraca's component set, spelled
|
|
805
|
-
// as functions -- LOWER CASE, like every other builtin in this
|
|
806
|
-
// language, while the node each one builds names the jostraca
|
|
807
|
-
// component it drives (`file(...)` is aontu, `"File"` is
|
|
808
|
-
// jostraca's). A document then says what FILES it produces
|
|
809
|
-
// instead of filling in the `aontu:code` vocabulary as data.
|
|
810
|
-
// Eight of jostraca's ten: `copy` and `list` are already builtins
|
|
811
|
-
// here with unrelated meanings, so those two have no lower-case
|
|
812
|
-
// spelling to take (see ts/src/val/CmpFuncVal.ts).
|
|
813
|
-
//
|
|
814
|
-
// TypeScript only, and so deliberately NOT in
|
|
815
|
-
// test/spec/signature.tsv, BUILTIN_FUNCS (ts/src/lsp.ts) or the
|
|
816
|
-
// grammar/ files -- each is asserted in cross-port parity and a
|
|
817
|
-
// TS-only entry turns the Go suite red. Arity and argument shape
|
|
818
|
-
// are refused in CmpFuncVal.resolve for the same reason.
|
|
819
490
|
...CmpFuncVal_1.CMP_FUNCS,
|
|
820
|
-
// NAME TRANSFORMATION -- SPIKE (ts/src/val/NamerFuncVal.ts).
|
|
821
|
-
// Generated code is mostly names, and no two targets spell them
|
|
822
|
-
// the same way. Splits a name into words whatever format it is
|
|
823
|
-
// written in, then renders it in the target's. TypeScript only,
|
|
824
|
-
// and out of the parity-pinned registries for the reason the
|
|
825
|
-
// component primitives are.
|
|
826
491
|
nom: NomFuncVal_1.NomFuncVal,
|
|
827
|
-
// PER-CHARACTER SUBSTITUTION AND DELETION -- SPIKE
|
|
828
|
-
// (ts/src/val/TranslateFuncVal.ts), after `tr`. Reads the source
|
|
829
|
-
// once and consults a table, which is what `rep` cannot do: a
|
|
830
|
-
// per-character map spelled as N `rep` calls composes wrongly,
|
|
831
|
-
// since each pass sees the previous one's output.
|
|
832
492
|
translate: TranslateFuncVal_1.TranslateFuncVal,
|
|
833
493
|
};
|
|
834
|
-
// A dangling operator (`a:1|`, `a:$`, `a:*` at end of input) leaves
|
|
835
|
-
// null/undefined unfilled terms. Junction ops drop them (so `a:1&`
|
|
836
|
-
// and `a:1|` are just 1); ops missing a required operand become an
|
|
837
|
-
// incomplete_expression nil, surfaced by generate() as a "Cannot
|
|
838
|
-
// resolve value" error (the Go port mirrors this in lang.go).
|
|
839
494
|
const dropUnfilled = (terms) => terms.filter((t) => null != t);
|
|
840
495
|
const incompleteNil = (r, ctx) => addsite(new NilVal_1.NilVal({ why: 'incomplete_expression' }), r, ctx);
|
|
841
496
|
// Build a call from a NAME and the argument terms as the author
|
|
@@ -843,27 +498,10 @@ help isolate the syntax error.`,
|
|
|
843
498
|
// raw-value conversion, stated once.
|
|
844
499
|
const buildCall = (r, ctx, fname, argterms) => {
|
|
845
500
|
const funcval = funcMap[fname];
|
|
846
|
-
// Arity is known for every built-in, so a surplus or missing
|
|
847
|
-
// argument is a mistake in the SOURCE, refused here where the
|
|
848
|
-
// author can see it (issue #51). It was previously left to each
|
|
849
|
-
// function to notice or not: the two ports disagreed on `upper()`
|
|
850
|
-
// and on `close()`, and `min(1,2)` noticed nothing at all -- it
|
|
851
|
-
// built a constraint that merely refused to generate later, with a
|
|
852
|
-
// message about the map rather than about the call.
|
|
853
|
-
//
|
|
854
|
-
// Counted BEFORE the rawToVal pass below, which is what makes the
|
|
855
|
-
// count possible: a comma group arrives as a RAW array and a
|
|
856
|
-
// written list literal as a ListVal, and rawToVal turns the first
|
|
857
|
-
// into the second.
|
|
858
501
|
const arity = funcArity[fname];
|
|
859
502
|
if (null != arity) {
|
|
860
503
|
const got = writtenArgCount(argterms);
|
|
861
504
|
if (got < arity[0] || (-1 !== arity[1] && got > arity[1])) {
|
|
862
|
-
// details is assigned AFTER construction: the NilVal
|
|
863
|
-
// constructor does not read it from its spec (only NilVal.make
|
|
864
|
-
// does), so passing it in the spec left the hint's
|
|
865
|
-
// {func}/{want}/{got} placeholders un-injected and printed
|
|
866
|
-
// literally.
|
|
867
505
|
const nil = new NilVal_1.NilVal({ why: 'func_arity' });
|
|
868
506
|
nil.details = {
|
|
869
507
|
func: fname,
|
|
@@ -873,22 +511,6 @@ help isolate the syntax error.`,
|
|
|
873
511
|
return addsite(nil, r, ctx);
|
|
874
512
|
}
|
|
875
513
|
}
|
|
876
|
-
// rawToVal EVERY argument. A degenerate expression can hand this
|
|
877
|
-
// handler raw parse values rather than Vals -- `pref(1-3)` arrives
|
|
878
|
-
// as the plain numbers 1 and -3 -- and a func's peg is unified
|
|
879
|
-
// element by element, so a raw one reached `arg.unify(...)` and
|
|
880
|
-
// threw. The unifier's catch-all turned that into an `internal`
|
|
881
|
-
// verdict: a crash reported as a unification result (issue #49).
|
|
882
|
-
// The Go port has always converted here (asVal in evaluate).
|
|
883
|
-
// A comma group is ONE raw-array term (see writtenArgCount).
|
|
884
|
-
// For a function whose arguments are distinct POSITIONS —
|
|
885
|
-
// deprecate's value and record, pack's and each's data and template
|
|
886
|
-
// — the group is expanded back into them here, while a written list
|
|
887
|
-
// literal, already a ListVal, stays one argument. The constraint
|
|
888
|
-
// atoms make the same move in their own constructor (atomArgs,
|
|
889
|
-
// ConstraintVal.ts), which is why they are not in this set:
|
|
890
|
-
// `neq(1,2)` is one argument LIST, not two positions, and expanding
|
|
891
|
-
// it here would take the list away from the code that reads it.
|
|
892
514
|
let terms = argterms;
|
|
893
515
|
if (true === POSITIONAL_ARG_FUNCS[fname] && 1 === terms.length &&
|
|
894
516
|
Array.isArray(terms[0])) {
|
|
@@ -911,24 +533,6 @@ help isolate the syntax error.`,
|
|
|
911
533
|
'star-prefix': (r, ctx, _op, terms) => {
|
|
912
534
|
if (null == terms[0])
|
|
913
535
|
return incompleteNil(r, ctx);
|
|
914
|
-
// A PREFERENCE MARKS A VALUE, AND A BARE KEY IS NOT ONE.
|
|
915
|
-
// `*a: 1` has no braces, so the prefix took the whole IMPLICIT
|
|
916
|
-
// map as its operand and the document silently became
|
|
917
|
-
// `*{"a":1}` -- `*a: 1, b: 2` became a one-element LIST, losing
|
|
918
|
-
// `b` outright. Neither is anything the author wrote.
|
|
919
|
-
//
|
|
920
|
-
// The accident is confined to the first position of the implicit
|
|
921
|
-
// top-level map, which is the only place no brace has yet
|
|
922
|
-
// committed the rule to a map: `{*a: 1}` and `a: 1, *b: 2` are
|
|
923
|
-
// ALREADY parse errors. This makes the third spelling agree with
|
|
924
|
-
// them rather than inventing a meaning for it.
|
|
925
|
-
//
|
|
926
|
-
// A BRACED operand is untouched, and that is the whole of the
|
|
927
|
-
// distinction: `*{x:1}` and `*[1]` are the real spelling, they
|
|
928
|
-
// are what `*{x:1} | *{y:2}` needs, and the shared spec pins them
|
|
929
|
-
// (11 rows). The open token's own source text is what separates
|
|
930
|
-
// the two -- `{` or `[` for a braced bag, the first key or
|
|
931
|
-
// element for an implicit one.
|
|
932
536
|
const bag = terms[0];
|
|
933
537
|
if ((bag.isMap && '{' !== bag.site.src) ||
|
|
934
538
|
(bag.isList && '[' !== bag.site.src)) {
|
|
@@ -952,7 +556,6 @@ help isolate the syntax error.`,
|
|
|
952
556
|
terms[0].peg.some((seg) => 'string' === typeof seg && ALIAS_RE.test(seg))) {
|
|
953
557
|
return addsite(new NilVal_1.NilVal({ why: 'alias_in_path' }), r, ctx);
|
|
954
558
|
}
|
|
955
|
-
// $.a.b absolute path
|
|
956
559
|
if (terms[0] instanceof RefVal_1.RefVal) {
|
|
957
560
|
terms[0].absolute = true;
|
|
958
561
|
return terms[0];
|
|
@@ -968,10 +571,6 @@ help isolate the syntax error.`,
|
|
|
968
571
|
let val = terms[0];
|
|
969
572
|
if (null == val)
|
|
970
573
|
return incompleteNil(r, ctx);
|
|
971
|
-
// The exact leaves negate exactly and never change kind. R2/D5
|
|
972
|
-
// holds here too: bigint has a single zero, and Decimal's
|
|
973
|
-
// normalising constructor sends every zero to the same form, so
|
|
974
|
-
// `-0d0` is `0d0` and `-0d0.0` is `0d0.0`.
|
|
975
574
|
if (val instanceof BigIntegerVal_1.BigIntegerVal) {
|
|
976
575
|
return addsite(new BigIntegerVal_1.BigIntegerVal({ peg: -val.peg, src: negsrc(val.src) }), r, ctx);
|
|
977
576
|
}
|
|
@@ -983,18 +582,10 @@ help isolate the syntax error.`,
|
|
|
983
582
|
if (!(val instanceof IntegerVal_1.IntegerVal) && !(val instanceof NumberVal_1.NumberVal)) {
|
|
984
583
|
return addsite(new NilVal_1.NilVal({ why: 'negative' }), r, ctx);
|
|
985
584
|
}
|
|
986
|
-
// Build a fresh Val rather than mutating in place: the expr plugin
|
|
987
|
-
// can evaluate the same node twice (e.g. inside `*-1` or a
|
|
988
|
-
// disjunct member), and an in-place `peg = -peg` applied twice
|
|
989
|
-
// silently un-negates the number.
|
|
990
585
|
let peg = -1 * val.peg;
|
|
991
586
|
// Normalize -0 to 0 (keeps the AST and canon free of negative zero).
|
|
992
587
|
if (0 === peg)
|
|
993
588
|
peg = 0;
|
|
994
|
-
// Negation never narrows the kind: a number stays a number. An
|
|
995
|
-
// integer stays an integer unless the negation leaves the int64
|
|
996
|
-
// range (only -(-2^63), which no literal can express), in which
|
|
997
|
-
// case it widens to a number rather than failing.
|
|
998
589
|
const out = val instanceof IntegerVal_1.IntegerVal && (0, numkind_1.isIntegerKind)(peg)
|
|
999
590
|
? new IntegerVal_1.IntegerVal({ peg })
|
|
1000
591
|
: new NumberVal_1.NumberVal({ peg });
|
|
@@ -1026,7 +617,6 @@ help isolate the syntax error.`,
|
|
|
1026
617
|
jsonic
|
|
1027
618
|
.use(asPlugin(expr_1.Expr), {
|
|
1028
619
|
op: {
|
|
1029
|
-
// disjunct < conjunct: c & b | a -> (c & b) | a
|
|
1030
620
|
'conjunct': {
|
|
1031
621
|
infix: true, src: '&', left: 16_000_000, right: 17_000_000
|
|
1032
622
|
},
|
|
@@ -1039,16 +629,6 @@ help isolate the syntax error.`,
|
|
|
1039
629
|
left: 20_000_000,
|
|
1040
630
|
right: 21_000_000,
|
|
1041
631
|
},
|
|
1042
|
-
// Re-base the unary prefixes for the same reason. Every aontu
|
|
1043
|
-
// operator sits far above the @tabnas/expr defaults, so the
|
|
1044
|
-
// default prefix binding power of 4_000_000 left unary `-`/`+`
|
|
1045
|
-
// LOOSER than every infix operator: `-1 & integer` parsed as
|
|
1046
|
-
// `-(1 & integer)`, and negative-prefix (below) then rejected
|
|
1047
|
-
// the composite operand as a `negative` error nil (likewise
|
|
1048
|
-
// `-2+3`, `-1|2`). Unary minus must bind tighter than `+`, `&`
|
|
1049
|
-
// and `|` — but still looser than `.` (dot-infix left is
|
|
1050
|
-
// 25_000_000), so `-0xFF.5` stays `-(0xFF.5)` and `$`.
|
|
1051
|
-
// Kept in lock-step with the op table in go/lang.go.
|
|
1052
632
|
'negative': {
|
|
1053
633
|
src: '-',
|
|
1054
634
|
prefix: true,
|
|
@@ -1097,15 +677,11 @@ help isolate the syntax error.`,
|
|
|
1097
677
|
remainder: null,
|
|
1098
678
|
},
|
|
1099
679
|
evaluate: (r, ctx, op, terms) => {
|
|
1100
|
-
// // console.log('EVAL-START', r.u)
|
|
1101
680
|
if ('func-paren' === op.name
|
|
1102
|
-
// && !r.parent.prev?.u?.paren_preval
|
|
1103
681
|
&& !r.u?.paren_preval) {
|
|
1104
|
-
// terms = [new StringVal({ peg: '' }), ...terms]
|
|
1105
682
|
terms = ['', ...terms];
|
|
1106
683
|
}
|
|
1107
684
|
let val = opmap[op.name](r, ctx, op, terms);
|
|
1108
|
-
// // console.log('EVAL', terms, '->', val)
|
|
1109
685
|
return val;
|
|
1110
686
|
}
|
|
1111
687
|
});
|
|
@@ -1119,16 +695,6 @@ help isolate the syntax error.`,
|
|
|
1119
695
|
const OPTKEY = [TX, ST, NR];
|
|
1120
696
|
jsonic.rule('expr', (rs) => {
|
|
1121
697
|
rs.close([
|
|
1122
|
-
// A `&` followed by `:` after an expression value belongs to the
|
|
1123
|
-
// enclosing map as a spread, not to the expression as a conjunct
|
|
1124
|
-
// — backtrack both tokens so the expression completes (and
|
|
1125
|
-
// evaluates to a Val) and the map's spread alts take over. This
|
|
1126
|
-
// is what makes `k1:$flag &:boolean` parse: without it the expr
|
|
1127
|
-
// plugin consumes the `&` as an infix conjunct, chokes on the
|
|
1128
|
-
// `:`, and leaves the raw unevaluated expr node in the map
|
|
1129
|
-
// (mirrors the expr-rule PrependClose in go/lang.go). The
|
|
1130
|
-
// `n: { expr: 0 }` reset matches the plugin's own expr-end alts —
|
|
1131
|
-
// the evaluation after-close only fires when the counter is 0.
|
|
1132
698
|
{ s: [CJ, CL], b: 2, n: { expr: 0 }, g: 'expr,expr-end,spread' },
|
|
1133
699
|
]);
|
|
1134
700
|
return rs;
|
|
@@ -1175,18 +741,6 @@ help isolate the syntax error.`,
|
|
|
1175
741
|
if (!Number.isFinite(r.node)) {
|
|
1176
742
|
valnode = addsite(new NilVal_1.NilVal({ why: 'not_number' }), r, ctx);
|
|
1177
743
|
}
|
|
1178
|
-
// D7 -- A LOSSY INTEGER LITERAL IS REFUSED, NOT ROUNDED. The
|
|
1179
|
-
// token above is already a double, so a literal the double
|
|
1180
|
-
// cannot hold exactly (2^53+1, 0x7fffffffffffffff,
|
|
1181
|
-
// 0xffffffffffffffff) has ALREADY become a different number by
|
|
1182
|
-
// the time it gets here. Storing it would mean the document
|
|
1183
|
-
// silently means something other than what it says, so the
|
|
1184
|
-
// literal becomes a located error whose hint names the escape:
|
|
1185
|
-
// write it `0d…` and get the exact value.
|
|
1186
|
-
//
|
|
1187
|
-
// The rule is EXACTNESS, not magnitude -- 10^20 and 2^124 are
|
|
1188
|
-
// both far outside the int64 window and both land exactly on a
|
|
1189
|
-
// binary64, so both stay values (see isLossyIntegerLiteral).
|
|
1190
744
|
else if ((0, numkind_1.isLossyIntegerLiteral)(r.node, r.o0.src)) {
|
|
1191
745
|
const nil = new NilVal_1.NilVal({ why: 'lossy_integer_literal' });
|
|
1192
746
|
nil.details = { src: r.o0.src };
|
|
@@ -1230,15 +784,6 @@ help isolate the syntax error.`,
|
|
|
1230
784
|
const optionalKeys = r.u.aontu_optional_keys ?? [];
|
|
1231
785
|
const aliasKeys = r.u.aontu_alias_keys ?? [];
|
|
1232
786
|
let mo = r.node;
|
|
1233
|
-
// An elided value (`a:`) leaves a raw null/undefined that never
|
|
1234
|
-
// passed through the val rule. It is REFUSED rather than made a
|
|
1235
|
-
// null (issue #48): a key with nothing after the colon is a
|
|
1236
|
-
// mistake in the source, and turning it into a value made that
|
|
1237
|
-
// mistake indistinguishable from a deliberate `a:null`.
|
|
1238
|
-
//
|
|
1239
|
-
// A colon chain (`a: b:1`) is not an elision -- the value is the
|
|
1240
|
-
// nested pair, which the val rule does produce -- and neither is
|
|
1241
|
-
// a trailing comma.
|
|
1242
787
|
for (const k in mo) {
|
|
1243
788
|
if (null == mo[k] && '___merge' !== k &&
|
|
1244
789
|
'___optional' !== k && '___alias' !== k) {
|
|
@@ -1249,45 +794,22 @@ help isolate the syntax error.`,
|
|
|
1249
794
|
const en = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
1250
795
|
en.path = [...(r.k?.path ?? []), k];
|
|
1251
796
|
mo[k] = en;
|
|
1252
|
-
// An elided value under an OPTIONAL key stops being optional.
|
|
1253
|
-
// Optionality is about a value that may be absent at
|
|
1254
|
-
// GENERATE; it does not excuse a source that stops after the
|
|
1255
|
-
// colon. Left optional, the refusal was dropped with the key
|
|
1256
|
-
// and `a?:` generated `{}` -- a silent nothing, which is
|
|
1257
|
-
// worse than either the old null or the error.
|
|
1258
797
|
const oi = optionalKeys.indexOf(k);
|
|
1259
798
|
if (-1 !== oi) {
|
|
1260
799
|
optionalKeys.splice(oi, 1);
|
|
1261
800
|
}
|
|
1262
801
|
}
|
|
1263
802
|
}
|
|
1264
|
-
// ... and the OPTIONAL spelling, `a?:`, which does not leave a
|
|
1265
|
-
// null behind to be found: its value never reaches the node at
|
|
1266
|
-
// all, so the key is simply absent and the map generated without
|
|
1267
|
-
// it. A key recorded as optional but missing from the node was
|
|
1268
|
-
// written with nothing after its colon.
|
|
1269
803
|
for (const k of optionalKeys) {
|
|
1270
804
|
if (!(k in mo)) {
|
|
1271
805
|
mo[k] = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
1272
806
|
}
|
|
1273
807
|
}
|
|
1274
|
-
// An elided SPREAD (`x:$obj&:` with nothing after the colon)
|
|
1275
|
-
// refuses the whole map, not a key (issue #48). A spread is not a
|
|
1276
|
-
// child, so a refusal stored in its place has nothing to attach
|
|
1277
|
-
// to: `x:&:` has no children for the spread to apply to, and the
|
|
1278
|
-
// map would generate as `{}` with the mistake silently gone.
|
|
1279
|
-
// Refusing the container is what makes it visible at all.
|
|
1280
808
|
const sp = mo[type_1.SPREAD];
|
|
1281
809
|
if (sp && sp.v.some((sv) => null == sv)) {
|
|
1282
810
|
r.node = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
1283
811
|
return undefined;
|
|
1284
812
|
}
|
|
1285
|
-
// A KEY REFUSAL (the pair rule records them: a declaration
|
|
1286
|
-
// spelled with a colon, a key the bare-text rule refuses) becomes
|
|
1287
|
-
// the refusal, in place of whatever followed the colon and sited
|
|
1288
|
-
// at the KEY rather than at the map -- at the offending character
|
|
1289
|
-
// of it, where there is one -- so the frame points at the
|
|
1290
|
-
// spelling to change.
|
|
1291
813
|
for (const { key, tkn, why, details } of (r.u.aontu_key_refusals ?? [])) {
|
|
1292
814
|
const en = siteAt(addsite(new NilVal_1.NilVal({ why }), r, ctx), tokenSite(tkn));
|
|
1293
815
|
if (null != details) {
|
|
@@ -1316,7 +838,6 @@ help isolate the syntax error.`,
|
|
|
1316
838
|
if (mo.___merge) {
|
|
1317
839
|
let mop = { ...mo };
|
|
1318
840
|
delete mop.___merge;
|
|
1319
|
-
// TODO: needs addpath?
|
|
1320
841
|
let mopv = new MapVal_1.MapVal({ peg: mop });
|
|
1321
842
|
mopv.optionalKeys = optionalKeys;
|
|
1322
843
|
mopv.aliasKeys = aliasKeys;
|
|
@@ -1335,13 +856,9 @@ help isolate the syntax error.`,
|
|
|
1335
856
|
});
|
|
1336
857
|
jsonic.rule('list', (rs) => {
|
|
1337
858
|
rs
|
|
1338
|
-
// .open([{ s: [CJ, CL], p: 'pair', b: 2, g: 'spread' }])
|
|
1339
859
|
.bc((r, ctx) => {
|
|
1340
860
|
const optionalKeys = r.u.aontu_optional_keys ?? [];
|
|
1341
861
|
let ao = r.node;
|
|
1342
|
-
// An elided ELEMENT (`[,]`, `[1,,2]`) is refused for the same
|
|
1343
|
-
// reason as an elided map value (issue #48). A trailing comma
|
|
1344
|
-
// (`[1,]`) is not an elision and never reaches here.
|
|
1345
862
|
for (let i = 0; i < ao.length; i++) {
|
|
1346
863
|
if (null == ao[i]) {
|
|
1347
864
|
// Pathed at the INDEX, for the same reason as the map case.
|
|
@@ -1359,36 +876,16 @@ help isolate the syntax error.`,
|
|
|
1359
876
|
}
|
|
1360
877
|
return undefined;
|
|
1361
878
|
});
|
|
1362
|
-
// .close([{ s: [CJ, CL], b: 2, g: 'spread,json,more' }])
|
|
1363
879
|
return rs;
|
|
1364
880
|
});
|
|
1365
|
-
// TODO: copied from jsonic grammar
|
|
1366
|
-
// jsonic should provide a way to export this
|
|
1367
881
|
const pairkey = (r) => {
|
|
1368
882
|
// Get key string value from first matching token of `Open` state.
|
|
1369
883
|
const key_token = r.o0;
|
|
1370
884
|
const key = ST === key_token.tin || TX === key_token.tin
|
|
1371
|
-
? key_token.val
|
|
885
|
+
? key_token.val
|
|
1372
886
|
: key_token.src; // Was number, use original text
|
|
1373
887
|
r.u.key = key;
|
|
1374
888
|
};
|
|
1375
|
-
// A pair in LIST position writes its value at `node[key]` like any
|
|
1376
|
-
// other pair, and the enclosing list's node is an ARRAY -- so a numeric
|
|
1377
|
-
// key lands on an index and becomes an element, and may land on an
|
|
1378
|
-
// index a real element already holds (`[5,0:1]`). Since the pair must
|
|
1379
|
-
// contribute nothing (issue #40), the slot is photographed before the
|
|
1380
|
-
// value is parsed and put back afterwards. Restoring beats deleting for
|
|
1381
|
-
// exactly the overwrite case: deleting `[5,0:1]`'s index 0 would take
|
|
1382
|
-
// the 5 with it, where restoring gives back the list the pair was
|
|
1383
|
-
// never part of.
|
|
1384
|
-
//
|
|
1385
|
-
// `length` is saved too: writing past the end grows an array, and
|
|
1386
|
-
// `[5,1?:9]` must be [5] again and not [5, <hole>].
|
|
1387
|
-
// Typed as a string bag deliberately: the slot may be named by a
|
|
1388
|
-
// non-numeric key (`[x:1]`), which the array type would refuse. Both
|
|
1389
|
-
// helpers run only from the elem rule, whose node is the enclosing
|
|
1390
|
-
// list, so neither guards against a non-array node — a guard there
|
|
1391
|
-
// proved unreachable and dead code is worse than none.
|
|
1392
889
|
const asSlots = (r) => r.node;
|
|
1393
890
|
const snapshotPairSlot = (r, key) => {
|
|
1394
891
|
const node = asSlots(r);
|
|
@@ -1448,40 +945,14 @@ help isolate the syntax error.`,
|
|
|
1448
945
|
})
|
|
1449
946
|
.bc((rule) => {
|
|
1450
947
|
// TRAVERSE PARENTS TO GET PATH
|
|
1451
|
-
// A DECLARATION IS A PAIR WHOSE KEY IS AN ALIAS NAME. The lexer
|
|
1452
|
-
// claims `%name` whole and hands it over as a #VL token whose
|
|
1453
|
-
// SOURCE is the name, so the key TEXT alone cannot be the test:
|
|
1454
|
-
// a quoted `"%a": 1` is an ordinary key that merely starts with
|
|
1455
|
-
// the sigil, and erasing that would be wrong. The token is what
|
|
1456
|
-
// separates them.
|
|
1457
|
-
//
|
|
1458
|
-
// Recorded on the enclosing map, never on the value, and that is
|
|
1459
|
-
// the point: a reference COPIES the value it resolves to, so a
|
|
1460
|
-
// mark riding the value would erase the referring field too.
|
|
1461
|
-
// Being a property of the map is also what carries it through a
|
|
1462
|
-
// meet, the way optional keys are carried.
|
|
1463
948
|
const ktkn = rule.o0;
|
|
1464
949
|
const holder = rule.parent;
|
|
1465
950
|
const kr = keyRefusalOf(ktkn, rule.o1);
|
|
1466
951
|
if (null != kr) {
|
|
1467
|
-
// A KEY REFUSAL (keyRefusalOf) is written where the map is
|
|
1468
|
-
// built, in the value's place and sited at the key, so the
|
|
1469
|
-
// frame points at the spelling to change. A declaration
|
|
1470
|
-
// spelled with a colon is refused rather than read as the
|
|
1471
|
-
// ordinary key `%foo` the text would otherwise become -- a
|
|
1472
|
-
// document written for the old form would then generate a
|
|
1473
|
-
// "%foo" field and every `%foo` use would resolve to nothing,
|
|
1474
|
-
// and neither says why.
|
|
1475
952
|
holder.u.aontu_key_refusals = (holder.u.aontu_key_refusals || []);
|
|
1476
953
|
holder.u.aontu_key_refusals.push({ key: '' + ktkn.src, tkn: ktkn, ...kr });
|
|
1477
954
|
}
|
|
1478
955
|
else if (isAliasDecl(ktkn, rule.o1)) {
|
|
1479
|
-
// Always recorded here; whether the map is ALLOWED to carry
|
|
1480
|
-
// declarations is decided on the VALUE (MapVal.unify), not at
|
|
1481
|
-
// the parse. The parse cannot see it: an INCLUDED file's
|
|
1482
|
-
// declarations are at the root of their own text, and only
|
|
1483
|
-
// once the loaded map is placed does it become apparent that
|
|
1484
|
-
// root is not the document's.
|
|
1485
956
|
holder.u.aontu_alias_keys = (holder.u.aontu_alias_keys || []);
|
|
1486
957
|
holder.u.aontu_alias_keys.push('' + ktkn.src);
|
|
1487
958
|
}
|
|
@@ -1493,11 +964,6 @@ help isolate the syntax error.`,
|
|
|
1493
964
|
return undefined;
|
|
1494
965
|
})
|
|
1495
966
|
.close([
|
|
1496
|
-
// A following `&:` starts a sibling spread pair in the current
|
|
1497
|
-
// map: directly inside a braced map (pk<=0) at any depth, or in
|
|
1498
|
-
// the implicit top-level map (dmap<=1). Inside an implicit
|
|
1499
|
-
// colon-chain map (pk>0) it bubbles up instead (second alt), so
|
|
1500
|
-
// `a:b:1 &:2` attaches the spread to a's map, not b's.
|
|
1501
967
|
{ s: [CJ, CL], c: (r) => r.lte('pk', 0) || r.lte('dmap', 1), r: 'pair', b: 2, g: 'spread,json,pair' },
|
|
1502
968
|
{ s: [CJ, CL], b: 2, g: 'spread,json,more' }
|
|
1503
969
|
]);
|
|
@@ -1532,17 +998,6 @@ help isolate the syntax error.`,
|
|
|
1532
998
|
},
|
|
1533
999
|
g: 'aontu-optional-elem'
|
|
1534
1000
|
},
|
|
1535
|
-
// A PLAIN pair in list position IS A SINGLE-KEY MAP ELEMENT:
|
|
1536
|
-
// `[a:1, b:2]` is `[{a:1}, {b:2}]` (the rule @tabnas/jsonic
|
|
1537
|
-
// spells as `list.pair`). This REVERSES issue #40's "a pair is
|
|
1538
|
-
// not an element": that rule was chosen because jsonic wrote
|
|
1539
|
-
// the pair at `node[key]` -- an array PROPERTY that never
|
|
1540
|
-
// showed up for a text key and an INDEX for a numeric one --
|
|
1541
|
-
// and inert beat that incoherence. But inert was itself a
|
|
1542
|
-
// silent drop: `x: [a:1, b:2]` evaluated to `x: []`, the
|
|
1543
|
-
// author's data gone at exit 0. The element is built in the
|
|
1544
|
-
// bc below, where the value is already a Val; the snapshot
|
|
1545
|
-
// still neutralises jsonic's raw slot write first.
|
|
1546
1001
|
{
|
|
1547
1002
|
s: [OPTKEY, CL], p: 'val',
|
|
1548
1003
|
u: { spread: true, done: true, list: true, pair: true },
|
|
@@ -1553,36 +1008,7 @@ help isolate the syntax error.`,
|
|
|
1553
1008
|
g: 'aontu-plain-pair-elem'
|
|
1554
1009
|
}
|
|
1555
1010
|
])
|
|
1556
|
-
// NOTE: manually adjust path - the twin of the `pair` rule's hook
|
|
1557
|
-
// above, and for the same reason, one layer down.
|
|
1558
|
-
//
|
|
1559
|
-
// Every alt above contributes NO element: a `&:` spread is a
|
|
1560
|
-
// constraint on the elements, and a `k:v` pair in list position is
|
|
1561
|
-
// simply not one (the `aontu-plain-pair-elem` note above). The array
|
|
1562
|
-
// slot they briefly occupy is already given back by
|
|
1563
|
-
// restorePairSlot. The PATH index was not: @tabnas/path's
|
|
1564
|
-
// `@elem-ao` increments `r.k.index` for every elem rule it sees, so
|
|
1565
|
-
// each of these stole an index and every later element's path was
|
|
1566
|
-
// one too high — `[&: integer, 10, 20, "bad"]` reported the bad
|
|
1567
|
-
// value at `$.l.3` while `aontu get $.l.2` returned it, and on a
|
|
1568
|
-
// one-element list the path pointed off the end. Generation was
|
|
1569
|
-
// never wrong, which is why nothing caught it: the array is right
|
|
1570
|
-
// and only the labels on it were shifted (BUGS.md 44).
|
|
1571
|
-
//
|
|
1572
|
-
// Rewinding here rather than in the plugin keeps the plugin's rule
|
|
1573
|
-
// ("in an array, the path property is the element index") true —
|
|
1574
|
-
// these alts are the aontu-specific exceptions to what counts as an
|
|
1575
|
-
// element, so the correction belongs with the grammar that
|
|
1576
|
-
// introduces them. The child is re-pathed because the plugin has
|
|
1577
|
-
// already stamped it with the index being given back: a spread
|
|
1578
|
-
// takes the `'&'` segment its map twin takes, and a pair takes its
|
|
1579
|
-
// key, as a map entry would.
|
|
1580
1011
|
.ao((r) => {
|
|
1581
|
-
// A pair IS an element now, so it keeps the index @tabnas/path
|
|
1582
|
-
// gave it, and its VALUE is pathed through both the index and
|
|
1583
|
-
// the key (`[a: $.nope]` fails at $.l.0.a). Only the `&:`
|
|
1584
|
-
// spread still contributes no element and gives its index back
|
|
1585
|
-
// (BUGS.md 44).
|
|
1586
1012
|
if (0 < r.d && r.u.spread && !r.u.pair) {
|
|
1587
1013
|
r.k.index = r.k.index - 1;
|
|
1588
1014
|
const seg = '&';
|
|
@@ -1590,11 +1016,6 @@ help isolate the syntax error.`,
|
|
|
1590
1016
|
r.child.k.key = seg;
|
|
1591
1017
|
}
|
|
1592
1018
|
else if (0 < r.d && r.u.pair) {
|
|
1593
|
-
// The element's index is the array length: everything before
|
|
1594
|
-
// it is already pushed, and the pair's own map is pushed at
|
|
1595
|
-
// close. `r.k.index` is not usable here -- the path plugin
|
|
1596
|
-
// counts only the elements it pushes itself, and this one is
|
|
1597
|
-
// aontu's.
|
|
1598
1019
|
const seg = '' + r.u.key;
|
|
1599
1020
|
r.child.k.path =
|
|
1600
1021
|
[...r.k.path, '' + (r.node?.length ?? 0), seg];
|
|
@@ -1603,39 +1024,14 @@ help isolate the syntax error.`,
|
|
|
1603
1024
|
})
|
|
1604
1025
|
.bc((rule, ctx) => {
|
|
1605
1026
|
// TRAVERSE PARENTS TO GET PATH
|
|
1606
|
-
// Only the `&:` alternative is a SPREAD. All four alts above set
|
|
1607
|
-
// `spread: true` -- it is what marks them as contributing no
|
|
1608
|
-
// element -- so this guard needs the narrower test, and `pair`
|
|
1609
|
-
// is what distinguishes a `k:v` in list position from a spread.
|
|
1610
|
-
//
|
|
1611
|
-
// Without it a pair BUILT the spread record, with `o` taken from
|
|
1612
|
-
// its own key rather than '&': `[x:1, &:integer, "bad"]` left
|
|
1613
|
-
// `{o:'x', v:[1, integer]}`, and ListVal's `'&' === spread.o`
|
|
1614
|
-
// then discarded the real constraint -- so the element spread
|
|
1615
|
-
// was silently dropped and the bad value generated (BUGS.md 46).
|
|
1616
|
-
// A pair alone did it too: `[x:1, 10]` produced a spread record
|
|
1617
|
-
// out of nothing.
|
|
1618
1027
|
if (rule.u.spread && !rule.u.pair) {
|
|
1619
1028
|
rule.node[type_1.SPREAD] =
|
|
1620
1029
|
(rule.node[type_1.SPREAD] || { o: rule.o0.src, v: [] });
|
|
1621
1030
|
rule.node[type_1.SPREAD].v.push(rule.child.node);
|
|
1622
1031
|
}
|
|
1623
|
-
// The slot is given back BEFORE the element is added: the
|
|
1624
|
-
// restore undoes jsonic's raw write (a property for a text
|
|
1625
|
-
// key, an INDEX for a numeric one -- restoring length is what
|
|
1626
|
-
// keeps `[1:2]` from padding with a null), and the push then
|
|
1627
|
-
// appends cleanly after it.
|
|
1628
1032
|
restorePairSlot(rule);
|
|
1629
|
-
// THE SINGLE-KEY MAP ELEMENT, for both pair spellings. The
|
|
1630
|
-
// value is a Val already (`p: 'val'`), so the map is built
|
|
1631
|
-
// exactly as the map rule builds one -- and an elided value
|
|
1632
|
-
// (`[a:]`) is refused exactly as the map rule refuses one
|
|
1633
|
-
// (issue #48): a key with nothing after the colon is a
|
|
1634
|
-
// mistake, not an empty value.
|
|
1635
1033
|
if (true === rule.u.pair) {
|
|
1636
1034
|
const key = '' + rule.u.key;
|
|
1637
|
-
// The key TOKEN: the optional spelling's sits on the elem rule
|
|
1638
|
-
// before this one (`[x?: 1]` is two elem rules).
|
|
1639
1035
|
const ktkn = true === rule.u.aontu_optional_elem ?
|
|
1640
1036
|
rule.prev.o0 : rule.o0;
|
|
1641
1037
|
let v = rule.child.node;
|
|
@@ -1663,9 +1059,6 @@ help isolate the syntax error.`,
|
|
|
1663
1059
|
// "is this the top level" test reads the path, so an element
|
|
1664
1060
|
// of a top-level list must not read as the root.
|
|
1665
1061
|
mv.path = [...(rule.k?.path ?? []), '' + rule.node.length];
|
|
1666
|
-
// `[a?: 1]` is `[{a?: 1}]`: the key is optional IN the
|
|
1667
|
-
// element, so the two spellings stay one rule apart rather
|
|
1668
|
-
// than two behaviours apart.
|
|
1669
1062
|
if (true === rule.u.aontu_optional_elem) {
|
|
1670
1063
|
mv.optionalKeys = [key];
|
|
1671
1064
|
}
|
|
@@ -1683,43 +1076,10 @@ help isolate the syntax error.`,
|
|
|
1683
1076
|
return rs;
|
|
1684
1077
|
});
|
|
1685
1078
|
};
|
|
1686
|
-
// INCLUDE_KINDS IS THE RULE FOR WHAT AN INCLUDE MEANS (ADR-012,
|
|
1687
|
-
// use-cases/BUGS.md §49). An extension is on this list or it is not
|
|
1688
|
-
// read at all, and its entry says WHICH OF TWO THINGS the file is.
|
|
1689
|
-
//
|
|
1690
|
-
// `source` — Aontu, with everything the language has: types, defaults,
|
|
1691
|
-
// references, constraints, its own includes. Two extensions, and they
|
|
1692
|
-
// are the ones this project owns.
|
|
1693
|
-
//
|
|
1694
|
-
// `text` — the file's BYTES, as one string scalar. No parser is
|
|
1695
|
-
// chosen, so there is nothing for two ports to disagree about and
|
|
1696
|
-
// nothing in the file that can mean anything: `notes: @"notes.txt"`
|
|
1697
|
-
// is a document loading prose into a string. `.txt` is the only
|
|
1698
|
-
// extension here by default; `AontuOptions.textExt` (the CLI's
|
|
1699
|
-
// `--text-ext`) adds others, because which name a project keeps its
|
|
1700
|
-
// templates under is the project's business, not this table's.
|
|
1701
|
-
//
|
|
1702
|
-
// A FORMAT NAME — configuration DATA, parsed by that format's own
|
|
1703
|
-
// parser into the JSON value it denotes, which then becomes Aontu
|
|
1704
|
-
// values like any other data. Every one of these formats maps onto
|
|
1705
|
-
// JSON, which is why one word covers them: a `.toml` file is a map of
|
|
1706
|
-
// scalars, lists and maps, and so is the `.aon` file that unifies with
|
|
1707
|
-
// it. What the format does NOT get is the language — a `&` in a YAML
|
|
1708
|
-
// file is a YAML anchor, not a spread key, because the YAML parser
|
|
1709
|
-
// reads it, not this one.
|
|
1710
|
-
//
|
|
1711
|
-
// The parsers are @tabnas's, one per format, and the Go port uses the
|
|
1712
|
-
// same ones (ADR-001): the two implementations agree because they are
|
|
1713
|
-
// running the same grammar, not because two hand-written readers were
|
|
1714
|
-
// kept in step.
|
|
1715
|
-
//
|
|
1716
|
-
// This table and go/source.go's includeKinds are the same table.
|
|
1717
1079
|
const INCLUDE_KINDS = {
|
|
1718
1080
|
aon: 'source',
|
|
1719
1081
|
aontu: 'source',
|
|
1720
1082
|
json: 'json',
|
|
1721
|
-
// JSON-LD is JSON: a `@context` is a key like any other here, and
|
|
1722
|
-
// what it MEANS is the vocabulary's business, not the reader's.
|
|
1723
1083
|
jsonld: 'json',
|
|
1724
1084
|
jsonc: 'jsonc',
|
|
1725
1085
|
json5: 'json5',
|
|
@@ -1731,25 +1091,11 @@ const INCLUDE_KINDS = {
|
|
|
1731
1091
|
ini: 'ini',
|
|
1732
1092
|
txt: 'text',
|
|
1733
1093
|
};
|
|
1734
|
-
// WHAT AN EXTENSION MEANS, for this parse. The table is the fixed
|
|
1735
|
-
// part; `textExt` is the per-parse widening, and it wins over nothing
|
|
1736
|
-
// -- a host cannot re-read `.toml` as text, because an extension the
|
|
1737
|
-
// table already names has a meaning documents rely on. Undefined is
|
|
1738
|
-
// the refusal, and it is the ONE place that decides it: the resolver's
|
|
1739
|
-
// gate and the processor map both ask here, so a widening cannot reach
|
|
1740
|
-
// one and not the other.
|
|
1741
1094
|
function includeFormat(ext, textExt) {
|
|
1742
1095
|
const known = INCLUDE_KINDS[ext];
|
|
1743
1096
|
if (undefined !== known) {
|
|
1744
1097
|
return known;
|
|
1745
1098
|
}
|
|
1746
|
-
// NOT EVEN AS TEXT. `.js` is the extension ADR-012 singles out
|
|
1747
|
-
// because multisource's own default EXECUTES it, and an extension
|
|
1748
|
-
// this project refuses on purpose stays refused however a flag is
|
|
1749
|
-
// spelled -- reading it is harmless, but a widening that can reach
|
|
1750
|
-
// the one name the rule names is a widening whose limit nobody can
|
|
1751
|
-
// state. Go's includeFormat holds the same list, and the two CLIs
|
|
1752
|
-
// are diffed on `--text-ext js` because they once disagreed here.
|
|
1753
1099
|
if (REFUSED_EXT.has(ext)) {
|
|
1754
1100
|
return undefined;
|
|
1755
1101
|
}
|
|
@@ -1759,17 +1105,6 @@ function includeFormat(ext, textExt) {
|
|
|
1759
1105
|
// default processor; `''` is the no-extension fallback, which names no
|
|
1760
1106
|
// file type at all.
|
|
1761
1107
|
const REFUSED_EXT = new Set(['js', '']);
|
|
1762
|
-
// `.csv` IS DELIBERATELY ABSENT, and the reason is ADR-001 rather than
|
|
1763
|
-
// taste. The two ports' CSV parsers disagree about what a CSV file IS:
|
|
1764
|
-
// one answers header-keyed records with string fields, the other raw
|
|
1765
|
-
// rows including the header, with numbers parsed. Admitting it would
|
|
1766
|
-
// admit a divergence into the one thing this project refuses to have
|
|
1767
|
-
// one in. Recorded in ADR-012 and pinned by file.tsv's load-ext-csv.
|
|
1768
|
-
// The multisource kind of a path: the LAST segment's extension, without
|
|
1769
|
-
// its dot, lowercased -- `''` for a name that has none. The rule is
|
|
1770
|
-
// @tabnas/multisource's own extKind (and Go's filepath.Ext), copied
|
|
1771
|
-
// rather than imported because it decides what a source IS: a dot in a
|
|
1772
|
-
// parent folder (`/my.app/conf`) must not read as an extension.
|
|
1773
1108
|
function extKindOf(full) {
|
|
1774
1109
|
const seg = full.match(/[^\\/]*$/)[0];
|
|
1775
1110
|
return (seg.match(/\.([^.]*)$/) || ['', ''])[1].toLowerCase();
|
|
@@ -1782,15 +1117,6 @@ function extensionMsg(path, ext) {
|
|
|
1782
1117
|
const which = '' === ext ? 'no extension' : 'extension: .' + ext;
|
|
1783
1118
|
return 'include not readable: ' + path + ' (' + which + ')';
|
|
1784
1119
|
}
|
|
1785
|
-
// THE RULE ALSO HOLDS FOR A RESOLVER THIS ENGINE DID NOT WRITE.
|
|
1786
|
-
// gateExtension refuses an unlisted extension inside makeModelResolver,
|
|
1787
|
-
// which is the default; a HOST may supply its own through
|
|
1788
|
-
// `AontuOptions.resolver`, and that one has never heard of
|
|
1789
|
-
// INCLUDE_KINDS. Without this the host's resolution would fall to
|
|
1790
|
-
// multisource's own default for an unnamed kind, which hands the file
|
|
1791
|
-
// back as TEXT — or, for `.js`, EXECUTES it. So the two roads end in
|
|
1792
|
-
// one place: whatever chose the source, an extension off the list is
|
|
1793
|
-
// refused with the same code and the same message.
|
|
1794
1120
|
const refuseProcessor = (res) => {
|
|
1795
1121
|
// `full` is the one part a host resolution may leave out -- it is the
|
|
1796
1122
|
// path the resolver CHOSE, and a resolver that answers from something
|
|
@@ -1826,22 +1152,6 @@ const DATA_READERS = (() => {
|
|
|
1826
1152
|
ini: viaPlugin(ini_1.Ini),
|
|
1827
1153
|
};
|
|
1828
1154
|
})();
|
|
1829
|
-
/**
|
|
1830
|
-
* A TOML document with its dates as the TEXT they were written as.
|
|
1831
|
-
*
|
|
1832
|
-
* TOML HAS DATES AND JSON DOES NOT, so the reader cannot hand one over
|
|
1833
|
-
* as itself: it answers with a marker object carrying the kind and the
|
|
1834
|
-
* source text. The value that reaches a document is that TEXT, which is
|
|
1835
|
-
* what a JSON document carries for a date anyway — and it is what the
|
|
1836
|
-
* Go port produces too, from a `*TomlTime` holding those same two
|
|
1837
|
-
* fields (`dataToValDepth`, go/source.go). Without this the same file
|
|
1838
|
-
* is a nested map in one port and a string in the other, which is the
|
|
1839
|
-
* class of divergence ADR-012 exists to stop.
|
|
1840
|
-
*
|
|
1841
|
-
* The guard is exact — one key, `__toml__`, holding a `kind` and a
|
|
1842
|
-
* `src` string — so a document whose own data happens to use the name
|
|
1843
|
-
* passes through untouched.
|
|
1844
|
-
*/
|
|
1845
1155
|
function tomlDates(node) {
|
|
1846
1156
|
if (Array.isArray(node)) {
|
|
1847
1157
|
return node.map(tomlDates);
|
|
@@ -1861,31 +1171,12 @@ function tomlDates(node) {
|
|
|
1861
1171
|
}
|
|
1862
1172
|
return out;
|
|
1863
1173
|
}
|
|
1864
|
-
/**
|
|
1865
|
-
* Read one included file as DATA in the named format.
|
|
1866
|
-
*
|
|
1867
|
-
* The parser hands back the JSON value the file denotes — plain maps,
|
|
1868
|
-
* lists and scalars — and rawToVal turns that into Vals. THE
|
|
1869
|
-
* CONVERSION HAPPENS HERE, not at the top level, because an include is
|
|
1870
|
-
* usually not at the top level: `a: @"conf.toml"` puts the value under
|
|
1871
|
-
* a key, where a raw JavaScript object is something the tree cannot
|
|
1872
|
-
* unify with (the crash that was BUGS §49b).
|
|
1873
|
-
*/
|
|
1874
1174
|
const dataProcessor = (format) => (res) => {
|
|
1875
1175
|
res.val = rawToVal(DATA_READERS[format](res.src, res.path));
|
|
1876
1176
|
};
|
|
1877
|
-
// TEXT IS NOT PARSED. The bytes multisource read are the value, so
|
|
1878
|
-
// this is the one processor with no reader behind it -- which is why
|
|
1879
|
-
// a `.txt` include cannot fail on content, only on being unreadable.
|
|
1880
1177
|
const textProcessor = (res) => {
|
|
1881
1178
|
res.val = new StringVal_1.StringVal({ peg: res.src });
|
|
1882
1179
|
};
|
|
1883
|
-
/**
|
|
1884
|
-
* The multisource processor map, built FROM the include table so the
|
|
1885
|
-
* two cannot drift: every extension the table names gets the reader
|
|
1886
|
-
* the table names for it, and the two kinds that are not in the table
|
|
1887
|
-
* refuse.
|
|
1888
|
-
*/
|
|
1889
1180
|
function includeProcessors(textExt) {
|
|
1890
1181
|
const map = {
|
|
1891
1182
|
// multisource's fallback for an extension no entry names, so it is
|
|
@@ -1906,10 +1197,6 @@ function includeProcessors(textExt) {
|
|
|
1906
1197
|
for (const kind of Object.keys(INCLUDE_KINDS)) {
|
|
1907
1198
|
map[kind] = forKind(kind);
|
|
1908
1199
|
}
|
|
1909
|
-
// A WIDENING NEVER OVERWRITES. `js` and the empty fallback refuse
|
|
1910
|
-
// above and stay refusing: `--text-ext js` would otherwise turn the
|
|
1911
|
-
// one extension ADR-012 singles out into a readable one, by a flag
|
|
1912
|
-
// whose whole promise is that it chooses no parser.
|
|
1913
1200
|
for (const ext of textExt ?? []) {
|
|
1914
1201
|
if (undefined === map[ext]) {
|
|
1915
1202
|
map[ext] = textProcessor;
|
|
@@ -1917,17 +1204,8 @@ function includeProcessors(textExt) {
|
|
|
1917
1204
|
}
|
|
1918
1205
|
return map;
|
|
1919
1206
|
}
|
|
1920
|
-
//
|
|
1921
|
-
//
|
|
1922
|
-
// relative paths (`@"../../etc/passwd.aon"`) and symlinks — so treat
|
|
1923
|
-
// opening an untrusted source as reading your disk. It no longer RUNS
|
|
1924
|
-
// one: @"pkg" could require() an arbitrary installed module until
|
|
1925
|
-
// ADR-012, which refuses a `.js` entry point by the same rule that
|
|
1926
|
-
// refuses `.txt`. The trust profile (G5, docs/trust.md) is the
|
|
1927
|
-
// confinement surface: `trust.include` of
|
|
1928
|
-
// 'none', `{ mem }` or `{ root }` restricts what `@"..."` may resolve,
|
|
1929
|
-
// and a denied resolution is a deterministic parse-stage
|
|
1930
|
-
// `include_denied` error.
|
|
1207
|
+
// What a resolved include may reach, and how it is confined:
|
|
1208
|
+
// docs/trust.md.
|
|
1931
1209
|
function makeModelResolver(options) {
|
|
1932
1210
|
const useRequire = options.require || require;
|
|
1933
1211
|
const capability = options.trust?.include ?? 'system';
|
|
@@ -1935,22 +1213,9 @@ function makeModelResolver(options) {
|
|
|
1935
1213
|
const rootDir = 'object' === typeof capability &&
|
|
1936
1214
|
'string' === typeof capability.root
|
|
1937
1215
|
? (0, node_path_1.resolve)(capability.root) : undefined;
|
|
1938
|
-
// Under the mem capability the CAPABILITY's file set is the whole
|
|
1939
|
-
// world; otherwise the host-injected `options.resolver.mem` entries
|
|
1940
|
-
// remain available under every capability but 'none' — they are
|
|
1941
|
-
// host-provided, not document-requested, so confining them would
|
|
1942
|
-
// confine the host against itself.
|
|
1943
|
-
// A LANGUAGE-SUPPLIED MODEL DOES NOT RIDE THIS LEG (ADR-028). Every
|
|
1944
|
-
// bundled schema is named under `aontu:` and answered by the scheme
|
|
1945
|
-
// leg above, which returns before the memory resolver is built, so
|
|
1946
|
-
// neither a host entry nor a capability's own file set can stand in
|
|
1947
|
-
// front of one: `aontu:system` is the engine's, always. That is what
|
|
1948
|
-
// the prefix buys, and it is why the bare-name leg that once let a
|
|
1949
|
-
// caller shadow `std/system` is gone.
|
|
1950
1216
|
let memResolver = (0, mem_1.makeMemResolver)(memCapability
|
|
1951
1217
|
? { ...capability.mem }
|
|
1952
1218
|
: { ...(options.resolver?.mem || {}) });
|
|
1953
|
-
// TODO: make this consistent with other resolvers
|
|
1954
1219
|
let fileResolver = (0, file_1.makeFileResolver)((spec) => {
|
|
1955
1220
|
return 'string' === typeof spec ? spec : spec?.peg;
|
|
1956
1221
|
});
|
|
@@ -1958,23 +1223,6 @@ function makeModelResolver(options) {
|
|
|
1958
1223
|
require: useRequire,
|
|
1959
1224
|
...(options.resolver?.pkg || {})
|
|
1960
1225
|
});
|
|
1961
|
-
// Confinement is realpath-then-prefix-check (docs/trust.md): the
|
|
1962
|
-
// RESOLVED file's real path must sit below the root's real path, so a
|
|
1963
|
-
// symlink inside the root pointing outside it is an escape, not a
|
|
1964
|
-
// loophole. A path realpath cannot resolve falls back to the lexical
|
|
1965
|
-
// form — the comparison is then against what the resolver actually
|
|
1966
|
-
// read.
|
|
1967
|
-
// Real fs, deliberately: `options.fs` is not a sandbox (it feeds
|
|
1968
|
-
// parse text; the file leg reads through its own channel), so the
|
|
1969
|
-
// containment check must see the same filesystem that leg read from.
|
|
1970
|
-
// A path that does not (fully) exist cannot be realpath'd whole, and
|
|
1971
|
-
// falling back to the LEXICAL form compares apples to oranges when
|
|
1972
|
-
// the root itself sits behind a symlink -- on macOS a root under
|
|
1973
|
-
// /var realpaths to /private/var, so a merely-missing file inside it
|
|
1974
|
-
// reads as an escape. Realpath the deepest EXISTING ancestor and
|
|
1975
|
-
// re-attach the rest, so both sides of the check are in real
|
|
1976
|
-
// coordinates. (The MCP server's own confinement carries the twin of
|
|
1977
|
-
// this rule; its CI failure is what found the shape.)
|
|
1978
1226
|
const realpath = (p) => {
|
|
1979
1227
|
try {
|
|
1980
1228
|
return (0, node_fs_1.realpathSync)(p);
|
|
@@ -1992,12 +1240,6 @@ function makeModelResolver(options) {
|
|
|
1992
1240
|
const fullReal = realpath(full);
|
|
1993
1241
|
return fullReal !== rootReal && !fullReal.startsWith(rootReal + node_path_1.sep);
|
|
1994
1242
|
};
|
|
1995
|
-
// A denial THROWS with the code; Lang.parse converts it to the
|
|
1996
|
-
// parse-stage `include_denied` nil (the same shape a syntax failure
|
|
1997
|
-
// takes). Raising beats injecting a nil value: a bare-member include
|
|
1998
|
-
// (`@"denied.aon"` at the top of a file) MERGES into the enclosing
|
|
1999
|
-
// map, and a nil contributes no keys, so an injected denial would
|
|
2000
|
-
// vanish and leave a plausible, silently-partial document.
|
|
2001
1243
|
const deny = (path) => {
|
|
2002
1244
|
// Only 'none' and 'root' can deny: the mem capability's misses are
|
|
2003
1245
|
// not-found (its set is the whole world), so there is no third arm.
|
|
@@ -2006,12 +1248,6 @@ function makeModelResolver(options) {
|
|
|
2006
1248
|
err.code = 'include_denied';
|
|
2007
1249
|
throw err;
|
|
2008
1250
|
};
|
|
2009
|
-
// AN UNREADABLE EXTENSION THROWS, exactly as a denial does, and for
|
|
2010
|
-
// the same reason: a bare-member include (`@"notes.txt"` at the top
|
|
2011
|
-
// of a file) MERGES into the enclosing map, and a nil contributes no
|
|
2012
|
-
// keys, so an injected refusal would vanish and leave a plausible,
|
|
2013
|
-
// silently-partial document. Lang.parse turns the throw into the
|
|
2014
|
-
// parse-stage `include_extension` nil.
|
|
2015
1251
|
const refuseExtension = (path, full) => {
|
|
2016
1252
|
const err = new Error(extensionMsg(path, extKindOf(full)));
|
|
2017
1253
|
err.code = 'include_extension';
|
|
@@ -2023,12 +1259,12 @@ function makeModelResolver(options) {
|
|
|
2023
1259
|
// set: a typo in an `aontu:` name must not go looking on disk.
|
|
2024
1260
|
const modelNotFound = (path) => {
|
|
2025
1261
|
const err = new Error('source not found: ' + path +
|
|
2026
|
-
' (the language-supplied models are ' +
|
|
1262
|
+
' (the language-supplied models are ' + aontumodel_1.AONTU_MODELS.join(', ') + ')');
|
|
2027
1263
|
err.code = 'multisource_not_found';
|
|
2028
1264
|
throw err;
|
|
2029
1265
|
};
|
|
2030
|
-
// The gate every leg that RESOLVES A NAME passes through. The
|
|
2031
|
-
// module legs do not: both state `kind: 'aon'` because what they
|
|
1266
|
+
// The gate every leg that RESOLVES A NAME passes through. The aontu:
|
|
1267
|
+
// and module legs do not: both state `kind: 'aon'` because what they
|
|
2032
1268
|
// serve is Aontu source by construction, not by its spelling.
|
|
2033
1269
|
const gateExtension = (path, full) => {
|
|
2034
1270
|
if (undefined === includeFormat(extKindOf(full), options.textExt)) {
|
|
@@ -2085,25 +1321,12 @@ function makeModelResolver(options) {
|
|
|
2085
1321
|
if ('none' === capability) {
|
|
2086
1322
|
deny(path);
|
|
2087
1323
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
// else -- the memory, module, file and package legs are never
|
|
2091
|
-
// asked, so nothing on disk can shadow one and a typo is refused
|
|
2092
|
-
// here, naming the set, rather than searched for. Available under
|
|
2093
|
-
// every capability but `none`, checked just above. A path that is
|
|
2094
|
-
// not a string (`a: @1`) is not a name at all: it falls through to
|
|
2095
|
-
// the legs below and is not found there, as it always was.
|
|
2096
|
-
//
|
|
2097
|
-
// This is the ONLY leg that serves a bundled model (ADR-028). The
|
|
2098
|
-
// vocabularies once had bare names (`std/system`) and a second leg
|
|
2099
|
-
// below to match them; the prefix is now the whole spelling, so one
|
|
2100
|
-
// leg answers for every language-supplied schema.
|
|
2101
|
-
if ('string' === typeof path && path.startsWith(std_1.AONTU_SCHEME)) {
|
|
2102
|
-
const model = std_1.STD_SOURCES[path];
|
|
1324
|
+
if ('string' === typeof path && path.startsWith(aontumodel_1.AONTU_SCHEME)) {
|
|
1325
|
+
const model = aontumodel_1.AONTU_SOURCES[path];
|
|
2103
1326
|
if (null == model) {
|
|
2104
1327
|
modelNotFound(path);
|
|
2105
1328
|
}
|
|
2106
|
-
record(ctx, path, '
|
|
1329
|
+
record(ctx, path, 'aontu');
|
|
2107
1330
|
return { found: true, path, full: path, kind: 'aon', src: model, search: [] };
|
|
2108
1331
|
}
|
|
2109
1332
|
let search = [];
|
|
@@ -2118,11 +1341,6 @@ function makeModelResolver(options) {
|
|
|
2118
1341
|
record(ctx, res.full ?? path, 'mem');
|
|
2119
1342
|
return res;
|
|
2120
1343
|
}
|
|
2121
|
-
// THE MODULE LEG (G6 phase 2, ts/src/mod.ts): memory -> MODULE ->
|
|
2122
|
-
// filesystem -> package. Memory stays FIRST so a sandbox and the
|
|
2123
|
-
// spec suite can stub a module path without touching disk; a path
|
|
2124
|
-
// that is not module-shaped falls straight through, so no existing
|
|
2125
|
-
// include can be routed somewhere new by this.
|
|
2126
1344
|
const modref = memCapability ? undefined : (0, mod_1.parseModuleRef)(path);
|
|
2127
1345
|
if (null != modref) {
|
|
2128
1346
|
const msmeta = ctx?.meta?.multisource;
|
|
@@ -2200,53 +1418,17 @@ function makeModelResolver(options) {
|
|
|
2200
1418
|
return res;
|
|
2201
1419
|
};
|
|
2202
1420
|
}
|
|
2203
|
-
// THE SIGNATURE REGISTRY (docs/design/SIGNATURES.0.md). The call
|
|
2204
|
-
// surface is DECLARED in test/spec/signature.tsv and parsed by the
|
|
2205
|
-
// signature grammar (ts/src/sig.ts) from the build-time-inlined copy;
|
|
2206
|
-
// the arity table and the positional set below are DERIVED from the
|
|
2207
|
-
// parsed registry (funcSig, ts/src/sig.ts), so the declaration is the
|
|
2208
|
-
// one source. go/func.go derives the same two tables from the same
|
|
2209
|
-
// text.
|
|
2210
|
-
// The functions whose comma-separated arguments are distinct POSITIONS
|
|
2211
|
-
// rather than one argument list. See the func-paren handler above: this
|
|
2212
|
-
// is the set whose comma group is expanded back into separate `peg`
|
|
2213
|
-
// entries. Derived: two or more declared argument slots, excluding the
|
|
2214
|
-
// residual producers (`constraint` results) -- the constraint atoms
|
|
2215
|
-
// make the same expansion in their own constructor (`atomArgs`,
|
|
2216
|
-
// ConstraintVal.ts, deliberately before the settled check), which is
|
|
2217
|
-
// why they are not in this set; `must` is the load-bearing example.
|
|
2218
|
-
// Arithmetic is here because `sub` is not commutative: `sub(a, b)`
|
|
2219
|
-
// reaching the engine as one two-element list would lose which is
|
|
2220
|
-
// which.
|
|
2221
1421
|
const POSITIONAL_ARG_FUNCS = {};
|
|
2222
1422
|
for (const name in sig_1.funcSig) {
|
|
2223
1423
|
if (2 <= sig_1.funcSig[name].args.length && 'constraint' !== sig_1.funcSig[name].out) {
|
|
2224
1424
|
POSITIONAL_ARG_FUNCS[name] = true;
|
|
2225
1425
|
}
|
|
2226
1426
|
}
|
|
2227
|
-
// THE COMPONENT PRIMITIVES, listed by hand (the spike, see funcMap
|
|
2228
|
-
// above and ts/src/val/CmpFuncVal.ts). They carry no signature
|
|
2229
|
-
// declaration, so the derivation above cannot see them -- and
|
|
2230
|
-
// `file("main.ts", [...])` without an entry arrives as ONE raw array
|
|
2231
|
-
// term, which the call then reads as its spec. The leaves are here
|
|
2232
|
-
// too, so that a written second argument is COUNTED and refused as
|
|
2233
|
-
// the arity mistake it is rather than arriving as a one-element list
|
|
2234
|
-
// that is merely the wrong shape.
|
|
2235
1427
|
for (const name of Object.keys(CmpFuncVal_1.CMP_FUNCS)) {
|
|
2236
1428
|
POSITIONAL_ARG_FUNCS[name] = true;
|
|
2237
1429
|
}
|
|
2238
1430
|
POSITIONAL_ARG_FUNCS['nom'] = true;
|
|
2239
1431
|
POSITIONAL_ARG_FUNCS['translate'] = true;
|
|
2240
|
-
// [min, max]; a max of -1 is unbounded. Every DECLARED name has an
|
|
2241
|
-
// entry, and the arity is a property of the language rather than of
|
|
2242
|
-
// either port -- go/func.go derives the same table. The spike's
|
|
2243
|
-
// component primitives are the one exception: they carry no
|
|
2244
|
-
// declaration, so they have no entry here and refuse a bad count in
|
|
2245
|
-
// their own resolve (ts/src/val/CmpFuncVal.ts). A required slot
|
|
2246
|
-
// counts toward the minimum; a rest slot makes the maximum unbounded
|
|
2247
|
-
// and counts its group size (one, for a plain rest type) toward the
|
|
2248
|
-
// minimum, which is what gives `match` its floor of three and `neq`
|
|
2249
|
-
// its floor of one.
|
|
2250
1432
|
function sigArity(sig) {
|
|
2251
1433
|
let min = 0;
|
|
2252
1434
|
let max = 0;
|
|
@@ -2270,14 +1452,6 @@ const funcArity = {};
|
|
|
2270
1452
|
for (const name in sig_1.funcSig) {
|
|
2271
1453
|
funcArity[name] = sigArity(sig_1.funcSig[name]);
|
|
2272
1454
|
}
|
|
2273
|
-
// writtenArgCount counts the arguments as the AUTHOR wrote them.
|
|
2274
|
-
//
|
|
2275
|
-
// It cannot simply be terms.length: a comma group reaches the func-paren
|
|
2276
|
-
// handler as ONE term holding a raw array, so `upper("a","b")` and
|
|
2277
|
-
// `upper(["a","b"])` both arrive as a single argument. They are still
|
|
2278
|
-
// distinguishable, and that is what makes an arity check possible at
|
|
2279
|
-
// all -- the comma group is a RAW array, while a written list literal
|
|
2280
|
-
// has already been built into a ListVal by the list rule.
|
|
2281
1455
|
function writtenArgCount(terms) {
|
|
2282
1456
|
if (1 === terms.length) {
|
|
2283
1457
|
// `terms[0]` is re-read rather than reusing a narrowed local:
|
|
@@ -2302,12 +1476,6 @@ function arityText(lo, hi) {
|
|
|
2302
1476
|
if (0 === lo) {
|
|
2303
1477
|
return 'no arguments or one';
|
|
2304
1478
|
}
|
|
2305
|
-
// The case range gave `upper` and `lower` a span rather than a
|
|
2306
|
-
// pair, and a two-arm phrasing cannot say it: [1,3] read as "one
|
|
2307
|
-
// argument or two", which is a wrong count rather than an
|
|
2308
|
-
// imprecise one. Each arm here is a shape the table actually
|
|
2309
|
-
// carries, and each is pinned by a row -- a phrasing for a count no
|
|
2310
|
-
// entry has would be untested prose pretending to be tested.
|
|
2311
1479
|
return 3 === hi ? 'one to three arguments' : 'one argument or two';
|
|
2312
1480
|
}
|
|
2313
1481
|
// The {0,0} arm returned with the container kinds and acyclic()
|
|
@@ -2320,17 +1488,6 @@ function arityText(lo, hi) {
|
|
|
2320
1488
|
}
|
|
2321
1489
|
return 'exactly one argument';
|
|
2322
1490
|
}
|
|
2323
|
-
// rawToVal converts a raw parse node (or raw elements inside one) into
|
|
2324
|
-
// the matching Val. Used for implicit top-level lists, whose nodes skip
|
|
2325
|
-
// the aontu val rule conversions (mirrors asVal in go/lang.go; like
|
|
2326
|
-
// there, source text is unavailable, so an integral number is an
|
|
2327
|
-
// integer).
|
|
2328
|
-
// The targeted parse hint for CUE-trained authors and models: `>` and
|
|
2329
|
-
// `<` are not Aontu operators (the op-chars reservation stands), and an
|
|
2330
|
-
// agent that emits `number > 0` should be redirected to the bound
|
|
2331
|
-
// atoms, not left with a bare "unexpected character". Appended to a
|
|
2332
|
-
// parse error's message when the source carries an unquoted `<` or
|
|
2333
|
-
// `>`; the Go twin is opCharHint in go/lang.go, byte-identical text.
|
|
2334
1491
|
function opCharHint(src) {
|
|
2335
1492
|
let q = '';
|
|
2336
1493
|
for (let i = 0; i < src.length; i++) {
|
|
@@ -2358,12 +1515,6 @@ function rawToVal(n) {
|
|
|
2358
1515
|
if (Array.isArray(n)) {
|
|
2359
1516
|
return new ListVal_1.ListVal({ peg: n.map(rawToVal) });
|
|
2360
1517
|
}
|
|
2361
|
-
// THE SCALAR ARMS ARE WHERE A CONFIG FILE BECOMES VALUES. Every
|
|
2362
|
-
// format on the include table is read by its own parser into plain
|
|
2363
|
-
// JavaScript -- a string, a number, a map -- and this is the walk
|
|
2364
|
-
// that turns that into Vals (dataProcessor, ADR-012). The two arms
|
|
2365
|
-
// above are the other caller: a raw expression TERM, which the
|
|
2366
|
-
// expression grammar hands over already built.
|
|
2367
1518
|
if (null == n) {
|
|
2368
1519
|
return new NullVal_1.NullVal({ peg: null });
|
|
2369
1520
|
}
|
|
@@ -2372,24 +1523,12 @@ function rawToVal(n) {
|
|
|
2372
1523
|
return new StringVal_1.StringVal({ peg: n });
|
|
2373
1524
|
}
|
|
2374
1525
|
if ('number' === t) {
|
|
2375
|
-
// No source text here, so the "no '.'" condition is vacuous and the
|
|
2376
|
-
// integral + int64-range conditions decide (same helper as the val
|
|
2377
|
-
// rule, so the two paths cannot drift).
|
|
2378
1526
|
return (0, numkind_1.isIntegerKind)(n) ?
|
|
2379
1527
|
new IntegerVal_1.IntegerVal({ peg: n }) : new NumberVal_1.NumberVal({ peg: n });
|
|
2380
1528
|
}
|
|
2381
1529
|
if ('boolean' === t) {
|
|
2382
1530
|
return new BooleanVal_1.BooleanVal({ peg: n });
|
|
2383
1531
|
}
|
|
2384
|
-
// AND EVERYTHING ELSE IS A MAP, with no arm after it because there is
|
|
2385
|
-
// nothing after it. Every reader on the include table answers with
|
|
2386
|
-
// the JSON kinds and no others -- probed, including the two that
|
|
2387
|
-
// could plausibly escape them: a big integer comes back a `number`,
|
|
2388
|
-
// and a TOML date is normalised to its text before it gets here. The
|
|
2389
|
-
// one include that could hand over a function was `.js`, which
|
|
2390
|
-
// ADR-012 refuses. `parse_unknown` lived here for that case and has
|
|
2391
|
-
// no producer left in this port; the Go twin keeps its own, where the
|
|
2392
|
-
// type switch really can be handed something unaccounted for.
|
|
2393
1532
|
const peg = {};
|
|
2394
1533
|
for (const k in n) {
|
|
2395
1534
|
peg[k] = rawToVal(n[k]);
|
|
@@ -2398,7 +1537,6 @@ function rawToVal(n) {
|
|
|
2398
1537
|
}
|
|
2399
1538
|
class Lang {
|
|
2400
1539
|
constructor(options) {
|
|
2401
|
-
// const start = performance.now()
|
|
2402
1540
|
this.opts = Object.assign((0, type_1.DEFAULT_OPTS)(), options);
|
|
2403
1541
|
const modelResolver = makeModelResolver(this.opts);
|
|
2404
1542
|
this.jsonic = jsonic_1.Jsonic.make();
|
|
@@ -2410,31 +1548,12 @@ class Lang {
|
|
|
2410
1548
|
this.jsonic
|
|
2411
1549
|
.use(asPlugin(multisource_1.MultiSource), {
|
|
2412
1550
|
resolver: options?.resolver || modelResolver,
|
|
2413
|
-
// `.aon` is the preferred Aontu source extension; `.aontu` also
|
|
2414
|
-
// works. `.jsonic` is retired (no longer auto-resolved); the
|
|
2415
|
-
// default `['jsonic','jsc','json','js']` is overridden here.
|
|
2416
|
-
// (Upstream option name is the misspelled `implictExt`.)
|
|
2417
|
-
//
|
|
2418
|
-
// Only these two are SEARCHED for a bare `@"name"`; `.json` and
|
|
2419
|
-
// `.jsonld` are read when NAMED, which is how a vendored
|
|
2420
|
-
// vocabulary is always written.
|
|
2421
1551
|
implictExt: ['aon', 'aontu'],
|
|
2422
|
-
// ONE ENTRY PER EXTENSION THE TABLE NAMES, built from it (see
|
|
2423
|
-
// includeProcessors) so the rule and its wiring cannot drift.
|
|
2424
|
-
//
|
|
2425
|
-
// The upstream defaults are REPLACED, not extended. Its `json`
|
|
2426
|
-
// entry is what made that extension the one that crashed: it
|
|
2427
|
-
// hands back a raw JS object where the aontu grammar produces
|
|
2428
|
-
// Vals, and the tree then met a value it could not convert
|
|
2429
|
-
// (BUGS §49b). Its `js` entry EXECUTES the file, which is not
|
|
2430
|
-
// something an extension should be able to ask for. And its
|
|
2431
|
-
// fallback hands any other file back as TEXT.
|
|
2432
1552
|
processor: includeProcessors(this.opts.textExt)
|
|
2433
1553
|
})
|
|
2434
1554
|
.use(AontuJsonic);
|
|
2435
1555
|
}
|
|
2436
1556
|
parse(src, opts) {
|
|
2437
|
-
// const start = performance.now()
|
|
2438
1557
|
// JSONIC-UPDATE - check meta
|
|
2439
1558
|
let jm = {
|
|
2440
1559
|
fs: opts?.fs,
|
|
@@ -2457,7 +1576,6 @@ class Lang {
|
|
|
2457
1576
|
if (opts && null != opts.log && Number.isInteger(opts.log)) {
|
|
2458
1577
|
jm.log = opts.log;
|
|
2459
1578
|
}
|
|
2460
|
-
// jm.log = -1
|
|
2461
1579
|
let val;
|
|
2462
1580
|
try {
|
|
2463
1581
|
val = this.jsonic(src, jm);
|
|
@@ -2472,14 +1590,6 @@ class Lang {
|
|
|
2472
1590
|
catch (e) {
|
|
2473
1591
|
if ('include_denied' === e?.code || 'include_extension' === e?.code ||
|
|
2474
1592
|
'multisource_not_found' === e?.code || mod_1.MODULE_REFUSAL_CODES.has(e?.code)) {
|
|
2475
|
-
// A denied include (G5), an include whose extension is not read
|
|
2476
|
-
// as Aontu source (ADR-012, INCLUDE_KINDS), an `aontu:` name the
|
|
2477
|
-
// engine does not serve (MODELS.0.md D1), and a module that is
|
|
2478
|
-
// missing, fails its pin, or names a path that escapes its store
|
|
2479
|
-
// (G6 phase 2) are refused the same way, for the same reason: the
|
|
2480
|
-
// resolver THROWS so a bare-member include cannot vanish in the
|
|
2481
|
-
// merge, and the code survives here as the parse-stage nil the
|
|
2482
|
-
// registry pins (errcodes.tsv).
|
|
2483
1593
|
val = new NilVal_1.NilVal({
|
|
2484
1594
|
why: 'parse',
|
|
2485
1595
|
err: new NilVal_1.NilVal({
|
|
@@ -2495,14 +1605,6 @@ class Lang {
|
|
|
2495
1605
|
msg: e.message + opCharHint(src),
|
|
2496
1606
|
err: e,
|
|
2497
1607
|
});
|
|
2498
|
-
// THE POSITION TRAVELS WITH IT. The parser knows exactly where
|
|
2499
|
-
// it stopped -- it draws a caret there -- and the rendered
|
|
2500
|
-
// message carried the only copy, so `vet --format json`
|
|
2501
|
-
// reported row -1, col -1 for a document whose fault the human
|
|
2502
|
-
// renderer located to the character. A machine-readable report
|
|
2503
|
-
// that says "somewhere in this file" is the one a repair loop
|
|
2504
|
-
// can do nothing with. Both numbers are already 1-based here,
|
|
2505
|
-
// which is the base a site uses (go/lang.go does the same).
|
|
2506
1608
|
if ('number' === typeof e.lineNumber) {
|
|
2507
1609
|
syntax.site.row = e.lineNumber;
|
|
2508
1610
|
}
|