aontu 0.61.0 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/agentsmd.d.ts +1 -0
- package/dist/agentsmd.js +7 -28
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.d.ts +23 -0
- package/dist/allow.js +138 -0
- package/dist/allow.js.map +1 -0
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +4 -80
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.d.ts +4 -0
- package/dist/aontumodel.js +33 -0
- package/dist/aontumodel.js.map +1 -0
- package/dist/cli.d.ts +10 -1
- package/dist/cli.js +877 -479
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +0 -48
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js +0 -32
- package/dist/diff.js.map +1 -1
- package/dist/err.js +0 -40
- package/dist/err.js.map +1 -1
- package/dist/escape.js +0 -45
- package/dist/escape.js.map +1 -1
- package/dist/exactjson.d.ts +0 -35
- package/dist/exactjson.js +0 -131
- package/dist/exactjson.js.map +1 -1
- package/dist/format.js +55 -189
- package/dist/format.js.map +1 -1
- package/dist/grammar.d.ts +9 -0
- package/dist/grammar.js +54 -0
- package/dist/grammar.js.map +1 -0
- package/dist/graph.js +0 -26
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +0 -82
- package/dist/hcanon.js.map +1 -1
- package/dist/helpdoc.d.ts +16 -0
- package/dist/helpdoc.js +59 -0
- package/dist/helpdoc.js.map +1 -0
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +59 -47
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +0 -114
- package/dist/jsonschema.js.map +1 -1
- package/dist/keyorder.d.ts +0 -7
- package/dist/keyorder.js +0 -41
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +32 -877
- package/dist/lang.js.map +1 -1
- package/dist/lower.d.ts +3 -0
- package/dist/lower.js +14 -61
- package/dist/lower.js.map +1 -1
- package/dist/lsp-server.js +0 -16
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +12 -159
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +0 -26
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +0 -113
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +0 -130
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +0 -162
- package/dist/mod.js.map +1 -1
- package/dist/patch.js +0 -217
- package/dist/patch.js.map +1 -1
- package/dist/provenance.js +0 -140
- package/dist/provenance.js.map +1 -1
- package/dist/query.js +0 -75
- package/dist/query.js.map +1 -1
- package/dist/reach.js +0 -43
- package/dist/reach.js.map +1 -1
- package/dist/relation.d.ts +2 -0
- package/dist/relation.js +3 -58
- package/dist/relation.js.map +1 -1
- package/dist/render.js +33 -143
- package/dist/render.js.map +1 -1
- package/dist/report-sarif.d.ts +0 -11
- package/dist/report-sarif.js +0 -28
- package/dist/report-sarif.js.map +1 -1
- package/dist/sig.js +0 -35
- package/dist/sig.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/siggate.js +0 -4
- package/dist/siggate.js.map +1 -1
- package/dist/site.js +3 -29
- package/dist/site.js.map +1 -1
- package/dist/subsume.d.ts +0 -10
- package/dist/subsume.js +0 -137
- package/dist/subsume.js.map +1 -1
- package/dist/template.d.ts +2 -1
- package/dist/template.js +58 -138
- package/dist/template.js.map +1 -1
- package/dist/trim.js +0 -41
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.js +12 -242
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +0 -22
- package/dist/utility.js.map +1 -1
- package/dist/val/AbnfFuncVal.d.ts +18 -0
- package/dist/val/AbnfFuncVal.js +132 -0
- package/dist/val/AbnfFuncVal.js.map +1 -0
- package/dist/val/AbsentVal.d.ts +11 -0
- package/dist/val/AbsentVal.js +30 -0
- package/dist/val/AbsentVal.js.map +1 -0
- package/dist/val/AggFuncVal.d.ts +10 -1
- package/dist/val/AggFuncVal.js +104 -116
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/ArithFuncVal.js +0 -12
- package/dist/val/ArithFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -78
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +0 -16
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +0 -16
- package/dist/val/BigIntegerVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +0 -9
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/CmpFuncVal.d.ts +20 -0
- package/dist/val/CmpFuncVal.js +188 -0
- package/dist/val/CmpFuncVal.js.map +1 -0
- package/dist/val/ConjunctVal.js +0 -29
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +0 -500
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.js +0 -2
- package/dist/val/ContainerKindVal.js.map +1 -1
- package/dist/val/CopyFuncVal.js +0 -3
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.js +0 -179
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +0 -152
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.d.ts +1 -2
- package/dist/val/EachFuncVal.js +12 -29
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +1 -1
- package/dist/val/EmitFuncVal.js +6 -119
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/ExpectVal.js +0 -62
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +0 -25
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +7 -127
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.js +0 -15
- package/dist/val/GraphAtomVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +0 -13
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.js +0 -61
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +0 -20
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.js +0 -46
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +0 -57
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +11 -6
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +0 -151
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +0 -27
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
- package/dist/val/MaybeFuncVal.js +50 -0
- package/dist/val/MaybeFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js +0 -18
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +2 -36
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.d.ts +12 -0
- package/dist/val/NomFuncVal.js +153 -0
- package/dist/val/NomFuncVal.js.map +1 -0
- package/dist/val/NumberVal.js +0 -15
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -0
- package/dist/val/OpBaseVal.js +3 -15
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +0 -34
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +0 -6
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.js +0 -41
- package/dist/val/PathVal.js.map +1 -1
- package/dist/val/PlaceVal.js +0 -25
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +1 -7
- package/dist/val/PlusOpVal.js +13 -74
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js +0 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.js +0 -167
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.js +0 -55
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.js +0 -282
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +0 -232
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +0 -49
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +0 -11
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StrFuncVal.js +0 -18
- package/dist/val/StrFuncVal.js.map +1 -1
- package/dist/val/SuperFuncVal.js +0 -32
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +0 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TranslateFuncVal.d.ts +12 -0
- package/dist/val/TranslateFuncVal.js +99 -0
- package/dist/val/TranslateFuncVal.js.map +1 -0
- package/dist/val/UpperFuncVal.js +11 -6
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -0
- package/dist/val/Val.js +2 -133
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +0 -12
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.js +0 -37
- package/dist/val/arith.js.map +1 -1
- package/dist/val/caserange.d.ts +3 -0
- package/dist/val/caserange.js +49 -0
- package/dist/val/caserange.js.map +1 -0
- package/dist/val/members.js +0 -6
- package/dist/val/members.js.map +1 -1
- package/dist/val/numcmp.js +0 -11
- package/dist/val/numcmp.js.map +1 -1
- package/dist/val/numkind.js +0 -145
- package/dist/val/numkind.js.map +1 -1
- package/dist/val/valutil.js +0 -16
- package/dist/val/valutil.js.map +1 -1
- package/dist/vet.d.ts +12 -0
- package/dist/vet.js +159 -412
- package/dist/vet.js.map +1 -1
- package/dist/view.js +0 -414
- package/dist/view.js.map +1 -1
- package/dist/walk.js +0 -41
- package/dist/walk.js.map +1 -1
- package/grammar/aontu.abnf +9 -7
- package/grammar/aontu.gbnf +5 -5
- package/grammar/aontu.lark +5 -5
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/skill/SKILL.md +8 -0
- package/skill/init/check.sh +28 -0
- package/skill/init/data.aon +12 -0
- package/skill/init/model.aon +19 -0
- package/skill/tasks.md +151 -0
- package/src/agentsmd.ts +8 -32
- package/src/alias.ts +0 -39
- package/src/allow.ts +221 -0
- package/src/aontu.ts +10 -108
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +1009 -540
- package/src/ctx.ts +0 -103
- package/src/diff.ts +0 -40
- package/src/err.ts +0 -40
- package/src/escape.ts +0 -46
- package/src/exactjson.ts +0 -131
- package/src/format.ts +63 -234
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +77 -0
- package/src/hints.ts +72 -49
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +39 -895
- package/src/lower.ts +15 -65
- package/src/lsp-server.ts +0 -16
- package/src/lsp.ts +12 -180
- package/src/mcp-server.ts +0 -31
- package/src/mcp.ts +0 -130
- package/src/mod-tool.ts +0 -158
- package/src/mod.ts +0 -178
- package/src/patch.ts +0 -232
- package/src/provenance.ts +0 -183
- package/src/query.ts +0 -84
- package/src/reach.ts +0 -53
- package/src/relation.ts +7 -71
- package/src/render.ts +33 -180
- package/src/report-sarif.ts +0 -48
- package/src/sig.ts +0 -35
- package/src/sigdecl.ts +1 -1
- package/src/siggate.ts +0 -30
- package/src/site.ts +3 -29
- package/src/subsume.ts +1 -161
- package/src/template.ts +69 -140
- package/src/trim.ts +0 -53
- package/src/type.ts +2 -45
- package/src/unify.ts +13 -251
- package/src/utility.ts +0 -31
- package/src/val/AbnfFuncVal.ts +181 -0
- package/src/val/AbsentVal.ts +54 -0
- package/src/val/AggFuncVal.ts +152 -188
- package/src/val/ArithFuncVal.ts +0 -20
- package/src/val/BagVal.ts +1 -78
- package/src/val/BigDecimalVal.ts +0 -16
- package/src/val/BigIntegerVal.ts +0 -16
- package/src/val/CloseFuncVal.ts +0 -9
- package/src/val/CmpFuncVal.ts +249 -0
- package/src/val/ConjunctVal.ts +0 -33
- package/src/val/ConstraintVal.ts +2 -537
- package/src/val/ContainerKindVal.ts +0 -18
- package/src/val/CopyFuncVal.ts +0 -5
- package/src/val/Decimal.ts +1 -185
- package/src/val/DeprecateFuncVal.ts +0 -10
- package/src/val/DisjunctVal.ts +0 -157
- package/src/val/EachFuncVal.ts +12 -53
- package/src/val/EmitFuncVal.ts +8 -208
- package/src/val/ExpectVal.ts +0 -62
- package/src/val/FilterFuncVal.ts +0 -55
- package/src/val/FuncBaseVal.ts +9 -130
- package/src/val/GraphAtomVal.ts +0 -42
- package/src/val/HideFuncVal.ts +0 -15
- package/src/val/IntegerVal.ts +0 -61
- package/src/val/JunctionVal.ts +0 -20
- package/src/val/KeyFuncVal.ts +0 -48
- package/src/val/ListVal.ts +0 -59
- package/src/val/LowerFuncVal.ts +12 -7
- package/src/val/MapVal.ts +0 -151
- package/src/val/MatchFuncVal.ts +0 -59
- package/src/val/MaybeFuncVal.ts +86 -0
- package/src/val/MoveFuncVal.ts +0 -20
- package/src/val/NilVal.ts +2 -36
- package/src/val/NomFuncVal.ts +200 -0
- package/src/val/NumberVal.ts +0 -16
- package/src/val/OpBaseVal.ts +4 -17
- package/src/val/PackFuncVal.ts +0 -63
- package/src/val/PathFuncVal.ts +0 -32
- package/src/val/PathVal.ts +0 -66
- package/src/val/PlaceVal.ts +0 -45
- package/src/val/PlusOpVal.ts +18 -75
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +0 -179
- package/src/val/RecurseVal.ts +0 -81
- package/src/val/RefVal.ts +1 -285
- package/src/val/ReferFuncVal.ts +0 -255
- package/src/val/ScalarKindVal.ts +0 -50
- package/src/val/ScalarVal.ts +0 -12
- package/src/val/StrFuncVal.ts +0 -44
- package/src/val/SuperFuncVal.ts +0 -42
- package/src/val/TopVal.ts +0 -1
- package/src/val/TranslateFuncVal.ts +132 -0
- package/src/val/UpperFuncVal.ts +12 -7
- package/src/val/Val.ts +3 -192
- package/src/val/VarVal.ts +0 -15
- package/src/val/arith.ts +0 -92
- package/src/val/caserange.ts +53 -0
- package/src/val/members.ts +0 -23
- package/src/val/numcmp.ts +1 -27
- package/src/val/numkind.ts +0 -149
- package/src/val/valutil.ts +0 -16
- package/src/vet.ts +209 -504
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -637
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/src/std.ts +0 -648
- package/src/val/FormFuncVal.ts +0 -119
package/src/val/RecurseVal.ts
CHANGED
|
@@ -1,31 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// THE RECURSIVE RESIDUAL (docs/design/RECURSION.0.md): where RefVal's
|
|
4
|
-
// prefix test used to answer `path_cycle` for a self-reference --
|
|
5
|
-
// `$.Node` written anywhere inside `Node` -- it now answers this
|
|
6
|
-
// value: a deferred reference carrying the target path, exactly as a
|
|
7
|
-
// constraint atom carries its bound. No new syntax: the reference the
|
|
8
|
-
// author wrote simply MEANS the fixpoint.
|
|
9
|
-
//
|
|
10
|
-
// The three moments of every residual:
|
|
11
|
-
//
|
|
12
|
-
// - At unification, EXPAND ONE LEVEL PER MEET WITH STRUCTURE: met by
|
|
13
|
-
// a map, list, or scalar, the residual clones the schema body one
|
|
14
|
-
// level -- per destination, under ADR-005's clone discipline -- and
|
|
15
|
-
// unifies the clone with the peer. The clone's own self-reference
|
|
16
|
-
// is again this residual, so each expansion consumes one level of
|
|
17
|
-
// concrete data; data is finite, so expansion terminates
|
|
18
|
-
// (structural descent), with the depth budget as the backstop
|
|
19
|
-
// (recursion_budget).
|
|
20
|
-
// - In canon and the aon1- hash, SYMBOLIC: the residual prints as the
|
|
21
|
-
// reference the author wrote, so a recursive schema's canon is
|
|
22
|
-
// finite and round-trips, and the hash pins the mu-form rather than
|
|
23
|
-
// any unrolling.
|
|
24
|
-
// - At generation, an unexpanded residual REFUSES with
|
|
25
|
-
// recursion_unexpanded. Guardedness is therefore EMERGENT: under
|
|
26
|
-
// `next?:` the refusal is isolated and the optional key drops;
|
|
27
|
-
// under `*null | $.Node` the preference generates; a REQUIRED
|
|
28
|
-
// recursive field with no data refuses at the instance.
|
|
29
3
|
|
|
30
4
|
import type {
|
|
31
5
|
Val,
|
|
@@ -78,12 +52,6 @@ class RecurseVal extends FeatureVal {
|
|
|
78
52
|
return out
|
|
79
53
|
}
|
|
80
54
|
|
|
81
|
-
// The schema body the target names, from the ROOT: the fixpoint is
|
|
82
|
-
// over the finished definition, and the definition's own residual
|
|
83
|
-
// keeps it finite. When the root does not contain the target -- the
|
|
84
|
-
// residual was LIFTED out of its defining tree, as vet's anchored
|
|
85
|
-
// meet does -- fall back to ctx._fixroot, the settled tree the
|
|
86
|
-
// lifter kept for exactly this walk.
|
|
87
55
|
private body(ctx: AontuContext): Val | undefined {
|
|
88
56
|
return walkTarget(ctx.root, this.target)
|
|
89
57
|
?? walkTarget((ctx as any)._fixroot, this.target)
|
|
@@ -92,9 +60,6 @@ class RecurseVal extends FeatureVal {
|
|
|
92
60
|
unify(peer: Val, ctx: AontuContext): Val {
|
|
93
61
|
const p: any = peer
|
|
94
62
|
|
|
95
|
-
// The self-drive: nothing to advance -- the residual waits for
|
|
96
|
-
// structure. (A null/nil peer never arrives; unite's ladder
|
|
97
|
-
// absorbs both.)
|
|
98
63
|
if (null == peer || true === p.isTop) {
|
|
99
64
|
return this
|
|
100
65
|
}
|
|
@@ -105,9 +70,6 @@ class RecurseVal extends FeatureVal {
|
|
|
105
70
|
&& this.target.every((s, i) => s === p.target[i])) {
|
|
106
71
|
return this
|
|
107
72
|
}
|
|
108
|
-
// Different targets -- mutual recursion meeting -- are BOTH
|
|
109
|
-
// held: each expands as data arrives, through the fold that
|
|
110
|
-
// keeps a conjunct's members separate.
|
|
111
73
|
const out = new ConjunctVal({ peg: [this, peer] }, ctx)
|
|
112
74
|
propagateMarks(this, out)
|
|
113
75
|
out.path = this.path
|
|
@@ -129,25 +91,6 @@ class RecurseVal extends FeatureVal {
|
|
|
129
91
|
out.path = this.path
|
|
130
92
|
return out
|
|
131
93
|
}
|
|
132
|
-
// ADR-005's clone discipline: the expansion is a per-destination
|
|
133
|
-
// instantiation, so the definition itself is never written
|
|
134
|
-
// into. The clone's type/hide marks are CLEARED at every depth,
|
|
135
|
-
// exactly as a plain reference copy clears them (concreteFlow's
|
|
136
|
-
// rule): the schema is hidden, the instances it expands into
|
|
137
|
-
// are the output.
|
|
138
|
-
// The clone is REBASED to the DRIVE path explicitly (spec.path;
|
|
139
|
-
// the Go twin passes cp(r.path), whose stored paths its clone
|
|
140
|
-
// arms keep clean): the default rebase slices the definition's
|
|
141
|
-
// path by the destination's length, which leaks definition
|
|
142
|
-
// segments into instance paths whenever the destination is
|
|
143
|
-
// shallower -- a residual carried inside a copied definition
|
|
144
|
-
// body (`chain: $.spec.Step` inside Policy, copied to a slot
|
|
145
|
-
// shallower than the definition) reported
|
|
146
|
-
// `$.payments_policy.Policy.chain.then.approver` for the
|
|
147
|
-
// finding Go placed at `$.payments_policy.chain.then.approver`.
|
|
148
|
-
// The drive path is also right under vet's anchored meet, which
|
|
149
|
-
// drives AT the anchor's own path (see vet.ts), so anchored
|
|
150
|
-
// findings land in the schema's namespace in both ports.
|
|
151
94
|
const level: any = body.clone(ctx, {
|
|
152
95
|
dup: true, path: [...ctx.path],
|
|
153
96
|
} as any)
|
|
@@ -173,9 +116,6 @@ class RecurseVal extends FeatureVal {
|
|
|
173
116
|
}
|
|
174
117
|
|
|
175
118
|
gen(ctx: AontuContext) {
|
|
176
|
-
// An unexpanded residual in a demanded position refuses;
|
|
177
|
-
// guardedness is emergent -- under an optional key the bag's
|
|
178
|
-
// isolated context swallows this and drops the key.
|
|
179
119
|
makeNilErr(ctx, 'recursion_unexpanded', this, undefined, 'recurse',
|
|
180
120
|
{ target: '$.' + this.target.join('.') })
|
|
181
121
|
return undefined
|
|
@@ -204,13 +144,6 @@ function bumpRecurse(v: any, xc: number): void {
|
|
|
204
144
|
v.xc = Math.max(v.xc, xc)
|
|
205
145
|
return
|
|
206
146
|
}
|
|
207
|
-
// A RAW REFERENCE TO A RECURSIVE TARGET IS THE RECURSION, minted or
|
|
208
|
-
// not -- the same reading containsRecurseOf already takes, and the
|
|
209
|
-
// reason bound 2 was inert. A freshly cloned level holds the
|
|
210
|
-
// definition's references UNRESOLVED, so this walk found no
|
|
211
|
-
// residual to stamp and `xc` read 0 at every expansion, in the
|
|
212
|
-
// healthy form too. The seed rides on the reference and the
|
|
213
|
-
// residual minted from it starts there (ts/src/val/RefVal.ts).
|
|
214
147
|
if (true === v.isRef) {
|
|
215
148
|
v.rxc = Math.max(v.rxc ?? 0, xc)
|
|
216
149
|
return
|
|
@@ -237,12 +170,6 @@ function bumpRecurse(v: any, xc: number): void {
|
|
|
237
170
|
}
|
|
238
171
|
|
|
239
172
|
|
|
240
|
-
// containsRecurseOf answers whether a definition holds a residual of
|
|
241
|
-
// the given target -- i.e. the definition is (transitively) the
|
|
242
|
-
// fixpoint that target names. A reference RESOLVING to such a
|
|
243
|
-
// definition must itself answer the residual: cloned instead, every
|
|
244
|
-
// reparse of a canon unrolled the schema one more level and canon
|
|
245
|
-
// never converged.
|
|
246
173
|
function containsRecurseOf(v: any, target: string[], depth?: number): boolean {
|
|
247
174
|
const d = depth ?? 0
|
|
248
175
|
if (null == v || true !== v.isVal || 8 < d) {
|
|
@@ -252,14 +179,6 @@ function containsRecurseOf(v: any, target: string[], depth?: number): boolean {
|
|
|
252
179
|
return v.target.length === target.length
|
|
253
180
|
&& v.target.every((s: string, i: number) => s === target[i])
|
|
254
181
|
}
|
|
255
|
-
// A RAW REFERENCE to the target IS the recursion, minted or not:
|
|
256
|
-
// the answer must not depend on whether the definition's own
|
|
257
|
-
// prefix position has been visited yet. Without this arm the
|
|
258
|
-
// answer was ORDER-DEPENDENT -- reparsing a generated canon puts
|
|
259
|
-
// the instance before the definition, its trailing `$.spec.Step`
|
|
260
|
-
// leaves resolved before `Step.then` had minted, and each resolve
|
|
261
|
-
// cloned one more unrolled level until the unify depth guard
|
|
262
|
-
// (unify_cycle) killed the document.
|
|
263
182
|
if (true === v.isRef && Array.isArray(v.peg)) {
|
|
264
183
|
if (v.peg.length === target.length
|
|
265
184
|
&& v.peg.every((s: any, i: number) => s === target[i])) {
|
package/src/val/RefVal.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* Copyright (c) 2021-2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
import {
|
|
6
5
|
walk,
|
|
7
6
|
explainOpen,
|
|
@@ -42,22 +41,12 @@ import { BigIntegerVal } from './BigIntegerVal'
|
|
|
42
41
|
import { BigDecimalVal } from './BigDecimalVal'
|
|
43
42
|
|
|
44
43
|
|
|
45
|
-
|
|
46
44
|
// A path segment no spelling can produce, used when append meets a Val
|
|
47
45
|
// class it has no rule for. A key cannot contain a NUL, so this can never
|
|
48
46
|
// match, which turns a silent path-shortening bug into a visible miss.
|
|
49
47
|
const UNSPELLABLE_SEGMENT = '\u0000unspellable'
|
|
50
48
|
|
|
51
49
|
|
|
52
|
-
// Is this value an unresolved type()/hide() call — or a conjunct still
|
|
53
|
-
// carrying one? A reference that lands on one must defer rather than
|
|
54
|
-
// clone it (see the call site in `find`): the marks such a call will
|
|
55
|
-
// stamp belong to the field it was WRITTEN at, and a clone resolving
|
|
56
|
-
// at the reference's site re-applies them after the reference's
|
|
57
|
-
// mark-clearing walk has already run. Only the two mark wrappers
|
|
58
|
-
// qualify — every other pending call resolves to an unmarked value,
|
|
59
|
-
// and the existing early-clone behaviour for those is pinned
|
|
60
|
-
// (move()/copy() ghost rows, hole-filling conjuncts).
|
|
61
50
|
function pendingMarkWrapper(v: any): boolean {
|
|
62
51
|
if (true === v.isTypeFunc || true === v.isHideFunc) {
|
|
63
52
|
return !v.done
|
|
@@ -108,13 +97,6 @@ class RefVal extends FeatureVal {
|
|
|
108
97
|
// a rendering of the settled tree, never a parse-time property.
|
|
109
98
|
expansion: Val | undefined = undefined
|
|
110
99
|
|
|
111
|
-
// THE RECURSION SEED (use-cases/BUGS.md §57). A reference that names
|
|
112
|
-
// a recursive definition IS the fixpoint reference; it mints a
|
|
113
|
-
// RecurseVal when it resolves. bumpRecurse stamps the expansion
|
|
114
|
-
// depth here, because a freshly cloned level holds the definition's
|
|
115
|
-
// references UNRESOLVED and so has no residual to stamp -- which is
|
|
116
|
-
// why the design's second termination bound read 0 at every
|
|
117
|
-
// expansion. The minted residual starts from this.
|
|
118
100
|
rxc: number = 0
|
|
119
101
|
prefix: boolean = false
|
|
120
102
|
|
|
@@ -139,14 +121,12 @@ class RefVal extends FeatureVal {
|
|
|
139
121
|
this.append(spec.peg[pI])
|
|
140
122
|
}
|
|
141
123
|
|
|
142
|
-
//console.log('RefVal', this.id, this.peg)
|
|
143
124
|
}
|
|
144
125
|
|
|
145
126
|
|
|
146
127
|
append(part: any) {
|
|
147
128
|
let partval
|
|
148
129
|
|
|
149
|
-
// console.log('APPEND', part)
|
|
150
130
|
|
|
151
131
|
if ('string' === typeof part) {
|
|
152
132
|
partval = part
|
|
@@ -159,33 +139,16 @@ class RefVal extends FeatureVal {
|
|
|
159
139
|
}
|
|
160
140
|
|
|
161
141
|
else if (part instanceof IntegerVal) {
|
|
162
|
-
// partval = '' + part.peg
|
|
163
142
|
partval = part.src
|
|
164
143
|
this.peg.push(partval)
|
|
165
144
|
}
|
|
166
145
|
|
|
167
|
-
// TODO: this is a bit of a hack, review
|
|
168
|
-
// Seems like a fundamental ambiguity?
|
|
169
|
-
// Resolved by path function
|
|
170
146
|
else if (part instanceof NumberVal) {
|
|
171
|
-
// let partvals: string[] = part.peg.toFixed(11).replace(/(\.0)?0+$/, '$1').split('.')
|
|
172
147
|
let partvals: string[] = part.src.split('.')
|
|
173
148
|
this.peg.push(...partvals)
|
|
174
149
|
}
|
|
175
150
|
|
|
176
|
-
// THE EXACT LEAVES ARE PATH TEXT LIKE ANY OTHER SPELLING. `0d1` as a
|
|
177
|
-
// segment addresses the key literally spelled `0d1` -- the same key
|
|
178
|
-
// `a:{0d1:7}` creates -- and is NOT the number 1, so it neither
|
|
179
|
-
// indexes a list nor reaches a key spelled `1`.
|
|
180
|
-
//
|
|
181
|
-
// Without these branches the part fell off the end of the chain and
|
|
182
|
-
// was SILENTLY DROPPED, so `$.a.0d0` resolved to `$.a` and handed back
|
|
183
|
-
// the CONTAINER. That is a wrong value, not a miss -- strictly worse
|
|
184
|
-
// than an error -- and it made `$.a.0d0` and `$.a.0d1` denote the same
|
|
185
|
-
// location.
|
|
186
151
|
else if (part instanceof BigIntegerVal || part instanceof BigDecimalVal) {
|
|
187
|
-
// A bigdecimal splits on its point exactly as a float does, so
|
|
188
|
-
// `$.x.0d1.5` addresses two levels.
|
|
189
152
|
this.peg.push(...part.src.split('.'))
|
|
190
153
|
}
|
|
191
154
|
|
|
@@ -219,12 +182,6 @@ class RefVal extends FeatureVal {
|
|
|
219
182
|
this.peg.push(...part.peg)
|
|
220
183
|
}
|
|
221
184
|
|
|
222
|
-
// A closed chain, deliberately. Every branch above ends in a push, so
|
|
223
|
-
// an unhandled Val class used to fall through in SILENCE and shorten
|
|
224
|
-
// the path by one segment -- which is how the two exact leaves, added
|
|
225
|
-
// by the number tower, made references resolve to their own container.
|
|
226
|
-
// A segment that cannot be spelled is pushed as one that cannot match,
|
|
227
|
-
// so the reference misses loudly instead of succeeding wrongly.
|
|
228
185
|
else {
|
|
229
186
|
this.peg.push(UNSPELLABLE_SEGMENT)
|
|
230
187
|
}
|
|
@@ -239,9 +196,6 @@ class RefVal extends FeatureVal {
|
|
|
239
196
|
|
|
240
197
|
if (this.id !== peer.id) {
|
|
241
198
|
|
|
242
|
-
// TODO: not resolved when all Vals in path are done is an error
|
|
243
|
-
// as path cannot be found
|
|
244
|
-
// let resolved: Val | undefined = null == ctx ? this : ctx.find(this)
|
|
245
199
|
let found: Val | undefined = this.find(ctx)
|
|
246
200
|
|
|
247
201
|
// `?? this` makes resolved non-nullish, so an unresolved reference
|
|
@@ -275,21 +229,12 @@ class RefVal extends FeatureVal {
|
|
|
275
229
|
out.dc = DONE === out.dc ? DONE : this.dc + 1
|
|
276
230
|
}
|
|
277
231
|
|
|
278
|
-
// console.log('REFVAL-UNIFY-OUT', ctx.cc, this.id, this.canon, this.done, 'P=', peer.id, peer.canon, peer.done, '->', out.id, out.canon, out.done)
|
|
279
232
|
|
|
280
233
|
explainClose(te, out)
|
|
281
234
|
return out
|
|
282
235
|
}
|
|
283
236
|
|
|
284
237
|
|
|
285
|
-
// `snap` is set by snapshotRefSpread (MapVal): a SPREAD snapshot
|
|
286
|
-
// wants the target's pre-resolution STRUCTURE — key()/path() still
|
|
287
|
-
// unresolved, to be re-resolved per destination — so the
|
|
288
|
-
// pending-mark-wrapper defer below must not apply to it. Deferring
|
|
289
|
-
// there made the snapshot wait until the target's own key() had
|
|
290
|
-
// resolved at the target, and the literal leaked into every
|
|
291
|
-
// destination (the exact failure the snapshot exists to prevent —
|
|
292
|
-
// test/spec/spread-type.tsv, spread-type-key-ref).
|
|
293
238
|
find(ctx: AontuContext, snap?: boolean) {
|
|
294
239
|
let out: Val | undefined = undefined
|
|
295
240
|
|
|
@@ -315,16 +260,8 @@ class RefVal extends FeatureVal {
|
|
|
315
260
|
|
|
316
261
|
let refpath: string[] = []
|
|
317
262
|
let pI = 0
|
|
318
|
-
// let descent = ''
|
|
319
263
|
|
|
320
264
|
if (isprefixpath) {
|
|
321
|
-
// THE DETECTOR'S ANSWER IS A RESIDUAL (RECURSION.0.md): a
|
|
322
|
-
// self-reference under a guarded shape is the fixpoint the
|
|
323
|
-
// author wrote, so the prefix hit mints the recursive residual
|
|
324
|
-
// instead of refusing -- except the degenerate all-empty
|
|
325
|
-
// spelling (path("")), which names nothing and keeps its
|
|
326
|
-
// path_cycle. Only all-string paths recurse; anything else
|
|
327
|
-
// keeps the conservative refusal.
|
|
328
265
|
let degenerate = 0 === this.path.length
|
|
329
266
|
let target: string[] = []
|
|
330
267
|
for (let i = 0; i < this.peg.length && !degenerate; i++) {
|
|
@@ -350,44 +287,16 @@ class RefVal extends FeatureVal {
|
|
|
350
287
|
|
|
351
288
|
for (let pI = 0; pI < this.peg.length; pI++) {
|
|
352
289
|
let part = this.peg[pI]
|
|
353
|
-
// An unspellable segment MISSES BEFORE ANY LOOKUP. The marker
|
|
354
|
-
// is NUL-prefixed because no spelling produces one, but a
|
|
355
|
-
// document can still hold a key spelled with an escaped NUL
|
|
356
|
-
// (`a:{"unspellable":7}`), and matching it would turn the
|
|
357
|
-
// silent path-shortening this marker exists to prevent into a
|
|
358
|
-
// different silent wrong value. The marker is a marker, never a
|
|
359
|
-
// lookup key.
|
|
360
290
|
if (UNSPELLABLE_SEGMENT === part) {
|
|
361
291
|
return makeNilErr(ctx, 'no_path', this)
|
|
362
292
|
}
|
|
363
293
|
if (part instanceof VarVal) {
|
|
364
|
-
// EVERY `$name` IN A PATH IS AN ORDINARY VARIABLE. `$KEY`,
|
|
365
|
-
// `$SELF` and `$PARENT` used to be intercepted here by name;
|
|
366
|
-
// they are gone (ADR-009). `key()` is the replacement for
|
|
367
|
-
// `$KEY` and answers where a value LANDS rather than where it
|
|
368
|
-
// was written, `$SELF.x` was only ever `$.x`, and `$PARENT.x`
|
|
369
|
-
// was only ever `.x`.
|
|
370
294
|
{
|
|
371
295
|
part = (part as VarVal).unify(top(), ctx)
|
|
372
296
|
if (part.isNil) {
|
|
373
|
-
// TODO: var not found, so can't find path
|
|
374
297
|
return
|
|
375
298
|
}
|
|
376
299
|
else {
|
|
377
|
-
// The resolved variable IS a path segment: $seg.r with
|
|
378
|
-
// seg="x" reads ...x.r (previously the coerced value was
|
|
379
|
-
// dropped, silently reading the path without it).
|
|
380
|
-
//
|
|
381
|
-
// Integer kind renders its EXACT digits -- the FOURTH site
|
|
382
|
-
// to get this wrong (see integerDigits and #21). `'' + peg`
|
|
383
|
-
// on a JS number gives the shortest round-tripping form, so
|
|
384
|
-
// a variable bound to 2^60 addressed the key
|
|
385
|
-
// "1152921504606847000" and missed the real one. Go's
|
|
386
|
-
// ref.go dispatches on kind here and was already correct.
|
|
387
|
-
//
|
|
388
|
-
// Every other kind is already right under `'' +`: a bigint
|
|
389
|
-
// and a Decimal stringify to exact digits, and a float must
|
|
390
|
-
// keep JS parity.
|
|
391
300
|
parts.push(part.isInteger ?
|
|
392
301
|
integerDigits(part.peg as number) : '' + part.peg)
|
|
393
302
|
}
|
|
@@ -419,9 +328,7 @@ class RefVal extends FeatureVal {
|
|
|
419
328
|
if (null != node) {
|
|
420
329
|
for (; pI < refpath.length; pI++) {
|
|
421
330
|
let part = refpath[pI]
|
|
422
|
-
// console.log('PART', pI, part, node)
|
|
423
331
|
|
|
424
|
-
// descent += (' | ' + pI + '=' + node.canon) // Util.inspect(node))
|
|
425
332
|
|
|
426
333
|
if (node.isMap) {
|
|
427
334
|
node = node.peg[part]
|
|
@@ -429,15 +336,6 @@ class RefVal extends FeatureVal {
|
|
|
429
336
|
else if (node.isList) {
|
|
430
337
|
node = node.peg[part]
|
|
431
338
|
}
|
|
432
|
-
// A PENDING MARK WRAPPER IS TRANSPARENT TO THE WALK: hide()
|
|
433
|
-
// and type() only mark, and their argument is the structure
|
|
434
|
-
// the path names. Without this, two sibling schemas in one
|
|
435
|
-
// hide() bag deadlock -- the wrapper waits for its argument,
|
|
436
|
-
// the argument's members wait for references that walk into
|
|
437
|
-
// the unresolved wrapper (BUGS.md §53's family; the
|
|
438
|
-
// recursive Policy/Step pair found it again). The found node
|
|
439
|
-
// is cloned and mark-cleared exactly as any reference target
|
|
440
|
-
// is, and the wrapper still marks its own field.
|
|
441
339
|
else if (true === (node as any).isFunc
|
|
442
340
|
&& ((node as any).isHideFunc || (node as any).isTypeFunc)
|
|
443
341
|
&& (true === (node as any).peg?.[0]?.isMap
|
|
@@ -445,26 +343,6 @@ class RefVal extends FeatureVal {
|
|
|
445
343
|
node = (node as any).peg[0].peg[part]
|
|
446
344
|
}
|
|
447
345
|
|
|
448
|
-
// AND SO IS A CONJUNCT THAT STILL CARRIES ONE (issue #164).
|
|
449
|
-
// Two statements for one key meet, so a key written as
|
|
450
|
-
// `T: type({...})` twice is a CONJUNCT of two wrappers -- and
|
|
451
|
-
// one written once beside a plain `T: {...}` is a conjunct
|
|
452
|
-
// too. The arm above sees a wrapper only when it is the whole
|
|
453
|
-
// node, so a reference into such a key walked into the
|
|
454
|
-
// conjunct and stopped: the wrapper waited for its argument,
|
|
455
|
-
// the argument waited for the reference, and neither moved.
|
|
456
|
-
// The first referring child of every consumer stayed
|
|
457
|
-
// unresolved and generation reported mapval_no_gen at a path
|
|
458
|
-
// that names none of this, which is how a five-file schema
|
|
459
|
-
// spent its evening being bisected.
|
|
460
|
-
//
|
|
461
|
-
// The answer at a segment is the MEET of what each term
|
|
462
|
-
// supplies, so terms that have no such member are skipped and
|
|
463
|
-
// the rest are conjoined -- one term answers as itself, and
|
|
464
|
-
// the ordinary map arm answers once the fold has happened.
|
|
465
|
-
// Restricted to a conjunct that still holds a pending
|
|
466
|
-
// wrapper: every other conjunct folds on its own, and this
|
|
467
|
-
// walk exists only to break the wrapper's deadlock.
|
|
468
346
|
else if (true === (node as any).isConjunct
|
|
469
347
|
&& Array.isArray((node as any).peg)
|
|
470
348
|
&& pendingMarkWrapper(node)) {
|
|
@@ -499,16 +377,6 @@ class RefVal extends FeatureVal {
|
|
|
499
377
|
}
|
|
500
378
|
}
|
|
501
379
|
|
|
502
|
-
// THE ANCHORED-MEET FALLBACK (vet --at): an absolute reference
|
|
503
|
-
// inside a lifted subtree names the SCHEMA's namespace, and the
|
|
504
|
-
// meet's root does not contain it. The settled schema root the
|
|
505
|
-
// lifter kept (AontuContext._fixroot; see RecurseVal.body) is
|
|
506
|
-
// the tree such a reference means. Without this, a recursion
|
|
507
|
-
// re-entering through a list spread died as no_path at the
|
|
508
|
-
// first element under vet --at, while the map-tail form (whose
|
|
509
|
-
// residual was minted during schema settling) worked; the Go
|
|
510
|
-
// port answers the anchored meet from settled structures and
|
|
511
|
-
// never sees the gap.
|
|
512
380
|
const fixroot: any = (ctx as any)._fixroot
|
|
513
381
|
if (this.absolute && null != fixroot
|
|
514
382
|
&& (nopath || pI !== refpath.length)) {
|
|
@@ -541,14 +409,6 @@ class RefVal extends FeatureVal {
|
|
|
541
409
|
else if (pI === refpath.length) {
|
|
542
410
|
out = node
|
|
543
411
|
|
|
544
|
-
// THE READ IS RECORDED, AND THE VALUE STAMPED WITH WHERE IT
|
|
545
|
-
// WAS FOUND (RENDER.0.md P7). A resolved reference clones its
|
|
546
|
-
// target into the referring position, so without the stamp a
|
|
547
|
-
// value that arrived by reference knows only where it came to
|
|
548
|
-
// rest -- and `render --coverage` has nothing to measure the
|
|
549
|
-
// model against. Off unless the run is instrumented; the first
|
|
550
|
-
// address wins, and every reference to one node names the same
|
|
551
|
-
// address anyway.
|
|
552
412
|
if (undefined !== ctx.reads && null != node) {
|
|
553
413
|
// The root's own address is `$`, as the coverage walk spells
|
|
554
414
|
// it: a dot with nothing after it would match no path there.
|
|
@@ -566,58 +426,18 @@ class RefVal extends FeatureVal {
|
|
|
566
426
|
}
|
|
567
427
|
}
|
|
568
428
|
|
|
569
|
-
// A reference landing on another reference -- or on a FUNCTION,
|
|
570
|
-
// whose arguments the chase now follows (issue #35) -- may be a
|
|
571
|
-
// PROVEN mutual cycle (a: $.b, b: $.a; a: $.b, b: upper($.a)).
|
|
572
|
-
// Follow the chain and, if it returns to a node still open above
|
|
573
|
-
// it, report path_cycle now instead of deferring every pass and
|
|
574
|
-
// dying later as a spent budget. No proof (the chain leaves plain
|
|
575
|
-
// refs and calls, or ends) defers as before.
|
|
576
429
|
if (null != out && ((out as any).isRef || (out as any).isFunc) &&
|
|
577
430
|
this.detectRefCycle(ctx)) {
|
|
578
431
|
out = makeNilErr(ctx, 'path_cycle', this)
|
|
579
432
|
}
|
|
580
|
-
// A PENDING MARK WRAPPER IS NOT YET A VALUE TO COPY (ADR-005).
|
|
581
|
-
// A type()/hide() call still waiting for its argument — an
|
|
582
|
-
// alias reference inside a type() body, a generator inside a
|
|
583
|
-
// hide() — would be cloned here as the CALL, and the clone
|
|
584
|
-
// then resolves at the REFERENCE's site, stamping marks that
|
|
585
|
-
// the mark-clearing walk below has already run too early to
|
|
586
|
-
// clear. That is how a type-marked alias silently suppressed
|
|
587
|
-
// the referring field's emission (use-cases/BUGS.md §12), how
|
|
588
|
-
// `hide(pack(...))` leaked its mark onto downstream packs
|
|
589
|
-
// (§11), and how hide() around a computed field swallowed the
|
|
590
|
-
// value into a silent [] (§35b). Defer instead: the reference
|
|
591
|
-
// residuates until the wrapper has resolved at its OWN field,
|
|
592
|
-
// and the ordinary marked-value path below then clears the
|
|
593
|
-
// marks on the clone as documented. The move() reference
|
|
594
|
-
// (`_hide_found`) is exempt: a move TRANSPLANTS the pending
|
|
595
|
-
// call, and the ghost rows (test/spec/func.tsv) pin that its
|
|
596
|
-
// innards resolve at the destination.
|
|
597
433
|
else if (null != out && !snap && !this.mark._hide_found &&
|
|
598
434
|
pendingMarkWrapper(out)) {
|
|
599
435
|
out = undefined
|
|
600
436
|
}
|
|
601
|
-
// A STAGED ARGUMENT SNAPSHOTS A SETTLED SOURCE (the argsnap
|
|
602
|
-
// flag, set by driveStagedArgs). A generator's data argument is
|
|
603
|
-
// a copy OUTSIDE the tree, so anything in the target that still
|
|
604
|
-
// resolves against its own tree location — a spread-injected
|
|
605
|
-
// relative reference, a pending template — must finish there
|
|
606
|
-
// BEFORE the copy is taken: cloned earlier, the copy's rebased
|
|
607
|
-
// relative refs dangle under the generator and the model dies
|
|
608
|
-
// as *_no_gen with the generator never firing. Deferring here
|
|
609
|
-
// is exactly the documented staging rule: the generator waits
|
|
610
|
-
// for the source, then snapshots it whole.
|
|
611
437
|
else if (null != out && !snap && true === (ctx as any).argsnap &&
|
|
612
438
|
!out.done) {
|
|
613
439
|
out = undefined
|
|
614
440
|
}
|
|
615
|
-
// A REFERENCE TO A RECURSIVE DEFINITION IS THE FIXPOINT
|
|
616
|
-
// REFERENCE (RECURSION.0.md): resolving it to a clone
|
|
617
|
-
// unrolled the schema one level, and every reparse of a
|
|
618
|
-
// canon then unrolled one more -- canon never converged. The
|
|
619
|
-
// residual is the resolved form, exactly as at the prefix
|
|
620
|
-
// positions inside the definition.
|
|
621
441
|
else if (null != out && !snap && containsRecurseOf(out, this.peg as any)) {
|
|
622
442
|
const rec: any = new RecurseVal(
|
|
623
443
|
{ target: [...this.peg], xc: this.rxc } as any, ctx)
|
|
@@ -628,83 +448,31 @@ class RefVal extends FeatureVal {
|
|
|
628
448
|
// Types and hidden values are cloned and made concrete
|
|
629
449
|
else if (null != out) { // && (out.mark.type || out.mark.hide)) {
|
|
630
450
|
|
|
631
|
-
// console.log('FOUND-A', out)
|
|
632
451
|
|
|
633
452
|
if (this.mark.type || this.mark.hide) {
|
|
634
453
|
out.mark.type = this.mark.type
|
|
635
454
|
out.mark.hide = this.mark.hide
|
|
636
455
|
|
|
637
|
-
// walk(out, (_key: string | number | undefined, val: Val) => {
|
|
638
|
-
// val.mark.type = this.mark.type
|
|
639
|
-
// val.mark.hide = this.mark.hide
|
|
640
|
-
// return val
|
|
641
|
-
// })
|
|
642
456
|
}
|
|
643
457
|
|
|
644
458
|
if (this.mark._hide_found) {
|
|
645
459
|
out.mark.hide = true
|
|
646
460
|
}
|
|
647
461
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
// A REFERENCE LIFTS: the copy is concrete, its type and hide
|
|
651
|
-
// marks cleared to the leaves -- a marked target is what the
|
|
652
|
-
// author hid or typed, and a reference to it is the author
|
|
653
|
-
// asking for it in the open. EXCEPT the snapshot a staged
|
|
654
|
-
// verb takes of its data (`argsnap`: each, emit, filter,
|
|
655
|
-
// pack, pick, join, the aggregates), when the target itself
|
|
656
|
-
// is not marked: a member marked inside an unmarked bag was
|
|
657
|
-
// hidden IN ITS OWN RIGHT, and the verb's enumeration
|
|
658
|
-
// (ts/src/val/members.ts, BUGS.md §79) needs to see that
|
|
659
|
-
// mark to leave the member out, as generation does. A marked
|
|
660
|
-
// target lifts even there, or `each($.schema.entities, _)`
|
|
661
|
-
// under `schema: hide({...})` would see every entity as
|
|
662
|
-
// hidden, since hide() marks to the leaves.
|
|
462
|
+
|
|
663
463
|
const lifted = true !== (ctx as any).argsnap
|
|
664
464
|
|| true === out.mark.type || true === out.mark.hide
|
|
665
465
|
|
|
666
|
-
// A REFERENCE'S COPY OWNS ITS ARGUMENTS (ADR-025). The copy
|
|
667
|
-
// is a per-destination instance exactly as a spread's or a
|
|
668
|
-
// generator's is, so ADR-005's rule holds here too: nothing
|
|
669
|
-
// path-dependent may be shared between two destinations, or
|
|
670
|
-
// the first destination's resolution answers for them all.
|
|
671
|
-
// The shallow clone shared a call's ARGUMENTS -- so
|
|
672
|
-
// `items: [&: $.entities.User]` over a `close({...})` target
|
|
673
|
-
// gave every element the one inner map, whose path each
|
|
674
|
-
// element rebased in turn, and the constraint that failed at
|
|
675
|
-
// element 2 reported element 0's path (use-cases GAP 8).
|
|
676
|
-
//
|
|
677
|
-
// A STAGED CALL IS THE EXCEPTION, because it has not decided
|
|
678
|
-
// yet. Its arguments are still being driven AT ITS OWN SITE
|
|
679
|
-
// (the staging rule, G8 phase 0), and a copy that owned them
|
|
680
|
-
// would drive its own set at the referring position instead:
|
|
681
|
-
// the relative `.side_effect` in a `match()` would read the
|
|
682
|
-
// referring field's siblings (use-cases/09-agent-tools), and
|
|
683
|
-
// an alias naming an `emit` rule table -- a template, which
|
|
684
|
-
// is exactly a value copied before it resolves -- would read
|
|
685
|
-
// its recursive `%w` as a self-reference. A staged call
|
|
686
|
-
// ANYWHERE in the target counts: what is referenced is
|
|
687
|
-
// usually the conjunct the call sits in, not the call.
|
|
688
|
-
// The copy shares what the source is still settling, and
|
|
689
|
-
// owns the rest.
|
|
690
466
|
out = out.clone(ctx, { dup: !out.holdsStaged })
|
|
691
467
|
|
|
692
468
|
if (lifted) {
|
|
693
469
|
walk(out, (_key: string | number | undefined, val: Val) => {
|
|
694
470
|
val.mark.type = false
|
|
695
471
|
val.mark.hide = false
|
|
696
|
-
// THE LINK IS NOT CLEARED (G4 phase 3): a link says what
|
|
697
|
-
// a value POINTS AT, and a copy of a link points at the
|
|
698
|
-
// same thing. An ABSOLUTE address still names the same
|
|
699
|
-
// node from the copy; a RELATIVE one is read from the
|
|
700
|
-
// copy's own position, which is what makes a referenced
|
|
701
|
-
// model resolve its internal links inside the copy
|
|
702
|
-
// (ADR-014).
|
|
703
472
|
return val
|
|
704
473
|
})
|
|
705
474
|
}
|
|
706
475
|
|
|
707
|
-
// onsole.log('FOUND-C', out)
|
|
708
476
|
}
|
|
709
477
|
}
|
|
710
478
|
}
|
|
@@ -715,45 +483,7 @@ class RefVal extends FeatureVal {
|
|
|
715
483
|
}
|
|
716
484
|
|
|
717
485
|
|
|
718
|
-
// Follow the chain of plain references from this node; true iff the
|
|
719
|
-
// chain revisits a node -- a PROVEN reference cycle, distinct from a
|
|
720
|
-
// merely unresolved reference. Detection is only on the resolution
|
|
721
|
-
// chain revisiting a node, never on syntactic shape: a chain that
|
|
722
|
-
// passes through a variable segment, a conjunct or any other non-ref
|
|
723
|
-
// value yields no proof and the ref defers as before.
|
|
724
|
-
//
|
|
725
|
-
// A FUNCTION is followed, through its arguments (issue #35). A
|
|
726
|
-
// function resolves only once every argument does, so a chain that
|
|
727
|
-
// reaches `b:upper($.a)` and out through `$.a` has proved the same
|
|
728
|
-
// dependency a bare `b:$.a` proves -- `a:$.b b:upper($.a)` is a cycle
|
|
729
|
-
// whichever link wears the call. Without this the shape exhausted the
|
|
730
|
-
// depth budget instead: a `unify_cycle`, which under the G5 taxonomy
|
|
731
|
-
// means "retry with more may help", where a proven structural cycle is
|
|
732
|
-
// FIX THE MODEL. A conjunct and a disjunct stay unfollowed for reasons
|
|
733
|
-
// that are not the same: a disjunct member may simply not be taken, so
|
|
734
|
-
// reaching one proves nothing; a conjunct would be sound to follow, and
|
|
735
|
-
// is left out only because nothing needs it yet.
|
|
736
|
-
//
|
|
737
|
-
// The Go port reaches the same verdict on this shape by a DIFFERENT
|
|
738
|
-
// arm, and that difference outlives this method: its clonePath re-paths
|
|
739
|
-
// a resolved clone to the referring site, so the inner `$.a` lands at
|
|
740
|
-
// path [a] and the plain isprefixpath test proves the cycle before any
|
|
741
|
-
// chase is needed. TypeScript's clone keeps the source paths. ADR-001
|
|
742
|
-
// asks for arm-for-arm correspondence, so the clone-path difference is
|
|
743
|
-
// worth closing on its own; it is wider than this issue and both ports
|
|
744
|
-
// now agree on the verdict and the code either way.
|
|
745
486
|
detectRefCycle(ctx: AontuContext): boolean {
|
|
746
|
-
// Depth-first with an explicit ANCESTOR set, because a function may
|
|
747
|
-
// carry several reference arguments and the cycle can run through
|
|
748
|
-
// any one of them. The set holds the chain currently being walked,
|
|
749
|
-
// not every node ever walked: revisiting a node reached down a
|
|
750
|
-
// DIFFERENT branch is an ordinary shared reference (two keys reading
|
|
751
|
-
// one third key), and only revisiting one that is still open above
|
|
752
|
-
// us is a cycle.
|
|
753
|
-
//
|
|
754
|
-
// Identity is the RESOLVED PATH, not the RefVal instance: the same
|
|
755
|
-
// target can be reached through distinct ref instances, and it is
|
|
756
|
-
// returning to the same place that closes a loop.
|
|
757
487
|
const chase = (ref: RefVal, ancestors: Set<string>): boolean => {
|
|
758
488
|
const rp = ref.plainRefPath()
|
|
759
489
|
if (null == rp) {
|
|
@@ -870,7 +600,6 @@ class RefVal extends FeatureVal {
|
|
|
870
600
|
}
|
|
871
601
|
return (this.absolute ? '$' : '') +
|
|
872
602
|
(0 < this.peg.length ? '.' : '') +
|
|
873
|
-
// this.peg.join(this.sep)
|
|
874
603
|
this.peg.map((p: any) => '.' === p ? '' :
|
|
875
604
|
(p.isVal ? p.canon : '' + p))
|
|
876
605
|
.join('.')
|
|
@@ -878,18 +607,6 @@ class RefVal extends FeatureVal {
|
|
|
878
607
|
|
|
879
608
|
|
|
880
609
|
get canon() {
|
|
881
|
-
// AN ALIAS REFERENCE CANONS AS THE VALUE IT NAMES. A reference left
|
|
882
|
-
// standing after unification is one inside a spread template
|
|
883
|
-
// (`[&: %u]`, `{&: {a: %u}}`): the template applies to children
|
|
884
|
-
// that have not arrived, so it is not resolved in place. Canon
|
|
885
|
-
// erases the declaration (an alias is a name for a value, and
|
|
886
|
-
// nothing more -- ALIASES.0.md §4), so the name alone would not
|
|
887
|
-
// reparse, and the hash of `t: {&: %u}` would differ from the hash
|
|
888
|
-
// of `t: {&: integer}`, which is the same document. The expansion
|
|
889
|
-
// is attached by expandAliases (ts/src/alias.ts) once the tree has
|
|
890
|
-
// settled; without one -- a parse-only tree, an unresolved name, or
|
|
891
|
-
// the KNOT of a recursive alias inside its own template -- the
|
|
892
|
-
// reference spells its name. Twin of RefVal.Canon in go/ref.go.
|
|
893
610
|
if (undefined !== this.expansion) {
|
|
894
611
|
return this.expansion.canon
|
|
895
612
|
}
|
|
@@ -906,7 +623,6 @@ class RefVal extends FeatureVal {
|
|
|
906
623
|
undefined,
|
|
907
624
|
)
|
|
908
625
|
|
|
909
|
-
// TODO: refactor to use Site pointer
|
|
910
626
|
nil.path = this.path
|
|
911
627
|
nil.site.url = this.site.url
|
|
912
628
|
nil.site.row = this.site.row
|