aontu 0.52.0 → 0.53.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 +88 -0
- package/bin/aontu-mcp.js +4 -0
- package/dist/agentsmd.d.ts +16 -0
- package/dist/agentsmd.js +107 -0
- package/dist/agentsmd.js.map +1 -0
- package/dist/aontu.d.ts +14 -3
- package/dist/aontu.js +145 -4
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +44 -1
- package/dist/cli.js +2401 -44
- package/dist/cli.js.map +1 -1
- package/dist/ctx.d.ts +16 -0
- package/dist/ctx.js +44 -0
- package/dist/ctx.js.map +1 -1
- package/dist/diff.d.ts +22 -0
- package/dist/diff.js +141 -0
- package/dist/diff.js.map +1 -0
- package/dist/err.d.ts +3 -1
- package/dist/err.js +48 -8
- package/dist/err.js.map +1 -1
- package/dist/graph.d.ts +16 -0
- package/dist/graph.js +73 -0
- package/dist/graph.js.map +1 -0
- package/dist/hcanon.d.ts +3 -0
- package/dist/hcanon.js +146 -0
- package/dist/hcanon.js.map +1 -0
- package/dist/hints.js +223 -5
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.d.ts +20 -0
- package/dist/jsonschema.js +391 -0
- package/dist/jsonschema.js.map +1 -0
- package/dist/lang.js +698 -35
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +9 -2
- package/dist/lsp.js +262 -46
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.d.ts +20 -0
- package/dist/mcp-server.js +147 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mcp.d.ts +42 -0
- package/dist/mcp.js +814 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mod-tool.d.ts +58 -0
- package/dist/mod-tool.js +498 -0
- package/dist/mod-tool.js.map +1 -0
- package/dist/mod.d.ts +31 -0
- package/dist/mod.js +250 -0
- package/dist/mod.js.map +1 -0
- package/dist/patch.d.ts +44 -0
- package/dist/patch.js +506 -0
- package/dist/patch.js.map +1 -0
- package/dist/provenance.d.ts +40 -0
- package/dist/provenance.js +335 -0
- package/dist/provenance.js.map +1 -0
- package/dist/query.d.ts +27 -0
- package/dist/query.js +294 -0
- package/dist/query.js.map +1 -0
- package/dist/reach.d.ts +14 -0
- package/dist/reach.js +140 -0
- package/dist/reach.js.map +1 -0
- package/dist/relation.d.ts +19 -0
- package/dist/relation.js +305 -0
- package/dist/relation.js.map +1 -0
- package/dist/report-sarif.d.ts +14 -0
- package/dist/report-sarif.js +102 -0
- package/dist/report-sarif.js.map +1 -0
- package/dist/site.d.ts +4 -0
- package/dist/site.js +31 -0
- package/dist/site.js.map +1 -1
- package/dist/std.d.ts +1 -0
- package/dist/std.js +73 -0
- package/dist/std.js.map +1 -0
- package/dist/subsume.d.ts +39 -0
- package/dist/subsume.js +526 -0
- package/dist/subsume.js.map +1 -0
- package/dist/trim.d.ts +19 -0
- package/dist/trim.js +155 -0
- package/dist/trim.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.d.ts +17 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.d.ts +3 -1
- package/dist/unify.js +287 -18
- package/dist/unify.js.map +1 -1
- package/dist/utility.d.ts +9 -1
- package/dist/utility.js +122 -1
- package/dist/utility.js.map +1 -1
- package/dist/val/AggFuncVal.d.ts +33 -0
- package/dist/val/AggFuncVal.js +202 -0
- package/dist/val/AggFuncVal.js.map +1 -0
- package/dist/val/ArithFuncVal.d.ts +31 -0
- package/dist/val/ArithFuncVal.js +62 -0
- package/dist/val/ArithFuncVal.js.map +1 -0
- package/dist/val/BagVal.d.ts +5 -0
- package/dist/val/BagVal.js +96 -5
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +9 -1
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/ConjunctVal.d.ts +1 -1
- package/dist/val/ConjunctVal.js +19 -0
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.d.ts +48 -1
- package/dist/val/ConstraintVal.js +1501 -110
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/CopyFuncVal.d.ts +1 -2
- package/dist/val/CopyFuncVal.js +7 -0
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.d.ts +1 -0
- package/dist/val/Decimal.js +13 -0
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.d.ts +11 -0
- package/dist/val/DeprecateFuncVal.js +47 -0
- package/dist/val/DeprecateFuncVal.js.map +1 -0
- package/dist/val/DisjunctVal.js +130 -21
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.d.ts +15 -0
- package/dist/val/EachFuncVal.js +75 -0
- package/dist/val/EachFuncVal.js.map +1 -0
- package/dist/val/ExpectVal.d.ts +1 -0
- package/dist/val/ExpectVal.js +41 -4
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FeatureVal.js +1 -1
- package/dist/val/FeatureVal.js.map +1 -1
- package/dist/val/FilterFuncVal.d.ts +15 -0
- package/dist/val/FilterFuncVal.js +91 -0
- package/dist/val/FilterFuncVal.js.map +1 -0
- package/dist/val/FuncBaseVal.d.ts +6 -1
- package/dist/val/FuncBaseVal.js +178 -2
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IdFuncVal.d.ts +13 -0
- package/dist/val/IdFuncVal.js +54 -0
- package/dist/val/IdFuncVal.js.map +1 -0
- package/dist/val/JunctionVal.js +7 -1
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.d.ts +1 -1
- package/dist/val/KeyFuncVal.js +38 -30
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +117 -17
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +102 -8
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.d.ts +15 -0
- package/dist/val/MatchFuncVal.js +107 -0
- package/dist/val/MatchFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +24 -0
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -1
- package/dist/val/OpBaseVal.js +24 -2
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/OpenFuncVal.js +4 -1
- package/dist/val/OpenFuncVal.js.map +1 -1
- package/dist/val/PackFuncVal.d.ts +15 -0
- package/dist/val/PackFuncVal.js +108 -0
- package/dist/val/PackFuncVal.js.map +1 -0
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PlaceVal.d.ts +13 -0
- package/dist/val/PlaceVal.js +131 -0
- package/dist/val/PlaceVal.js.map +1 -0
- package/dist/val/PlusOpVal.js +11 -2
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.d.ts +2 -2
- package/dist/val/PrefVal.js +78 -23
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RefVal.d.ts +1 -1
- package/dist/val/RefVal.js +158 -30
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.d.ts +36 -0
- package/dist/val/ReferFuncVal.js +303 -0
- package/dist/val/ReferFuncVal.js.map +1 -0
- package/dist/val/ScalarKindVal.d.ts +1 -2
- package/dist/val/ScalarKindVal.js +0 -11
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TypeFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +9 -2
- package/dist/val/Val.js +150 -4
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.d.ts +6 -0
- package/dist/val/arith.js +170 -0
- package/dist/val/arith.js.map +1 -0
- package/dist/vet.d.ts +45 -0
- package/dist/vet.js +776 -0
- package/dist/vet.js.map +1 -0
- package/dist/walk.d.ts +2 -0
- package/dist/walk.js +91 -0
- package/dist/walk.js.map +1 -0
- package/grammar/aontu.gbnf +130 -0
- package/grammar/aontu.lark +113 -0
- package/package.json +30 -15
- package/skill/SKILL.md +37 -0
- package/skill/error-codes.md +62 -0
- package/skill/examples.md +99 -0
- package/skill/grammar-card.md +57 -0
- package/src/agentsmd.ts +135 -0
- package/src/aontu.ts +192 -4
- package/src/cli.ts +2858 -71
- package/src/ctx.ts +81 -0
- package/src/diff.ts +196 -0
- package/src/err.ts +52 -8
- package/src/graph.ts +135 -0
- package/src/hcanon.ts +169 -0
- package/src/hints.ts +271 -5
- package/src/jsonschema.ts +511 -0
- package/src/lang.ts +779 -37
- package/src/lsp.ts +281 -47
- package/src/mcp-server.ts +187 -0
- package/src/mcp.ts +993 -0
- package/src/mod-tool.ts +679 -0
- package/src/mod.ts +344 -0
- package/src/patch.ts +624 -0
- package/src/provenance.ts +430 -0
- package/src/query.ts +379 -0
- package/src/reach.ts +184 -0
- package/src/relation.ts +395 -0
- package/src/report-sarif.ts +137 -0
- package/src/site.ts +36 -1
- package/src/std.ts +73 -0
- package/src/subsume.ts +690 -0
- package/src/trim.ts +195 -0
- package/src/tsconfig.json +10 -4
- package/src/type.ts +51 -2
- package/src/unify.ts +311 -16
- package/src/utility.ts +139 -1
- package/src/val/AggFuncVal.ts +319 -0
- package/src/val/ArithFuncVal.ts +108 -0
- package/src/val/BagVal.ts +101 -4
- package/src/val/CloseFuncVal.ts +9 -1
- package/src/val/ConjunctVal.ts +20 -0
- package/src/val/ConstraintVal.ts +1699 -116
- package/src/val/CopyFuncVal.ts +7 -1
- package/src/val/Decimal.ts +15 -0
- package/src/val/DeprecateFuncVal.ts +84 -0
- package/src/val/DisjunctVal.ts +139 -28
- package/src/val/EachFuncVal.ts +133 -0
- package/src/val/ExpectVal.ts +43 -6
- package/src/val/FeatureVal.ts +1 -1
- package/src/val/FilterFuncVal.ts +154 -0
- package/src/val/FuncBaseVal.ts +200 -3
- package/src/val/HideFuncVal.ts +0 -2
- package/src/val/IdFuncVal.ts +91 -0
- package/src/val/JunctionVal.ts +7 -1
- package/src/val/KeyFuncVal.ts +39 -35
- package/src/val/ListVal.ts +125 -18
- package/src/val/LowerFuncVal.ts +0 -1
- package/src/val/MapVal.ts +110 -8
- package/src/val/MatchFuncVal.ts +176 -0
- package/src/val/MoveFuncVal.ts +0 -2
- package/src/val/NilVal.ts +25 -0
- package/src/val/OpBaseVal.ts +26 -3
- package/src/val/OpenFuncVal.ts +4 -2
- package/src/val/PackFuncVal.ts +175 -0
- package/src/val/PathFuncVal.ts +0 -1
- package/src/val/PlaceVal.ts +193 -0
- package/src/val/PlusOpVal.ts +11 -2
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +79 -36
- package/src/val/RefVal.ts +163 -30
- package/src/val/ReferFuncVal.ts +387 -0
- package/src/val/ScalarKindVal.ts +0 -13
- package/src/val/TopVal.ts +0 -1
- package/src/val/TypeFuncVal.ts +0 -2
- package/src/val/UpperFuncVal.ts +0 -1
- package/src/val/Val.ts +213 -3
- package/src/val/VarVal.ts +0 -1
- package/src/val/arith.ts +316 -0
- package/src/vet.ts +992 -0
- package/src/walk.ts +99 -0
package/src/val/CopyFuncVal.ts
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
|
|
14
14
|
import { makeNilErr } from '../err'
|
|
15
15
|
|
|
16
|
-
import { NilVal } from '../val/NilVal'
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
import {
|
|
@@ -66,6 +65,13 @@ class CopyFuncVal extends FuncBaseVal {
|
|
|
66
65
|
// console.log('WALK', val)
|
|
67
66
|
val.mark.type = false
|
|
68
67
|
val.mark.hide = false
|
|
68
|
+
// `copy()` CLEARS IDENTITY (G4 phase 1, clearing rule 2),
|
|
69
|
+
// consistent with its clearing of the marks: a copy of an
|
|
70
|
+
// entity is a second value shaped like it, and leaving the id
|
|
71
|
+
// on would merge the copy straight back into the original —
|
|
72
|
+
// making `copy()` a no-op for exactly the values it exists to
|
|
73
|
+
// detach.
|
|
74
|
+
val.entity = undefined
|
|
69
75
|
return val
|
|
70
76
|
})
|
|
71
77
|
}
|
package/src/val/Decimal.ts
CHANGED
|
@@ -176,6 +176,21 @@ class Decimal {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
|
|
179
|
+
// D6 -- EXACT MULTIPLICATION. Multiply the coefficients, ADD the
|
|
180
|
+
// scales: (a/10^s)(b/10^t) is ab/10^(s+t), with no alignment step and
|
|
181
|
+
// no rounding mode, exactly as add() has none.
|
|
182
|
+
//
|
|
183
|
+
// The result leaves the budget far more readily than a sum does --
|
|
184
|
+
// scales add rather than taking the maximum, and coefficient digits
|
|
185
|
+
// add too -- so squaring a value at half the budget is already over
|
|
186
|
+
// it. Every caller must test with decimalOverBudget() and report
|
|
187
|
+
// `decimal_budget`, for the same reason add()'s callers must: at the
|
|
188
|
+
// limit, refusing is the only answer that is not a rounded one.
|
|
189
|
+
multiply(peer: Decimal): Decimal {
|
|
190
|
+
return new Decimal(this.unscaled * peer.unscaled, this.scale + peer.scale)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
179
194
|
// Exact ceiling and floor, for `upper()`/`lower()`. Coefficient
|
|
180
195
|
// arithmetic only -- Math.ceil of this value would mean rounding it to
|
|
181
196
|
// binary64 first, which for a leaf that exists to escape binary64 is
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
// The deprecation mark (G3 phase 4,
|
|
4
|
+
// docs/capability-review/g3-subsumption-evolution.md): a function-form
|
|
5
|
+
// builtin, `deprecate(x, m)`, that unifies EXACTLY as `x` while the
|
|
6
|
+
// record `m` rides the result through meets. The record's keys are
|
|
7
|
+
// msg, use and since — all optional, all strings; `use` is a path
|
|
8
|
+
// spelled as a STRING, because a live reference would resolve and
|
|
9
|
+
// unify, which is not wanted. Boolean ValMarks cannot hold a record,
|
|
10
|
+
// so the Val carries one optional field (Val.deprecation), propagated
|
|
11
|
+
// by the same channel as the marks (propagateMarks) and rendered back
|
|
12
|
+
// reparseably by canon (canonRiders).
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
Val,
|
|
16
|
+
ValSpec,
|
|
17
|
+
} from '../type'
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
AontuContext,
|
|
21
|
+
} from '../ctx'
|
|
22
|
+
|
|
23
|
+
import { makeNilErr } from '../err'
|
|
24
|
+
|
|
25
|
+
import { FuncBaseVal } from './FuncBaseVal'
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
// The record's whole vocabulary. Other keys are DROPPED, not carried:
|
|
29
|
+
// the record is a contract the tooling reads (vet, the LSP tag, the
|
|
30
|
+
// breaking downgrade), and a bag of free-form keys would be a second,
|
|
31
|
+
// unspecified metadata channel.
|
|
32
|
+
const DEPRECATION_KEYS = ['msg', 'use', 'since']
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DeprecateFuncVal extends FuncBaseVal {
|
|
36
|
+
isDeprecateFunc = true
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
spec: ValSpec,
|
|
40
|
+
ctx?: AontuContext
|
|
41
|
+
) {
|
|
42
|
+
super(spec, ctx)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
make(_ctx: AontuContext, spec: ValSpec): Val {
|
|
46
|
+
return new DeprecateFuncVal(spec)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
funcname() {
|
|
50
|
+
return 'deprecate'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
resolve(ctx: AontuContext, args: Val[]) {
|
|
54
|
+
let out = args[0] ?? makeNilErr(ctx, 'arg', this)
|
|
55
|
+
|
|
56
|
+
// A nil ARGUMENT is returned unchanged, never marked: marking it
|
|
57
|
+
// makes the bag's marked-child skip drop it (the type()/hide()
|
|
58
|
+
// lesson — refusal over corruption, D7).
|
|
59
|
+
if (out.isNil) {
|
|
60
|
+
return out
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
out = out.clone(ctx)
|
|
64
|
+
|
|
65
|
+
const record: Record<string, string> = {}
|
|
66
|
+
const m: any = args[1]
|
|
67
|
+
if (true === m?.isMap && null != m.peg) {
|
|
68
|
+
for (const key of DEPRECATION_KEYS) {
|
|
69
|
+
const v = m.peg[key]
|
|
70
|
+
if (true === v?.isScalar && 'string' === typeof v.peg) {
|
|
71
|
+
record[key] = v.peg
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
out.deprecation = record
|
|
76
|
+
|
|
77
|
+
return out
|
|
78
|
+
}
|
|
79
|
+
} /* node:coverage ignore next 6 */
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
DeprecateFuncVal,
|
|
84
|
+
}
|
package/src/val/DisjunctVal.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
|
|
14
14
|
import { AontuContext } from '../ctx'
|
|
15
15
|
|
|
16
|
-
import { makeNilErr } from '../err'
|
|
16
|
+
import { AontuError, descErr, makeNilErr } from '../err'
|
|
17
17
|
import { unite } from '../unify'
|
|
18
18
|
|
|
19
19
|
import {
|
|
@@ -30,8 +30,8 @@ import {
|
|
|
30
30
|
top
|
|
31
31
|
} from './top'
|
|
32
32
|
|
|
33
|
-
import {
|
|
34
|
-
import { PrefVal } from '../val/PrefVal'
|
|
33
|
+
import { TRIAL_NIL } from '../val/NilVal'
|
|
34
|
+
import { PrefVal, prefInnerPeg } from '../val/PrefVal'
|
|
35
35
|
import { JunctionVal } from '../val/JunctionVal'
|
|
36
36
|
|
|
37
37
|
|
|
@@ -102,6 +102,7 @@ class DisjunctVal extends JunctionVal {
|
|
|
102
102
|
// leaving ctx._trialMode=true would collapse every subsequent real
|
|
103
103
|
// error in this ctx to the shared TRIAL_NIL sentinel.
|
|
104
104
|
ctx._trialMode = true
|
|
105
|
+
let gate: number[] | undefined = undefined
|
|
105
106
|
try {
|
|
106
107
|
for (let vI = 0; vI < this.peg.length; vI++) {
|
|
107
108
|
const v = this.peg[vI]
|
|
@@ -117,9 +118,60 @@ class DisjunctVal extends JunctionVal {
|
|
|
117
118
|
// sentinel instead of allocating a fresh NilVal per trial.
|
|
118
119
|
oval[vI] = TRIAL_NIL
|
|
119
120
|
}
|
|
121
|
+
else if (v instanceof PrefVal &&
|
|
122
|
+
!(peer as any).isPref && !peer.isTop &&
|
|
123
|
+
true === (prefInnerPeg(v) as any).isScalar) {
|
|
124
|
+
// A candidate for the admission gate below: a non-pref,
|
|
125
|
+
// non-top peer met a scalar preference inside this
|
|
126
|
+
// disjunction.
|
|
127
|
+
; (gate = gate ?? []).push(vI)
|
|
128
|
+
}
|
|
120
129
|
|
|
121
130
|
done = done && DONE === oval[vI].dc
|
|
122
131
|
}
|
|
132
|
+
|
|
133
|
+
// THE ADMISSION GATE (ADR-004). A peer that meets a preference
|
|
134
|
+
// INSIDE a disjunction must be admitted by the disjunction: by
|
|
135
|
+
// some sibling alternative (whose own trial above already
|
|
136
|
+
// answers that), or by the preferred value itself (the pref
|
|
137
|
+
// branch's own admitted set). The pref's kind gate alone used to
|
|
138
|
+
// decide, so a same-kind concrete peer replaced the default with
|
|
139
|
+
// the alternatives never consulted -- `k:*'auto'|'literal'|'data'`
|
|
140
|
+
// plus `k:'autoo'` answered "autoo", and `*8080|(integer&neq(80))`
|
|
141
|
+
// admitted 80 (use-cases/BUGS.md §1-2). An inadmissible override
|
|
142
|
+
// now fails the pref member's trial, and when every member is
|
|
143
|
+
// gone the meet is the existing `|:empty` refusal.
|
|
144
|
+
//
|
|
145
|
+
// SCALAR preferred values only, exactly the kind gate's own
|
|
146
|
+
// boundary (test/spec/pref.tsv, "THE GATE IS A SCALAR GATE"): a
|
|
147
|
+
// structural or kind-peg default stays ungated. A deliberately
|
|
148
|
+
// open default remains spellable as `*x|top` -- the top branch
|
|
149
|
+
// admits every override (the apidef machine-emitted idiom).
|
|
150
|
+
if (undefined !== gate) {
|
|
151
|
+
for (const gI of gate) {
|
|
152
|
+
let admitted = false
|
|
153
|
+
for (let kI = 0; kI < oval.length && !admitted; kI++) {
|
|
154
|
+
// Sibling alternatives only: a pref member cannot admit
|
|
155
|
+
// its own override (post-rankPrefs at most one pref
|
|
156
|
+
// stands at this level, so this is defensive).
|
|
157
|
+
admitted = kI !== gI && !oval[kI].isNil &&
|
|
158
|
+
!(this.peg[kI] as any).isPref
|
|
159
|
+
}
|
|
160
|
+
if (!admitted) {
|
|
161
|
+
const admitErr: any[] = []
|
|
162
|
+
ctx.err = admitErr
|
|
163
|
+
// The trial is against a CLONE: the preferred value must
|
|
164
|
+
// stay pristine for the surviving preference (the
|
|
165
|
+
// MatchFuncVal.resolve precedent).
|
|
166
|
+
const met = unite(ctx,
|
|
167
|
+
prefInnerPeg(this.peg[gI] as PrefVal).clone(ctx), peer,
|
|
168
|
+
'dj-admit')
|
|
169
|
+
if (0 < admitErr.length || met.isNil) {
|
|
170
|
+
oval[gI] = TRIAL_NIL
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
123
175
|
}
|
|
124
176
|
finally {
|
|
125
177
|
ctx._trialMode = savedTrialMode
|
|
@@ -128,6 +180,33 @@ class DisjunctVal extends JunctionVal {
|
|
|
128
180
|
|
|
129
181
|
// // // console.log('DISJUNCT-unify-B', this.id, oval.map(v => v.canon))
|
|
130
182
|
|
|
183
|
+
// A PREFERENCE CONJOINED WITH A DISJUNCTION IS A PREFERENCE ON THE
|
|
184
|
+
// ALTERNATIVE IT NAMES: `(A|B) & *A` is `*A|B`, the same value the
|
|
185
|
+
// direct spelling `*A|B` denotes. Distribution carries the peer to
|
|
186
|
+
// each member, and a scalar preference meeting a concrete same-kind
|
|
187
|
+
// member is replaced BY that member (the kind gate) -- so the
|
|
188
|
+
// preference simply vanished, and `specversion: ("1.0"|"1.1") &
|
|
189
|
+
// *"1.0"`, the enum-with-default written the other way round, held
|
|
190
|
+
// no default at all. The old generation fold hid it by folding the
|
|
191
|
+
// members together; ADR-007 does not, and a disjunction that has
|
|
192
|
+
// lost its default is not the value the author wrote.
|
|
193
|
+
//
|
|
194
|
+
// A preference naming no alternative is dropped, as it is today: it
|
|
195
|
+
// has nothing to prefer, and the default-validity lint is what
|
|
196
|
+
// reports that shape.
|
|
197
|
+
if (true === (peer as any).isPref) {
|
|
198
|
+
const want: any = prefInnerPeg(peer as PrefVal)
|
|
199
|
+
for (let vI = 0; vI < oval.length; vI++) {
|
|
200
|
+
const got: any = oval[vI]
|
|
201
|
+
if (!got.isNil && true !== got.isPref && got.same(want)) {
|
|
202
|
+
const wrapped = new PrefVal({ peg: got }, ctx)
|
|
203
|
+
wrapped.rank = (peer as PrefVal).rank
|
|
204
|
+
;(peer as PrefVal).place(wrapped)
|
|
205
|
+
oval[vI] = wrapped
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
131
210
|
// Remove duplicates, and normalize
|
|
132
211
|
if (1 < oval.length) {
|
|
133
212
|
for (let vI = 0; vI < oval.length; vI++) {
|
|
@@ -150,10 +229,14 @@ class DisjunctVal extends JunctionVal {
|
|
|
150
229
|
}
|
|
151
230
|
|
|
152
231
|
// // // console.log('DISJUNCT-unify-D', this.id, oval.map(v => v.canon))
|
|
153
|
-
|
|
154
|
-
oval = oval.filter(v => !v.isNil)
|
|
155
232
|
}
|
|
156
233
|
|
|
234
|
+
// Outside the 1<length block: a SINGLE-member disjunction (e.g. a
|
|
235
|
+
// rankPrefs collapse) whose one member fails the trial or the
|
|
236
|
+
// admission gate must reach the `|:empty` refusal below, not
|
|
237
|
+
// return the trial sentinel as if it were the answer.
|
|
238
|
+
oval = oval.filter(v => !v.isNil)
|
|
239
|
+
|
|
157
240
|
let out: Val
|
|
158
241
|
|
|
159
242
|
if (1 == oval.length) {
|
|
@@ -164,6 +247,14 @@ class DisjunctVal extends JunctionVal {
|
|
|
164
247
|
}
|
|
165
248
|
else {
|
|
166
249
|
out = new DisjunctVal({ peg: oval }, ctx)
|
|
250
|
+
// A NARROWED DISJUNCTION IS STILL THAT DISJUNCTION. The meet mints
|
|
251
|
+
// a fresh value, which used to arrive unsited and file-less -- so
|
|
252
|
+
// every finding naming a disjunction that had met anything
|
|
253
|
+
// pointed at row -1 with no file, and an agent handed the report
|
|
254
|
+
// had nowhere to go (the review's finding F). `place` copies the
|
|
255
|
+
// whole site, position and url together, which is what tells the
|
|
256
|
+
// report which document it came from.
|
|
257
|
+
this.place(out)
|
|
167
258
|
}
|
|
168
259
|
|
|
169
260
|
out.dc = done ? DONE : this.dc + 1
|
|
@@ -177,7 +268,11 @@ class DisjunctVal extends JunctionVal {
|
|
|
177
268
|
}
|
|
178
269
|
|
|
179
270
|
|
|
180
|
-
|
|
271
|
+
// Answers the sole surviving preference when ranking collapsed the
|
|
272
|
+
// disjunction to one -- which the RECURSIVE call below consumes to
|
|
273
|
+
// lift a nested disjunct's winner into this one. Undefined when
|
|
274
|
+
// more than one alternative survives, so the type says both.
|
|
275
|
+
rankPrefs(ctx: AontuContext): PrefVal | undefined {
|
|
181
276
|
let lastpref: PrefVal | undefined = undefined
|
|
182
277
|
let lastprefI = -1
|
|
183
278
|
|
|
@@ -214,7 +309,7 @@ class DisjunctVal extends JunctionVal {
|
|
|
214
309
|
}
|
|
215
310
|
}
|
|
216
311
|
else if (v.isDisjunct) {
|
|
217
|
-
|
|
312
|
+
const subrank = (v as DisjunctVal).rankPrefs(ctx)
|
|
218
313
|
if (subrank instanceof PrefVal) {
|
|
219
314
|
this.peg[vI] = subrank
|
|
220
315
|
lastpref = subrank
|
|
@@ -231,6 +326,8 @@ class DisjunctVal extends JunctionVal {
|
|
|
231
326
|
if (1 === this.peg.length && this.peg[0] instanceof PrefVal) {
|
|
232
327
|
return this.peg[0]
|
|
233
328
|
}
|
|
329
|
+
|
|
330
|
+
return undefined
|
|
234
331
|
}
|
|
235
332
|
|
|
236
333
|
|
|
@@ -246,35 +343,49 @@ class DisjunctVal extends JunctionVal {
|
|
|
246
343
|
}
|
|
247
344
|
|
|
248
345
|
|
|
346
|
+
// AN UNRESOLVED DISJUNCTION IS NOT A VALUE (ADR-007).
|
|
347
|
+
//
|
|
348
|
+
// Generation used to FOLD the surviving members together with unify
|
|
349
|
+
// and emit the result. That answer is in no branch of the
|
|
350
|
+
// disjunction: `({x:1}|{y:2}) & {z:3}` generated `{x:1,y:2,z:3}`, a
|
|
351
|
+
// map the model never admits, and `1|2` died as a scalar_value
|
|
352
|
+
// CONFLICT -- the conflict of the fold, not of anything the author
|
|
353
|
+
// wrote. The second half is what made vet decorative: vet's
|
|
354
|
+
// incompleteness check keeps incomplete-class findings, so a missing
|
|
355
|
+
// required enum field (`role: 'a'|'b'` with no data) arrived as a
|
|
356
|
+
// conflict, was filtered out, and vetted VALID with zero findings
|
|
357
|
+
// (use-cases/BUGS.md §13, the review's finding C).
|
|
358
|
+
//
|
|
359
|
+
// What remains after unification is what the model still admits, so
|
|
360
|
+
// more than one surviving alternative means the truth is not yet
|
|
361
|
+
// settled -- incomplete, the same class a bare `string` residue
|
|
362
|
+
// answers, and the same answer CUE gives for a non-concrete export.
|
|
363
|
+
// A preference resolves it (that is what `*` is for), and so does a
|
|
364
|
+
// single surviving member.
|
|
249
365
|
gen(ctx: AontuContext) {
|
|
250
|
-
// TODO: move this to main unify
|
|
251
|
-
|
|
252
|
-
// console.log('DJ-GEN', this.peg.map((p: any) => p.canon), ctx.err)
|
|
253
|
-
|
|
254
366
|
if (0 < this.peg.length) {
|
|
367
|
+
// Ranking may not have run when gen is reached without a prior
|
|
368
|
+
// unify (a library caller generating a freshly parsed tree), and
|
|
369
|
+
// it is what guarantees at most one preference stands here.
|
|
370
|
+
if (!this.prefsRanked) {
|
|
371
|
+
this.rankPrefs(ctx)
|
|
372
|
+
}
|
|
255
373
|
|
|
256
|
-
|
|
257
|
-
// // // console.log('DJ-GEN-VALS-A', vals.map((p: any) => p.canon))
|
|
374
|
+
const prefs = this.peg.filter((v: Val) => v instanceof PrefVal)
|
|
258
375
|
|
|
259
|
-
|
|
376
|
+
if (0 === prefs.length && 1 < this.peg.length) {
|
|
377
|
+
const nerr = makeNilErr(ctx, 'disjunct_no_gen', this)
|
|
378
|
+
descErr(nerr, ctx)
|
|
379
|
+
ctx?.adderr(nerr)
|
|
260
380
|
|
|
261
|
-
|
|
381
|
+
if (null == ctx || !ctx.collect) {
|
|
382
|
+
throw new AontuError(nerr.msg, [nerr])
|
|
383
|
+
}
|
|
262
384
|
|
|
263
|
-
|
|
264
|
-
// ({x:1}|{y:2})&{z:3} should be {"x":1,"z":3}|{"y":2,"z":3} not { x:1, z:3, y:2 }
|
|
265
|
-
for (let vI = 1; vI < vals.length; vI++) {
|
|
266
|
-
// Index `vals`, not `this.peg`: when the pref members are not the
|
|
267
|
-
// leading entries the two arrays differ, and folding against
|
|
268
|
-
// this.peg[vI] would unify the wrong (or a repeated) member.
|
|
269
|
-
let valnext = val.unify(vals[vI], ctx)
|
|
270
|
-
// // // console.log('DJ-GEN-VALS-NEXT', valnext.canon)
|
|
271
|
-
val = valnext
|
|
385
|
+
return undefined
|
|
272
386
|
}
|
|
273
387
|
|
|
274
|
-
|
|
275
|
-
const out = val.gen(ctx)
|
|
276
|
-
// console.log('DJ-GEN-VALS-C', out)
|
|
277
|
-
return out
|
|
388
|
+
return (0 < prefs.length ? prefs[0] : this.peg[0]).gen(ctx)
|
|
278
389
|
}
|
|
279
390
|
|
|
280
391
|
return super.gen(ctx)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
// GENERATION: `each(data, tmpl)` (G8 phase 1,
|
|
4
|
+
// docs/capability-review/g8-generation.md). One element of the result
|
|
5
|
+
// list per child of `data`, each of them that child met with `tmpl`.
|
|
6
|
+
// Written with one argument, `each(m)` is a map's children as a list.
|
|
7
|
+
//
|
|
8
|
+
// ports: {http: 80, https: 443}
|
|
9
|
+
// open: each($.ports, integer) -> [80, 443]
|
|
10
|
+
//
|
|
11
|
+
// ORDER IS FIXED, and fixed the way canon already fixes it: source
|
|
12
|
+
// order for a list, sorted-key order for a map (`cmpCodePoint`, the
|
|
13
|
+
// comparator `MapVal.canon` and the Go port's marshalling use). A
|
|
14
|
+
// generated list whose order depended on insertion history would differ
|
|
15
|
+
// between two runs of the same document, and between the two ports --
|
|
16
|
+
// the one thing the shared spec exists to prevent.
|
|
17
|
+
//
|
|
18
|
+
// The element is the source child CLONED, not shared: it is a second
|
|
19
|
+
// position holding that value, and a position is where path-dependent
|
|
20
|
+
// content resolves. What the clone keeps is the identity, if the child
|
|
21
|
+
// carries one (G4 phase 1) -- a listed entity is still that entity, and
|
|
22
|
+
// the merge that follows is the point.
|
|
23
|
+
|
|
24
|
+
import type {
|
|
25
|
+
Val,
|
|
26
|
+
ValSpec,
|
|
27
|
+
} from '../type'
|
|
28
|
+
|
|
29
|
+
import {
|
|
30
|
+
AontuContext,
|
|
31
|
+
} from '../ctx'
|
|
32
|
+
|
|
33
|
+
import { unite } from '../unify'
|
|
34
|
+
import { makeNilErr } from '../err'
|
|
35
|
+
import { ListVal } from './ListVal'
|
|
36
|
+
import { FuncBaseVal } from './FuncBaseVal'
|
|
37
|
+
import { repathInstance } from './Val'
|
|
38
|
+
import { fillPlace } from './PlaceVal'
|
|
39
|
+
import { cmpCodePoint } from '../keyorder'
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
// The children a data bag holds, in the order the result must carry
|
|
43
|
+
// them, or the code naming what is wrong with the argument.
|
|
44
|
+
function dataValues(data: Val | undefined): Val[] | string {
|
|
45
|
+
const d: any = data
|
|
46
|
+
|
|
47
|
+
if (true === d?.isMap) {
|
|
48
|
+
return Object.keys(d.peg).sort(cmpCodePoint).map((k: string) => d.peg[k])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (true === d?.isList) {
|
|
52
|
+
return [...(d.peg as Val[])]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return 'each_data'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class EachFuncVal extends FuncBaseVal {
|
|
60
|
+
isEachFunc = true
|
|
61
|
+
|
|
62
|
+
// THE STAGING RULE, for the reason given in PackFuncVal.
|
|
63
|
+
staged = true
|
|
64
|
+
|
|
65
|
+
constructor(
|
|
66
|
+
spec: ValSpec,
|
|
67
|
+
ctx?: AontuContext
|
|
68
|
+
) {
|
|
69
|
+
super(spec, ctx)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
funcname() {
|
|
75
|
+
return 'each'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
// The template is not an argument to drive (see PackFuncVal.prepare).
|
|
80
|
+
prepare(_ctx: AontuContext, _args: Val[]) {
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
unify(peer: Val, ctx: AontuContext): Val {
|
|
86
|
+
// ONE argument is driven: the data. The template is not (see
|
|
87
|
+
// prepare above), and driveStagedArgs answers whether the data has
|
|
88
|
+
// settled -- the other half of "ready to fire".
|
|
89
|
+
const ready = this.driveStagedArgs(ctx, 1)
|
|
90
|
+
|
|
91
|
+
if (!ready || !ctx.settle) {
|
|
92
|
+
return this.residuate(peer, ctx)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return super.unify(peer, ctx)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
resolve(ctx: AontuContext, args: Val[]) {
|
|
100
|
+
const vals = dataValues(args?.[0])
|
|
101
|
+
if ('string' === typeof vals) {
|
|
102
|
+
return makeNilErr(ctx, vals, this)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const tmpl: Val | undefined = args?.[1]
|
|
106
|
+
const peg: Val[] = []
|
|
107
|
+
|
|
108
|
+
for (let i = 0; i < vals.length; i++) {
|
|
109
|
+
const elctx = ctx.descend(String(i))
|
|
110
|
+
const el = vals[i].clone(elctx)
|
|
111
|
+
// The template is CLONED per element, never shared — a FULL
|
|
112
|
+
// instance to the leaves (`dup`, ADR-005): see PackFuncVal.resolve.
|
|
113
|
+
// `_` inside the template binds the source child (G8 phase 3),
|
|
114
|
+
// which for `each` is the element itself.
|
|
115
|
+
let inst: Val | undefined = undefined
|
|
116
|
+
if (undefined !== tmpl) {
|
|
117
|
+
inst = tmpl.clone(elctx, { dup: true })
|
|
118
|
+
repathInstance(inst, inst.path)
|
|
119
|
+
}
|
|
120
|
+
peg.push(undefined === inst ? el :
|
|
121
|
+
unite(elctx, el, fillPlace(inst, vals[i], elctx), 'each'))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return new ListVal({ peg }, ctx)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
} /* node:coverage ignore next 7 */
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
dataValues,
|
|
132
|
+
EachFuncVal,
|
|
133
|
+
}
|
package/src/val/ExpectVal.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
import { unite } from '../unify'
|
|
17
17
|
|
|
18
18
|
import {
|
|
19
|
-
propagateMarks,
|
|
20
19
|
explainOpen,
|
|
21
20
|
ec,
|
|
22
21
|
explainClose,
|
|
@@ -35,6 +34,21 @@ class ExpectVal extends FeatureVal {
|
|
|
35
34
|
parent?: Val
|
|
36
35
|
key?: string
|
|
37
36
|
|
|
37
|
+
// An expectation canons as THE EXPECTATION ITSELF -- the peg the peer
|
|
38
|
+
// must satisfy. Val.canon's default was the empty string, which
|
|
39
|
+
// rendered a key with no value (`{"r":}`): text that is not a document
|
|
40
|
+
// and could not be reparsed, breaking canon's round-trip contract in
|
|
41
|
+
// both engines (issue #43).
|
|
42
|
+
//
|
|
43
|
+
// Not `top`, which was the first fix here and was wrong. An ExpectVal
|
|
44
|
+
// is created for EVERY peer-introduced non-generable key, not just for
|
|
45
|
+
// `&:` spread children -- `m:{x:1} m:{y:string}` makes one at `y` with
|
|
46
|
+
// no spread in sight -- so rendering `top` erased the `string` and the
|
|
47
|
+
// canon reparsed into a document that accepts values the original
|
|
48
|
+
// rejects. A canon that silently drops a constraint is worse than one
|
|
49
|
+
// that fails to parse. Go's ExpectVal.Canon renders the same peg.
|
|
50
|
+
get canon() { return this.peg.canon }
|
|
51
|
+
|
|
38
52
|
constructor(
|
|
39
53
|
spec: ValSpec,
|
|
40
54
|
ctx?: AontuContext
|
|
@@ -42,21 +56,42 @@ class ExpectVal extends FeatureVal {
|
|
|
42
56
|
super(spec, ctx)
|
|
43
57
|
}
|
|
44
58
|
|
|
59
|
+
// PURE, deliberately (the unequal-spread crosswire, BUGS.md §6-§7).
|
|
60
|
+
// The old body accumulated `this.peer` IN PLACE, which was invisible
|
|
61
|
+
// while an expectation only ever lived at one destination -- but the
|
|
62
|
+
// spread-combination meet (MapVal.unify's 'map-self' unite) bakes an
|
|
63
|
+
// ExpectVal INTO the combined template, and a path-independent
|
|
64
|
+
// template is SHARED across every destination (spreadClone tier 1).
|
|
65
|
+
// One stateful node in a shared template unified each sibling's own
|
|
66
|
+
// data with the next sibling's ($.w.y.r: "Cannot unify value: 6 with
|
|
67
|
+
// value: 5", both values sibling data). An expectation now answers
|
|
68
|
+
// with a NEW node when it must keep accumulated state, so a shared
|
|
69
|
+
// template's expect stays exactly what was written.
|
|
45
70
|
unify(peer: Val, ctx: AontuContext): Val {
|
|
46
71
|
const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Expect', this, peer)
|
|
47
72
|
|
|
48
|
-
let out = this
|
|
73
|
+
let out: Val = this
|
|
49
74
|
|
|
50
75
|
if (!peer.isTop) {
|
|
51
|
-
|
|
76
|
+
const acc = undefined === this.peer ? peer :
|
|
52
77
|
unite(te ? ctx.clone({ explain: ec(te, 'PEER') }) : ctx, this.peer, peer, 'expect-peer')
|
|
53
78
|
|
|
54
79
|
const peeru =
|
|
55
|
-
unite(te ? ctx.clone({ explain: ec(te, 'EXPECT') }) : ctx,
|
|
80
|
+
unite(te ? ctx.clone({ explain: ec(te, 'EXPECT') }) : ctx, acc, this.peg, 'expect-self')
|
|
56
81
|
|
|
57
82
|
if (peeru.isGenable) {
|
|
58
83
|
out = peeru
|
|
59
84
|
}
|
|
85
|
+
else {
|
|
86
|
+
// Still an expectation: carry the accumulated peer forward in a
|
|
87
|
+
// fresh node stored at THIS destination by the caller, leaving
|
|
88
|
+
// `this` -- possibly a shared template's child -- untouched.
|
|
89
|
+
const e = new ExpectVal({ peg: this.peg }, ctx)
|
|
90
|
+
e.key = this.key
|
|
91
|
+
e.parent = this.parent
|
|
92
|
+
e.peer = acc
|
|
93
|
+
out = e
|
|
94
|
+
}
|
|
60
95
|
}
|
|
61
96
|
|
|
62
97
|
out.dc = DONE
|
|
@@ -68,8 +103,10 @@ class ExpectVal extends FeatureVal {
|
|
|
68
103
|
|
|
69
104
|
|
|
70
105
|
gen(ctx: AontuContext) {
|
|
71
|
-
// Unresolved expect cannot be generated, so always an error.
|
|
72
|
-
|
|
106
|
+
// Unresolved expect cannot be generated, so always an error. The
|
|
107
|
+
// CALL is the point -- it records the failure on ctx -- and there
|
|
108
|
+
// is no value to bind: generation answers nothing.
|
|
109
|
+
makeNilErr(
|
|
73
110
|
ctx,
|
|
74
111
|
'expect',
|
|
75
112
|
this.peg,
|
package/src/val/FeatureVal.ts
CHANGED