aontu 0.62.0 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agentsmd.js +0 -27
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.js +0 -92
- package/dist/allow.js.map +1 -1
- package/dist/aontu.d.ts +1 -1
- package/dist/aontu.js +1 -79
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.d.ts +4 -0
- package/dist/aontumodel.js +33 -0
- package/dist/aontumodel.js.map +1 -0
- package/dist/cli.js +101 -620
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +0 -48
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js +0 -32
- package/dist/diff.js.map +1 -1
- package/dist/err.js +0 -40
- package/dist/err.js.map +1 -1
- package/dist/escape.js +0 -45
- package/dist/escape.js.map +1 -1
- package/dist/exactjson.d.ts +0 -35
- package/dist/exactjson.js +0 -131
- package/dist/exactjson.js.map +1 -1
- package/dist/format.js +13 -203
- package/dist/format.js.map +1 -1
- package/dist/grammar.d.ts +9 -0
- package/dist/grammar.js +54 -0
- package/dist/grammar.js.map +1 -0
- package/dist/graph.js +0 -26
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +0 -82
- package/dist/hcanon.js.map +1 -1
- package/dist/helpdoc.js +1 -1
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +54 -55
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +0 -114
- package/dist/jsonschema.js.map +1 -1
- package/dist/keyorder.d.ts +0 -7
- package/dist/keyorder.js +0 -41
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +17 -915
- package/dist/lang.js.map +1 -1
- package/dist/lower.js +11 -61
- package/dist/lower.js.map +1 -1
- package/dist/lsp-server.js +0 -16
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +12 -159
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +0 -26
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +0 -113
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +0 -130
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +0 -162
- package/dist/mod.js.map +1 -1
- package/dist/patch.js +0 -217
- package/dist/patch.js.map +1 -1
- package/dist/provenance.js +0 -140
- package/dist/provenance.js.map +1 -1
- package/dist/query.js +0 -75
- package/dist/query.js.map +1 -1
- package/dist/reach.js +0 -43
- package/dist/reach.js.map +1 -1
- package/dist/relation.js +0 -61
- package/dist/relation.js.map +1 -1
- package/dist/render.js +20 -135
- package/dist/render.js.map +1 -1
- package/dist/report-sarif.d.ts +0 -11
- package/dist/report-sarif.js +0 -28
- package/dist/report-sarif.js.map +1 -1
- package/dist/sig.js +0 -35
- package/dist/sig.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/siggate.js +0 -4
- package/dist/siggate.js.map +1 -1
- package/dist/site.js +3 -29
- package/dist/site.js.map +1 -1
- package/dist/subsume.d.ts +0 -10
- package/dist/subsume.js +0 -137
- package/dist/subsume.js.map +1 -1
- package/dist/template.d.ts +2 -1
- package/dist/template.js +58 -138
- package/dist/template.js.map +1 -1
- package/dist/trim.js +0 -41
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.js +12 -242
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +0 -22
- package/dist/utility.js.map +1 -1
- package/dist/val/AbnfFuncVal.d.ts +18 -0
- package/dist/val/AbnfFuncVal.js +132 -0
- package/dist/val/AbnfFuncVal.js.map +1 -0
- package/dist/val/AbsentVal.d.ts +11 -0
- package/dist/val/AbsentVal.js +30 -0
- package/dist/val/AbsentVal.js.map +1 -0
- package/dist/val/AggFuncVal.d.ts +10 -1
- package/dist/val/AggFuncVal.js +104 -116
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/ArithFuncVal.js +0 -12
- package/dist/val/ArithFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -78
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +0 -16
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +0 -16
- package/dist/val/BigIntegerVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +0 -9
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/CmpFuncVal.js +2 -59
- package/dist/val/CmpFuncVal.js.map +1 -1
- package/dist/val/ConjunctVal.js +0 -29
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +0 -500
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.js +0 -2
- package/dist/val/ContainerKindVal.js.map +1 -1
- package/dist/val/CopyFuncVal.js +0 -3
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.js +0 -179
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +0 -152
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.js +0 -3
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +1 -1
- package/dist/val/EmitFuncVal.js +6 -119
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/ExpectVal.js +0 -62
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +0 -25
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +7 -127
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.js +0 -15
- package/dist/val/GraphAtomVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +0 -13
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.js +0 -61
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +0 -20
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.js +0 -46
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +0 -57
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +0 -11
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +0 -151
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +0 -27
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
- package/dist/val/MaybeFuncVal.js +50 -0
- package/dist/val/MaybeFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js +0 -18
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +0 -60
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.js +8 -42
- package/dist/val/NomFuncVal.js.map +1 -1
- package/dist/val/NumberVal.js +0 -15
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -0
- package/dist/val/OpBaseVal.js +3 -15
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +0 -34
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +0 -6
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.js +0 -41
- package/dist/val/PathVal.js.map +1 -1
- package/dist/val/PlaceVal.js +0 -25
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +1 -7
- package/dist/val/PlusOpVal.js +13 -74
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js +0 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.js +0 -167
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.js +0 -55
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.js +0 -282
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +0 -232
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +0 -49
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +0 -11
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StrFuncVal.js +0 -18
- package/dist/val/StrFuncVal.js.map +1 -1
- package/dist/val/SuperFuncVal.js +0 -32
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +0 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TranslateFuncVal.js +1 -3
- package/dist/val/TranslateFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js +0 -11
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -0
- package/dist/val/Val.js +2 -133
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +0 -12
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.js +0 -37
- package/dist/val/arith.js.map +1 -1
- package/dist/val/caserange.js +0 -61
- package/dist/val/caserange.js.map +1 -1
- package/dist/val/members.js +0 -6
- package/dist/val/members.js.map +1 -1
- package/dist/val/numcmp.js +0 -11
- package/dist/val/numcmp.js.map +1 -1
- package/dist/val/numkind.js +0 -145
- package/dist/val/numkind.js.map +1 -1
- package/dist/val/valutil.js +0 -16
- package/dist/val/valutil.js.map +1 -1
- package/dist/vet.js +0 -461
- package/dist/vet.js.map +1 -1
- package/dist/view.js +0 -414
- package/dist/view.js.map +1 -1
- package/dist/walk.js +0 -41
- package/dist/walk.js.map +1 -1
- package/grammar/aontu.abnf +8 -6
- package/grammar/aontu.gbnf +4 -4
- package/grammar/aontu.lark +4 -4
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/src/agentsmd.ts +0 -35
- package/src/alias.ts +0 -39
- package/src/allow.ts +1 -96
- package/src/aontu.ts +3 -110
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +113 -682
- package/src/ctx.ts +0 -103
- package/src/diff.ts +0 -40
- package/src/err.ts +0 -40
- package/src/escape.ts +0 -46
- package/src/exactjson.ts +0 -131
- package/src/format.ts +14 -257
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +1 -1
- package/src/hints.ts +66 -57
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +19 -931
- package/src/lower.ts +12 -62
- package/src/lsp-server.ts +0 -16
- package/src/lsp.ts +12 -180
- package/src/mcp-server.ts +0 -31
- package/src/mcp.ts +0 -130
- package/src/mod-tool.ts +0 -158
- package/src/mod.ts +0 -178
- package/src/patch.ts +0 -232
- package/src/provenance.ts +0 -183
- package/src/query.ts +0 -84
- package/src/reach.ts +0 -53
- package/src/relation.ts +0 -84
- package/src/render.ts +20 -172
- package/src/report-sarif.ts +0 -48
- package/src/sig.ts +0 -35
- package/src/sigdecl.ts +1 -1
- package/src/siggate.ts +0 -30
- package/src/site.ts +3 -29
- package/src/subsume.ts +1 -161
- package/src/template.ts +69 -140
- package/src/trim.ts +0 -53
- package/src/type.ts +2 -45
- package/src/unify.ts +13 -251
- package/src/utility.ts +0 -31
- package/src/val/AbnfFuncVal.ts +181 -0
- package/src/val/AbsentVal.ts +54 -0
- package/src/val/AggFuncVal.ts +152 -188
- package/src/val/ArithFuncVal.ts +0 -20
- package/src/val/BagVal.ts +1 -78
- package/src/val/BigDecimalVal.ts +0 -16
- package/src/val/BigIntegerVal.ts +0 -16
- package/src/val/CloseFuncVal.ts +0 -9
- package/src/val/CmpFuncVal.ts +4 -166
- package/src/val/ConjunctVal.ts +0 -33
- package/src/val/ConstraintVal.ts +2 -537
- package/src/val/ContainerKindVal.ts +0 -18
- package/src/val/CopyFuncVal.ts +0 -5
- package/src/val/Decimal.ts +1 -185
- package/src/val/DeprecateFuncVal.ts +0 -10
- package/src/val/DisjunctVal.ts +0 -157
- package/src/val/EachFuncVal.ts +0 -40
- package/src/val/EmitFuncVal.ts +8 -208
- package/src/val/ExpectVal.ts +0 -62
- package/src/val/FilterFuncVal.ts +0 -55
- package/src/val/FuncBaseVal.ts +9 -130
- package/src/val/GraphAtomVal.ts +0 -42
- package/src/val/HideFuncVal.ts +0 -15
- package/src/val/IntegerVal.ts +0 -61
- package/src/val/JunctionVal.ts +0 -20
- package/src/val/KeyFuncVal.ts +0 -48
- package/src/val/ListVal.ts +0 -59
- package/src/val/LowerFuncVal.ts +0 -12
- package/src/val/MapVal.ts +0 -151
- package/src/val/MatchFuncVal.ts +0 -59
- package/src/val/MaybeFuncVal.ts +86 -0
- package/src/val/MoveFuncVal.ts +0 -20
- package/src/val/NilVal.ts +0 -60
- package/src/val/NomFuncVal.ts +8 -95
- package/src/val/NumberVal.ts +0 -16
- package/src/val/OpBaseVal.ts +4 -17
- package/src/val/PackFuncVal.ts +0 -63
- package/src/val/PathFuncVal.ts +0 -32
- package/src/val/PathVal.ts +0 -66
- package/src/val/PlaceVal.ts +0 -45
- package/src/val/PlusOpVal.ts +18 -75
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +0 -179
- package/src/val/RecurseVal.ts +0 -81
- package/src/val/RefVal.ts +1 -285
- package/src/val/ReferFuncVal.ts +0 -255
- package/src/val/ScalarKindVal.ts +0 -50
- package/src/val/ScalarVal.ts +0 -12
- package/src/val/StrFuncVal.ts +0 -44
- package/src/val/SuperFuncVal.ts +0 -42
- package/src/val/TopVal.ts +0 -1
- package/src/val/TranslateFuncVal.ts +1 -51
- package/src/val/UpperFuncVal.ts +0 -12
- package/src/val/Val.ts +3 -192
- package/src/val/VarVal.ts +0 -15
- package/src/val/arith.ts +0 -92
- package/src/val/caserange.ts +0 -62
- package/src/val/members.ts +0 -23
- package/src/val/numcmp.ts +1 -27
- package/src/val/numkind.ts +0 -149
- package/src/val/valutil.ts +0 -16
- package/src/vet.ts +1 -582
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -672
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/dist/val/NamerFuncVal.d.ts +0 -12
- package/dist/val/NamerFuncVal.js +0 -176
- package/dist/val/NamerFuncVal.js.map +0 -1
- package/src/std.ts +0 -683
package/src/val/ConstraintVal.ts
CHANGED
|
@@ -1,36 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
/*
|
|
4
|
-
* The constraint algebra's residual value (G1 phase 1: bounds and neq;
|
|
5
|
-
* docs/reference-language.md, "The constraint algebra"). A
|
|
6
|
-
* ConstraintVal is the normal form of any meet of Band A atoms over
|
|
7
|
-
* one domain: an interval (endpoints with open/closed flags), an
|
|
8
|
-
* exclusion set (from neq), and an optional numeric-leaf kind
|
|
9
|
-
* narrowing (from meeting `integer` etc.). Its rules, decided in
|
|
10
|
-
* phase 0 and mirrored by go/constraint.go:
|
|
11
|
-
*
|
|
12
|
-
* - Order is a property of the number line: a numeric bound admits
|
|
13
|
-
* ANY numeric leaf at an admissible position, compared exactly
|
|
14
|
-
* (numcmp.ts), and never narrows the peer's leaf by itself.
|
|
15
|
-
* - Endpoints keep their written leaf (canon renders the stored
|
|
16
|
-
* scalar); two endpoints at the SAME point keep the tower-lowest
|
|
17
|
-
* leaf. No endpoint rewriting, ever (lazy endpoints).
|
|
18
|
-
* - neq excludes by scalar identity — leaf AND value.
|
|
19
|
-
* - Emptiness is decided eagerly where it is exact: empty interval,
|
|
20
|
-
* integral gap under an integer/biginteger narrowing, point
|
|
21
|
-
* deletion under a narrowed leaf, domain mixing. Representability
|
|
22
|
-
* holes of the int64-window integer leaf are deliberately NOT
|
|
23
|
-
* modelled (sound — no false conflicts; incomplete — those
|
|
24
|
-
* contradictions surface against data), matching the algebra's
|
|
25
|
-
* regex-approximation philosophy.
|
|
26
|
-
* - Canonical atom order: kind, lower bound, upper bound, neq
|
|
27
|
-
* (arguments sorted); `parse(canon(v)) == v` holds because the
|
|
28
|
-
* reparse is a conjunct of atoms that normalises back to the
|
|
29
|
-
* identical residual.
|
|
30
|
-
*
|
|
31
|
-
* A constraint violation raises the registered `constraint` code
|
|
32
|
-
* (class conflict), with the admissible set in NilVal.details.
|
|
33
|
-
*/
|
|
34
3
|
|
|
35
4
|
import type {
|
|
36
5
|
Val,
|
|
@@ -92,7 +61,7 @@ type Bound = {
|
|
|
92
61
|
}
|
|
93
62
|
|
|
94
63
|
type ReAtom = {
|
|
95
|
-
v: any
|
|
64
|
+
v: any
|
|
96
65
|
src: string // the pattern text AS WRITTEN — canon and dedup use this,
|
|
97
66
|
// never the normalised form, because canon round-trips
|
|
98
67
|
// source and G6's hash will be taken over canon
|
|
@@ -115,7 +84,7 @@ type ConstraintState = {
|
|
|
115
84
|
count?: ConstraintState // the COUNT residual (length()), itself a residual
|
|
116
85
|
// over the integer domain -- the count atom reuses
|
|
117
86
|
// this same algebra recursively
|
|
118
|
-
uniq: boolean
|
|
87
|
+
uniq: boolean
|
|
119
88
|
uniqBy: string[] // ... and distinct ON EACH OF THESE KEYS
|
|
120
89
|
// (unique(k)), sorted and deduplicated
|
|
121
90
|
musts: MustAtom[] // Band B checks, kept in written order, never simplified
|
|
@@ -126,73 +95,6 @@ type ConstraintState = {
|
|
|
126
95
|
}
|
|
127
96
|
|
|
128
97
|
|
|
129
|
-
// THE PATTERN SUBSET, AND HOW IT IS ENFORCED (G1 phase 2; ADR-003).
|
|
130
|
-
//
|
|
131
|
-
// `re(p)` must mean the same thing in both engines and cost about the
|
|
132
|
-
// same, and the two host engines guarantee neither: TypeScript compiles
|
|
133
|
-
// with JavaScript's backtracking RegExp, Go with RE2 — a different
|
|
134
|
-
// language in a different complexity class, over a different alphabet.
|
|
135
|
-
//
|
|
136
|
-
// The enforcement is NORMALISATION, not refusal (ADR-003). Every
|
|
137
|
-
// construct whose expansion is engine-defined is rewritten here, by
|
|
138
|
-
// this function, into an explicit form that cannot be read two ways;
|
|
139
|
-
// only the rewritten pattern reaches a host engine. The alternative —
|
|
140
|
-
// refusing everything that might differ — was tried first and leaked
|
|
141
|
-
// three times, because its correctness depended on this comment knowing
|
|
142
|
-
// every difference between two large engines.
|
|
143
|
-
//
|
|
144
|
-
// Aontu therefore DEFINES the abbreviations rather than inheriting
|
|
145
|
-
// either host's. The definitions are deliberately the small ASCII ones,
|
|
146
|
-
// because a config value containing U+00A0 is a mistake to catch, not a
|
|
147
|
-
// space to accept silently:
|
|
148
|
-
//
|
|
149
|
-
// \d [0-9] \D [^0-9]
|
|
150
|
-
// \w [0-9A-Za-z_] \W [^0-9A-Za-z_]
|
|
151
|
-
// \s [ \t\n\r\f\v] \S [^ \t\n\r\f\v]
|
|
152
|
-
// . [^\n]
|
|
153
|
-
// \A ^ \z $
|
|
154
|
-
//
|
|
155
|
-
// Neither host agreed with all of these before rewriting: JavaScript's
|
|
156
|
-
// \s also matches U+00A0 and other Unicode spaces, RE2's omits \v, and
|
|
157
|
-
// the two `.` sets differ by \r and the Unicode line separators. After
|
|
158
|
-
// rewriting, both engines see one explicit class and cannot disagree.
|
|
159
|
-
//
|
|
160
|
-
// What is still REFUSED, and why refusal is right for these:
|
|
161
|
-
//
|
|
162
|
-
// 1. Constructs one engine simply lacks — backreferences and
|
|
163
|
-
// lookaround (not in RE2, and not expressible as regular
|
|
164
|
-
// expressions at all), POSIX classes, `\p{...}`, `\x{...}`, `\u`.
|
|
165
|
-
// There is nothing to normalise them TO.
|
|
166
|
-
// 2. `(?` other than `(?:` — named groups are spelled differently
|
|
167
|
-
// (`(?P<n>` in RE2, `(?<n>` in JavaScript) and inline flags change
|
|
168
|
-
// the meaning of everything after them.
|
|
169
|
-
// 3. A quantifier applied to a group containing a quantifier or an
|
|
170
|
-
// alternation. This one is about TIME, not meaning: `(a+)+$`
|
|
171
|
-
// against twenty-nine characters takes 45 SECONDS in JavaScript
|
|
172
|
-
// and 0.065s under RE2, and a regex match is counted by no
|
|
173
|
-
// evaluator budget, so an untrusted schema could otherwise stall
|
|
174
|
-
// the TypeScript evaluator indefinitely (docs/trust.md clause 2).
|
|
175
|
-
// Normalisation cannot fix a complexity difference; only owning the
|
|
176
|
-
// matcher could, which ADR-003 records as the future option.
|
|
177
|
-
//
|
|
178
|
-
// The alphabet is fixed separately, by compiling with the `u` flag:
|
|
179
|
-
// JavaScript otherwise matches UTF-16 code units where RE2 matches code
|
|
180
|
-
// points, so `^.$` accepted U+1D11E in Go and refused it in TypeScript.
|
|
181
|
-
//
|
|
182
|
-
// This function is mirrored statement for statement in go/constraint.go,
|
|
183
|
-
// and `test/spec/files/regex-corpus.txt` pins that the two produce
|
|
184
|
-
// byte-identical output for every pattern in a generated corpus.
|
|
185
|
-
|
|
186
|
-
// The largest repeat count Aontu's pattern language admits. RE2 caps a
|
|
187
|
-
// repeat at 1000 and refuses to compile past it, where JavaScript's
|
|
188
|
-
// backtracking engine accepts any count -- so `re("^a{1001}$")` was
|
|
189
|
-
// VALID in TypeScript and an `error` verdict in Go, a cross-port
|
|
190
|
-
// verdict flip on a schema an agent could be handed
|
|
191
|
-
// (status-2026-08-21.md section 4). Under ADR-003 the host's own
|
|
192
|
-
// compile failure must never be what a user sees, so the bound is
|
|
193
|
-
// Aontu's: at most RE_REPEAT_MAX, refused identically in both ports
|
|
194
|
-
// before either engine compiles. Nested products beyond the cap were
|
|
195
|
-
// already refused, by the quantified-group rule below.
|
|
196
98
|
const RE_REPEAT_MAX = 1000
|
|
197
99
|
|
|
198
100
|
// The normative expansions. These are Aontu's definitions, not either
|
|
@@ -201,28 +103,12 @@ const RE_CLASS_DIGIT = '0-9'
|
|
|
201
103
|
const RE_CLASS_WORD = '0-9A-Za-z_'
|
|
202
104
|
const RE_CLASS_SPACE = ' \\t\\n\\r\\f\\v'
|
|
203
105
|
|
|
204
|
-
// Metacharacters that may be escaped to mean themselves, in both
|
|
205
|
-
// engines. `-` is handled separately: it is legal escaped only INSIDE a
|
|
206
|
-
// character class, because RE2 accepts `a\-b` and JavaScript's unicode
|
|
207
|
-
// mode makes it a syntax error.
|
|
208
106
|
const RE_ESCAPE_PUNCT = '\\.+*?()[]{}|^$/'
|
|
209
107
|
|
|
210
108
|
// Escapes passed through unchanged: the control characters, the ASCII
|
|
211
109
|
// word boundary, and `\xHH`. Each was probed in both engines.
|
|
212
110
|
const RE_ESCAPE_PASS = 'tnrfv'
|
|
213
111
|
|
|
214
|
-
// A counted quantifier `{n}`, `{n,}` or `{n,m}` starting at `src[at]`.
|
|
215
|
-
// Two rules, both about what the hosts do NOT share:
|
|
216
|
-
//
|
|
217
|
-
// - A bound above RE_REPEAT_MAX: RE2 refuses to compile it, JavaScript
|
|
218
|
-
// accepts it.
|
|
219
|
-
// - A brace that does not open a well-formed counted quantifier at
|
|
220
|
-
// all (`x{y}`, `a{`, `{,5}`): JavaScript compiled with the `u` flag
|
|
221
|
-
// makes it a SYNTAX ERROR, while RE2 reads it as a literal brace, so
|
|
222
|
-
// `re("^x{y}$")` was `constraint_pattern` in TypeScript and a plain
|
|
223
|
-
// unresolved value in Go -- the same class of verdict flip as the
|
|
224
|
-
// repeat cap, found by sweeping around it. A literal brace is
|
|
225
|
-
// written escaped (`a\\{1001\\}`), which both engines share.
|
|
226
112
|
function repeatWhy(src: string, at: number): [string, number] {
|
|
227
113
|
const bad = (what: string): [string, number] => [
|
|
228
114
|
'a ' + what + ', which the two engines do not read the same way', -1]
|
|
@@ -367,10 +253,6 @@ function normaliseRe(src: string): [string, string] {
|
|
|
367
253
|
let inClass = false
|
|
368
254
|
const out: string[] = []
|
|
369
255
|
|
|
370
|
-
// One frame per open group, recording whether it contains a quantifier
|
|
371
|
-
// or an alternation. A group carrying either may not itself be
|
|
372
|
-
// quantified; containment is transitive, so a frame hands its flags up
|
|
373
|
-
// to its parent when it closes.
|
|
374
256
|
const groups: { q: boolean, alt: boolean }[] = []
|
|
375
257
|
const mark = (k: 'q' | 'alt') => {
|
|
376
258
|
if (0 < groups.length) {
|
|
@@ -395,14 +277,6 @@ function normaliseRe(src: string): [string, string] {
|
|
|
395
277
|
return ['', why]
|
|
396
278
|
}
|
|
397
279
|
out.push(emit)
|
|
398
|
-
// `\b` AND `\B` ARE ASSERTIONS TOO, and quantifying one is the
|
|
399
|
-
// same disagreement `^{1}` is: JavaScript under `u` calls it a
|
|
400
|
-
// syntax error, RE2 quantifies the assertion happily. The rule
|
|
401
|
-
// said "`\b` and `\B` quantify identically in both and are left
|
|
402
|
-
// alone" and that was measured wrong -- `re("\\b{1}x")` is
|
|
403
|
-
// `constraint_pattern` in TypeScript and an accepted schema in
|
|
404
|
-
// Go. Only OUTSIDE a class: inside one, `\b` is a backspace in
|
|
405
|
-
// both engines and repeats like any other character.
|
|
406
280
|
if (!inClass && ('b' === src[i + 1] || 'B' === src[i + 1])) {
|
|
407
281
|
anchorPrev = true
|
|
408
282
|
}
|
|
@@ -410,9 +284,6 @@ function normaliseRe(src: string): [string, string] {
|
|
|
410
284
|
continue
|
|
411
285
|
}
|
|
412
286
|
|
|
413
|
-
// A POSIX class opener, anywhere: the form lives inside an ordinary
|
|
414
|
-
// class (`[[:alpha:]]`), and refusing it everywhere is one rule
|
|
415
|
-
// rather than two.
|
|
416
287
|
if ('[' === c && ':' === src[i + 1]) {
|
|
417
288
|
return ['', 'a POSIX class ([:...:]), which JavaScript does not have']
|
|
418
289
|
}
|
|
@@ -482,12 +353,6 @@ function normaliseRe(src: string): [string, string] {
|
|
|
482
353
|
}
|
|
483
354
|
|
|
484
355
|
if ('*' === c || '+' === c || '?' === c || '{' === c) {
|
|
485
|
-
// Nothing to repeat. JavaScript under the `u` flag makes this a
|
|
486
|
-
// SYNTAX ERROR, where RE2 quantifies the assertion happily and
|
|
487
|
-
// matches, so `re("^{1}")` was `constraint_pattern` in
|
|
488
|
-
// TypeScript and an accepted schema in Go. The four assertions
|
|
489
|
-
// behave alike here -- `^`, `$`, `\b` and `\B` -- so the rule
|
|
490
|
-
// names all four.
|
|
491
356
|
if (afterAnchor) {
|
|
492
357
|
return ['', 'a quantifier applied to `^`, `$`, `\\b` or ' +
|
|
493
358
|
'`\\B`, which has nothing to repeat']
|
|
@@ -504,10 +369,6 @@ function normaliseRe(src: string): [string, string] {
|
|
|
504
369
|
continue
|
|
505
370
|
}
|
|
506
371
|
|
|
507
|
-
// A `}` that closes no counted quantifier: JavaScript under `u`
|
|
508
|
-
// refuses it as a lone quantifier bracket, RE2 reads it as a
|
|
509
|
-
// literal. Written escaped inside a class (`[}]`) it is a literal
|
|
510
|
-
// in both, which is the spelling that survives.
|
|
511
372
|
if ('}' === c) {
|
|
512
373
|
if (i !== repeatEnd) {
|
|
513
374
|
return ['', 'a `}` that closes no counted quantifier, which ' +
|
|
@@ -544,20 +405,11 @@ function stringLeaf(v: any): boolean {
|
|
|
544
405
|
return true === v?.isScalar && 'string' === typeof v.peg && v.isString
|
|
545
406
|
}
|
|
546
407
|
|
|
547
|
-
// The VALUE-admission widening of stringLeaf: a path value is a string
|
|
548
|
-
// with more structure (path <: string, ADR-016), so the string-domain
|
|
549
|
-
// constraints admit one -- `refer() & re("auth$")` must still check a
|
|
550
|
-
// link whose value is now a path. The ARGUMENT sites keep the strict
|
|
551
|
-
// test: a pattern, a bound or an exclusion is spelled with a plain
|
|
552
|
-
// string, never a path.
|
|
553
408
|
function stringishLeaf(v: any): boolean {
|
|
554
409
|
return stringLeaf(v) || (true === v?.isScalar && true === v.isPath)
|
|
555
410
|
}
|
|
556
411
|
|
|
557
412
|
|
|
558
|
-
// Scalar identity: leaf AND value, the lattice's own rule (1 and 1.0
|
|
559
|
-
// are different scalars). Exact numeric comparison decides the value
|
|
560
|
-
// half for numeric leaves.
|
|
561
413
|
function sameScalar(a: any, b: any): boolean {
|
|
562
414
|
if (numericLeaf(a) && numericLeaf(b)) {
|
|
563
415
|
return towerRank(a) === towerRank(b) && 0 === cmpNumeric(a, b)
|
|
@@ -589,20 +441,6 @@ function leafMarker(v: any): any {
|
|
|
589
441
|
}
|
|
590
442
|
|
|
591
443
|
|
|
592
|
-
// Conjunct sort order for an atom that must see the WHOLE value.
|
|
593
|
-
// Every other value sorts below the container default (99999), so such
|
|
594
|
-
// an atom is the LAST term to fold: `a:length(2) a:{x:1} a:{y:2}` must
|
|
595
|
-
// count the MERGED map, and a constraint that folded at 50000 would
|
|
596
|
-
// count `{x:1}` alone and refuse the layering that is the whole point
|
|
597
|
-
// of the language.
|
|
598
|
-
//
|
|
599
|
-
// The order atoms keep the low slot: `min(2) & 1 & 2` may decide as
|
|
600
|
-
// soon as it sees a scalar, because meeting more scalars can only
|
|
601
|
-
// narrow. Meeting more containers GROWS the member set, which is why
|
|
602
|
-
// the two orders differ.
|
|
603
|
-
//
|
|
604
|
-
// Three atoms are late: `length` and `unique` (they count members), and
|
|
605
|
-
// `must` (an evaluate-only check against the finished value).
|
|
606
444
|
const LATE_CJO = 150000
|
|
607
445
|
|
|
608
446
|
function lateAtom(atom: string): boolean {
|
|
@@ -655,16 +493,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
655
493
|
}
|
|
656
494
|
else if (spec.atom) {
|
|
657
495
|
const args = atomArgs(spec.atom, (spec.peg as any[]) ?? [])
|
|
658
|
-
// An argument that is not yet concrete — a reference, an
|
|
659
|
-
// arithmetic expression, a conjunct of atoms — makes the whole
|
|
660
|
-
// atom PENDING rather than invalid (G1 phase 4). It is resolved
|
|
661
|
-
// in unify, where there is a ctx to resolve through, and the
|
|
662
|
-
// residual is built from the settled arguments. Only a settled
|
|
663
|
-
// argument of the wrong shape is an `invalid-arg`.
|
|
664
|
-
// The effectful-argument refusal happens HERE, on the written
|
|
665
|
-
// form, and not in fromAtom: settling is what runs the effect, so
|
|
666
|
-
// by the time fromAtom sees a settled `move($.b)` the move has
|
|
667
|
-
// already happened and the argument is just its result.
|
|
668
496
|
if ('must' === spec.atom && args.some((a: any) => holdsMove(a))) {
|
|
669
497
|
this.invalid = 'invalid-arg'
|
|
670
498
|
}
|
|
@@ -694,27 +522,11 @@ class ConstraintVal extends FeatureVal {
|
|
|
694
522
|
}
|
|
695
523
|
|
|
696
524
|
|
|
697
|
-
// Normalise one atom call into state. Every argument here is already
|
|
698
|
-
// SETTLED — the constructor routes an unsettled one to `pending` —
|
|
699
|
-
// so a shape this cannot use is a genuine `invalid-arg`, not a
|
|
700
|
-
// not-yet.
|
|
701
525
|
private fromAtom(atom: string, args: any[]): void {
|
|
702
|
-
// Mark the residual invalid. It answers NOTHING: every caller
|
|
703
|
-
// spells its exit `return bad(...)` and none reads a value, so a
|
|
704
|
-
// return type would be a value nobody consumes -- and a routine
|
|
705
|
-
// that answers on some paths and not others is the shape a reader
|
|
706
|
-
// (and a static analyser) has to stop and check.
|
|
707
526
|
const bad = (why: string): void => {
|
|
708
527
|
this.invalid = why
|
|
709
528
|
}
|
|
710
529
|
|
|
711
|
-
// `unique()` is a property of the container -- not a comparison
|
|
712
|
-
// against a value -- so with no argument it says the members are
|
|
713
|
-
// pairwise DISTINCT. THE ONE ARGUMENT IS A PROJECTOR (the review's
|
|
714
|
-
// finding I: "unique()-by-field is reserved but absent", and the
|
|
715
|
-
// arity was reserved for exactly this): `unique(port)` says no two
|
|
716
|
-
// members share a `port`, which is how "no two services share a
|
|
717
|
-
// port" and "event ids are unique" are said.
|
|
718
530
|
if ('unique' === atom) {
|
|
719
531
|
if (0 === args.length) {
|
|
720
532
|
this.uniq = true
|
|
@@ -727,12 +539,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
727
539
|
return
|
|
728
540
|
}
|
|
729
541
|
|
|
730
|
-
// `must(c, msg)` is Band B: an evaluate-only check against the
|
|
731
|
-
// finished value, carrying the author's own message. It is KEPT,
|
|
732
|
-
// never simplified and never consulted for emptiness or
|
|
733
|
-
// subsumption — Band B is opaque by construction, which is exactly
|
|
734
|
-
// what makes it the honest channel for a rule the algebra cannot
|
|
735
|
-
// reason about (docs/reference-language.md, "Band B: `must`").
|
|
736
542
|
if ('must' === atom) {
|
|
737
543
|
if (2 !== args.length) {
|
|
738
544
|
return bad('arg')
|
|
@@ -740,11 +546,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
740
546
|
if (!stringLeaf(args[1])) {
|
|
741
547
|
return bad('invalid-arg')
|
|
742
548
|
}
|
|
743
|
-
// A check carrying a nil can never be satisfied, so it is refused
|
|
744
|
-
// as an ARGUMENT rather than left to fail against every value with
|
|
745
|
-
// the author's message attached -- which would blame the data for
|
|
746
|
-
// a mistake in the check. `must([1-x],m)` is the reachable case: a
|
|
747
|
-
// degenerate expression leaves a nil inside the written list.
|
|
748
549
|
if (holdsNil(args[0])) {
|
|
749
550
|
return bad('invalid-arg')
|
|
750
551
|
}
|
|
@@ -785,8 +586,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
785
586
|
return bad('invalid-arg')
|
|
786
587
|
}
|
|
787
588
|
const src = a.peg as string
|
|
788
|
-
// Normalise BEFORE compiling: the host engines only ever see a
|
|
789
|
-
// pattern that cannot be read two ways (ADR-003).
|
|
790
589
|
const [norm, why] = normaliseRe(src)
|
|
791
590
|
if ('' !== why) {
|
|
792
591
|
this.invalidWhy = why
|
|
@@ -794,23 +593,9 @@ class ConstraintVal extends FeatureVal {
|
|
|
794
593
|
}
|
|
795
594
|
let re: RegExp
|
|
796
595
|
try {
|
|
797
|
-
// The `u` flag is REQUIRED for parity, not an optimisation.
|
|
798
|
-
// Without it JavaScript matches UTF-16 code units while RE2
|
|
799
|
-
// matches code points, so `re("^.$")` accepted U+1D11E in Go
|
|
800
|
-
// and refused it in TypeScript (and `^..$` did the reverse).
|
|
801
|
-
// With it, `.` and every quantifier count code points in both.
|
|
802
|
-
// It also makes JavaScript refuse the identity escapes this
|
|
803
|
-
// scanner rejects by hand, which is defence in depth rather
|
|
804
|
-
// than a substitute: RE2 accepts some of them, so the scanner
|
|
805
|
-
// is what keeps the two ports agreeing.
|
|
806
596
|
re = new RegExp(norm, 'u')
|
|
807
597
|
}
|
|
808
598
|
catch (e: any) {
|
|
809
|
-
// The host engine refuses what the subset scanner passed — a
|
|
810
|
-
// malformed quantifier, an unbalanced group. Same refusal under
|
|
811
|
-
// the same code: the author gets one rule, not two. The message
|
|
812
|
-
// is the host's, so it is NOT pinned by a shared row; the code
|
|
813
|
-
// and the located frame are.
|
|
814
599
|
this.invalidWhy = 'not a valid pattern'
|
|
815
600
|
return bad('constraint_pattern')
|
|
816
601
|
}
|
|
@@ -819,16 +604,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
819
604
|
return
|
|
820
605
|
}
|
|
821
606
|
|
|
822
|
-
// `length` is the other non-ORDER atom: its argument constrains the
|
|
823
|
-
// COUNT, not the value, so it is itself a residual over the integer
|
|
824
|
-
// domain (docs/reference-language.md, "`length` semantics"). It is
|
|
825
|
-
// resolved HERE, at construction, by walking the written argument
|
|
826
|
-
// rather than by unifying it: the func-paren handler builds atoms
|
|
827
|
-
// without an AontuContext, so there is nothing to fold a nested
|
|
828
|
-
// conjunct through. Walking is enough because a length argument is by
|
|
829
|
-
// definition a meet of concrete Band A atoms; anything else (a
|
|
830
|
-
// reference, an expression) is refused rather than deferred, the
|
|
831
|
-
// same discipline min/max apply to their own arguments.
|
|
832
607
|
if ('length' === atom) {
|
|
833
608
|
const arg = countArgState(a)
|
|
834
609
|
if (null == arg) {
|
|
@@ -868,15 +643,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
868
643
|
// residual is stable and the ladder is total.
|
|
869
644
|
let out: Val
|
|
870
645
|
|
|
871
|
-
// A rel residual or a graph atom HOLDS constraints for the value
|
|
872
|
-
// they stand for (RELATIONS P1/P2): hand the drive over before
|
|
873
|
-
// any settling, exactly as a container does, so `rel(t) & re(x)`
|
|
874
|
-
// reads the same in either order. Reached through the INCLUDE
|
|
875
|
-
// flow (a loaded schema's conjunct re-drives with the constraint
|
|
876
|
-
// on the left) -- inline documents route rel/atom peers through
|
|
877
|
-
// unite's b-drives first, which is why use-cases/12-relations
|
|
878
|
-
// refused without this arm while every inline row stayed green;
|
|
879
|
-
// pinned by constraint-hands-drive-to-rel-and-atom.
|
|
880
646
|
if (true === (peer as any)?.isRel
|
|
881
647
|
|| true === (peer as any)?.isGraphAtom) {
|
|
882
648
|
out = (peer as any).unify(this, ctx)
|
|
@@ -908,15 +674,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
908
674
|
}
|
|
909
675
|
/* node:coverage ignore next 12 */
|
|
910
676
|
else {
|
|
911
|
-
// Every other shape: no order, no membership, nothing to count —
|
|
912
|
-
// a conflict of the constraint family. The ladder above is total
|
|
913
|
-
// in practice: every remaining Val kind either sorts BELOW a
|
|
914
|
-
// constraint in a conjunct (conjunct, disjunct, pref, ref) and so
|
|
915
|
-
// drives the meet from its own side, or resolves to a
|
|
916
|
-
// scalar/container before a constraint sees it (func, op, var,
|
|
917
|
-
// expect). The arm is kept because "in practice" depends on the
|
|
918
|
-
// cjo table, and a future value class would land here rather than
|
|
919
|
-
// falling out of unify with no result.
|
|
920
677
|
out = this.fail(ctx, peer)
|
|
921
678
|
}
|
|
922
679
|
|
|
@@ -926,17 +683,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
926
683
|
}
|
|
927
684
|
|
|
928
685
|
|
|
929
|
-
// Resolve a pending atom's arguments and, once they have all settled,
|
|
930
|
-
// become the residual they describe (G1 phase 4).
|
|
931
|
-
//
|
|
932
|
-
// This is the residuation discipline FuncBaseVal already follows for
|
|
933
|
-
// its own operands: push each unsettled argument one step by unifying
|
|
934
|
-
// it with `top`, and if any is still moving, mark not-done and defer
|
|
935
|
-
// — either as this same pending atom (against a `top` peer) or
|
|
936
|
-
// wrapped with the peer in a conjunct the next pass will re-enter.
|
|
937
|
-
// Nothing is decided from a half-resolved argument, which is what
|
|
938
|
-
// keeps `min($.lo)` from reporting a conflict against a bound that
|
|
939
|
-
// has not arrived yet.
|
|
940
686
|
private settle(peer: Val, ctx: AontuContext): Val {
|
|
941
687
|
const TOP = top()
|
|
942
688
|
const pend = this.pending as { atom: string, args: any[] }
|
|
@@ -946,9 +692,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
946
692
|
for (const arg of pend.args) {
|
|
947
693
|
let next = arg
|
|
948
694
|
if (true !== arg?.done) {
|
|
949
|
-
// Charged to the depth budget: this recurses without going
|
|
950
|
-
// through `unite`, so the counter would otherwise stay flat
|
|
951
|
-
// while the stack grows (the rule FuncBaseVal follows).
|
|
952
695
|
next = withDepth(ctx, arg, TOP, () => arg.unify(TOP, ctx))
|
|
953
696
|
}
|
|
954
697
|
settled = settled && true === next?.done
|
|
@@ -1001,9 +744,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1001
744
|
return this.fail(ctx, peer)
|
|
1002
745
|
}
|
|
1003
746
|
if (null != this.count) {
|
|
1004
|
-
// Only a string among the scalars has a length, and it is counted
|
|
1005
|
-
// in CODE POINTS -- not UTF-16 units (this host's native count)
|
|
1006
|
-
// and not bytes (Go's). Iterating a string yields code points.
|
|
1007
747
|
if (!stringishLeaf(peer)) {
|
|
1008
748
|
return this.fail(ctx, peer)
|
|
1009
749
|
}
|
|
@@ -1022,31 +762,11 @@ class ConstraintVal extends FeatureVal {
|
|
|
1022
762
|
}
|
|
1023
763
|
|
|
1024
764
|
|
|
1025
|
-
// Band B, applied to a finished value. Each check is a plain
|
|
1026
|
-
// unification against a CLONE of the peer: `must` reports, it never
|
|
1027
|
-
// contributes: whatever the check would have added to the value is
|
|
1028
|
-
// discarded, and `peer` is returned untouched by the callers.
|
|
1029
|
-
//
|
|
1030
|
-
// The trial runs in an isolated collect context so a failing check
|
|
1031
|
-
// leaves nothing on the caller's error list — only the located nil
|
|
1032
|
-
// this returns, carrying the author's own message.
|
|
1033
|
-
// `final` is the generation-time reading (see settleContainer): a
|
|
1034
|
-
// must whose own check is a SIZING atom inherits that atom's
|
|
1035
|
-
// provisionality, because `must(length(2), …)` against a map that may
|
|
1036
|
-
// still gain members has not failed yet -- it has not been answered.
|
|
1037
|
-
// Without this the must would decide against whatever the container
|
|
1038
|
-
// held when it first settled, which is the very defect the sizing
|
|
1039
|
-
// atoms were fixed for (use-cases/BUGS.md §16, §17).
|
|
1040
765
|
private checkMusts(
|
|
1041
766
|
peer: any, ctx: AontuContext, final?: boolean): Val | undefined {
|
|
1042
767
|
for (const m of this.musts) {
|
|
1043
768
|
const trial = ctx.clone({ err: [], collect: true })
|
|
1044
769
|
let got: any = unite(trial, m.v.clone(trial), peer.clone(trial), 'must')
|
|
1045
|
-
// A must whose check is a SIZING atom answers a residue rather
|
|
1046
|
-
// than a verdict, because the atom is waiting for members that
|
|
1047
|
-
// may still arrive. Before generation that residue IS the answer
|
|
1048
|
-
// -- the must has not failed, it has not been asked yet -- and at
|
|
1049
|
-
// generation it is settled, because nothing more can arrive.
|
|
1050
770
|
const residue = sizingResidue(got)
|
|
1051
771
|
if (undefined !== residue) {
|
|
1052
772
|
if (true !== final) {
|
|
@@ -1066,27 +786,11 @@ class ConstraintVal extends FeatureVal {
|
|
|
1066
786
|
}
|
|
1067
787
|
|
|
1068
788
|
|
|
1069
|
-
// THE FINAL READING of a sizing atom over a container: the same
|
|
1070
|
-
// checks admitContainer makes, with the provisional ones taken as
|
|
1071
|
-
// decided. Called from ConjunctVal.gen, which is where no more
|
|
1072
|
-
// members can arrive. Returns the container (to generate) or the
|
|
1073
|
-
// constraint's own nil (to report).
|
|
1074
789
|
settleContainer(peer: any, ctx: AontuContext): Val {
|
|
1075
790
|
return this.admitContainer(peer, ctx, true)
|
|
1076
791
|
}
|
|
1077
792
|
|
|
1078
793
|
|
|
1079
|
-
// Membership for a container peer. Only the SIZING atoms have anything
|
|
1080
|
-
// to say about a map or a list; every other atom is scalar-domain and
|
|
1081
|
-
// refuses one.
|
|
1082
|
-
//
|
|
1083
|
-
// The members that count are the members that GENERATE
|
|
1084
|
-
// (docs/reference-language.md, "`length` semantics"), and rather than
|
|
1085
|
-
// mirror generation's filter — type/hide marks, optional keys that
|
|
1086
|
-
// drop, empty optional values — this asks generation itself, in an
|
|
1087
|
-
// isolated collect context so nothing leaks into the caller's errors.
|
|
1088
|
-
// A mirror would be a second copy of a filter that has already grown
|
|
1089
|
-
// subtle, free to drift from it; asking is correct by construction.
|
|
1090
794
|
private admitContainer(
|
|
1091
795
|
peer: any, ctx: AontuContext, final?: boolean): Val {
|
|
1092
796
|
// A scalar-domain residual has no reading over a container.
|
|
@@ -1106,13 +810,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1106
810
|
return bad
|
|
1107
811
|
}
|
|
1108
812
|
|
|
1109
|
-
// A MUST OVER A CONTAINER RESIDUATES with the atoms, for the same
|
|
1110
|
-
// reason (use-cases/BUGS.md §17): `must({t: max(60)}, …)` beside a
|
|
1111
|
-
// `{t: integer}` schema was answered against the schema layer
|
|
1112
|
-
// ALONE, and discharged before the data it was written to judge
|
|
1113
|
-
// ever arrived. It is decided at generation, where the value is
|
|
1114
|
-
// whole -- unless there is nothing else on the constraint AND the
|
|
1115
|
-
// reading is already final.
|
|
1116
813
|
if (!this.uniq && 0 === this.uniqBy.length && null == this.count) {
|
|
1117
814
|
if (true === final || 0 === this.musts.length) {
|
|
1118
815
|
return peer
|
|
@@ -1122,43 +819,12 @@ class ConstraintVal extends FeatureVal {
|
|
|
1122
819
|
|
|
1123
820
|
const members = emittedMembers(peer, ctx)
|
|
1124
821
|
if (null == members) {
|
|
1125
|
-
// NOT COUNTABLE YET IS NOT A PASS. A container that cannot
|
|
1126
|
-
// generate cannot be counted, and a SCHEMA is exactly that: the
|
|
1127
|
-
// members of `{a: integer}` are types, so nothing is emitted and
|
|
1128
|
-
// nothing can be counted. Discharging the atom here was the §16
|
|
1129
|
-
// defect wearing its other face -- `length(min(2)) & {a: integer}`
|
|
1130
|
-
// dropped its bound while still alone, so the data half of a
|
|
1131
|
-
// `vet` meet was never measured at all and short data vetted
|
|
1132
|
-
// clean against a bound the evaluator enforces.
|
|
1133
|
-
//
|
|
1134
|
-
// At generation the reading IS final: a container that still
|
|
1135
|
-
// cannot generate has its own error, and that error is the one
|
|
1136
|
-
// worth reporting, so it passes through untouched.
|
|
1137
822
|
if (true === final) {
|
|
1138
823
|
return peer
|
|
1139
824
|
}
|
|
1140
825
|
return this.hold(peer, ctx)
|
|
1141
826
|
}
|
|
1142
827
|
|
|
1143
|
-
// MONOTONE READINGS ONLY (the review's finding C, use-cases/BUGS.md
|
|
1144
|
-
// §16). Members ACCUMULATE under unification -- a meet adds keys and
|
|
1145
|
-
// never removes them -- so a settled container is settled ON ITS
|
|
1146
|
-
// OWN and not against every value that may still contribute. The
|
|
1147
|
-
// schema half of a `vet` meet, a document that is about to receive
|
|
1148
|
-
// an `@` include, a bag a later `pack` will fill: each settles, and
|
|
1149
|
-
// an atom that decided there decided too early.
|
|
1150
|
-
//
|
|
1151
|
-
// So a verdict is taken only when MORE MEMBERS CANNOT CHANGE IT:
|
|
1152
|
-
// - an upper bound VIOLATED is permanent -> refuse now;
|
|
1153
|
-
// satisfied is provisional -> keep the atom, re-check later.
|
|
1154
|
-
// - a lower bound SATISFIED is permanent -> that part may go;
|
|
1155
|
-
// violated is provisional -> keep the atom (which is why
|
|
1156
|
-
// `length(min(1))` beside a template no longer kills the schema
|
|
1157
|
-
// it was written for).
|
|
1158
|
-
// - a DUPLICATE is permanent -> refuse now; distinctness is
|
|
1159
|
-
// provisional -> keep the atom.
|
|
1160
|
-
// Anything provisional residuates, exactly as an unsettled
|
|
1161
|
-
// container does above, and the two spellings then agree.
|
|
1162
828
|
const count = null == this.count ? undefined : this.count
|
|
1163
829
|
const n = members.length
|
|
1164
830
|
if (null != count) {
|
|
@@ -1179,11 +845,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1179
845
|
}
|
|
1180
846
|
|
|
1181
847
|
if (this.uniq) {
|
|
1182
|
-
// Members compare by CANONICAL FORM, which reduces to scalar
|
|
1183
|
-
// identity for scalars (so [1, 1.0] is distinct) and gives
|
|
1184
|
-
// structural equality for container members without a second
|
|
1185
|
-
// rule. A generated value could not express the first: `1` and
|
|
1186
|
-
// `1.0` generate the same JSON number.
|
|
1187
848
|
const seen = new Set<string>()
|
|
1188
849
|
for (const m of members) {
|
|
1189
850
|
const key = m.canon
|
|
@@ -1194,10 +855,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1194
855
|
}
|
|
1195
856
|
}
|
|
1196
857
|
|
|
1197
|
-
// ... and the same test per PROJECTED key. A member that has no such
|
|
1198
|
-
// key FAILS the constraint rather than being skipped: distinctness
|
|
1199
|
-
// it cannot be shown to have is distinctness it does not have, and
|
|
1200
|
-
// skipping would let one keyless record hide a duplicate.
|
|
1201
858
|
for (const field of this.uniqBy) {
|
|
1202
859
|
const seen = new Set<string>()
|
|
1203
860
|
for (const m of members) {
|
|
@@ -1225,32 +882,10 @@ class ConstraintVal extends FeatureVal {
|
|
|
1225
882
|
if (spent) {
|
|
1226
883
|
return peer
|
|
1227
884
|
}
|
|
1228
|
-
// DONE, unlike the unsettled case above. The container HAS settled;
|
|
1229
|
-
// the atom is kept only because a LATER value could still add
|
|
1230
|
-
// members, and a residue that reported itself unresolved would
|
|
1231
|
-
// leave every enclosing value unresolved with it -- a `type()`
|
|
1232
|
-
// waiting on its argument for ever, and use case 09's whole
|
|
1233
|
-
// registry with it.
|
|
1234
|
-
// The ATOM is done too, not just the conjunct. An earlier pass may
|
|
1235
|
-
// have set `dc = 0` on the unsettled branch above, and a conjunct
|
|
1236
|
-
// recomputes its own doneness from its terms on every later meet --
|
|
1237
|
-
// so a stale 0 here would drag the residue, and every value holding
|
|
1238
|
-
// it, back to unresolved for ever.
|
|
1239
885
|
return this.hold(peer, ctx)
|
|
1240
886
|
}
|
|
1241
887
|
|
|
1242
888
|
|
|
1243
|
-
// The atom kept on a value whose reading is still provisional.
|
|
1244
|
-
// DONE, unlike the unsettled container above: the value HAS settled;
|
|
1245
|
-
// the atom is kept only because a LATER value could still add
|
|
1246
|
-
// members, and a residue that reported itself unresolved would leave
|
|
1247
|
-
// every enclosing value unresolved with it -- a `type()` waiting on
|
|
1248
|
-
// its argument for ever, and use case 09's whole registry with it.
|
|
1249
|
-
// The ATOM is done too, not just the conjunct. An earlier pass may
|
|
1250
|
-
// have set `dc = 0` on the unsettled branch, and a conjunct
|
|
1251
|
-
// recomputes its own doneness from its terms on every later meet --
|
|
1252
|
-
// so a stale 0 here would drag the residue, and every value holding
|
|
1253
|
-
// it, back to unresolved for ever.
|
|
1254
889
|
private hold(peer: any, ctx: AontuContext): Val {
|
|
1255
890
|
this.dc = DONE
|
|
1256
891
|
const held: any = new ConjunctVal({ peg: [this, peer] }, ctx)
|
|
@@ -1259,16 +894,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1259
894
|
}
|
|
1260
895
|
|
|
1261
896
|
|
|
1262
|
-
// Meet with a kind: `number` (or `string` on the string domain) is
|
|
1263
|
-
// already implied by an ORDER atom's argument; a numeric LEAF narrows
|
|
1264
|
-
// the residual; anything else has an empty intersection with the
|
|
1265
|
-
// constraint's domain.
|
|
1266
|
-
//
|
|
1267
|
-
// A sizing residual (`length`, `unique`) has no domain of its own -- a
|
|
1268
|
-
// count says nothing about what is counted -- so a kind here SETS one
|
|
1269
|
-
// rather than merely agreeing with it: `string & length(3)` is a
|
|
1270
|
-
// three-character string, and `number & length(3)` is empty because a
|
|
1271
|
-
// number has no length (stateEmpty decides that, not this).
|
|
1272
897
|
private meetKind(peer: any, ctx: AontuContext): Val {
|
|
1273
898
|
const marker = peer.peg
|
|
1274
899
|
const merged = this.cloneState()
|
|
@@ -1328,14 +953,7 @@ class ConstraintVal extends FeatureVal {
|
|
|
1328
953
|
null == peer.count ? this.count : meetCount(this.count, peer.count)
|
|
1329
954
|
// `unique()` is idempotent: two of them are one.
|
|
1330
955
|
merged.uniq = this.uniq || peer.uniq
|
|
1331
|
-
// `unique(a) & unique(b)` is BOTH, not the later one: each names a
|
|
1332
|
-
// key on which the members must differ, and dropping either would
|
|
1333
|
-
// silently weaken the constraint. Sorted and deduplicated, so the
|
|
1334
|
-
// meet is commutative and `unique(a) & unique(a)` is one atom.
|
|
1335
956
|
merged.uniqBy = [...new Set([...this.uniqBy, ...peer.uniqBy])].sort()
|
|
1336
|
-
// Band B checks accumulate in written order and are never merged,
|
|
1337
|
-
// deduplicated or reordered: each carries its own author message,
|
|
1338
|
-
// and two checks with the same shape may still say different things.
|
|
1339
957
|
merged.musts = [...this.musts, ...peer.musts]
|
|
1340
958
|
|
|
1341
959
|
return this.finish(merged, ctx, peer)
|
|
@@ -1353,10 +971,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1353
971
|
out.site.row = this.site.row
|
|
1354
972
|
out.site.col = this.site.col
|
|
1355
973
|
out.site.url = this.site.url
|
|
1356
|
-
// Marks ratchet across a meet (the propagateMarks rule): a fresh
|
|
1357
|
-
// residual must carry both operands' type/hide marks, or a
|
|
1358
|
-
// `type(min(0)) & max(10)` merge would silently unmark the field
|
|
1359
|
-
// (the Go fold re-ratchets from its terms; this is the TS twin).
|
|
1360
974
|
propagateMarks(this, out)
|
|
1361
975
|
propagateMarks(peer, out)
|
|
1362
976
|
return out
|
|
@@ -1432,9 +1046,6 @@ class ConstraintVal extends FeatureVal {
|
|
|
1432
1046
|
}
|
|
1433
1047
|
|
|
1434
1048
|
|
|
1435
|
-
// The tighter of two like-direction bounds: the higher lower bound (or
|
|
1436
|
-
// lower upper bound); on the same point the OPEN bound wins, and on a
|
|
1437
|
-
// full tie the tower-lowest endpoint spelling survives.
|
|
1438
1049
|
function tighter(
|
|
1439
1050
|
domain: 'number' | 'string',
|
|
1440
1051
|
a: Bound | undefined,
|
|
@@ -1475,13 +1086,6 @@ function dedupSorted(domain: 'number' | 'string', neqs: any[]): any[] {
|
|
|
1475
1086
|
}
|
|
1476
1087
|
|
|
1477
1088
|
|
|
1478
|
-
// Is this value, or anything inside it, a nil? A written argument that
|
|
1479
|
-
// holds one can never be satisfied, so the atom refuses it as an
|
|
1480
|
-
// argument rather than reporting a mystery failure against every peer.
|
|
1481
|
-
// Every caller passes a Val: `args[0]` comes from atomArgs, and the
|
|
1482
|
-
// walk below descends only into container pegs, which hold Vals. The
|
|
1483
|
-
// null/non-Val guard this function used to open with was therefore
|
|
1484
|
-
// unreachable, and the coverage gate said so.
|
|
1485
1089
|
function holdsNil(v: any): boolean {
|
|
1486
1090
|
if (true === v.isNil) {
|
|
1487
1091
|
return true
|
|
@@ -1501,12 +1105,6 @@ function holdsNil(v: any): boolean {
|
|
|
1501
1105
|
}
|
|
1502
1106
|
|
|
1503
1107
|
|
|
1504
|
-
// Whether a value, or anything inside it, is an effectful call — one
|
|
1505
|
-
// whose evaluation changes a node OTHER than the one being computed.
|
|
1506
|
-
// `move()` is the only builtin that does: it hides its resolution
|
|
1507
|
-
// target in place. Band B refuses one as an argument, because settling
|
|
1508
|
-
// it runs the effect against the live root before `must`'s trial clone
|
|
1509
|
-
// is taken, and a check that mutates cannot be report-only.
|
|
1510
1108
|
function holdsMove(v: any): boolean {
|
|
1511
1109
|
if (true === v.isFunc && 'move' === v.funcname?.()) {
|
|
1512
1110
|
return true
|
|
@@ -1526,15 +1124,6 @@ function holdsMove(v: any): boolean {
|
|
|
1526
1124
|
}
|
|
1527
1125
|
|
|
1528
1126
|
|
|
1529
|
-
// The written arguments of an atom, flattened.
|
|
1530
|
-
//
|
|
1531
|
-
// A multi-argument call arrives from the func-paren grammar as ONE
|
|
1532
|
-
// entry holding the comma group, and `neq([3,1,2])` means the same as
|
|
1533
|
-
// `neq(3,1,2)`. The group is always a ListVal by the time it reaches
|
|
1534
|
-
// here -- the func-paren handler rawToVals every argument (issue #49) --
|
|
1535
|
-
// so there is no raw-array case to unwrap. Flattening happens before
|
|
1536
|
-
// the settled check, because an unsettled member hiding inside the
|
|
1537
|
-
// group would otherwise make the atom look ready.
|
|
1538
1127
|
function atomArgs(atom: string, args: any[]): any[] {
|
|
1539
1128
|
if (('neq' === atom || 'must' === atom) && 1 === args.length &&
|
|
1540
1129
|
true === (args[0] as any)?.isList) {
|
|
@@ -1544,19 +1133,11 @@ function atomArgs(atom: string, args: any[]): any[] {
|
|
|
1544
1133
|
}
|
|
1545
1134
|
|
|
1546
1135
|
|
|
1547
|
-
// The canonical rendering of a residual, in the fixed atom order:
|
|
1548
|
-
// kind, lower bound, upper bound, neq, re, length, unique. Taken over the
|
|
1549
|
-
// STATE rather than the Val because `length`'s argument is a residual too,
|
|
1550
|
-
// and renders by exactly the same rules.
|
|
1551
1136
|
function canonState(s: ConstraintState): string {
|
|
1552
1137
|
const parts: string[] = []
|
|
1553
1138
|
if (null != s.kind) {
|
|
1554
1139
|
parts.push((s.kind as any).name.toLowerCase())
|
|
1555
1140
|
}
|
|
1556
|
-
// An ORDER atom's argument implies the domain, so it is not spelled
|
|
1557
|
-
// out. A SIZING residual carries no order, and there `string` is the
|
|
1558
|
-
// only thing saying what is being sized -- drop it and the reparse
|
|
1559
|
-
// would admit lists and maps too.
|
|
1560
1141
|
else if ('string' === s.domain &&
|
|
1561
1142
|
null == s.lo && null == s.hi && 0 === s.neqs.length && 0 === s.res.length) {
|
|
1562
1143
|
parts.push('string')
|
|
@@ -1574,19 +1155,11 @@ function canonState(s: ConstraintState): string {
|
|
|
1574
1155
|
parts.push('re(' + r.v.canon + ')')
|
|
1575
1156
|
}
|
|
1576
1157
|
if (null != s.count) {
|
|
1577
|
-
// Rendered UNABRIDGED, implied parts and all: `length(3)` canonicalises
|
|
1578
|
-
// to `length(integer&min(3)&max(3))` because that IS the residual the
|
|
1579
|
-
// count must satisfy, and canon is a normal form (G6 hashes it),
|
|
1580
|
-
// not a pretty-printer. Abbreviating would mean a second set of
|
|
1581
|
-
// rules for when the implied `integer & min(0)` may be dropped.
|
|
1582
1158
|
parts.push('length(' + canonState(s.count) + ')')
|
|
1583
1159
|
}
|
|
1584
1160
|
if (s.uniq) {
|
|
1585
1161
|
parts.push('unique()')
|
|
1586
1162
|
}
|
|
1587
|
-
// After the bare atom, and sorted: canon is a normal form, so two
|
|
1588
|
-
// documents writing the same keys in different orders must render
|
|
1589
|
-
// the same string.
|
|
1590
1163
|
for (const key of s.uniqBy) {
|
|
1591
1164
|
parts.push('unique(' + JSON.stringify(key) + ')')
|
|
1592
1165
|
}
|
|
@@ -1601,15 +1174,6 @@ function canonState(s: ConstraintState): string {
|
|
|
1601
1174
|
}
|
|
1602
1175
|
|
|
1603
1176
|
|
|
1604
|
-
// SUBSUMPTION over two residuals (G3, the query built on the table in
|
|
1605
|
-
// docs/reference-language.md "Subsumption"): does every value `s`
|
|
1606
|
-
// admits pass `g` too? Implemented here because the compare machinery
|
|
1607
|
-
// (cmpVal, sameScalar, the recursive count state) is this module's.
|
|
1608
|
-
//
|
|
1609
|
-
// Three-valued: true / false / 'undecided'. `must` on the GENERAL side
|
|
1610
|
-
// is undecided by construction (a Band B predicate is opaque — G3 maps
|
|
1611
|
-
// the table's "never" to the query's honest sub_evaluate_only); every
|
|
1612
|
-
// other approximation folds toward false, the safe direction.
|
|
1613
1177
|
function constraintStateSubsumes(
|
|
1614
1178
|
g: {
|
|
1615
1179
|
domain?: 'number' | 'string', kind?: any, lo?: Bound, hi?: Bound,
|
|
@@ -1683,11 +1247,6 @@ function constraintStateSubsumes(
|
|
|
1683
1247
|
}
|
|
1684
1248
|
}
|
|
1685
1249
|
|
|
1686
|
-
// `unique()` subsumes only itself on that axis: a general uniqueness
|
|
1687
|
-
// demand admits no container the unconstrained specific also admits.
|
|
1688
|
-
// ... and a general `unique(k)` needs the same key on the specific
|
|
1689
|
-
// side: distinctness on `port` says nothing about distinctness on
|
|
1690
|
-
// `name`.
|
|
1691
1250
|
if (g.uniqBy.some((k: string) => !s.uniqBy.includes(k))) {
|
|
1692
1251
|
return false
|
|
1693
1252
|
}
|
|
@@ -1723,9 +1282,6 @@ function constraintAdmitsScalar(
|
|
|
1723
1282
|
if (g.uniq || 0 < g.uniqBy.length) {
|
|
1724
1283
|
return false
|
|
1725
1284
|
}
|
|
1726
|
-
// A count residual admits by LENGTH, which is the meet's business;
|
|
1727
|
-
// the query answers false (the safe direction) rather than
|
|
1728
|
-
// reimplementing the sizing walk here.
|
|
1729
1285
|
if (null != (g as any).count) {
|
|
1730
1286
|
return false
|
|
1731
1287
|
}
|
|
@@ -1733,10 +1289,6 @@ function constraintAdmitsScalar(
|
|
|
1733
1289
|
}
|
|
1734
1290
|
|
|
1735
1291
|
|
|
1736
|
-
// Does this residual's ORDER and MEMBERSHIP part admit the scalar? The
|
|
1737
|
-
// sizing atoms are deliberately not consulted: `admit` applies them to
|
|
1738
|
-
// the peer's length, and the count check applies this same function to
|
|
1739
|
-
// the count.
|
|
1740
1292
|
function stateAdmits(s: ConstraintState, peer: any): boolean {
|
|
1741
1293
|
const domainOf = numericLeaf(peer) ? 'number' :
|
|
1742
1294
|
stringishLeaf(peer) ? 'string' : undefined
|
|
@@ -1774,10 +1326,6 @@ function stateAdmits(s: ConstraintState, peer: any): boolean {
|
|
|
1774
1326
|
return false
|
|
1775
1327
|
}
|
|
1776
1328
|
}
|
|
1777
|
-
// Every accumulated pattern must match: the meet of two `re` atoms
|
|
1778
|
-
// is conjunction, and matching is UNANCHORED in both engines
|
|
1779
|
-
// (JS RegExp.test, Go regexp.MatchString), so `re("el")` admits
|
|
1780
|
-
// "hello". Anchor with ^ and $ to mean the whole string.
|
|
1781
1329
|
for (const r of s.res) {
|
|
1782
1330
|
if (!r.re.test(peer.peg)) {
|
|
1783
1331
|
return false
|
|
@@ -1787,13 +1335,7 @@ function stateAdmits(s: ConstraintState, peer: any): boolean {
|
|
|
1787
1335
|
}
|
|
1788
1336
|
|
|
1789
1337
|
|
|
1790
|
-
// The eager emptiness rules. Each is EXACT -- it reports empty only
|
|
1791
|
-
// where no value could satisfy the residual -- so the algebra stays
|
|
1792
|
-
// sound; the incompleteness it accepts is documented in
|
|
1793
|
-
// docs/reference-language.md, "Emptiness".
|
|
1794
1338
|
function stateEmpty(s: ConstraintState): boolean {
|
|
1795
|
-
// Two disagreeing kind narrowings inside a length argument, recorded by
|
|
1796
|
-
// meetCount because that meet has no ctx to fail through.
|
|
1797
1339
|
if (s.clash) {
|
|
1798
1340
|
return true
|
|
1799
1341
|
}
|
|
@@ -1832,10 +1374,6 @@ function stateEmpty(s: ConstraintState): boolean {
|
|
|
1832
1374
|
}
|
|
1833
1375
|
}
|
|
1834
1376
|
|
|
1835
|
-
// Point deletion under a narrowed leaf: a closed point interval
|
|
1836
|
-
// whose single value of the narrowed leaf is excluded is empty
|
|
1837
|
-
// (integer & min(3) & max(3) & neq(3)). Without a narrowing the
|
|
1838
|
-
// point survives in the other leaves.
|
|
1839
1377
|
if (null != s.kind && null != s.lo && null != s.hi &&
|
|
1840
1378
|
!s.lo.open && !s.hi.open &&
|
|
1841
1379
|
0 === cmpVal(d, s.lo.v, s.hi.v)) {
|
|
@@ -1846,10 +1384,6 @@ function stateEmpty(s: ConstraintState): boolean {
|
|
|
1846
1384
|
}
|
|
1847
1385
|
}
|
|
1848
1386
|
|
|
1849
|
-
// Sizing over the number domain: a number has neither a length nor
|
|
1850
|
-
// members, so `integer & length(3)` and `min(2) & unique()` admit
|
|
1851
|
-
// nothing. Uniqueness over the string domain is empty for the same
|
|
1852
|
-
// reason -- a string's members are not values the algebra compares.
|
|
1853
1387
|
if ('number' === d && (null != s.count || s.uniq ||
|
|
1854
1388
|
0 < s.uniqBy.length)) {
|
|
1855
1389
|
return true
|
|
@@ -1868,10 +1402,6 @@ function stateEmpty(s: ConstraintState): boolean {
|
|
|
1868
1402
|
}
|
|
1869
1403
|
|
|
1870
1404
|
|
|
1871
|
-
// The base every `length` argument meets: a count is a non-negative
|
|
1872
|
-
// integer, whatever else the argument says (docs/reference-language.md,
|
|
1873
|
-
// "`length` semantics" -- `length(c)` is empty iff `c & integer & min(0)`
|
|
1874
|
-
// is).
|
|
1875
1405
|
function countBase(): ConstraintState {
|
|
1876
1406
|
return {
|
|
1877
1407
|
domain: 'number',
|
|
@@ -1894,12 +1424,6 @@ function countVal(n: number): any {
|
|
|
1894
1424
|
}
|
|
1895
1425
|
|
|
1896
1426
|
|
|
1897
|
-
// The pure meet of two count residuals. Both are number-domain and
|
|
1898
|
-
// carry no pattern or sizing atom of their own, so the merge is the
|
|
1899
|
-
// interval/exclusion part alone. A kind disagreement becomes a `clash`
|
|
1900
|
-
// rather than an error: this meet runs at construction, where there is
|
|
1901
|
-
// no AontuContext to raise through, and an empty residual carries the
|
|
1902
|
-
// same news to `unify`.
|
|
1903
1427
|
function meetCount(a: ConstraintState, b: ConstraintState): ConstraintState {
|
|
1904
1428
|
return {
|
|
1905
1429
|
domain: 'number',
|
|
@@ -1919,18 +1443,6 @@ function meetCount(a: ConstraintState, b: ConstraintState): ConstraintState {
|
|
|
1919
1443
|
}
|
|
1920
1444
|
|
|
1921
1445
|
|
|
1922
|
-
// Read a WRITTEN `length` argument as a count residual, or undefined when
|
|
1923
|
-
// it is not one. Accepted: an integer literal (an exact count), a
|
|
1924
|
-
// numeric kind, a Band A residual over the number domain, and any
|
|
1925
|
-
// conjunct of those. A conjunct never reaches here any more: an
|
|
1926
|
-
// unsettled argument is held as `pending` and folded before the count
|
|
1927
|
-
// reads it (G1 phase 4), so `length(min(2)&max(5))` arrives as the
|
|
1928
|
-
// single residual it folds to.
|
|
1929
|
-
//
|
|
1930
|
-
// Anything else is refused rather than deferred. A reference or an
|
|
1931
|
-
// expression would have to residuate, and the sizing atoms do not
|
|
1932
|
-
// residuate on their ARGUMENT -- only on the peer whose members are
|
|
1933
|
-
// still settling.
|
|
1934
1446
|
function countArgState(arg: any): ConstraintState | undefined {
|
|
1935
1447
|
if (numericLeaf(arg)) {
|
|
1936
1448
|
return {
|
|
@@ -1982,18 +1494,7 @@ function countArgState(arg: any): ConstraintState | undefined {
|
|
|
1982
1494
|
}
|
|
1983
1495
|
|
|
1984
1496
|
|
|
1985
|
-
// A container is SETTLED when it and every child have converged. Until
|
|
1986
|
-
// then the member set can still change — an optional key whose value is
|
|
1987
|
-
// a still-resolving reference may yet generate — so a sizing atom must
|
|
1988
|
-
// defer rather than decide (docs/reference-language.md, "`length`
|
|
1989
|
-
// semantics"). Note that an optional holding a settled-but-ungenerable
|
|
1990
|
-
// value, `{x:1,y?:number}`, IS settled: the map converges on the first
|
|
1991
|
-
// pass and `y` is simply never emitted.
|
|
1992
1497
|
function containerSettled(bag: any): boolean {
|
|
1993
|
-
// The bag's OWN done-counter is enough: BagVal.unify sets it from the
|
|
1994
|
-
// AND over its children, so an unsettled child already leaves the bag
|
|
1995
|
-
// unsettled. Walking the children again would be a second, drifting
|
|
1996
|
-
// copy of that rule.
|
|
1997
1498
|
return true === bag.done
|
|
1998
1499
|
}
|
|
1999
1500
|
|
|
@@ -2006,35 +1507,15 @@ function genable(child: any): boolean {
|
|
|
2006
1507
|
true === child.isList || true === child.isPref ||
|
|
2007
1508
|
true === child.isRef || true === child.isDisjunct ||
|
|
2008
1509
|
true === child.isNil ||
|
|
2009
|
-
// A settled sizing residue generates through ConjunctVal.gen, so it
|
|
2010
|
-
// is a member like any other -- and a `length` that did not count
|
|
2011
|
-
// its sibling's `unique` would be the early-fold defect again, one
|
|
2012
|
-
// level up.
|
|
2013
1510
|
undefined !== sizingResidue(child)
|
|
2014
1511
|
}
|
|
2015
1512
|
|
|
2016
1513
|
|
|
2017
|
-
// The children a bag would EMIT, mirroring the selection in
|
|
2018
|
-
// `BagVal.gen` — type/hide marks skipped, non-generable residue and
|
|
2019
|
-
// values that generate nothing dropped, optional keys dropped when
|
|
2020
|
-
// they generate empty.
|
|
2021
|
-
//
|
|
2022
|
-
// It returns the member VALS rather than their generated values,
|
|
2023
|
-
// because uniqueness compares canon and a generated value cannot
|
|
2024
|
-
// express that distinction: `1` and `1.0` generate the same JSON number
|
|
2025
|
-
// and canon differently. Counting uses the same list, so both sizing
|
|
2026
|
-
// atoms see exactly one definition of "member".
|
|
2027
|
-
//
|
|
2028
|
-
// Returns undefined when a REQUIRED child is residue: the container's
|
|
2029
|
-
// own `gen` raises there, and that error is the one worth reporting.
|
|
2030
1514
|
function emittedMembers(bag: any, ctx: AontuContext): any[] | undefined {
|
|
2031
1515
|
const out: any[] = []
|
|
2032
1516
|
|
|
2033
1517
|
let entries = items(bag.peg)
|
|
2034
1518
|
if (bag.isMap) {
|
|
2035
|
-
// Code-point order, because the two ports disagree on raw key order
|
|
2036
|
-
// — JavaScript hoists integer-like keys, Go keeps insertion order —
|
|
2037
|
-
// and a duplicate report must name the same pair in both.
|
|
2038
1519
|
entries = entries
|
|
2039
1520
|
.slice()
|
|
2040
1521
|
.sort((a: any, b: any) => cmpCodePoint(String(a[0]), String(b[0])))
|
|
@@ -2057,10 +1538,6 @@ function emittedMembers(bag: any, ctx: AontuContext): any[] | undefined {
|
|
|
2057
1538
|
return undefined
|
|
2058
1539
|
}
|
|
2059
1540
|
|
|
2060
|
-
// Generation decides in an isolated collect context, so an
|
|
2061
|
-
// unresolved inner value neither raises here nor pollutes the
|
|
2062
|
-
// caller's errors — the same isolation BagVal.gen uses for an
|
|
2063
|
-
// optional child.
|
|
2064
1541
|
const cval = child.gen(ctx.clone({ err: [], collect: true }))
|
|
2065
1542
|
|
|
2066
1543
|
if (undefined === cval || (optional && empty(cval))) {
|
|
@@ -2074,12 +1551,6 @@ function emittedMembers(bag: any, ctx: AontuContext): any[] | undefined {
|
|
|
2074
1551
|
}
|
|
2075
1552
|
|
|
2076
1553
|
|
|
2077
|
-
// Sort accumulated patterns by source in code-point order and drop
|
|
2078
|
-
// exact duplicates. Patterns are NEVER simplified or compared for
|
|
2079
|
-
// containment: deciding `re("a")` subsumes `re("a|b")` is regex
|
|
2080
|
-
// containment, which the algebra deliberately does not do (emptiness
|
|
2081
|
-
// stays approximate — sound, incomplete). Two spellings of one language
|
|
2082
|
-
// therefore both survive, and both are tested.
|
|
2083
1554
|
function dedupSortedRes(res: ReAtom[]): ReAtom[] {
|
|
2084
1555
|
const sorted = [...res].sort((a, b) => cmpCodePoints(a.src, b.src))
|
|
2085
1556
|
const out: ReAtom[] = []
|
|
@@ -2092,9 +1563,6 @@ function dedupSortedRes(res: ReAtom[]): ReAtom[] {
|
|
|
2092
1563
|
}
|
|
2093
1564
|
|
|
2094
1565
|
|
|
2095
|
-
// The atom classes registered in the parser's funcMap: each is a
|
|
2096
|
-
// ConstraintVal that knows its atom name. Constructed by the
|
|
2097
|
-
// func-paren handler as `new funcval({peg: args})`.
|
|
2098
1566
|
class MinConstraintVal extends ConstraintVal {
|
|
2099
1567
|
constructor(spec: ValSpec, ctx?: AontuContext) {
|
|
2100
1568
|
super({ ...spec, atom: 'min' }, ctx)
|
|
@@ -2151,9 +1619,6 @@ class UniqueConstraintVal extends ConstraintVal {
|
|
|
2151
1619
|
|
|
2152
1620
|
|
|
2153
1621
|
export {
|
|
2154
|
-
// Exported for the differential corpus test (ADR-003): the two ports'
|
|
2155
|
-
// normalisers must produce byte-identical output, and that can only be
|
|
2156
|
-
// checked by calling them.
|
|
2157
1622
|
normaliseRe,
|
|
2158
1623
|
// Exported for the subsumption query (G3, ts/src/subsume.ts): the
|
|
2159
1624
|
// residual-vs-residual and residual-vs-scalar rules live here beside
|