aontu 0.61.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 +4 -4
- package/dist/agentsmd.d.ts +1 -0
- package/dist/agentsmd.js +7 -28
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.d.ts +23 -0
- package/dist/allow.js +138 -0
- package/dist/allow.js.map +1 -0
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +4 -80
- 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.d.ts +10 -1
- package/dist/cli.js +877 -479
- 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 +55 -189
- 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.d.ts +16 -0
- package/dist/helpdoc.js +59 -0
- package/dist/helpdoc.js.map +1 -0
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +59 -47
- 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 +32 -877
- package/dist/lang.js.map +1 -1
- package/dist/lower.d.ts +3 -0
- package/dist/lower.js +14 -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.d.ts +2 -0
- package/dist/relation.js +3 -58
- package/dist/relation.js.map +1 -1
- package/dist/render.js +33 -143
- 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.d.ts +20 -0
- package/dist/val/CmpFuncVal.js +188 -0
- package/dist/val/CmpFuncVal.js.map +1 -0
- 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.d.ts +1 -2
- package/dist/val/EachFuncVal.js +12 -29
- 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 +11 -6
- 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 +2 -36
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.d.ts +12 -0
- package/dist/val/NomFuncVal.js +153 -0
- package/dist/val/NomFuncVal.js.map +1 -0
- 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.d.ts +12 -0
- package/dist/val/TranslateFuncVal.js +99 -0
- package/dist/val/TranslateFuncVal.js.map +1 -0
- package/dist/val/UpperFuncVal.js +11 -6
- 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.d.ts +3 -0
- package/dist/val/caserange.js +49 -0
- package/dist/val/caserange.js.map +1 -0
- 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.d.ts +12 -0
- package/dist/vet.js +159 -412
- 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 +9 -7
- package/grammar/aontu.gbnf +5 -5
- package/grammar/aontu.lark +5 -5
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/skill/SKILL.md +8 -0
- package/skill/init/check.sh +28 -0
- package/skill/init/data.aon +12 -0
- package/skill/init/model.aon +19 -0
- package/skill/tasks.md +151 -0
- package/src/agentsmd.ts +8 -32
- package/src/alias.ts +0 -39
- package/src/allow.ts +221 -0
- package/src/aontu.ts +10 -108
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +1009 -540
- 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 +63 -234
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +77 -0
- package/src/hints.ts +72 -49
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +39 -895
- package/src/lower.ts +15 -65
- 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 +7 -71
- package/src/render.ts +33 -180
- 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 +249 -0
- 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 +12 -53
- 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 +12 -7
- 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 +2 -36
- package/src/val/NomFuncVal.ts +200 -0
- 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 +132 -0
- package/src/val/UpperFuncVal.ts +12 -7
- 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 +53 -0
- 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 +209 -504
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -637
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/src/std.ts +0 -648
- package/src/val/FormFuncVal.ts +0 -119
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,12 +51,16 @@ 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");
|
|
59
|
+
const CmpFuncVal_1 = require("./val/CmpFuncVal");
|
|
60
|
+
const MaybeFuncVal_1 = require("./val/MaybeFuncVal");
|
|
61
|
+
const NomFuncVal_1 = require("./val/NomFuncVal");
|
|
62
|
+
const TranslateFuncVal_1 = require("./val/TranslateFuncVal");
|
|
74
63
|
const EachFuncVal_1 = require("./val/EachFuncVal");
|
|
75
|
-
const FormFuncVal_1 = require("./val/FormFuncVal");
|
|
76
64
|
const FilterFuncVal_1 = require("./val/FilterFuncVal");
|
|
77
65
|
const MatchFuncVal_1 = require("./val/MatchFuncVal");
|
|
78
66
|
const EmitFuncVal_1 = require("./val/EmitFuncVal");
|
|
@@ -89,32 +77,11 @@ const OpenFuncVal_1 = require("./val/OpenFuncVal");
|
|
|
89
77
|
const SuperFuncVal_1 = require("./val/SuperFuncVal");
|
|
90
78
|
const ConstraintVal_1 = require("./val/ConstraintVal");
|
|
91
79
|
const asPlugin = (p) => p;
|
|
92
|
-
// Build the Val for a matched `0d` literal (see the `0d` value matcher
|
|
93
|
-
// below). Leaf by source: digits only is a biginteger, a `.` or an
|
|
94
|
-
// exponent makes it a bigdecimal.
|
|
95
|
-
//
|
|
96
|
-
// A literal over the D6 exactness budget becomes a LOCATED ERROR here
|
|
97
|
-
// and not a rounded or expanded value: `0d1e1000000000` has a one-digit
|
|
98
|
-
// coefficient, so only the scale bound catches it, and it is caught at
|
|
99
|
-
// parse -- before plain-form rendering would try to materialise a
|
|
100
|
-
// gigabyte of zeros.
|
|
101
|
-
// The source text of a negated exact literal. `-` is a prefix OPERATOR,
|
|
102
|
-
// not part of the literal, so the text has to be rebuilt here to keep
|
|
103
|
-
// `src` meaning "how this value is spelled" (see bigVal).
|
|
104
80
|
function negsrc(src) {
|
|
105
|
-
// src is never empty here: it is a BIG_LITERAL_RE match (at minimum
|
|
106
|
-
// the two chars `0d`) or an already-negated spelling. Computed exact
|
|
107
|
-
// values do carry src '', but they are built at unify time, long
|
|
108
|
-
// after this parse-time opmap.
|
|
109
81
|
return src.startsWith('-') ? src.slice(1) : '-' + src;
|
|
110
82
|
}
|
|
111
83
|
function bigVal(res) {
|
|
112
84
|
const lit = (0, Decimal_1.readBigLiteral)(res);
|
|
113
|
-
// `src` is the literal's own text, and it is not decoration: a path
|
|
114
|
-
// segment is spelled text, so `$.a.0d1` must address the key `0d1` --
|
|
115
|
-
// the same key `a:{0d1:7}` creates -- rather than the number 1. See
|
|
116
|
-
// RefVal.append. Without it the segment was empty and the reference
|
|
117
|
-
// silently resolved to its own container.
|
|
118
85
|
const src = res[0];
|
|
119
86
|
return 'biginteger' === lit.leaf ? new BigIntegerVal_1.BigIntegerVal({ peg: lit.int, src }) :
|
|
120
87
|
'bigdecimal' === lit.leaf ? new BigDecimalVal_1.BigDecimalVal({ peg: lit.dec, src }) :
|
|
@@ -124,43 +91,11 @@ function bigVal(res) {
|
|
|
124
91
|
const CC_0 = 48;
|
|
125
92
|
const CC_d = 100;
|
|
126
93
|
const CC_D = 68;
|
|
127
|
-
// THE ALIAS SIGIL. `%` is part of an alias's name, so the name is one
|
|
128
|
-
// lexeme wherever it appears and its meaning is decided by position:
|
|
129
|
-
// a BINDING in key position (`%uint8 = …` declares), a USE in value
|
|
130
|
-
// position (`listen: %uint8` refers). docs/design/ALIASES.0.md §4.
|
|
131
94
|
const CC_PCT = 37;
|
|
132
95
|
const ALIAS_RE = /^%[A-Za-z_][A-Za-z0-9_]*/;
|
|
133
|
-
// THE DECLARATION OPERATOR. `%name = value` declares; the `=` is the
|
|
134
|
-
// pair's separator, lexed as the colon token so the declaration then
|
|
135
|
-
// parses as a pair whose key is the alias name (ALIASES.0.md X-1, as
|
|
136
|
-
// settled 2026-09-05). `=` is syntax ONLY there: anywhere else it is
|
|
137
|
-
// punctuation outside its syntax, and the bare-text scan below refuses
|
|
138
|
-
// it (`foo = 1`, `a: x=y`).
|
|
139
96
|
const CC_EQ = 61;
|
|
140
97
|
const CC_SP = 32;
|
|
141
98
|
const CC_TAB = 9;
|
|
142
|
-
// THE BARE-TEXT RULE. A bare string holds letters, digits, `-` and `_`,
|
|
143
|
-
// and nothing else. Every other punctuation character is either SYNTAX,
|
|
144
|
-
// where the grammar gives it a meaning, or an ERROR where it does not
|
|
145
|
-
// -- never silently part of a string. `x=y`, `6/2`, `50%` and `>10`
|
|
146
|
-
// were all bare strings once, each a well-formed wrong document, and
|
|
147
|
-
// each is refused now, naming the character (bare_punct).
|
|
148
|
-
//
|
|
149
|
-
// scanBareRun classifies each character of a run three ways, in this
|
|
150
|
-
// order: TEXT continues the run; an ENDER stops it; anything else is
|
|
151
|
-
// BAD. The ender set is the lexer's own -- space, line, fixed tokens,
|
|
152
|
-
// comment starters -- read from the config its text matcher was built
|
|
153
|
-
// from, so it cannot drift from the grammar. A bad run is still scanned
|
|
154
|
-
// to its ender, so the refusal claims the whole spelling and the lexer
|
|
155
|
-
// never reads the tail of it as syntax.
|
|
156
|
-
//
|
|
157
|
-
// `-` is text wherever the scan sees it. A run never STARTS on one:
|
|
158
|
-
// `-` is the sign of a number and the negation prefix, a fixed token
|
|
159
|
-
// the fixed matcher claims before either scanning stage can run, so
|
|
160
|
-
// `a:-1` is the negation of 1 and `a:6-2` the string. The `+` of an
|
|
161
|
-
// exponent (`1e+2`) is admitted only by the NUMBER stage's scan, the
|
|
162
|
-
// one stage that can make a number of it. Mirrors scanBareRun in
|
|
163
|
-
// go/lang.go, decision for decision.
|
|
164
99
|
const CC_9 = 57;
|
|
165
100
|
const CC_A = 65;
|
|
166
101
|
const CC_Z = 90;
|
|
@@ -231,34 +166,10 @@ const NUMBER_RUN_RE = /^[-+]?(?:0(?:[xX][0-9a-fA-F_]+|[oO][0-7_]+|[bB][01_]+)|[0
|
|
|
231
166
|
const NOT_A_NUMBER = { done: true, token: undefined };
|
|
232
167
|
let AontuJsonic = function AontuLang(jsonic) {
|
|
233
168
|
jsonic.use(asPlugin(path_1.Path));
|
|
234
|
-
// Only # line comments are valid Aontu syntax (see
|
|
235
|
-
// docs/reference-language.md; go/lang.go sets the same). Clear the
|
|
236
|
-
// underlying jsonic comment markers entirely, then define # directly,
|
|
237
|
-
// so the comment set is hash-only regardless of those defaults.
|
|
238
169
|
let dotRef = (r, ctx, terms, prefix) => {
|
|
239
170
|
terms = dropUnfilled(terms);
|
|
240
171
|
if (0 === terms.length)
|
|
241
172
|
return incompleteNil(r, ctx);
|
|
242
|
-
// AN ALIAS IS NOT A PATH SEGMENT. `$.%foo` is refused: the alias
|
|
243
|
-
// namespace and the path namespace are disjoint, and an alias is
|
|
244
|
-
// reached by writing `%foo` and only that.
|
|
245
|
-
//
|
|
246
|
-
// The engine spells an alias reference AS a root reference to the
|
|
247
|
-
// declaration -- which is what gives it order independence and a
|
|
248
|
-
// cycle check shared with paths -- but that is an implementation of
|
|
249
|
-
// the name, not a second way to write it. Left writable, the two
|
|
250
|
-
// spellings would drift apart the moment aliases stop being
|
|
251
|
-
// file-shaped, and `$.%b` inside an included file would reach the
|
|
252
|
-
// INCLUDER's `%b` rather than its own, which is exactly the
|
|
253
|
-
// cross-file capture the sigil exists to prevent.
|
|
254
|
-
// `%foo` lexes to the reference itself, so in `$.%foo` it arrives
|
|
255
|
-
// as a TERM rather than as a string segment -- both shapes are
|
|
256
|
-
// checked, since a quoted `$."%foo"` would arrive as the string.
|
|
257
|
-
// Terms here are always Vals -- dropUnfilled has removed the
|
|
258
|
-
// nulls, and the dot rules never hand over a raw string -- so the
|
|
259
|
-
// shapes are exactly three: a RefVal (peg is the segment array), a
|
|
260
|
-
// StringVal (peg is the segment), and anything else (a numeric or
|
|
261
|
-
// exact segment, which cannot be an alias name).
|
|
262
173
|
for (const t of terms) {
|
|
263
174
|
const segs = Array.isArray(t.peg) ? t.peg :
|
|
264
175
|
('string' === typeof t.peg ? [t.peg] : []);
|
|
@@ -279,48 +190,12 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
279
190
|
},
|
|
280
191
|
},
|
|
281
192
|
});
|
|
282
|
-
// Digit separators are legal only as a SINGLE separator BETWEEN
|
|
283
|
-
// digits (the rule test/spec/engine-parity.tsv records as the engine's
|
|
284
|
-
// adjudication; pinned by the sep-* rows in
|
|
285
|
-
// test/spec/number-model.tsv). The engine's number matcher
|
|
286
|
-
// enforces most of that already — `1_`, `_1`, `1_.5`, `1._5`, `1e_2`,
|
|
287
|
-
// `1e2_` all fall through to text — but two gaps remain: a REPEATED
|
|
288
|
-
// separator (`1__0` lexed as 10) and a separator at the edge of a
|
|
289
|
-
// base-prefixed digit run (`0x_ff`, `0xff_` lexed as 255). Both
|
|
290
|
-
// silently accept a typo as a different number, so aontu declines the
|
|
291
|
-
// whole run instead and it lexes as text ("1__0"), exactly as `1_`
|
|
292
|
-
// already does.
|
|
293
|
-
//
|
|
294
|
-
// `number.exclude` is tested against the matched number source and,
|
|
295
|
-
// when it matches, makes the matcher decline the entire span. Kept in
|
|
296
|
-
// lock-step with sepInvalid in go/lang.go, which is wired to the
|
|
297
|
-
// equivalent `Number.Exclude` hook (and to the Check hook, which
|
|
298
|
-
// constructs big base-prefixed tokens itself and so bypasses Exclude).
|
|
299
193
|
jsonic.options({
|
|
300
194
|
number: {
|
|
301
|
-
// `__` repeated separator; `0x_`/`0o_`/`0b_` separator opening a
|
|
302
|
-
// base-prefixed run; `_` closing any run. The prefix letter is
|
|
303
|
-
// matched case-insensitively so the rule does not depend on which
|
|
304
|
-
// prefix spellings the engine accepts.
|
|
305
195
|
exclude: /__|^[-+]?0[xXoObB]_|_$/,
|
|
306
|
-
// THE NUMBER STAGE OF THE BARE-TEXT RULE. The matcher runs before
|
|
307
|
-
// the text matcher and reads a number up to the next ender -- and
|
|
308
|
-
// `-` is an ender, being the negation prefix's fixed token, so it
|
|
309
|
-
// would take the `2026` of `2026-09-05` and leave `-09-05` to the
|
|
310
|
-
// grammar. The hook scans the whole run first and declines for
|
|
311
|
-
// the matcher wherever the run is not its to lex: a run with a
|
|
312
|
-
// bad character (the text stage refuses it), a run that is not a
|
|
313
|
-
// number at all (`2026-09-05`, `6-2` are text). Twin of tsNumCheck
|
|
314
|
-
// in go/lang.go.
|
|
315
196
|
check: (lex) => {
|
|
316
197
|
const pnt = lex.pnt;
|
|
317
198
|
const src = lex.src;
|
|
318
|
-
// The hook makes the matcher a candidate at every position, so
|
|
319
|
-
// the common case -- a run no number can open -- declines for it
|
|
320
|
-
// in one char read. A DIGIT opens a number here and nothing
|
|
321
|
-
// else: the sign and the dot open the matcher's own grammar, but
|
|
322
|
-
// they are fixed tokens (the prefix operators and member
|
|
323
|
-
// access), claimed before this hook can run.
|
|
324
199
|
const c = src.charCodeAt(pnt.sI);
|
|
325
200
|
if (!(CC_0 <= c && c <= CC_9)) {
|
|
326
201
|
return NOT_A_NUMBER;
|
|
@@ -333,67 +208,15 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
333
208
|
},
|
|
334
209
|
},
|
|
335
210
|
});
|
|
336
|
-
// D3 -- the `0d` literal, the only route to the exact leaves
|
|
337
|
-
// (biginteger and bigdecimal). See BIG_LITERAL_RE for the grammar and
|
|
338
|
-
// the leaf-by-source rule.
|
|
339
|
-
//
|
|
340
|
-
// The literal is claimed by the TEXT MATCHER'S CHECK HOOK (the sibling
|
|
341
|
-
// of the `Number.Check` hook the Go port already uses for big
|
|
342
|
-
// base-prefixed literals), not by a `value.def` entry, because a `0d`
|
|
343
|
-
// run may contain a `.` and the two claim source differently:
|
|
344
|
-
//
|
|
345
|
-
// - A value def -- even a consuming one, matched against the full
|
|
346
|
-
// forward source -- is applied INSIDE the text matcher, AFTER its
|
|
347
|
-
// ender regexp has already carved the run at the `.`. The def
|
|
348
|
-
// claims `0d1.5` whole, but the matcher then still emits the
|
|
349
|
-
// ender's `.` as a fixed token, so `x:0d1.5` lexed as the
|
|
350
|
-
// bigdecimal FOLLOWED BY a dangling member-access dot (a path
|
|
351
|
-
// cycle). Verified, not theorised.
|
|
352
|
-
// - The check hook runs BEFORE that ender regexp and returns the
|
|
353
|
-
// token outright, so the run is claimed whole and nothing else is
|
|
354
|
-
// emitted.
|
|
355
|
-
//
|
|
356
|
-
// A `match.value` matcher (which runs ahead of every other matcher)
|
|
357
|
-
// also claims it correctly, but it is a candidate at EVERY lex
|
|
358
|
-
// position and materializes the forward source there: ~8% on a
|
|
359
|
-
// text-heavy document, for a syntax almost none of them use. The check
|
|
360
|
-
// hook only runs where the text matcher already runs, and measures at
|
|
361
|
-
// parity with not having it.
|
|
362
|
-
//
|
|
363
|
-
// The number matcher never sees these runs at all: it declines `0d…`
|
|
364
|
-
// outright, since `d` is not an ender.
|
|
365
211
|
jsonic.options({
|
|
366
212
|
text: {
|
|
367
213
|
check: (lex) => {
|
|
368
|
-
// Guard first, on char codes: this hook runs at every text
|
|
369
|
-
// position, and the common case (any run that cannot be a `0d`
|
|
370
|
-
// literal or an alias) must cost two char reads and no
|
|
371
|
-
// allocation.
|
|
372
214
|
const pnt = lex.pnt;
|
|
373
215
|
const src = lex.src;
|
|
374
|
-
// AN ALIAS NAME IS CLAIMED WHOLE, for the same reason the `0d`
|
|
375
|
-
// run below is: the text matcher's ender regexp would otherwise
|
|
376
|
-
// carve `%uint8` at the `%` and emit the sigil as its own token,
|
|
377
|
-
// leaving a bare `uint8` behind -- which is exactly the capture
|
|
378
|
-
// the sigil exists to prevent. Claiming it here, before that
|
|
379
|
-
// ender runs, keeps the name one lexeme.
|
|
380
|
-
//
|
|
381
|
-
// The token's SOURCE is the whole `%name`, which is what makes
|
|
382
|
-
// the same lexeme work in both positions: jsonic keys a pair by
|
|
383
|
-
// the token's source text (`0d1: 5` yields the key `0d1`), so a
|
|
384
|
-
// declaration reads as the key `%uint8`, while a value position
|
|
385
|
-
// calls the function below and gets the reference.
|
|
386
|
-
// A `%` that opens no name (`%`, `%1`, `50%`) falls through to
|
|
387
|
-
// the bare-text scan below, which refuses it.
|
|
388
216
|
const ares = CC_PCT === src.charCodeAt(pnt.sI) ?
|
|
389
217
|
ALIAS_RE.exec(lex.refwd()) : null;
|
|
390
218
|
if (null != ares) {
|
|
391
219
|
const asrc = ares[0];
|
|
392
|
-
// A lone `=` after the name, across horizontal space only, is
|
|
393
|
-
// the declaration operator. Decided HERE, where the name is
|
|
394
|
-
// claimed, and only its position is kept: the very next text
|
|
395
|
-
// position is that `=`, since nothing but space sits between,
|
|
396
|
-
// so the mark cannot outlive its one use. `==` is not it.
|
|
397
220
|
let j = pnt.sI + asrc.length;
|
|
398
221
|
while (j < src.length &&
|
|
399
222
|
(CC_SP === src.charCodeAt(j) || CC_TAB === src.charCodeAt(j))) {
|
|
@@ -402,24 +225,11 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
402
225
|
if (CC_EQ === src.charCodeAt(j) && CC_EQ !== src.charCodeAt(j + 1)) {
|
|
403
226
|
lex.aontu_eq_at = j;
|
|
404
227
|
}
|
|
405
|
-
const atkn = lex.token('#VL',
|
|
406
|
-
// AN ALIAS REFERENCE IS A PATH REFERENCE. `%uint8` is
|
|
407
|
-
// `$.%uint8`: root-absolute, one segment, spelled with the
|
|
408
|
-
// sigil the declaration is spelled with. Everything the
|
|
409
|
-
// design asks of it -- order independence, alias-of-alias,
|
|
410
|
-
// redeclaration unifying, cycle refusal spanning both
|
|
411
|
-
// namespaces -- is then the reference machinery already in
|
|
412
|
-
// the language, not a second resolver beside it.
|
|
413
|
-
(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);
|
|
414
229
|
pnt.sI += asrc.length;
|
|
415
230
|
pnt.cI += asrc.length;
|
|
416
231
|
return { done: true, token: atkn };
|
|
417
232
|
}
|
|
418
|
-
// The `=` the alias arm above marked: the separator of a
|
|
419
|
-
// declaration, as a colon token whose source is `=`. The pair rule
|
|
420
|
-
// is then the pair rule, and the formatter writes the spelling it
|
|
421
|
-
// read. Marked in `use` so the pair rule can tell it from a colon,
|
|
422
|
-
// which no longer declares.
|
|
423
233
|
if (CC_EQ === src.charCodeAt(pnt.sI) && lex.aontu_eq_at === pnt.sI) {
|
|
424
234
|
delete lex.aontu_eq_at;
|
|
425
235
|
const eqtkn = lex.token('#CL', undefined, '=', pnt, { aontu_eq: true });
|
|
@@ -430,18 +240,9 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
430
240
|
if (CC_0 === src.charCodeAt(pnt.sI)) {
|
|
431
241
|
const c1 = src.charCodeAt(pnt.sI + 1);
|
|
432
242
|
if (CC_d === c1 || CC_D === c1) {
|
|
433
|
-
// BIG_LITERAL_RE is `^`-anchored and read against the
|
|
434
|
-
// forward source (memoized per position by refwd), which is
|
|
435
|
-
// what lets it claim the `.` of `0d1.5`. A `0d` run it does
|
|
436
|
-
// not match falls through to the bare-text scan below.
|
|
437
243
|
const res = Decimal_1.BIG_LITERAL_RE.exec(lex.refwd());
|
|
438
244
|
if (null != res) {
|
|
439
245
|
const msrc = res[0];
|
|
440
|
-
// The token value is a FUNCTION so Val construction
|
|
441
|
-
// happens at parse time, where the rule and context needed
|
|
442
|
-
// for the site exist (jsonic calls a #VL token's function
|
|
443
|
-
// value with them). A `0d` literal never spans a line, so
|
|
444
|
-
// only the source and column positions advance.
|
|
445
246
|
const tkn = lex.token('#VL', (r, ctx) => addsite(bigVal(res), r, ctx), msrc, pnt);
|
|
446
247
|
pnt.sI += msrc.length;
|
|
447
248
|
pnt.cI += msrc.length;
|
|
@@ -449,21 +250,9 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
449
250
|
}
|
|
450
251
|
}
|
|
451
252
|
}
|
|
452
|
-
// THE BARE-TEXT RULE (scanBareRun). Last, so that a name, a
|
|
453
|
-
// declaration operator and an exact literal are read before a
|
|
454
|
-
// run is judged as text.
|
|
455
|
-
// The run is never empty: every ender is a token an earlier
|
|
456
|
-
// matcher claims, so the text stage only opens on a character
|
|
457
|
-
// the scan classifies as text or as bad.
|
|
458
253
|
const run = scanBareRun(lex.cfg, src, pnt.sI, false);
|
|
459
254
|
const msrc = src.slice(pnt.sI, run.end);
|
|
460
255
|
if (-1 !== run.bad) {
|
|
461
|
-
// BAD: the run is refused whole, sited at the character (the
|
|
462
|
-
// mark in `use` is what tokenSite reads). As a VALUE the
|
|
463
|
-
// token's function builds the refusal at the parse, where the
|
|
464
|
-
// rule carries the position. As a KEY the token is read for
|
|
465
|
-
// its source alone, so the mark is what the pair and elem
|
|
466
|
-
// rules read to write the refusal where the map is built.
|
|
467
256
|
const ch = run.ch;
|
|
468
257
|
const tkn = lex.token('#VL', (r, ctx) => {
|
|
469
258
|
const nv = addsite(new NilVal_1.NilVal({ why: 'bare_punct' }), r, ctx);
|
|
@@ -474,11 +263,6 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
474
263
|
pnt.cI += msrc.length;
|
|
475
264
|
return { done: true, token: tkn };
|
|
476
265
|
}
|
|
477
|
-
// CLEAN, with a `-` past its start (`team-payments`,
|
|
478
|
-
// `2026-09-05`): claimed here as one text token, because the
|
|
479
|
-
// default matcher's ender set would carve the run at the `-`.
|
|
480
|
-
// Any other clean run is the default matcher's, which also reads
|
|
481
|
-
// the value keywords and the `_` hole.
|
|
482
266
|
if (-1 !== msrc.indexOf('-')) {
|
|
483
267
|
const tkn = lex.token('#TX', msrc, msrc, pnt);
|
|
484
268
|
pnt.sI += msrc.length;
|
|
@@ -516,14 +300,6 @@ let AontuJsonic = function AontuLang(jsonic) {
|
|
|
516
300
|
v.path = r.k ? [...r.k.path] : [];
|
|
517
301
|
return v;
|
|
518
302
|
};
|
|
519
|
-
// THE KEY REFUSALS a pair may carry, decided from its key TOKEN --
|
|
520
|
-
// never from the key text alone, since a quoted `"%a"` or `"x=y"` is
|
|
521
|
-
// an ordinary key: a declaration spelled with a colon (alias_colon),
|
|
522
|
-
// and a key the bare-text rule refuses (bare_punct). Undefined for an
|
|
523
|
-
// ordinary key, and for a declaration (`%a = 1`), which is a binding
|
|
524
|
-
// (isAliasDecl), not a refusal. Asked FIRST by the pair rule and by
|
|
525
|
-
// the elem rule, before the declaration is, so a pair in list
|
|
526
|
-
// position is held to the map's rules.
|
|
527
303
|
const isAliasDecl = (ktkn, sep) => null != ktkn && VL === ktkn.tin && ALIAS_RE.test('' + ktkn.src) &&
|
|
528
304
|
true === sep?.use?.aontu_eq;
|
|
529
305
|
const keyRefusalOf = (ktkn, sep) => {
|
|
@@ -562,10 +338,6 @@ help isolate the syntax error.`,
|
|
|
562
338
|
},
|
|
563
339
|
value: {
|
|
564
340
|
def: {
|
|
565
|
-
// NOTE: specify with functions as jsonic/deep will
|
|
566
|
-
// remove class prototype as options are assumed plain
|
|
567
|
-
// (except for functions).
|
|
568
|
-
// TODO: jsonic should be able to pass context into these
|
|
569
341
|
'string': {
|
|
570
342
|
val: (r, ctx) => addsite(new ScalarKindVal_1.ScalarKindVal({ peg: String }), r, ctx)
|
|
571
343
|
},
|
|
@@ -581,8 +353,6 @@ help isolate the syntax error.`,
|
|
|
581
353
|
'float': {
|
|
582
354
|
val: (r, ctx) => addsite(new ScalarKindVal_1.ScalarKindVal({ peg: ScalarKindVal_1.Float }), r, ctx)
|
|
583
355
|
},
|
|
584
|
-
// The two exact leaves. Their keywords are the marker class
|
|
585
|
-
// names lowercased, which is also how ScalarKindVal canons them.
|
|
586
356
|
'biginteger': {
|
|
587
357
|
val: (r, ctx) => addsite(new ScalarKindVal_1.ScalarKindVal({ peg: ScalarKindVal_1.BigInteger }), r, ctx)
|
|
588
358
|
},
|
|
@@ -595,7 +365,6 @@ help isolate the syntax error.`,
|
|
|
595
365
|
'nil': {
|
|
596
366
|
val: (r, ctx) => addsite(new NilVal_1.NilVal({ why: 'literal_nil' }), r, ctx)
|
|
597
367
|
},
|
|
598
|
-
// TODO: FIX: need a TOP instance to hold path
|
|
599
368
|
'top': { val: () => (0, top_1.top)() },
|
|
600
369
|
// G8 phase 3: the placeholder. A BARE `_` is the hole; `"_"`
|
|
601
370
|
// quoted, and any longer bare word containing it, stay text.
|
|
@@ -610,7 +379,6 @@ help isolate the syntax error.`,
|
|
|
610
379
|
let pval = prev;
|
|
611
380
|
let cval = curr;
|
|
612
381
|
if (pval?.isVal && cval?.isVal) {
|
|
613
|
-
// TODO: test multi element conjuncts work
|
|
614
382
|
if (pval.isConjunct && cval.isConjunct) {
|
|
615
383
|
pval.append(cval);
|
|
616
384
|
return pval;
|
|
@@ -626,14 +394,6 @@ help isolate the syntax error.`,
|
|
|
626
394
|
// Handle defered conjuncts, where MapVal does not yet
|
|
627
395
|
// exist, by creating ConjunctVal later.
|
|
628
396
|
else {
|
|
629
|
-
// AN INCLUDE UNIFIES IN PLACE. multisource calls this hook at
|
|
630
|
-
// the `@`'s own source position, so `prev` holds exactly the
|
|
631
|
-
// pairs written BEFORE it. Folding the loaded map's keys in
|
|
632
|
-
// here -- host-so-far first, arriving value second -- is what
|
|
633
|
-
// inlining the loaded bytes at the `@` does, and mirrors
|
|
634
|
-
// go/lang.go's Map.Merge, which multisource-go drives one key
|
|
635
|
-
// at a time. A non-map load has no keys to fold and stays a
|
|
636
|
-
// deferred conjunct arm.
|
|
637
397
|
if (true === cval?.isMap) {
|
|
638
398
|
const lm = cval;
|
|
639
399
|
for (const k of Object.keys(lm.peg)) {
|
|
@@ -643,10 +403,6 @@ help isolate the syntax error.`,
|
|
|
643
403
|
? new ConjunctVal_1.ConjunctVal({ peg: [own, lm.peg[k]] })
|
|
644
404
|
: lm.peg[k]);
|
|
645
405
|
}
|
|
646
|
-
// The loaded map's spread joins THIS map's spread list at
|
|
647
|
-
// the `@`'s position: the parse pushes each `&:` onto the
|
|
648
|
-
// node as it is read, so `prev[SPREAD].v` already holds the
|
|
649
|
-
// spreads written before the `@` and nothing after it.
|
|
650
406
|
if (null != lm.spread?.cj) {
|
|
651
407
|
;
|
|
652
408
|
prev[type_1.SPREAD] =
|
|
@@ -680,20 +436,11 @@ help isolate the syntax error.`,
|
|
|
680
436
|
move: MoveFuncVal_1.MoveFuncVal,
|
|
681
437
|
path: PathFuncVal_1.PathFuncVal,
|
|
682
438
|
pref: PrefFuncVal_1.PrefFuncVal,
|
|
683
|
-
// First-class paths and the container kinds
|
|
684
|
-
// (docs/design/PATHS.0.md). `path(p)` CAPTURES a path as a value;
|
|
685
|
-
// `path()`, `map()` and `list()` are kinds -- the vacuous
|
|
686
|
-
// constructor call admits its values and defaults to nothing,
|
|
687
|
-
// where the container LITERALS `{}`/`[]` default to empty.
|
|
688
439
|
map: ContainerKindVal_1.MapFuncVal,
|
|
689
440
|
list: ContainerKindVal_1.ListFuncVal,
|
|
690
441
|
close: CloseFuncVal_1.CloseFuncVal,
|
|
691
442
|
open: OpenFuncVal_1.OpenFuncVal,
|
|
692
443
|
super: SuperFuncVal_1.SuperFuncVal,
|
|
693
|
-
// The constraint algebra's Band A atoms (G1 phase 1;
|
|
694
|
-
// docs/reference-language.md, "The constraint algebra"): bounds
|
|
695
|
-
// and exclusion enter through the function registry — the
|
|
696
|
-
// established extension point — with zero grammar change.
|
|
697
444
|
min: ConstraintVal_1.MinConstraintVal,
|
|
698
445
|
max: ConstraintVal_1.MaxConstraintVal,
|
|
699
446
|
above: ConstraintVal_1.AboveConstraintVal,
|
|
@@ -702,25 +449,15 @@ help isolate the syntax error.`,
|
|
|
702
449
|
// G1 phase 2: pattern membership, over the portable subset both
|
|
703
450
|
// host regex engines agree on (nonPortableRe in ConstraintVal.ts).
|
|
704
451
|
re: ConstraintVal_1.ReConstraintVal,
|
|
705
|
-
// G1 phase 3: the sizing atoms. Both are properties of a CONTAINER
|
|
706
|
-
// (or, for length, of a string) rather than comparisons against a
|
|
707
|
-
// value, which is why `unique` is the one built-in taking no
|
|
708
|
-
// argument at all.
|
|
709
452
|
length: ConstraintVal_1.LengthConstraintVal,
|
|
710
453
|
unique: ConstraintVal_1.UniqueConstraintVal,
|
|
711
|
-
// G1 phase 5: Band B. `must` is the one atom the algebra does not
|
|
712
|
-
// reason about -- it is checked against the finished value and
|
|
713
|
-
// reported with the author's own message, never simplified and
|
|
714
|
-
// never consulted for emptiness or subsumption.
|
|
715
454
|
must: ConstraintVal_1.MustConstraintVal,
|
|
455
|
+
abnf: AbnfFuncVal_1.AbnfFuncVal,
|
|
456
|
+
parse: AbnfFuncVal_1.ParseFuncVal,
|
|
716
457
|
// G3 phase 4: the deprecation mark. Unification-transparent; the
|
|
717
458
|
// record rides the result (Val.deprecation) and canon renders the
|
|
718
459
|
// call back (canonRiders).
|
|
719
460
|
deprecate: DeprecateFuncVal_1.DeprecateFuncVal,
|
|
720
|
-
// G4 phase 2: the checked, typed, LINK-shaped reference. A
|
|
721
|
-
// constraint on a string field: the string must be a TREE ADDRESS
|
|
722
|
-
// (`$.a.b` or `.b`), the address must resolve, and the optional
|
|
723
|
-
// argument flows INTO the target. The field keeps the string.
|
|
724
461
|
refer: ReferFuncVal_1.ReferFuncVal,
|
|
725
462
|
rel: ReferFuncVal_1.RelFuncVal,
|
|
726
463
|
// RELATIONS P2 (docs/design/RELATIONS.0.md §3.3): the graph
|
|
@@ -728,78 +465,32 @@ help isolate the syntax error.`,
|
|
|
728
465
|
// govern. Lattice-inert; the verdict lands at generation.
|
|
729
466
|
acyclic: GraphAtomVal_1.AcyclicFuncVal,
|
|
730
467
|
inverse: GraphAtomVal_1.InverseFuncVal,
|
|
731
|
-
// G8 phase 1: the generation combinators. `pack` makes one keyed
|
|
732
|
-
// child per child of its data, `each` one list element; both clone
|
|
733
|
-
// their template per destination exactly as a spread does, and both
|
|
734
|
-
// wait for the model to settle before they fire (the staging rule,
|
|
735
|
-
// G8 phase 0).
|
|
736
468
|
pack: PackFuncVal_1.PackFuncVal,
|
|
737
469
|
each: EachFuncVal_1.EachFuncVal,
|
|
738
|
-
// RENDER P6: the order-preserving map. `form` makes one list
|
|
739
|
-
// element per child of its data, being the template with `_`
|
|
740
|
-
// bound to the source child -- a construction, where `each` is a
|
|
741
|
-
// bound (G9 §4). It exists because `pick(pack(...))` re-sorts to
|
|
742
|
-
// code-point order, and a struct's fields or a file's imports
|
|
743
|
-
// are the model's order or they are wrong.
|
|
744
|
-
form: FormFuncVal_1.FormFuncVal,
|
|
745
|
-
// G8 phase 2: selection. `filter` keeps the children of a bag that
|
|
746
|
-
// unify with a condition; `match` picks the first arm whose
|
|
747
|
-
// pattern the scrutinee unifies with. Both select by
|
|
748
|
-
// UNIFIABILITY, tried in trial mode, so neither adds a predicate
|
|
749
|
-
// language to the one the lattice already is.
|
|
750
470
|
filter: FilterFuncVal_1.FilterFuncVal,
|
|
751
471
|
match: MatchFuncVal_1.MatchFuncVal,
|
|
752
|
-
// The arithmetic family (the review's finding I). Maths beyond `+`
|
|
753
|
-
// arrives as FUNCTIONS — `-` `*` `/` `%` stay reserved — and the
|
|
754
|
-
// family is numeric where the operator is polymorphic, which is
|
|
755
|
-
// what makes `add` more than a second spelling of `+`: it refuses
|
|
756
|
-
// the string concatenation that silently answers `"500m" + "500m"`.
|
|
757
|
-
// Every rule they obey is in ts/src/val/arith.ts.
|
|
758
472
|
add: ArithFuncVal_1.AddFuncVal,
|
|
759
473
|
sub: ArithFuncVal_1.SubFuncVal,
|
|
760
474
|
mul: ArithFuncVal_1.MulFuncVal,
|
|
761
475
|
div: ArithFuncVal_1.DivFuncVal,
|
|
762
476
|
mod: ArithFuncVal_1.ModFuncVal,
|
|
763
477
|
rem: ArithFuncVal_1.RemFuncVal,
|
|
764
|
-
// Aggregation over a finite, settled bag (the review's finding I).
|
|
765
|
-
// `least` and `greatest` rather than min and max, which are already
|
|
766
|
-
// the atoms for a lower and an upper BOUND -- an aggregate over a
|
|
767
|
-
// set and a bound on a value must not share a spelling.
|
|
768
478
|
sum: AggFuncVal_1.SumFuncVal,
|
|
769
479
|
least: AggFuncVal_1.LeastFuncVal,
|
|
770
480
|
greatest: AggFuncVal_1.GreatestFuncVal,
|
|
771
|
-
|
|
772
|
-
// RECORDS: `sum(pick($.lines, amountCents))`. Not a clever `each`
|
|
773
|
-
// template -- `each` MEETS each child, and a meet cannot select.
|
|
481
|
+
maybe: MaybeFuncVal_1.MaybeFuncVal,
|
|
774
482
|
pick: AggFuncVal_1.PickFuncVal,
|
|
775
|
-
|
|
776
|
-
// folds with `+`, so it inherits the one number-to-text rule and
|
|
777
|
-
// the language does not grow a second. It is the primitive that
|
|
778
|
-
// turns a bag of computed lines into a file.
|
|
483
|
+
sort: AggFuncVal_1.SortFuncVal,
|
|
779
484
|
join: AggFuncVal_1.JoinFuncVal,
|
|
780
|
-
// G9 phase 6: apply-templates. One flat list of pieces from a
|
|
781
|
-
// selection and a RULE TABLE -- for each node, the first template
|
|
782
|
-
// whose `match` it unifies with, its `body` instantiated at that
|
|
783
|
-
// node. The dispatch is the engine's because a body referenced by
|
|
784
|
-
// path resolves its references at the definition site, and the
|
|
785
|
-
// relative resolution that does exist is a dot count that does not
|
|
786
|
-
// survive a second dispatch (docs/design/EMIT.0.md).
|
|
787
485
|
emit: EmitFuncVal_1.EmitFuncVal,
|
|
788
|
-
// G9 phase 6: the string builtins the rule layer needs. `esc`
|
|
789
|
-
// makes a value safe inside a literal and `usc` reads it back;
|
|
790
|
-
// `rep` and `split` derive names from model data. All four are
|
|
791
|
-
// ordinary string functions -- they know nothing about generation,
|
|
792
|
-
// which is why they can land before the renderer does.
|
|
793
486
|
esc: StrFuncVal_1.EscFuncVal,
|
|
794
487
|
usc: StrFuncVal_1.UscFuncVal,
|
|
795
488
|
rep: StrFuncVal_1.RepFuncVal,
|
|
796
489
|
split: StrFuncVal_1.SplitFuncVal,
|
|
490
|
+
...CmpFuncVal_1.CMP_FUNCS,
|
|
491
|
+
nom: NomFuncVal_1.NomFuncVal,
|
|
492
|
+
translate: TranslateFuncVal_1.TranslateFuncVal,
|
|
797
493
|
};
|
|
798
|
-
// A dangling operator (`a:1|`, `a:$`, `a:*` at end of input) leaves
|
|
799
|
-
// null/undefined unfilled terms. Junction ops drop them (so `a:1&`
|
|
800
|
-
// and `a:1|` are just 1); ops missing a required operand become an
|
|
801
|
-
// incomplete_expression nil, surfaced by generate() as a "Cannot
|
|
802
|
-
// resolve value" error (the Go port mirrors this in lang.go).
|
|
803
494
|
const dropUnfilled = (terms) => terms.filter((t) => null != t);
|
|
804
495
|
const incompleteNil = (r, ctx) => addsite(new NilVal_1.NilVal({ why: 'incomplete_expression' }), r, ctx);
|
|
805
496
|
// Build a call from a NAME and the argument terms as the author
|
|
@@ -807,27 +498,10 @@ help isolate the syntax error.`,
|
|
|
807
498
|
// raw-value conversion, stated once.
|
|
808
499
|
const buildCall = (r, ctx, fname, argterms) => {
|
|
809
500
|
const funcval = funcMap[fname];
|
|
810
|
-
// Arity is known for every built-in, so a surplus or missing
|
|
811
|
-
// argument is a mistake in the SOURCE, refused here where the
|
|
812
|
-
// author can see it (issue #51). It was previously left to each
|
|
813
|
-
// function to notice or not: the two ports disagreed on `upper()`
|
|
814
|
-
// and on `close()`, and `min(1,2)` noticed nothing at all -- it
|
|
815
|
-
// built a constraint that merely refused to generate later, with a
|
|
816
|
-
// message about the map rather than about the call.
|
|
817
|
-
//
|
|
818
|
-
// Counted BEFORE the rawToVal pass below, which is what makes the
|
|
819
|
-
// count possible: a comma group arrives as a RAW array and a
|
|
820
|
-
// written list literal as a ListVal, and rawToVal turns the first
|
|
821
|
-
// into the second.
|
|
822
501
|
const arity = funcArity[fname];
|
|
823
502
|
if (null != arity) {
|
|
824
503
|
const got = writtenArgCount(argterms);
|
|
825
504
|
if (got < arity[0] || (-1 !== arity[1] && got > arity[1])) {
|
|
826
|
-
// details is assigned AFTER construction: the NilVal
|
|
827
|
-
// constructor does not read it from its spec (only NilVal.make
|
|
828
|
-
// does), so passing it in the spec left the hint's
|
|
829
|
-
// {func}/{want}/{got} placeholders un-injected and printed
|
|
830
|
-
// literally.
|
|
831
505
|
const nil = new NilVal_1.NilVal({ why: 'func_arity' });
|
|
832
506
|
nil.details = {
|
|
833
507
|
func: fname,
|
|
@@ -837,22 +511,6 @@ help isolate the syntax error.`,
|
|
|
837
511
|
return addsite(nil, r, ctx);
|
|
838
512
|
}
|
|
839
513
|
}
|
|
840
|
-
// rawToVal EVERY argument. A degenerate expression can hand this
|
|
841
|
-
// handler raw parse values rather than Vals -- `pref(1-3)` arrives
|
|
842
|
-
// as the plain numbers 1 and -3 -- and a func's peg is unified
|
|
843
|
-
// element by element, so a raw one reached `arg.unify(...)` and
|
|
844
|
-
// threw. The unifier's catch-all turned that into an `internal`
|
|
845
|
-
// verdict: a crash reported as a unification result (issue #49).
|
|
846
|
-
// The Go port has always converted here (asVal in evaluate).
|
|
847
|
-
// A comma group is ONE raw-array term (see writtenArgCount).
|
|
848
|
-
// For a function whose arguments are distinct POSITIONS —
|
|
849
|
-
// deprecate's value and record, pack's and each's data and template
|
|
850
|
-
// — the group is expanded back into them here, while a written list
|
|
851
|
-
// literal, already a ListVal, stays one argument. The constraint
|
|
852
|
-
// atoms make the same move in their own constructor (atomArgs,
|
|
853
|
-
// ConstraintVal.ts), which is why they are not in this set:
|
|
854
|
-
// `neq(1,2)` is one argument LIST, not two positions, and expanding
|
|
855
|
-
// it here would take the list away from the code that reads it.
|
|
856
514
|
let terms = argterms;
|
|
857
515
|
if (true === POSITIONAL_ARG_FUNCS[fname] && 1 === terms.length &&
|
|
858
516
|
Array.isArray(terms[0])) {
|
|
@@ -875,24 +533,6 @@ help isolate the syntax error.`,
|
|
|
875
533
|
'star-prefix': (r, ctx, _op, terms) => {
|
|
876
534
|
if (null == terms[0])
|
|
877
535
|
return incompleteNil(r, ctx);
|
|
878
|
-
// A PREFERENCE MARKS A VALUE, AND A BARE KEY IS NOT ONE.
|
|
879
|
-
// `*a: 1` has no braces, so the prefix took the whole IMPLICIT
|
|
880
|
-
// map as its operand and the document silently became
|
|
881
|
-
// `*{"a":1}` -- `*a: 1, b: 2` became a one-element LIST, losing
|
|
882
|
-
// `b` outright. Neither is anything the author wrote.
|
|
883
|
-
//
|
|
884
|
-
// The accident is confined to the first position of the implicit
|
|
885
|
-
// top-level map, which is the only place no brace has yet
|
|
886
|
-
// committed the rule to a map: `{*a: 1}` and `a: 1, *b: 2` are
|
|
887
|
-
// ALREADY parse errors. This makes the third spelling agree with
|
|
888
|
-
// them rather than inventing a meaning for it.
|
|
889
|
-
//
|
|
890
|
-
// A BRACED operand is untouched, and that is the whole of the
|
|
891
|
-
// distinction: `*{x:1}` and `*[1]` are the real spelling, they
|
|
892
|
-
// are what `*{x:1} | *{y:2}` needs, and the shared spec pins them
|
|
893
|
-
// (11 rows). The open token's own source text is what separates
|
|
894
|
-
// the two -- `{` or `[` for a braced bag, the first key or
|
|
895
|
-
// element for an implicit one.
|
|
896
536
|
const bag = terms[0];
|
|
897
537
|
if ((bag.isMap && '{' !== bag.site.src) ||
|
|
898
538
|
(bag.isList && '[' !== bag.site.src)) {
|
|
@@ -916,7 +556,6 @@ help isolate the syntax error.`,
|
|
|
916
556
|
terms[0].peg.some((seg) => 'string' === typeof seg && ALIAS_RE.test(seg))) {
|
|
917
557
|
return addsite(new NilVal_1.NilVal({ why: 'alias_in_path' }), r, ctx);
|
|
918
558
|
}
|
|
919
|
-
// $.a.b absolute path
|
|
920
559
|
if (terms[0] instanceof RefVal_1.RefVal) {
|
|
921
560
|
terms[0].absolute = true;
|
|
922
561
|
return terms[0];
|
|
@@ -932,10 +571,6 @@ help isolate the syntax error.`,
|
|
|
932
571
|
let val = terms[0];
|
|
933
572
|
if (null == val)
|
|
934
573
|
return incompleteNil(r, ctx);
|
|
935
|
-
// The exact leaves negate exactly and never change kind. R2/D5
|
|
936
|
-
// holds here too: bigint has a single zero, and Decimal's
|
|
937
|
-
// normalising constructor sends every zero to the same form, so
|
|
938
|
-
// `-0d0` is `0d0` and `-0d0.0` is `0d0.0`.
|
|
939
574
|
if (val instanceof BigIntegerVal_1.BigIntegerVal) {
|
|
940
575
|
return addsite(new BigIntegerVal_1.BigIntegerVal({ peg: -val.peg, src: negsrc(val.src) }), r, ctx);
|
|
941
576
|
}
|
|
@@ -947,18 +582,10 @@ help isolate the syntax error.`,
|
|
|
947
582
|
if (!(val instanceof IntegerVal_1.IntegerVal) && !(val instanceof NumberVal_1.NumberVal)) {
|
|
948
583
|
return addsite(new NilVal_1.NilVal({ why: 'negative' }), r, ctx);
|
|
949
584
|
}
|
|
950
|
-
// Build a fresh Val rather than mutating in place: the expr plugin
|
|
951
|
-
// can evaluate the same node twice (e.g. inside `*-1` or a
|
|
952
|
-
// disjunct member), and an in-place `peg = -peg` applied twice
|
|
953
|
-
// silently un-negates the number.
|
|
954
585
|
let peg = -1 * val.peg;
|
|
955
586
|
// Normalize -0 to 0 (keeps the AST and canon free of negative zero).
|
|
956
587
|
if (0 === peg)
|
|
957
588
|
peg = 0;
|
|
958
|
-
// Negation never narrows the kind: a number stays a number. An
|
|
959
|
-
// integer stays an integer unless the negation leaves the int64
|
|
960
|
-
// range (only -(-2^63), which no literal can express), in which
|
|
961
|
-
// case it widens to a number rather than failing.
|
|
962
589
|
const out = val instanceof IntegerVal_1.IntegerVal && (0, numkind_1.isIntegerKind)(peg)
|
|
963
590
|
? new IntegerVal_1.IntegerVal({ peg })
|
|
964
591
|
: new NumberVal_1.NumberVal({ peg });
|
|
@@ -990,7 +617,6 @@ help isolate the syntax error.`,
|
|
|
990
617
|
jsonic
|
|
991
618
|
.use(asPlugin(expr_1.Expr), {
|
|
992
619
|
op: {
|
|
993
|
-
// disjunct < conjunct: c & b | a -> (c & b) | a
|
|
994
620
|
'conjunct': {
|
|
995
621
|
infix: true, src: '&', left: 16_000_000, right: 17_000_000
|
|
996
622
|
},
|
|
@@ -1003,16 +629,6 @@ help isolate the syntax error.`,
|
|
|
1003
629
|
left: 20_000_000,
|
|
1004
630
|
right: 21_000_000,
|
|
1005
631
|
},
|
|
1006
|
-
// Re-base the unary prefixes for the same reason. Every aontu
|
|
1007
|
-
// operator sits far above the @tabnas/expr defaults, so the
|
|
1008
|
-
// default prefix binding power of 4_000_000 left unary `-`/`+`
|
|
1009
|
-
// LOOSER than every infix operator: `-1 & integer` parsed as
|
|
1010
|
-
// `-(1 & integer)`, and negative-prefix (below) then rejected
|
|
1011
|
-
// the composite operand as a `negative` error nil (likewise
|
|
1012
|
-
// `-2+3`, `-1|2`). Unary minus must bind tighter than `+`, `&`
|
|
1013
|
-
// and `|` — but still looser than `.` (dot-infix left is
|
|
1014
|
-
// 25_000_000), so `-0xFF.5` stays `-(0xFF.5)` and `$`.
|
|
1015
|
-
// Kept in lock-step with the op table in go/lang.go.
|
|
1016
632
|
'negative': {
|
|
1017
633
|
src: '-',
|
|
1018
634
|
prefix: true,
|
|
@@ -1061,15 +677,11 @@ help isolate the syntax error.`,
|
|
|
1061
677
|
remainder: null,
|
|
1062
678
|
},
|
|
1063
679
|
evaluate: (r, ctx, op, terms) => {
|
|
1064
|
-
// // console.log('EVAL-START', r.u)
|
|
1065
680
|
if ('func-paren' === op.name
|
|
1066
|
-
// && !r.parent.prev?.u?.paren_preval
|
|
1067
681
|
&& !r.u?.paren_preval) {
|
|
1068
|
-
// terms = [new StringVal({ peg: '' }), ...terms]
|
|
1069
682
|
terms = ['', ...terms];
|
|
1070
683
|
}
|
|
1071
684
|
let val = opmap[op.name](r, ctx, op, terms);
|
|
1072
|
-
// // console.log('EVAL', terms, '->', val)
|
|
1073
685
|
return val;
|
|
1074
686
|
}
|
|
1075
687
|
});
|
|
@@ -1083,16 +695,6 @@ help isolate the syntax error.`,
|
|
|
1083
695
|
const OPTKEY = [TX, ST, NR];
|
|
1084
696
|
jsonic.rule('expr', (rs) => {
|
|
1085
697
|
rs.close([
|
|
1086
|
-
// A `&` followed by `:` after an expression value belongs to the
|
|
1087
|
-
// enclosing map as a spread, not to the expression as a conjunct
|
|
1088
|
-
// — backtrack both tokens so the expression completes (and
|
|
1089
|
-
// evaluates to a Val) and the map's spread alts take over. This
|
|
1090
|
-
// is what makes `k1:$flag &:boolean` parse: without it the expr
|
|
1091
|
-
// plugin consumes the `&` as an infix conjunct, chokes on the
|
|
1092
|
-
// `:`, and leaves the raw unevaluated expr node in the map
|
|
1093
|
-
// (mirrors the expr-rule PrependClose in go/lang.go). The
|
|
1094
|
-
// `n: { expr: 0 }` reset matches the plugin's own expr-end alts —
|
|
1095
|
-
// the evaluation after-close only fires when the counter is 0.
|
|
1096
698
|
{ s: [CJ, CL], b: 2, n: { expr: 0 }, g: 'expr,expr-end,spread' },
|
|
1097
699
|
]);
|
|
1098
700
|
return rs;
|
|
@@ -1139,18 +741,6 @@ help isolate the syntax error.`,
|
|
|
1139
741
|
if (!Number.isFinite(r.node)) {
|
|
1140
742
|
valnode = addsite(new NilVal_1.NilVal({ why: 'not_number' }), r, ctx);
|
|
1141
743
|
}
|
|
1142
|
-
// D7 -- A LOSSY INTEGER LITERAL IS REFUSED, NOT ROUNDED. The
|
|
1143
|
-
// token above is already a double, so a literal the double
|
|
1144
|
-
// cannot hold exactly (2^53+1, 0x7fffffffffffffff,
|
|
1145
|
-
// 0xffffffffffffffff) has ALREADY become a different number by
|
|
1146
|
-
// the time it gets here. Storing it would mean the document
|
|
1147
|
-
// silently means something other than what it says, so the
|
|
1148
|
-
// literal becomes a located error whose hint names the escape:
|
|
1149
|
-
// write it `0d…` and get the exact value.
|
|
1150
|
-
//
|
|
1151
|
-
// The rule is EXACTNESS, not magnitude -- 10^20 and 2^124 are
|
|
1152
|
-
// both far outside the int64 window and both land exactly on a
|
|
1153
|
-
// binary64, so both stay values (see isLossyIntegerLiteral).
|
|
1154
744
|
else if ((0, numkind_1.isLossyIntegerLiteral)(r.node, r.o0.src)) {
|
|
1155
745
|
const nil = new NilVal_1.NilVal({ why: 'lossy_integer_literal' });
|
|
1156
746
|
nil.details = { src: r.o0.src };
|
|
@@ -1194,15 +784,6 @@ help isolate the syntax error.`,
|
|
|
1194
784
|
const optionalKeys = r.u.aontu_optional_keys ?? [];
|
|
1195
785
|
const aliasKeys = r.u.aontu_alias_keys ?? [];
|
|
1196
786
|
let mo = r.node;
|
|
1197
|
-
// An elided value (`a:`) leaves a raw null/undefined that never
|
|
1198
|
-
// passed through the val rule. It is REFUSED rather than made a
|
|
1199
|
-
// null (issue #48): a key with nothing after the colon is a
|
|
1200
|
-
// mistake in the source, and turning it into a value made that
|
|
1201
|
-
// mistake indistinguishable from a deliberate `a:null`.
|
|
1202
|
-
//
|
|
1203
|
-
// A colon chain (`a: b:1`) is not an elision -- the value is the
|
|
1204
|
-
// nested pair, which the val rule does produce -- and neither is
|
|
1205
|
-
// a trailing comma.
|
|
1206
787
|
for (const k in mo) {
|
|
1207
788
|
if (null == mo[k] && '___merge' !== k &&
|
|
1208
789
|
'___optional' !== k && '___alias' !== k) {
|
|
@@ -1213,45 +794,22 @@ help isolate the syntax error.`,
|
|
|
1213
794
|
const en = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
1214
795
|
en.path = [...(r.k?.path ?? []), k];
|
|
1215
796
|
mo[k] = en;
|
|
1216
|
-
// An elided value under an OPTIONAL key stops being optional.
|
|
1217
|
-
// Optionality is about a value that may be absent at
|
|
1218
|
-
// GENERATE; it does not excuse a source that stops after the
|
|
1219
|
-
// colon. Left optional, the refusal was dropped with the key
|
|
1220
|
-
// and `a?:` generated `{}` -- a silent nothing, which is
|
|
1221
|
-
// worse than either the old null or the error.
|
|
1222
797
|
const oi = optionalKeys.indexOf(k);
|
|
1223
798
|
if (-1 !== oi) {
|
|
1224
799
|
optionalKeys.splice(oi, 1);
|
|
1225
800
|
}
|
|
1226
801
|
}
|
|
1227
802
|
}
|
|
1228
|
-
// ... and the OPTIONAL spelling, `a?:`, which does not leave a
|
|
1229
|
-
// null behind to be found: its value never reaches the node at
|
|
1230
|
-
// all, so the key is simply absent and the map generated without
|
|
1231
|
-
// it. A key recorded as optional but missing from the node was
|
|
1232
|
-
// written with nothing after its colon.
|
|
1233
803
|
for (const k of optionalKeys) {
|
|
1234
804
|
if (!(k in mo)) {
|
|
1235
805
|
mo[k] = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
1236
806
|
}
|
|
1237
807
|
}
|
|
1238
|
-
// An elided SPREAD (`x:$obj&:` with nothing after the colon)
|
|
1239
|
-
// refuses the whole map, not a key (issue #48). A spread is not a
|
|
1240
|
-
// child, so a refusal stored in its place has nothing to attach
|
|
1241
|
-
// to: `x:&:` has no children for the spread to apply to, and the
|
|
1242
|
-
// map would generate as `{}` with the mistake silently gone.
|
|
1243
|
-
// Refusing the container is what makes it visible at all.
|
|
1244
808
|
const sp = mo[type_1.SPREAD];
|
|
1245
809
|
if (sp && sp.v.some((sv) => null == sv)) {
|
|
1246
810
|
r.node = addsite(new NilVal_1.NilVal({ why: 'elided_value' }), r, ctx);
|
|
1247
811
|
return undefined;
|
|
1248
812
|
}
|
|
1249
|
-
// A KEY REFUSAL (the pair rule records them: a declaration
|
|
1250
|
-
// spelled with a colon, a key the bare-text rule refuses) becomes
|
|
1251
|
-
// the refusal, in place of whatever followed the colon and sited
|
|
1252
|
-
// at the KEY rather than at the map -- at the offending character
|
|
1253
|
-
// of it, where there is one -- so the frame points at the
|
|
1254
|
-
// spelling to change.
|
|
1255
813
|
for (const { key, tkn, why, details } of (r.u.aontu_key_refusals ?? [])) {
|
|
1256
814
|
const en = siteAt(addsite(new NilVal_1.NilVal({ why }), r, ctx), tokenSite(tkn));
|
|
1257
815
|
if (null != details) {
|
|
@@ -1280,7 +838,6 @@ help isolate the syntax error.`,
|
|
|
1280
838
|
if (mo.___merge) {
|
|
1281
839
|
let mop = { ...mo };
|
|
1282
840
|
delete mop.___merge;
|
|
1283
|
-
// TODO: needs addpath?
|
|
1284
841
|
let mopv = new MapVal_1.MapVal({ peg: mop });
|
|
1285
842
|
mopv.optionalKeys = optionalKeys;
|
|
1286
843
|
mopv.aliasKeys = aliasKeys;
|
|
@@ -1299,13 +856,9 @@ help isolate the syntax error.`,
|
|
|
1299
856
|
});
|
|
1300
857
|
jsonic.rule('list', (rs) => {
|
|
1301
858
|
rs
|
|
1302
|
-
// .open([{ s: [CJ, CL], p: 'pair', b: 2, g: 'spread' }])
|
|
1303
859
|
.bc((r, ctx) => {
|
|
1304
860
|
const optionalKeys = r.u.aontu_optional_keys ?? [];
|
|
1305
861
|
let ao = r.node;
|
|
1306
|
-
// An elided ELEMENT (`[,]`, `[1,,2]`) is refused for the same
|
|
1307
|
-
// reason as an elided map value (issue #48). A trailing comma
|
|
1308
|
-
// (`[1,]`) is not an elision and never reaches here.
|
|
1309
862
|
for (let i = 0; i < ao.length; i++) {
|
|
1310
863
|
if (null == ao[i]) {
|
|
1311
864
|
// Pathed at the INDEX, for the same reason as the map case.
|
|
@@ -1323,36 +876,16 @@ help isolate the syntax error.`,
|
|
|
1323
876
|
}
|
|
1324
877
|
return undefined;
|
|
1325
878
|
});
|
|
1326
|
-
// .close([{ s: [CJ, CL], b: 2, g: 'spread,json,more' }])
|
|
1327
879
|
return rs;
|
|
1328
880
|
});
|
|
1329
|
-
// TODO: copied from jsonic grammar
|
|
1330
|
-
// jsonic should provide a way to export this
|
|
1331
881
|
const pairkey = (r) => {
|
|
1332
882
|
// Get key string value from first matching token of `Open` state.
|
|
1333
883
|
const key_token = r.o0;
|
|
1334
884
|
const key = ST === key_token.tin || TX === key_token.tin
|
|
1335
|
-
? key_token.val
|
|
885
|
+
? key_token.val
|
|
1336
886
|
: key_token.src; // Was number, use original text
|
|
1337
887
|
r.u.key = key;
|
|
1338
888
|
};
|
|
1339
|
-
// A pair in LIST position writes its value at `node[key]` like any
|
|
1340
|
-
// other pair, and the enclosing list's node is an ARRAY -- so a numeric
|
|
1341
|
-
// key lands on an index and becomes an element, and may land on an
|
|
1342
|
-
// index a real element already holds (`[5,0:1]`). Since the pair must
|
|
1343
|
-
// contribute nothing (issue #40), the slot is photographed before the
|
|
1344
|
-
// value is parsed and put back afterwards. Restoring beats deleting for
|
|
1345
|
-
// exactly the overwrite case: deleting `[5,0:1]`'s index 0 would take
|
|
1346
|
-
// the 5 with it, where restoring gives back the list the pair was
|
|
1347
|
-
// never part of.
|
|
1348
|
-
//
|
|
1349
|
-
// `length` is saved too: writing past the end grows an array, and
|
|
1350
|
-
// `[5,1?:9]` must be [5] again and not [5, <hole>].
|
|
1351
|
-
// Typed as a string bag deliberately: the slot may be named by a
|
|
1352
|
-
// non-numeric key (`[x:1]`), which the array type would refuse. Both
|
|
1353
|
-
// helpers run only from the elem rule, whose node is the enclosing
|
|
1354
|
-
// list, so neither guards against a non-array node — a guard there
|
|
1355
|
-
// proved unreachable and dead code is worse than none.
|
|
1356
889
|
const asSlots = (r) => r.node;
|
|
1357
890
|
const snapshotPairSlot = (r, key) => {
|
|
1358
891
|
const node = asSlots(r);
|
|
@@ -1412,40 +945,14 @@ help isolate the syntax error.`,
|
|
|
1412
945
|
})
|
|
1413
946
|
.bc((rule) => {
|
|
1414
947
|
// TRAVERSE PARENTS TO GET PATH
|
|
1415
|
-
// A DECLARATION IS A PAIR WHOSE KEY IS AN ALIAS NAME. The lexer
|
|
1416
|
-
// claims `%name` whole and hands it over as a #VL token whose
|
|
1417
|
-
// SOURCE is the name, so the key TEXT alone cannot be the test:
|
|
1418
|
-
// a quoted `"%a": 1` is an ordinary key that merely starts with
|
|
1419
|
-
// the sigil, and erasing that would be wrong. The token is what
|
|
1420
|
-
// separates them.
|
|
1421
|
-
//
|
|
1422
|
-
// Recorded on the enclosing map, never on the value, and that is
|
|
1423
|
-
// the point: a reference COPIES the value it resolves to, so a
|
|
1424
|
-
// mark riding the value would erase the referring field too.
|
|
1425
|
-
// Being a property of the map is also what carries it through a
|
|
1426
|
-
// meet, the way optional keys are carried.
|
|
1427
948
|
const ktkn = rule.o0;
|
|
1428
949
|
const holder = rule.parent;
|
|
1429
950
|
const kr = keyRefusalOf(ktkn, rule.o1);
|
|
1430
951
|
if (null != kr) {
|
|
1431
|
-
// A KEY REFUSAL (keyRefusalOf) is written where the map is
|
|
1432
|
-
// built, in the value's place and sited at the key, so the
|
|
1433
|
-
// frame points at the spelling to change. A declaration
|
|
1434
|
-
// spelled with a colon is refused rather than read as the
|
|
1435
|
-
// ordinary key `%foo` the text would otherwise become -- a
|
|
1436
|
-
// document written for the old form would then generate a
|
|
1437
|
-
// "%foo" field and every `%foo` use would resolve to nothing,
|
|
1438
|
-
// and neither says why.
|
|
1439
952
|
holder.u.aontu_key_refusals = (holder.u.aontu_key_refusals || []);
|
|
1440
953
|
holder.u.aontu_key_refusals.push({ key: '' + ktkn.src, tkn: ktkn, ...kr });
|
|
1441
954
|
}
|
|
1442
955
|
else if (isAliasDecl(ktkn, rule.o1)) {
|
|
1443
|
-
// Always recorded here; whether the map is ALLOWED to carry
|
|
1444
|
-
// declarations is decided on the VALUE (MapVal.unify), not at
|
|
1445
|
-
// the parse. The parse cannot see it: an INCLUDED file's
|
|
1446
|
-
// declarations are at the root of their own text, and only
|
|
1447
|
-
// once the loaded map is placed does it become apparent that
|
|
1448
|
-
// root is not the document's.
|
|
1449
956
|
holder.u.aontu_alias_keys = (holder.u.aontu_alias_keys || []);
|
|
1450
957
|
holder.u.aontu_alias_keys.push('' + ktkn.src);
|
|
1451
958
|
}
|
|
@@ -1457,11 +964,6 @@ help isolate the syntax error.`,
|
|
|
1457
964
|
return undefined;
|
|
1458
965
|
})
|
|
1459
966
|
.close([
|
|
1460
|
-
// A following `&:` starts a sibling spread pair in the current
|
|
1461
|
-
// map: directly inside a braced map (pk<=0) at any depth, or in
|
|
1462
|
-
// the implicit top-level map (dmap<=1). Inside an implicit
|
|
1463
|
-
// colon-chain map (pk>0) it bubbles up instead (second alt), so
|
|
1464
|
-
// `a:b:1 &:2` attaches the spread to a's map, not b's.
|
|
1465
967
|
{ s: [CJ, CL], c: (r) => r.lte('pk', 0) || r.lte('dmap', 1), r: 'pair', b: 2, g: 'spread,json,pair' },
|
|
1466
968
|
{ s: [CJ, CL], b: 2, g: 'spread,json,more' }
|
|
1467
969
|
]);
|
|
@@ -1496,17 +998,6 @@ help isolate the syntax error.`,
|
|
|
1496
998
|
},
|
|
1497
999
|
g: 'aontu-optional-elem'
|
|
1498
1000
|
},
|
|
1499
|
-
// A PLAIN pair in list position IS A SINGLE-KEY MAP ELEMENT:
|
|
1500
|
-
// `[a:1, b:2]` is `[{a:1}, {b:2}]` (the rule @tabnas/jsonic
|
|
1501
|
-
// spells as `list.pair`). This REVERSES issue #40's "a pair is
|
|
1502
|
-
// not an element": that rule was chosen because jsonic wrote
|
|
1503
|
-
// the pair at `node[key]` -- an array PROPERTY that never
|
|
1504
|
-
// showed up for a text key and an INDEX for a numeric one --
|
|
1505
|
-
// and inert beat that incoherence. But inert was itself a
|
|
1506
|
-
// silent drop: `x: [a:1, b:2]` evaluated to `x: []`, the
|
|
1507
|
-
// author's data gone at exit 0. The element is built in the
|
|
1508
|
-
// bc below, where the value is already a Val; the snapshot
|
|
1509
|
-
// still neutralises jsonic's raw slot write first.
|
|
1510
1001
|
{
|
|
1511
1002
|
s: [OPTKEY, CL], p: 'val',
|
|
1512
1003
|
u: { spread: true, done: true, list: true, pair: true },
|
|
@@ -1517,36 +1008,7 @@ help isolate the syntax error.`,
|
|
|
1517
1008
|
g: 'aontu-plain-pair-elem'
|
|
1518
1009
|
}
|
|
1519
1010
|
])
|
|
1520
|
-
// NOTE: manually adjust path - the twin of the `pair` rule's hook
|
|
1521
|
-
// above, and for the same reason, one layer down.
|
|
1522
|
-
//
|
|
1523
|
-
// Every alt above contributes NO element: a `&:` spread is a
|
|
1524
|
-
// constraint on the elements, and a `k:v` pair in list position is
|
|
1525
|
-
// simply not one (the `aontu-plain-pair-elem` note above). The array
|
|
1526
|
-
// slot they briefly occupy is already given back by
|
|
1527
|
-
// restorePairSlot. The PATH index was not: @tabnas/path's
|
|
1528
|
-
// `@elem-ao` increments `r.k.index` for every elem rule it sees, so
|
|
1529
|
-
// each of these stole an index and every later element's path was
|
|
1530
|
-
// one too high — `[&: integer, 10, 20, "bad"]` reported the bad
|
|
1531
|
-
// value at `$.l.3` while `aontu get $.l.2` returned it, and on a
|
|
1532
|
-
// one-element list the path pointed off the end. Generation was
|
|
1533
|
-
// never wrong, which is why nothing caught it: the array is right
|
|
1534
|
-
// and only the labels on it were shifted (BUGS.md 44).
|
|
1535
|
-
//
|
|
1536
|
-
// Rewinding here rather than in the plugin keeps the plugin's rule
|
|
1537
|
-
// ("in an array, the path property is the element index") true —
|
|
1538
|
-
// these alts are the aontu-specific exceptions to what counts as an
|
|
1539
|
-
// element, so the correction belongs with the grammar that
|
|
1540
|
-
// introduces them. The child is re-pathed because the plugin has
|
|
1541
|
-
// already stamped it with the index being given back: a spread
|
|
1542
|
-
// takes the `'&'` segment its map twin takes, and a pair takes its
|
|
1543
|
-
// key, as a map entry would.
|
|
1544
1011
|
.ao((r) => {
|
|
1545
|
-
// A pair IS an element now, so it keeps the index @tabnas/path
|
|
1546
|
-
// gave it, and its VALUE is pathed through both the index and
|
|
1547
|
-
// the key (`[a: $.nope]` fails at $.l.0.a). Only the `&:`
|
|
1548
|
-
// spread still contributes no element and gives its index back
|
|
1549
|
-
// (BUGS.md 44).
|
|
1550
1012
|
if (0 < r.d && r.u.spread && !r.u.pair) {
|
|
1551
1013
|
r.k.index = r.k.index - 1;
|
|
1552
1014
|
const seg = '&';
|
|
@@ -1554,11 +1016,6 @@ help isolate the syntax error.`,
|
|
|
1554
1016
|
r.child.k.key = seg;
|
|
1555
1017
|
}
|
|
1556
1018
|
else if (0 < r.d && r.u.pair) {
|
|
1557
|
-
// The element's index is the array length: everything before
|
|
1558
|
-
// it is already pushed, and the pair's own map is pushed at
|
|
1559
|
-
// close. `r.k.index` is not usable here -- the path plugin
|
|
1560
|
-
// counts only the elements it pushes itself, and this one is
|
|
1561
|
-
// aontu's.
|
|
1562
1019
|
const seg = '' + r.u.key;
|
|
1563
1020
|
r.child.k.path =
|
|
1564
1021
|
[...r.k.path, '' + (r.node?.length ?? 0), seg];
|
|
@@ -1567,39 +1024,14 @@ help isolate the syntax error.`,
|
|
|
1567
1024
|
})
|
|
1568
1025
|
.bc((rule, ctx) => {
|
|
1569
1026
|
// TRAVERSE PARENTS TO GET PATH
|
|
1570
|
-
// Only the `&:` alternative is a SPREAD. All four alts above set
|
|
1571
|
-
// `spread: true` -- it is what marks them as contributing no
|
|
1572
|
-
// element -- so this guard needs the narrower test, and `pair`
|
|
1573
|
-
// is what distinguishes a `k:v` in list position from a spread.
|
|
1574
|
-
//
|
|
1575
|
-
// Without it a pair BUILT the spread record, with `o` taken from
|
|
1576
|
-
// its own key rather than '&': `[x:1, &:integer, "bad"]` left
|
|
1577
|
-
// `{o:'x', v:[1, integer]}`, and ListVal's `'&' === spread.o`
|
|
1578
|
-
// then discarded the real constraint -- so the element spread
|
|
1579
|
-
// was silently dropped and the bad value generated (BUGS.md 46).
|
|
1580
|
-
// A pair alone did it too: `[x:1, 10]` produced a spread record
|
|
1581
|
-
// out of nothing.
|
|
1582
1027
|
if (rule.u.spread && !rule.u.pair) {
|
|
1583
1028
|
rule.node[type_1.SPREAD] =
|
|
1584
1029
|
(rule.node[type_1.SPREAD] || { o: rule.o0.src, v: [] });
|
|
1585
1030
|
rule.node[type_1.SPREAD].v.push(rule.child.node);
|
|
1586
1031
|
}
|
|
1587
|
-
// The slot is given back BEFORE the element is added: the
|
|
1588
|
-
// restore undoes jsonic's raw write (a property for a text
|
|
1589
|
-
// key, an INDEX for a numeric one -- restoring length is what
|
|
1590
|
-
// keeps `[1:2]` from padding with a null), and the push then
|
|
1591
|
-
// appends cleanly after it.
|
|
1592
1032
|
restorePairSlot(rule);
|
|
1593
|
-
// THE SINGLE-KEY MAP ELEMENT, for both pair spellings. The
|
|
1594
|
-
// value is a Val already (`p: 'val'`), so the map is built
|
|
1595
|
-
// exactly as the map rule builds one -- and an elided value
|
|
1596
|
-
// (`[a:]`) is refused exactly as the map rule refuses one
|
|
1597
|
-
// (issue #48): a key with nothing after the colon is a
|
|
1598
|
-
// mistake, not an empty value.
|
|
1599
1033
|
if (true === rule.u.pair) {
|
|
1600
1034
|
const key = '' + rule.u.key;
|
|
1601
|
-
// The key TOKEN: the optional spelling's sits on the elem rule
|
|
1602
|
-
// before this one (`[x?: 1]` is two elem rules).
|
|
1603
1035
|
const ktkn = true === rule.u.aontu_optional_elem ?
|
|
1604
1036
|
rule.prev.o0 : rule.o0;
|
|
1605
1037
|
let v = rule.child.node;
|
|
@@ -1627,9 +1059,6 @@ help isolate the syntax error.`,
|
|
|
1627
1059
|
// "is this the top level" test reads the path, so an element
|
|
1628
1060
|
// of a top-level list must not read as the root.
|
|
1629
1061
|
mv.path = [...(rule.k?.path ?? []), '' + rule.node.length];
|
|
1630
|
-
// `[a?: 1]` is `[{a?: 1}]`: the key is optional IN the
|
|
1631
|
-
// element, so the two spellings stay one rule apart rather
|
|
1632
|
-
// than two behaviours apart.
|
|
1633
1062
|
if (true === rule.u.aontu_optional_elem) {
|
|
1634
1063
|
mv.optionalKeys = [key];
|
|
1635
1064
|
}
|
|
@@ -1647,43 +1076,10 @@ help isolate the syntax error.`,
|
|
|
1647
1076
|
return rs;
|
|
1648
1077
|
});
|
|
1649
1078
|
};
|
|
1650
|
-
// INCLUDE_KINDS IS THE RULE FOR WHAT AN INCLUDE MEANS (ADR-012,
|
|
1651
|
-
// use-cases/BUGS.md §49). An extension is on this list or it is not
|
|
1652
|
-
// read at all, and its entry says WHICH OF TWO THINGS the file is.
|
|
1653
|
-
//
|
|
1654
|
-
// `source` — Aontu, with everything the language has: types, defaults,
|
|
1655
|
-
// references, constraints, its own includes. Two extensions, and they
|
|
1656
|
-
// are the ones this project owns.
|
|
1657
|
-
//
|
|
1658
|
-
// `text` — the file's BYTES, as one string scalar. No parser is
|
|
1659
|
-
// chosen, so there is nothing for two ports to disagree about and
|
|
1660
|
-
// nothing in the file that can mean anything: `notes: @"notes.txt"`
|
|
1661
|
-
// is a document loading prose into a string. `.txt` is the only
|
|
1662
|
-
// extension here by default; `AontuOptions.textExt` (the CLI's
|
|
1663
|
-
// `--text-ext`) adds others, because which name a project keeps its
|
|
1664
|
-
// templates under is the project's business, not this table's.
|
|
1665
|
-
//
|
|
1666
|
-
// A FORMAT NAME — configuration DATA, parsed by that format's own
|
|
1667
|
-
// parser into the JSON value it denotes, which then becomes Aontu
|
|
1668
|
-
// values like any other data. Every one of these formats maps onto
|
|
1669
|
-
// JSON, which is why one word covers them: a `.toml` file is a map of
|
|
1670
|
-
// scalars, lists and maps, and so is the `.aon` file that unifies with
|
|
1671
|
-
// it. What the format does NOT get is the language — a `&` in a YAML
|
|
1672
|
-
// file is a YAML anchor, not a spread key, because the YAML parser
|
|
1673
|
-
// reads it, not this one.
|
|
1674
|
-
//
|
|
1675
|
-
// The parsers are @tabnas's, one per format, and the Go port uses the
|
|
1676
|
-
// same ones (ADR-001): the two implementations agree because they are
|
|
1677
|
-
// running the same grammar, not because two hand-written readers were
|
|
1678
|
-
// kept in step.
|
|
1679
|
-
//
|
|
1680
|
-
// This table and go/source.go's includeKinds are the same table.
|
|
1681
1079
|
const INCLUDE_KINDS = {
|
|
1682
1080
|
aon: 'source',
|
|
1683
1081
|
aontu: 'source',
|
|
1684
1082
|
json: 'json',
|
|
1685
|
-
// JSON-LD is JSON: a `@context` is a key like any other here, and
|
|
1686
|
-
// what it MEANS is the vocabulary's business, not the reader's.
|
|
1687
1083
|
jsonld: 'json',
|
|
1688
1084
|
jsonc: 'jsonc',
|
|
1689
1085
|
json5: 'json5',
|
|
@@ -1695,25 +1091,11 @@ const INCLUDE_KINDS = {
|
|
|
1695
1091
|
ini: 'ini',
|
|
1696
1092
|
txt: 'text',
|
|
1697
1093
|
};
|
|
1698
|
-
// WHAT AN EXTENSION MEANS, for this parse. The table is the fixed
|
|
1699
|
-
// part; `textExt` is the per-parse widening, and it wins over nothing
|
|
1700
|
-
// -- a host cannot re-read `.toml` as text, because an extension the
|
|
1701
|
-
// table already names has a meaning documents rely on. Undefined is
|
|
1702
|
-
// the refusal, and it is the ONE place that decides it: the resolver's
|
|
1703
|
-
// gate and the processor map both ask here, so a widening cannot reach
|
|
1704
|
-
// one and not the other.
|
|
1705
1094
|
function includeFormat(ext, textExt) {
|
|
1706
1095
|
const known = INCLUDE_KINDS[ext];
|
|
1707
1096
|
if (undefined !== known) {
|
|
1708
1097
|
return known;
|
|
1709
1098
|
}
|
|
1710
|
-
// NOT EVEN AS TEXT. `.js` is the extension ADR-012 singles out
|
|
1711
|
-
// because multisource's own default EXECUTES it, and an extension
|
|
1712
|
-
// this project refuses on purpose stays refused however a flag is
|
|
1713
|
-
// spelled -- reading it is harmless, but a widening that can reach
|
|
1714
|
-
// the one name the rule names is a widening whose limit nobody can
|
|
1715
|
-
// state. Go's includeFormat holds the same list, and the two CLIs
|
|
1716
|
-
// are diffed on `--text-ext js` because they once disagreed here.
|
|
1717
1099
|
if (REFUSED_EXT.has(ext)) {
|
|
1718
1100
|
return undefined;
|
|
1719
1101
|
}
|
|
@@ -1723,17 +1105,6 @@ function includeFormat(ext, textExt) {
|
|
|
1723
1105
|
// default processor; `''` is the no-extension fallback, which names no
|
|
1724
1106
|
// file type at all.
|
|
1725
1107
|
const REFUSED_EXT = new Set(['js', '']);
|
|
1726
|
-
// `.csv` IS DELIBERATELY ABSENT, and the reason is ADR-001 rather than
|
|
1727
|
-
// taste. The two ports' CSV parsers disagree about what a CSV file IS:
|
|
1728
|
-
// one answers header-keyed records with string fields, the other raw
|
|
1729
|
-
// rows including the header, with numbers parsed. Admitting it would
|
|
1730
|
-
// admit a divergence into the one thing this project refuses to have
|
|
1731
|
-
// one in. Recorded in ADR-012 and pinned by file.tsv's load-ext-csv.
|
|
1732
|
-
// The multisource kind of a path: the LAST segment's extension, without
|
|
1733
|
-
// its dot, lowercased -- `''` for a name that has none. The rule is
|
|
1734
|
-
// @tabnas/multisource's own extKind (and Go's filepath.Ext), copied
|
|
1735
|
-
// rather than imported because it decides what a source IS: a dot in a
|
|
1736
|
-
// parent folder (`/my.app/conf`) must not read as an extension.
|
|
1737
1108
|
function extKindOf(full) {
|
|
1738
1109
|
const seg = full.match(/[^\\/]*$/)[0];
|
|
1739
1110
|
return (seg.match(/\.([^.]*)$/) || ['', ''])[1].toLowerCase();
|
|
@@ -1746,15 +1117,6 @@ function extensionMsg(path, ext) {
|
|
|
1746
1117
|
const which = '' === ext ? 'no extension' : 'extension: .' + ext;
|
|
1747
1118
|
return 'include not readable: ' + path + ' (' + which + ')';
|
|
1748
1119
|
}
|
|
1749
|
-
// THE RULE ALSO HOLDS FOR A RESOLVER THIS ENGINE DID NOT WRITE.
|
|
1750
|
-
// gateExtension refuses an unlisted extension inside makeModelResolver,
|
|
1751
|
-
// which is the default; a HOST may supply its own through
|
|
1752
|
-
// `AontuOptions.resolver`, and that one has never heard of
|
|
1753
|
-
// INCLUDE_KINDS. Without this the host's resolution would fall to
|
|
1754
|
-
// multisource's own default for an unnamed kind, which hands the file
|
|
1755
|
-
// back as TEXT — or, for `.js`, EXECUTES it. So the two roads end in
|
|
1756
|
-
// one place: whatever chose the source, an extension off the list is
|
|
1757
|
-
// refused with the same code and the same message.
|
|
1758
1120
|
const refuseProcessor = (res) => {
|
|
1759
1121
|
// `full` is the one part a host resolution may leave out -- it is the
|
|
1760
1122
|
// path the resolver CHOSE, and a resolver that answers from something
|
|
@@ -1790,22 +1152,6 @@ const DATA_READERS = (() => {
|
|
|
1790
1152
|
ini: viaPlugin(ini_1.Ini),
|
|
1791
1153
|
};
|
|
1792
1154
|
})();
|
|
1793
|
-
/**
|
|
1794
|
-
* A TOML document with its dates as the TEXT they were written as.
|
|
1795
|
-
*
|
|
1796
|
-
* TOML HAS DATES AND JSON DOES NOT, so the reader cannot hand one over
|
|
1797
|
-
* as itself: it answers with a marker object carrying the kind and the
|
|
1798
|
-
* source text. The value that reaches a document is that TEXT, which is
|
|
1799
|
-
* what a JSON document carries for a date anyway — and it is what the
|
|
1800
|
-
* Go port produces too, from a `*TomlTime` holding those same two
|
|
1801
|
-
* fields (`dataToValDepth`, go/source.go). Without this the same file
|
|
1802
|
-
* is a nested map in one port and a string in the other, which is the
|
|
1803
|
-
* class of divergence ADR-012 exists to stop.
|
|
1804
|
-
*
|
|
1805
|
-
* The guard is exact — one key, `__toml__`, holding a `kind` and a
|
|
1806
|
-
* `src` string — so a document whose own data happens to use the name
|
|
1807
|
-
* passes through untouched.
|
|
1808
|
-
*/
|
|
1809
1155
|
function tomlDates(node) {
|
|
1810
1156
|
if (Array.isArray(node)) {
|
|
1811
1157
|
return node.map(tomlDates);
|
|
@@ -1825,31 +1171,12 @@ function tomlDates(node) {
|
|
|
1825
1171
|
}
|
|
1826
1172
|
return out;
|
|
1827
1173
|
}
|
|
1828
|
-
/**
|
|
1829
|
-
* Read one included file as DATA in the named format.
|
|
1830
|
-
*
|
|
1831
|
-
* The parser hands back the JSON value the file denotes — plain maps,
|
|
1832
|
-
* lists and scalars — and rawToVal turns that into Vals. THE
|
|
1833
|
-
* CONVERSION HAPPENS HERE, not at the top level, because an include is
|
|
1834
|
-
* usually not at the top level: `a: @"conf.toml"` puts the value under
|
|
1835
|
-
* a key, where a raw JavaScript object is something the tree cannot
|
|
1836
|
-
* unify with (the crash that was BUGS §49b).
|
|
1837
|
-
*/
|
|
1838
1174
|
const dataProcessor = (format) => (res) => {
|
|
1839
1175
|
res.val = rawToVal(DATA_READERS[format](res.src, res.path));
|
|
1840
1176
|
};
|
|
1841
|
-
// TEXT IS NOT PARSED. The bytes multisource read are the value, so
|
|
1842
|
-
// this is the one processor with no reader behind it -- which is why
|
|
1843
|
-
// a `.txt` include cannot fail on content, only on being unreadable.
|
|
1844
1177
|
const textProcessor = (res) => {
|
|
1845
1178
|
res.val = new StringVal_1.StringVal({ peg: res.src });
|
|
1846
1179
|
};
|
|
1847
|
-
/**
|
|
1848
|
-
* The multisource processor map, built FROM the include table so the
|
|
1849
|
-
* two cannot drift: every extension the table names gets the reader
|
|
1850
|
-
* the table names for it, and the two kinds that are not in the table
|
|
1851
|
-
* refuse.
|
|
1852
|
-
*/
|
|
1853
1180
|
function includeProcessors(textExt) {
|
|
1854
1181
|
const map = {
|
|
1855
1182
|
// multisource's fallback for an extension no entry names, so it is
|
|
@@ -1870,10 +1197,6 @@ function includeProcessors(textExt) {
|
|
|
1870
1197
|
for (const kind of Object.keys(INCLUDE_KINDS)) {
|
|
1871
1198
|
map[kind] = forKind(kind);
|
|
1872
1199
|
}
|
|
1873
|
-
// A WIDENING NEVER OVERWRITES. `js` and the empty fallback refuse
|
|
1874
|
-
// above and stay refusing: `--text-ext js` would otherwise turn the
|
|
1875
|
-
// one extension ADR-012 singles out into a readable one, by a flag
|
|
1876
|
-
// whose whole promise is that it chooses no parser.
|
|
1877
1200
|
for (const ext of textExt ?? []) {
|
|
1878
1201
|
if (undefined === map[ext]) {
|
|
1879
1202
|
map[ext] = textProcessor;
|
|
@@ -1881,17 +1204,8 @@ function includeProcessors(textExt) {
|
|
|
1881
1204
|
}
|
|
1882
1205
|
return map;
|
|
1883
1206
|
}
|
|
1884
|
-
//
|
|
1885
|
-
//
|
|
1886
|
-
// relative paths (`@"../../etc/passwd.aon"`) and symlinks — so treat
|
|
1887
|
-
// opening an untrusted source as reading your disk. It no longer RUNS
|
|
1888
|
-
// one: @"pkg" could require() an arbitrary installed module until
|
|
1889
|
-
// ADR-012, which refuses a `.js` entry point by the same rule that
|
|
1890
|
-
// refuses `.txt`. The trust profile (G5, docs/trust.md) is the
|
|
1891
|
-
// confinement surface: `trust.include` of
|
|
1892
|
-
// 'none', `{ mem }` or `{ root }` restricts what `@"..."` may resolve,
|
|
1893
|
-
// and a denied resolution is a deterministic parse-stage
|
|
1894
|
-
// `include_denied` error.
|
|
1207
|
+
// What a resolved include may reach, and how it is confined:
|
|
1208
|
+
// docs/trust.md.
|
|
1895
1209
|
function makeModelResolver(options) {
|
|
1896
1210
|
const useRequire = options.require || require;
|
|
1897
1211
|
const capability = options.trust?.include ?? 'system';
|
|
@@ -1899,22 +1213,9 @@ function makeModelResolver(options) {
|
|
|
1899
1213
|
const rootDir = 'object' === typeof capability &&
|
|
1900
1214
|
'string' === typeof capability.root
|
|
1901
1215
|
? (0, node_path_1.resolve)(capability.root) : undefined;
|
|
1902
|
-
// Under the mem capability the CAPABILITY's file set is the whole
|
|
1903
|
-
// world; otherwise the host-injected `options.resolver.mem` entries
|
|
1904
|
-
// remain available under every capability but 'none' — they are
|
|
1905
|
-
// host-provided, not document-requested, so confining them would
|
|
1906
|
-
// confine the host against itself.
|
|
1907
|
-
// THE BUNDLED VOCABULARY (G4 phase 4, ts/src/std.ts) rides the
|
|
1908
|
-
// memory leg: served from the engine itself, so it needs neither the
|
|
1909
|
-
// filesystem nor package resolution and is available under every
|
|
1910
|
-
// capability but `none` — which denies every include outright, that
|
|
1911
|
-
// being what `none` means. Host entries and the capability's own set
|
|
1912
|
-
// WIN over it: a caller that supplies its own `std/system` gets the
|
|
1913
|
-
// one it supplied.
|
|
1914
1216
|
let memResolver = (0, mem_1.makeMemResolver)(memCapability
|
|
1915
1217
|
? { ...capability.mem }
|
|
1916
1218
|
: { ...(options.resolver?.mem || {}) });
|
|
1917
|
-
// TODO: make this consistent with other resolvers
|
|
1918
1219
|
let fileResolver = (0, file_1.makeFileResolver)((spec) => {
|
|
1919
1220
|
return 'string' === typeof spec ? spec : spec?.peg;
|
|
1920
1221
|
});
|
|
@@ -1922,23 +1223,6 @@ function makeModelResolver(options) {
|
|
|
1922
1223
|
require: useRequire,
|
|
1923
1224
|
...(options.resolver?.pkg || {})
|
|
1924
1225
|
});
|
|
1925
|
-
// Confinement is realpath-then-prefix-check (docs/trust.md): the
|
|
1926
|
-
// RESOLVED file's real path must sit below the root's real path, so a
|
|
1927
|
-
// symlink inside the root pointing outside it is an escape, not a
|
|
1928
|
-
// loophole. A path realpath cannot resolve falls back to the lexical
|
|
1929
|
-
// form — the comparison is then against what the resolver actually
|
|
1930
|
-
// read.
|
|
1931
|
-
// Real fs, deliberately: `options.fs` is not a sandbox (it feeds
|
|
1932
|
-
// parse text; the file leg reads through its own channel), so the
|
|
1933
|
-
// containment check must see the same filesystem that leg read from.
|
|
1934
|
-
// A path that does not (fully) exist cannot be realpath'd whole, and
|
|
1935
|
-
// falling back to the LEXICAL form compares apples to oranges when
|
|
1936
|
-
// the root itself sits behind a symlink -- on macOS a root under
|
|
1937
|
-
// /var realpaths to /private/var, so a merely-missing file inside it
|
|
1938
|
-
// reads as an escape. Realpath the deepest EXISTING ancestor and
|
|
1939
|
-
// re-attach the rest, so both sides of the check are in real
|
|
1940
|
-
// coordinates. (The MCP server's own confinement carries the twin of
|
|
1941
|
-
// this rule; its CI failure is what found the shape.)
|
|
1942
1226
|
const realpath = (p) => {
|
|
1943
1227
|
try {
|
|
1944
1228
|
return (0, node_fs_1.realpathSync)(p);
|
|
@@ -1956,12 +1240,6 @@ function makeModelResolver(options) {
|
|
|
1956
1240
|
const fullReal = realpath(full);
|
|
1957
1241
|
return fullReal !== rootReal && !fullReal.startsWith(rootReal + node_path_1.sep);
|
|
1958
1242
|
};
|
|
1959
|
-
// A denial THROWS with the code; Lang.parse converts it to the
|
|
1960
|
-
// parse-stage `include_denied` nil (the same shape a syntax failure
|
|
1961
|
-
// takes). Raising beats injecting a nil value: a bare-member include
|
|
1962
|
-
// (`@"denied.aon"` at the top of a file) MERGES into the enclosing
|
|
1963
|
-
// map, and a nil contributes no keys, so an injected denial would
|
|
1964
|
-
// vanish and leave a plausible, silently-partial document.
|
|
1965
1243
|
const deny = (path) => {
|
|
1966
1244
|
// Only 'none' and 'root' can deny: the mem capability's misses are
|
|
1967
1245
|
// not-found (its set is the whole world), so there is no third arm.
|
|
@@ -1970,12 +1248,6 @@ function makeModelResolver(options) {
|
|
|
1970
1248
|
err.code = 'include_denied';
|
|
1971
1249
|
throw err;
|
|
1972
1250
|
};
|
|
1973
|
-
// AN UNREADABLE EXTENSION THROWS, exactly as a denial does, and for
|
|
1974
|
-
// the same reason: a bare-member include (`@"notes.txt"` at the top
|
|
1975
|
-
// of a file) MERGES into the enclosing map, and a nil contributes no
|
|
1976
|
-
// keys, so an injected refusal would vanish and leave a plausible,
|
|
1977
|
-
// silently-partial document. Lang.parse turns the throw into the
|
|
1978
|
-
// parse-stage `include_extension` nil.
|
|
1979
1251
|
const refuseExtension = (path, full) => {
|
|
1980
1252
|
const err = new Error(extensionMsg(path, extKindOf(full)));
|
|
1981
1253
|
err.code = 'include_extension';
|
|
@@ -1987,12 +1259,12 @@ function makeModelResolver(options) {
|
|
|
1987
1259
|
// set: a typo in an `aontu:` name must not go looking on disk.
|
|
1988
1260
|
const modelNotFound = (path) => {
|
|
1989
1261
|
const err = new Error('source not found: ' + path +
|
|
1990
|
-
' (the language-supplied models are ' +
|
|
1262
|
+
' (the language-supplied models are ' + aontumodel_1.AONTU_MODELS.join(', ') + ')');
|
|
1991
1263
|
err.code = 'multisource_not_found';
|
|
1992
1264
|
throw err;
|
|
1993
1265
|
};
|
|
1994
|
-
// The gate every leg that RESOLVES A NAME passes through. The
|
|
1995
|
-
// 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
|
|
1996
1268
|
// serve is Aontu source by construction, not by its spelling.
|
|
1997
1269
|
const gateExtension = (path, full) => {
|
|
1998
1270
|
if (undefined === includeFormat(extKindOf(full), options.textExt)) {
|
|
@@ -2049,35 +1321,14 @@ function makeModelResolver(options) {
|
|
|
2049
1321
|
if ('none' === capability) {
|
|
2050
1322
|
deny(path);
|
|
2051
1323
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
// else -- the memory, module, file and package legs are never
|
|
2055
|
-
// asked, so nothing on disk can shadow one and a typo is refused
|
|
2056
|
-
// here, naming the set, rather than searched for. Available under
|
|
2057
|
-
// every capability but `none`, checked just above, like the std
|
|
2058
|
-
// names below. A path that is not a string (`a: @1`) is not a name
|
|
2059
|
-
// at all: it falls through to the legs below and is not found there,
|
|
2060
|
-
// as it always was.
|
|
2061
|
-
if ('string' === typeof path && path.startsWith(std_1.AONTU_SCHEME)) {
|
|
2062
|
-
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];
|
|
2063
1326
|
if (null == model) {
|
|
2064
1327
|
modelNotFound(path);
|
|
2065
1328
|
}
|
|
2066
|
-
record(ctx, path, '
|
|
1329
|
+
record(ctx, path, 'aontu');
|
|
2067
1330
|
return { found: true, path, full: path, kind: 'aon', src: model, search: [] };
|
|
2068
1331
|
}
|
|
2069
|
-
// THE BUNDLED VOCABULARY (G4 phase 4, ts/src/std.ts): served from
|
|
2070
|
-
// the engine itself, so it needs neither the filesystem nor package
|
|
2071
|
-
// resolution and is available under every capability but `none` —
|
|
2072
|
-
// checked just above, that being what `none` means. Matched against
|
|
2073
|
-
// the name the author WROTE, before the memory leg, so the kind is
|
|
2074
|
-
// stated rather than guessed from an extension the bare name does
|
|
2075
|
-
// not have.
|
|
2076
|
-
const std = std_1.STD_SOURCES[path];
|
|
2077
|
-
if (null != std) {
|
|
2078
|
-
record(ctx, path, 'std');
|
|
2079
|
-
return { found: true, path, full: path, kind: 'aon', src: std, search: [] };
|
|
2080
|
-
}
|
|
2081
1332
|
let search = [];
|
|
2082
1333
|
let res = memResolver(path, popts, rule, ctx, jsonic);
|
|
2083
1334
|
res.path = path;
|
|
@@ -2090,11 +1341,6 @@ function makeModelResolver(options) {
|
|
|
2090
1341
|
record(ctx, res.full ?? path, 'mem');
|
|
2091
1342
|
return res;
|
|
2092
1343
|
}
|
|
2093
|
-
// THE MODULE LEG (G6 phase 2, ts/src/mod.ts): memory -> MODULE ->
|
|
2094
|
-
// filesystem -> package. Memory stays FIRST so a sandbox and the
|
|
2095
|
-
// spec suite can stub a module path without touching disk; a path
|
|
2096
|
-
// that is not module-shaped falls straight through, so no existing
|
|
2097
|
-
// include can be routed somewhere new by this.
|
|
2098
1344
|
const modref = memCapability ? undefined : (0, mod_1.parseModuleRef)(path);
|
|
2099
1345
|
if (null != modref) {
|
|
2100
1346
|
const msmeta = ctx?.meta?.multisource;
|
|
@@ -2172,37 +1418,17 @@ function makeModelResolver(options) {
|
|
|
2172
1418
|
return res;
|
|
2173
1419
|
};
|
|
2174
1420
|
}
|
|
2175
|
-
// THE SIGNATURE REGISTRY (docs/design/SIGNATURES.0.md). The call
|
|
2176
|
-
// surface is DECLARED in test/spec/signature.tsv and parsed by the
|
|
2177
|
-
// signature grammar (ts/src/sig.ts) from the build-time-inlined copy;
|
|
2178
|
-
// the arity table and the positional set below are DERIVED from the
|
|
2179
|
-
// parsed registry (funcSig, ts/src/sig.ts), so the declaration is the
|
|
2180
|
-
// one source. go/func.go derives the same two tables from the same
|
|
2181
|
-
// text.
|
|
2182
|
-
// The functions whose comma-separated arguments are distinct POSITIONS
|
|
2183
|
-
// rather than one argument list. See the func-paren handler above: this
|
|
2184
|
-
// is the set whose comma group is expanded back into separate `peg`
|
|
2185
|
-
// entries. Derived: two or more declared argument slots, excluding the
|
|
2186
|
-
// residual producers (`constraint` results) -- the constraint atoms
|
|
2187
|
-
// make the same expansion in their own constructor (`atomArgs`,
|
|
2188
|
-
// ConstraintVal.ts, deliberately before the settled check), which is
|
|
2189
|
-
// why they are not in this set; `must` is the load-bearing example.
|
|
2190
|
-
// Arithmetic is here because `sub` is not commutative: `sub(a, b)`
|
|
2191
|
-
// reaching the engine as one two-element list would lose which is
|
|
2192
|
-
// which.
|
|
2193
1421
|
const POSITIONAL_ARG_FUNCS = {};
|
|
2194
1422
|
for (const name in sig_1.funcSig) {
|
|
2195
1423
|
if (2 <= sig_1.funcSig[name].args.length && 'constraint' !== sig_1.funcSig[name].out) {
|
|
2196
1424
|
POSITIONAL_ARG_FUNCS[name] = true;
|
|
2197
1425
|
}
|
|
2198
1426
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
// minimum, which is what gives `match` its floor of three and `neq`
|
|
2205
|
-
// its floor of one.
|
|
1427
|
+
for (const name of Object.keys(CmpFuncVal_1.CMP_FUNCS)) {
|
|
1428
|
+
POSITIONAL_ARG_FUNCS[name] = true;
|
|
1429
|
+
}
|
|
1430
|
+
POSITIONAL_ARG_FUNCS['nom'] = true;
|
|
1431
|
+
POSITIONAL_ARG_FUNCS['translate'] = true;
|
|
2206
1432
|
function sigArity(sig) {
|
|
2207
1433
|
let min = 0;
|
|
2208
1434
|
let max = 0;
|
|
@@ -2226,14 +1452,6 @@ const funcArity = {};
|
|
|
2226
1452
|
for (const name in sig_1.funcSig) {
|
|
2227
1453
|
funcArity[name] = sigArity(sig_1.funcSig[name]);
|
|
2228
1454
|
}
|
|
2229
|
-
// writtenArgCount counts the arguments as the AUTHOR wrote them.
|
|
2230
|
-
//
|
|
2231
|
-
// It cannot simply be terms.length: a comma group reaches the func-paren
|
|
2232
|
-
// handler as ONE term holding a raw array, so `upper("a","b")` and
|
|
2233
|
-
// `upper(["a","b"])` both arrive as a single argument. They are still
|
|
2234
|
-
// distinguishable, and that is what makes an arity check possible at
|
|
2235
|
-
// all -- the comma group is a RAW array, while a written list literal
|
|
2236
|
-
// has already been built into a ListVal by the list rule.
|
|
2237
1455
|
function writtenArgCount(terms) {
|
|
2238
1456
|
if (1 === terms.length) {
|
|
2239
1457
|
// `terms[0]` is re-read rather than reusing a narrowed local:
|
|
@@ -2255,7 +1473,10 @@ function arityText(lo, hi) {
|
|
|
2255
1473
|
return 'one or more arguments';
|
|
2256
1474
|
}
|
|
2257
1475
|
if (lo !== hi) {
|
|
2258
|
-
|
|
1476
|
+
if (0 === lo) {
|
|
1477
|
+
return 'no arguments or one';
|
|
1478
|
+
}
|
|
1479
|
+
return 3 === hi ? 'one to three arguments' : 'one argument or two';
|
|
2259
1480
|
}
|
|
2260
1481
|
// The {0,0} arm returned with the container kinds and acyclic()
|
|
2261
1482
|
// (ADR-015): `map(1)` must not claim map takes exactly one.
|
|
@@ -2267,17 +1488,6 @@ function arityText(lo, hi) {
|
|
|
2267
1488
|
}
|
|
2268
1489
|
return 'exactly one argument';
|
|
2269
1490
|
}
|
|
2270
|
-
// rawToVal converts a raw parse node (or raw elements inside one) into
|
|
2271
|
-
// the matching Val. Used for implicit top-level lists, whose nodes skip
|
|
2272
|
-
// the aontu val rule conversions (mirrors asVal in go/lang.go; like
|
|
2273
|
-
// there, source text is unavailable, so an integral number is an
|
|
2274
|
-
// integer).
|
|
2275
|
-
// The targeted parse hint for CUE-trained authors and models: `>` and
|
|
2276
|
-
// `<` are not Aontu operators (the op-chars reservation stands), and an
|
|
2277
|
-
// agent that emits `number > 0` should be redirected to the bound
|
|
2278
|
-
// atoms, not left with a bare "unexpected character". Appended to a
|
|
2279
|
-
// parse error's message when the source carries an unquoted `<` or
|
|
2280
|
-
// `>`; the Go twin is opCharHint in go/lang.go, byte-identical text.
|
|
2281
1491
|
function opCharHint(src) {
|
|
2282
1492
|
let q = '';
|
|
2283
1493
|
for (let i = 0; i < src.length; i++) {
|
|
@@ -2305,12 +1515,6 @@ function rawToVal(n) {
|
|
|
2305
1515
|
if (Array.isArray(n)) {
|
|
2306
1516
|
return new ListVal_1.ListVal({ peg: n.map(rawToVal) });
|
|
2307
1517
|
}
|
|
2308
|
-
// THE SCALAR ARMS ARE WHERE A CONFIG FILE BECOMES VALUES. Every
|
|
2309
|
-
// format on the include table is read by its own parser into plain
|
|
2310
|
-
// JavaScript -- a string, a number, a map -- and this is the walk
|
|
2311
|
-
// that turns that into Vals (dataProcessor, ADR-012). The two arms
|
|
2312
|
-
// above are the other caller: a raw expression TERM, which the
|
|
2313
|
-
// expression grammar hands over already built.
|
|
2314
1518
|
if (null == n) {
|
|
2315
1519
|
return new NullVal_1.NullVal({ peg: null });
|
|
2316
1520
|
}
|
|
@@ -2319,24 +1523,12 @@ function rawToVal(n) {
|
|
|
2319
1523
|
return new StringVal_1.StringVal({ peg: n });
|
|
2320
1524
|
}
|
|
2321
1525
|
if ('number' === t) {
|
|
2322
|
-
// No source text here, so the "no '.'" condition is vacuous and the
|
|
2323
|
-
// integral + int64-range conditions decide (same helper as the val
|
|
2324
|
-
// rule, so the two paths cannot drift).
|
|
2325
1526
|
return (0, numkind_1.isIntegerKind)(n) ?
|
|
2326
1527
|
new IntegerVal_1.IntegerVal({ peg: n }) : new NumberVal_1.NumberVal({ peg: n });
|
|
2327
1528
|
}
|
|
2328
1529
|
if ('boolean' === t) {
|
|
2329
1530
|
return new BooleanVal_1.BooleanVal({ peg: n });
|
|
2330
1531
|
}
|
|
2331
|
-
// AND EVERYTHING ELSE IS A MAP, with no arm after it because there is
|
|
2332
|
-
// nothing after it. Every reader on the include table answers with
|
|
2333
|
-
// the JSON kinds and no others -- probed, including the two that
|
|
2334
|
-
// could plausibly escape them: a big integer comes back a `number`,
|
|
2335
|
-
// and a TOML date is normalised to its text before it gets here. The
|
|
2336
|
-
// one include that could hand over a function was `.js`, which
|
|
2337
|
-
// ADR-012 refuses. `parse_unknown` lived here for that case and has
|
|
2338
|
-
// no producer left in this port; the Go twin keeps its own, where the
|
|
2339
|
-
// type switch really can be handed something unaccounted for.
|
|
2340
1532
|
const peg = {};
|
|
2341
1533
|
for (const k in n) {
|
|
2342
1534
|
peg[k] = rawToVal(n[k]);
|
|
@@ -2345,7 +1537,6 @@ function rawToVal(n) {
|
|
|
2345
1537
|
}
|
|
2346
1538
|
class Lang {
|
|
2347
1539
|
constructor(options) {
|
|
2348
|
-
// const start = performance.now()
|
|
2349
1540
|
this.opts = Object.assign((0, type_1.DEFAULT_OPTS)(), options);
|
|
2350
1541
|
const modelResolver = makeModelResolver(this.opts);
|
|
2351
1542
|
this.jsonic = jsonic_1.Jsonic.make();
|
|
@@ -2357,31 +1548,12 @@ class Lang {
|
|
|
2357
1548
|
this.jsonic
|
|
2358
1549
|
.use(asPlugin(multisource_1.MultiSource), {
|
|
2359
1550
|
resolver: options?.resolver || modelResolver,
|
|
2360
|
-
// `.aon` is the preferred Aontu source extension; `.aontu` also
|
|
2361
|
-
// works. `.jsonic` is retired (no longer auto-resolved); the
|
|
2362
|
-
// default `['jsonic','jsc','json','js']` is overridden here.
|
|
2363
|
-
// (Upstream option name is the misspelled `implictExt`.)
|
|
2364
|
-
//
|
|
2365
|
-
// Only these two are SEARCHED for a bare `@"name"`; `.json` and
|
|
2366
|
-
// `.jsonld` are read when NAMED, which is how a vendored
|
|
2367
|
-
// vocabulary is always written.
|
|
2368
1551
|
implictExt: ['aon', 'aontu'],
|
|
2369
|
-
// ONE ENTRY PER EXTENSION THE TABLE NAMES, built from it (see
|
|
2370
|
-
// includeProcessors) so the rule and its wiring cannot drift.
|
|
2371
|
-
//
|
|
2372
|
-
// The upstream defaults are REPLACED, not extended. Its `json`
|
|
2373
|
-
// entry is what made that extension the one that crashed: it
|
|
2374
|
-
// hands back a raw JS object where the aontu grammar produces
|
|
2375
|
-
// Vals, and the tree then met a value it could not convert
|
|
2376
|
-
// (BUGS §49b). Its `js` entry EXECUTES the file, which is not
|
|
2377
|
-
// something an extension should be able to ask for. And its
|
|
2378
|
-
// fallback hands any other file back as TEXT.
|
|
2379
1552
|
processor: includeProcessors(this.opts.textExt)
|
|
2380
1553
|
})
|
|
2381
1554
|
.use(AontuJsonic);
|
|
2382
1555
|
}
|
|
2383
1556
|
parse(src, opts) {
|
|
2384
|
-
// const start = performance.now()
|
|
2385
1557
|
// JSONIC-UPDATE - check meta
|
|
2386
1558
|
let jm = {
|
|
2387
1559
|
fs: opts?.fs,
|
|
@@ -2404,7 +1576,6 @@ class Lang {
|
|
|
2404
1576
|
if (opts && null != opts.log && Number.isInteger(opts.log)) {
|
|
2405
1577
|
jm.log = opts.log;
|
|
2406
1578
|
}
|
|
2407
|
-
// jm.log = -1
|
|
2408
1579
|
let val;
|
|
2409
1580
|
try {
|
|
2410
1581
|
val = this.jsonic(src, jm);
|
|
@@ -2419,14 +1590,6 @@ class Lang {
|
|
|
2419
1590
|
catch (e) {
|
|
2420
1591
|
if ('include_denied' === e?.code || 'include_extension' === e?.code ||
|
|
2421
1592
|
'multisource_not_found' === e?.code || mod_1.MODULE_REFUSAL_CODES.has(e?.code)) {
|
|
2422
|
-
// A denied include (G5), an include whose extension is not read
|
|
2423
|
-
// as Aontu source (ADR-012, INCLUDE_KINDS), an `aontu:` name the
|
|
2424
|
-
// engine does not serve (MODELS.0.md D1), and a module that is
|
|
2425
|
-
// missing, fails its pin, or names a path that escapes its store
|
|
2426
|
-
// (G6 phase 2) are refused the same way, for the same reason: the
|
|
2427
|
-
// resolver THROWS so a bare-member include cannot vanish in the
|
|
2428
|
-
// merge, and the code survives here as the parse-stage nil the
|
|
2429
|
-
// registry pins (errcodes.tsv).
|
|
2430
1593
|
val = new NilVal_1.NilVal({
|
|
2431
1594
|
why: 'parse',
|
|
2432
1595
|
err: new NilVal_1.NilVal({
|
|
@@ -2442,14 +1605,6 @@ class Lang {
|
|
|
2442
1605
|
msg: e.message + opCharHint(src),
|
|
2443
1606
|
err: e,
|
|
2444
1607
|
});
|
|
2445
|
-
// THE POSITION TRAVELS WITH IT. The parser knows exactly where
|
|
2446
|
-
// it stopped -- it draws a caret there -- and the rendered
|
|
2447
|
-
// message carried the only copy, so `vet --format json`
|
|
2448
|
-
// reported row -1, col -1 for a document whose fault the human
|
|
2449
|
-
// renderer located to the character. A machine-readable report
|
|
2450
|
-
// that says "somewhere in this file" is the one a repair loop
|
|
2451
|
-
// can do nothing with. Both numbers are already 1-based here,
|
|
2452
|
-
// which is the base a site uses (go/lang.go does the same).
|
|
2453
1608
|
if ('number' === typeof e.lineNumber) {
|
|
2454
1609
|
syntax.site.row = e.lineNumber;
|
|
2455
1610
|
}
|