aontu 0.52.1 → 0.54.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 +15 -3
- package/dist/aontu.js +126 -5
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +45 -1
- package/dist/cli.js +2845 -69
- package/dist/cli.js.map +1 -1
- package/dist/ctx.d.ts +18 -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 +45 -8
- package/dist/err.js.map +1 -1
- package/dist/graph.d.ts +13 -0
- package/dist/graph.js +110 -0
- package/dist/graph.js.map +1 -0
- package/dist/hcanon.d.ts +3 -0
- package/dist/hcanon.js +145 -0
- package/dist/hcanon.js.map +1 -0
- package/dist/hints.js +235 -8
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.d.ts +20 -0
- package/dist/jsonschema.js +425 -0
- package/dist/jsonschema.js.map +1 -0
- package/dist/lang.js +955 -110
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +9 -2
- package/dist/lsp.js +343 -48
- 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 +941 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mod-tool.d.ts +58 -0
- package/dist/mod-tool.js +532 -0
- package/dist/mod-tool.js.map +1 -0
- package/dist/mod.d.ts +35 -0
- package/dist/mod.js +345 -0
- package/dist/mod.js.map +1 -0
- package/dist/patch.d.ts +49 -0
- package/dist/patch.js +506 -0
- package/dist/patch.js.map +1 -0
- package/dist/provenance.d.ts +41 -0
- package/dist/provenance.js +336 -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 +15 -0
- package/dist/reach.js +168 -0
- package/dist/reach.js.map +1 -0
- package/dist/relation.d.ts +23 -0
- package/dist/relation.js +230 -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/sig.d.ts +25 -0
- package/dist/sig.js +277 -0
- package/dist/sig.js.map +1 -0
- package/dist/sigdecl.d.ts +2 -0
- package/dist/sigdecl.js +11 -0
- package/dist/sigdecl.js.map +1 -0
- package/dist/siggate.d.ts +4 -0
- package/dist/siggate.js +90 -0
- package/dist/siggate.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 +129 -0
- package/dist/std.js.map +1 -0
- package/dist/subsume.d.ts +39 -0
- package/dist/subsume.js +573 -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 +2 -1
- package/dist/unify.js +234 -38
- package/dist/unify.js.map +1 -1
- package/dist/utility.d.ts +8 -1
- package/dist/utility.js +68 -1
- package/dist/utility.js.map +1 -1
- package/dist/val/AggFuncVal.d.ts +44 -0
- package/dist/val/AggFuncVal.js +364 -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 +7 -0
- package/dist/val/BagVal.js +150 -11
- 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 +7 -1
- package/dist/val/ConstraintVal.js +523 -45
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.d.ts +35 -0
- package/dist/val/ContainerKindVal.js +99 -0
- package/dist/val/ContainerKindVal.js.map +1 -0
- package/dist/val/CopyFuncVal.d.ts +1 -2
- 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.d.ts +1 -2
- package/dist/val/DisjunctVal.js +269 -53
- 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.js +62 -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 +7 -1
- package/dist/val/FuncBaseVal.js +183 -2
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.d.ts +39 -0
- package/dist/val/GraphAtomVal.js +184 -0
- package/dist/val/GraphAtomVal.js.map +1 -0
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/JunctionVal.js +24 -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 +94 -14
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.d.ts +1 -0
- package/dist/val/MapVal.js +146 -14
- 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 +19 -1
- 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.d.ts +2 -2
- package/dist/val/PathFuncVal.js +75 -16
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.d.ts +25 -0
- package/dist/val/PathVal.js +150 -0
- package/dist/val/PathVal.js.map +1 -0
- 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.d.ts +2 -1
- package/dist/val/PlusOpVal.js +61 -37
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.d.ts +4 -2
- package/dist/val/PrefVal.js +223 -41
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.d.ts +19 -0
- package/dist/val/RecurseVal.js +217 -0
- package/dist/val/RecurseVal.js.map +1 -0
- package/dist/val/RefVal.d.ts +3 -2
- package/dist/val/RefVal.js +181 -66
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.d.ts +59 -0
- package/dist/val/ReferFuncVal.js +604 -0
- package/dist/val/ReferFuncVal.js.map +1 -0
- package/dist/val/ScalarKindVal.d.ts +4 -3
- package/dist/val/ScalarKindVal.js +12 -12
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/SuperFuncVal.d.ts +4 -2
- package/dist/val/SuperFuncVal.js +118 -14
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.d.ts +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 +7 -1
- package/dist/val/Val.js +170 -2
- 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 +173 -0
- package/dist/val/arith.js.map +1 -0
- package/dist/vet.d.ts +45 -0
- package/dist/vet.js +802 -0
- package/dist/vet.js.map +1 -0
- package/dist/view.d.ts +85 -0
- package/dist/view.js +1948 -0
- package/dist/view.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 +138 -0
- package/grammar/aontu.lark +118 -0
- package/grammar/aontu.tmLanguage.json +184 -0
- package/package.json +30 -8
- package/skill/SKILL.md +37 -0
- package/skill/error-codes.md +62 -0
- package/skill/examples.md +99 -0
- package/skill/grammar-card.md +56 -0
- package/src/agentsmd.ts +135 -0
- package/src/aontu.ts +166 -5
- package/src/cli.ts +3324 -72
- package/src/ctx.ts +93 -1
- package/src/diff.ts +198 -0
- package/src/err.ts +50 -8
- package/src/graph.ts +185 -0
- package/src/hcanon.ts +167 -0
- package/src/hints.ts +291 -8
- package/src/jsonschema.ts +552 -0
- package/src/lang.ts +1049 -110
- package/src/lsp.ts +351 -49
- package/src/mcp-server.ts +187 -0
- package/src/mcp.ts +1130 -0
- package/src/mod-tool.ts +718 -0
- package/src/mod.ts +453 -0
- package/src/patch.ts +628 -0
- package/src/provenance.ts +437 -0
- package/src/query.ts +381 -0
- package/src/reach.ts +213 -0
- package/src/relation.ts +298 -0
- package/src/report-sarif.ts +137 -0
- package/src/sig.ts +345 -0
- package/src/sigdecl.ts +11 -0
- package/src/siggate.ts +144 -0
- package/src/site.ts +36 -1
- package/src/std.ts +131 -0
- package/src/subsume.ts +739 -0
- package/src/trim.ts +195 -0
- package/src/tsconfig.json +10 -4
- package/src/type.ts +51 -2
- package/src/unify.ts +253 -38
- package/src/utility.ts +79 -1
- package/src/val/AggFuncVal.ts +546 -0
- package/src/val/ArithFuncVal.ts +108 -0
- package/src/val/BagVal.ts +158 -12
- package/src/val/CloseFuncVal.ts +9 -1
- package/src/val/ConjunctVal.ts +20 -0
- package/src/val/ConstraintVal.ts +576 -48
- package/src/val/ContainerKindVal.ts +158 -0
- package/src/val/CopyFuncVal.ts +0 -1
- package/src/val/Decimal.ts +15 -0
- package/src/val/DeprecateFuncVal.ts +84 -0
- package/src/val/DisjunctVal.ts +282 -59
- package/src/val/EachFuncVal.ts +133 -0
- package/src/val/ExpectVal.ts +65 -8
- package/src/val/FeatureVal.ts +1 -1
- package/src/val/FilterFuncVal.ts +154 -0
- package/src/val/FuncBaseVal.ts +206 -2
- package/src/val/GraphAtomVal.ts +264 -0
- package/src/val/HideFuncVal.ts +0 -2
- package/src/val/JunctionVal.ts +24 -1
- package/src/val/KeyFuncVal.ts +39 -35
- package/src/val/ListVal.ts +101 -15
- package/src/val/LowerFuncVal.ts +0 -1
- package/src/val/MapVal.ts +153 -14
- 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 +20 -1
- package/src/val/OpenFuncVal.ts +4 -2
- package/src/val/PackFuncVal.ts +175 -0
- package/src/val/PathFuncVal.ts +107 -20
- package/src/val/PathVal.ts +221 -0
- package/src/val/PlaceVal.ts +193 -0
- package/src/val/PlusOpVal.ts +67 -39
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +251 -60
- package/src/val/RecurseVal.ts +285 -0
- package/src/val/RefVal.ts +183 -78
- package/src/val/ReferFuncVal.ts +732 -0
- package/src/val/ScalarKindVal.ts +12 -13
- package/src/val/SuperFuncVal.ts +137 -13
- package/src/val/TopVal.ts +1 -2
- package/src/val/TypeFuncVal.ts +0 -2
- package/src/val/UpperFuncVal.ts +0 -1
- package/src/val/Val.ts +216 -4
- package/src/val/VarVal.ts +0 -1
- package/src/val/arith.ts +319 -0
- package/src/vet.ts +1025 -0
- package/src/view.ts +2563 -0
- package/src/walk.ts +99 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
// THE GRAPH ATOMS (RELATIONS.0.md §3.3): `acyclic()` and
|
|
4
|
+
// `inverse(name)`, conjoined at the same field as the `rel()` they
|
|
5
|
+
// govern. Their model is the sizing atoms -- a property that cannot be
|
|
6
|
+
// decided while information can still arrive is HELD during
|
|
7
|
+
// unification and DECIDED at generation, where no more can.
|
|
8
|
+
//
|
|
9
|
+
// During unification they are lattice-inert: both properties are
|
|
10
|
+
// global and non-monotone (one more edge can make an acyclic graph
|
|
11
|
+
// cyclic), and the lattice guarantee -- more information never
|
|
12
|
+
// falsifies what has been observed -- forbids a constraint that could
|
|
13
|
+
// answer true and then false. So the atoms only RESIDUATE: they ride
|
|
14
|
+
// the field through meets, dedup additively, appear in canon and reach
|
|
15
|
+
// the `aon1-` hash, and REGISTER the declaration on the context. The
|
|
16
|
+
// predicate they govern is the key they sit on, evaluation-global,
|
|
17
|
+
// additive across declarations.
|
|
18
|
+
//
|
|
19
|
+
// The verdict lands at generation (relationVerdict,
|
|
20
|
+
// ts/src/relation.ts) and is reported identically by the `relations`
|
|
21
|
+
// verb -- one decision, two surfaces.
|
|
22
|
+
|
|
23
|
+
import type {
|
|
24
|
+
Val,
|
|
25
|
+
ValSpec,
|
|
26
|
+
} from '../type'
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
DONE,
|
|
30
|
+
} from '../type'
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
AontuContext,
|
|
34
|
+
} from '../ctx'
|
|
35
|
+
|
|
36
|
+
import { makeNilErr } from '../err'
|
|
37
|
+
|
|
38
|
+
import { FuncBaseVal } from './FuncBaseVal'
|
|
39
|
+
import { FeatureVal } from './FeatureVal'
|
|
40
|
+
import { unite } from '../unify'
|
|
41
|
+
import { propagateMarks } from '../utility'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
// The declarations one evaluation accumulates: predicate -> what its
|
|
45
|
+
// atoms said. Additive, exactly as two statements of one map are. The
|
|
46
|
+
// map lives on the CONTEXT (created in the constructor, like the
|
|
47
|
+
// _depth box), so every clone shares one registry.
|
|
48
|
+
export type RelDecl = {
|
|
49
|
+
acyclic?: boolean
|
|
50
|
+
inverses: Set<string>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function relDecls(ctx: any): Map<string, RelDecl> {
|
|
54
|
+
return ctx._reldecls
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class GraphAtomVal extends FeatureVal {
|
|
59
|
+
isGraphAtom = true
|
|
60
|
+
isGenable = true
|
|
61
|
+
// AFTER rel() (45000): the atoms say nothing about the value.
|
|
62
|
+
cjo = 46000
|
|
63
|
+
|
|
64
|
+
akind: 'acyclic' | 'inverse'
|
|
65
|
+
invname?: string
|
|
66
|
+
// The value the atom rides on -- the sizing-constraint shape: the
|
|
67
|
+
// atom ABSORBS its fold neighbours (the rel, the container, another
|
|
68
|
+
// atom) and carries them, so the fold's pairwise walk still merges
|
|
69
|
+
// the value across it. Absent until the atom meets one.
|
|
70
|
+
held?: Val
|
|
71
|
+
|
|
72
|
+
constructor(spec: ValSpec, ctx?: AontuContext) {
|
|
73
|
+
super(spec, ctx)
|
|
74
|
+
this.akind = (spec as any).akind ?? 'acyclic'
|
|
75
|
+
this.invname = (spec as any).invname
|
|
76
|
+
this.held = (spec as any).held
|
|
77
|
+
// A settled residual, like an unmet rel(): the bare atom is its
|
|
78
|
+
// own value, and a type() body carrying one must settle. Holding
|
|
79
|
+
// an unsettled value, it is exactly as done as the value.
|
|
80
|
+
this.dc = undefined === this.held || true === this.held.done
|
|
81
|
+
? DONE : 0
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
clone(ctx: AontuContext, spec?: ValSpec): Val {
|
|
85
|
+
const out: any = super.clone(ctx, spec)
|
|
86
|
+
out.akind = this.akind
|
|
87
|
+
out.invname = this.invname
|
|
88
|
+
out.held = this.held
|
|
89
|
+
out.dc = this.dc
|
|
90
|
+
return out
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// A rebuilt atom around a new held, at this atom's position.
|
|
94
|
+
private carry(ctx: AontuContext, held: Val): Val {
|
|
95
|
+
const out: any = new GraphAtomVal(
|
|
96
|
+
{ akind: this.akind, invname: this.invname, held } as any, ctx)
|
|
97
|
+
propagateMarks(this, out)
|
|
98
|
+
out.site = this.site
|
|
99
|
+
out.path = this.path
|
|
100
|
+
return out
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// The predicate is the key the atom sits on -- and a predicate is a
|
|
104
|
+
// D-1 NAME, by exactly fieldkey's rule: an atom landed anywhere
|
|
105
|
+
// else declares nothing. Registration is idempotent (the
|
|
106
|
+
// declaration set is a set) and happens at every drive, so
|
|
107
|
+
// whichever pass first sees the atom at its landed position records
|
|
108
|
+
// it.
|
|
109
|
+
register(ctx: AontuContext): void {
|
|
110
|
+
const seg = this.path[this.path.length - 1]
|
|
111
|
+
if ('string' !== typeof seg || !GRAPH_ATOM_NAME.test(seg)) {
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
const decls = relDecls(ctx)
|
|
115
|
+
let d = decls.get(seg)
|
|
116
|
+
if (undefined === d) {
|
|
117
|
+
d = { inverses: new Set() }
|
|
118
|
+
decls.set(seg, d)
|
|
119
|
+
}
|
|
120
|
+
if ('acyclic' === this.akind) {
|
|
121
|
+
d.acyclic = true
|
|
122
|
+
}
|
|
123
|
+
else if (undefined !== this.invname) {
|
|
124
|
+
d.inverses.add(this.invname)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
unify(peer: Val, ctx: AontuContext): Val {
|
|
129
|
+
const p: any = peer
|
|
130
|
+
this.register(ctx)
|
|
131
|
+
|
|
132
|
+
// The self-drive: unite's tail calls unify(top) directly on any
|
|
133
|
+
// not-done result, and the held is what still has work to do.
|
|
134
|
+
// (A null/nil peer never arrives -- unite's ladder absorbs both.)
|
|
135
|
+
if (null == peer || true === p.isTop) {
|
|
136
|
+
if (undefined === this.held) {
|
|
137
|
+
return this
|
|
138
|
+
}
|
|
139
|
+
if (true === this.held.done) {
|
|
140
|
+
// Doneness is monotone, so recording it in place is safe --
|
|
141
|
+
// and without it the bag walk keeps asking and generation
|
|
142
|
+
// refuses a finished value.
|
|
143
|
+
this.dc = DONE
|
|
144
|
+
return this
|
|
145
|
+
}
|
|
146
|
+
// The self-drive refines IN PLACE (the MapVal top-peer
|
|
147
|
+
// pattern): a fresh atom per pass changes object identity, so
|
|
148
|
+
// spread apply-once stamps and the entity merge's fast paths
|
|
149
|
+
// stop holding, and the enclosing bags re-open every pass --
|
|
150
|
+
// the service catalog never converged.
|
|
151
|
+
const held = unite(ctx, this.held, undefined, 'atom-drive')
|
|
152
|
+
if (true === held.isNil) {
|
|
153
|
+
return held
|
|
154
|
+
}
|
|
155
|
+
this.held = held
|
|
156
|
+
if (true === held.done) {
|
|
157
|
+
this.dc = DONE
|
|
158
|
+
}
|
|
159
|
+
return this
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// The SAME declaration twice is one declaration; their helds
|
|
163
|
+
// merge.
|
|
164
|
+
if (true === p.isGraphAtom &&
|
|
165
|
+
p.akind === this.akind && p.invname === this.invname) {
|
|
166
|
+
const held = undefined === this.held ? p.held
|
|
167
|
+
: undefined === p.held ? this.held
|
|
168
|
+
: unite(ctx, this.held, p.held, 'atom-dup')
|
|
169
|
+
if (undefined !== held && true === held.isNil) {
|
|
170
|
+
return held
|
|
171
|
+
}
|
|
172
|
+
return undefined === held ? this : this.carry(ctx, held)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Anything else -- the rel, the container, a different atom -- is
|
|
176
|
+
// ABSORBED: the atom carries the value and the fold's pairwise
|
|
177
|
+
// walk merges across it.
|
|
178
|
+
const held = undefined === this.held ? peer
|
|
179
|
+
: unite(ctx, this.held, peer, 'atom-held')
|
|
180
|
+
return true === held.isNil ? held : this.carry(ctx, held)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
get canon(): string {
|
|
184
|
+
const own = 'acyclic' === this.akind
|
|
185
|
+
? 'acyclic()'
|
|
186
|
+
: 'inverse(' + JSON.stringify(this.invname) + ')'
|
|
187
|
+
return undefined === this.held ? own : this.held.canon + '&' + own
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
gen(ctx: AontuContext) {
|
|
191
|
+
// The atom is transparent at generation -- its verdict is global
|
|
192
|
+
// (relationVerdict), never a value at this field -- and a BARE
|
|
193
|
+
// atom is silent, exactly as an unmet rel() is.
|
|
194
|
+
return undefined === this.held ? undefined : this.held.gen(ctx)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
// D-1 (docs/design/RELATIONS.0.md): the name grammar shared by entity
|
|
200
|
+
// names, edge predicates and inverse names.
|
|
201
|
+
const GRAPH_ATOM_NAME = /^[_a-zA-Z][-_a-zA-Z0-9]*$/
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class AcyclicFuncVal extends FuncBaseVal {
|
|
205
|
+
isAcyclicFunc = true
|
|
206
|
+
|
|
207
|
+
constructor(spec: ValSpec, ctx?: AontuContext) {
|
|
208
|
+
super(spec, ctx)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
make(_ctx: AontuContext, spec: ValSpec): Val {
|
|
212
|
+
return new AcyclicFuncVal(spec)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
funcname() {
|
|
216
|
+
return 'acyclic'
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
resolve(ctx: AontuContext, _args: Val[]) {
|
|
220
|
+
const out: any = new GraphAtomVal({ akind: 'acyclic' } as any, ctx)
|
|
221
|
+
out.site = this.site
|
|
222
|
+
out.path = this.path
|
|
223
|
+
return out
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class InverseFuncVal extends FuncBaseVal {
|
|
229
|
+
isInverseFunc = true
|
|
230
|
+
|
|
231
|
+
constructor(spec: ValSpec, ctx?: AontuContext) {
|
|
232
|
+
super(spec, ctx)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
make(_ctx: AontuContext, spec: ValSpec): Val {
|
|
236
|
+
return new InverseFuncVal(spec)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
funcname() {
|
|
240
|
+
return 'inverse'
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
resolve(ctx: AontuContext, args: Val[]) {
|
|
244
|
+
const a: any = args[0]
|
|
245
|
+
// The mirroring predicate is a NAME -- D-1, spelled bare or
|
|
246
|
+
// quoted. A relation is a vocabulary term, not an address.
|
|
247
|
+
if (true !== a?.isScalar || 'string' !== typeof a.peg
|
|
248
|
+
|| !GRAPH_ATOM_NAME.test(a.peg)) {
|
|
249
|
+
return makeNilErr(ctx, 'inverse_name', this, undefined, 'inverse')
|
|
250
|
+
}
|
|
251
|
+
const out: any = new GraphAtomVal(
|
|
252
|
+
{ akind: 'inverse', invname: a.peg } as any, ctx)
|
|
253
|
+
out.site = this.site
|
|
254
|
+
out.path = this.path
|
|
255
|
+
return out
|
|
256
|
+
}
|
|
257
|
+
} /* node:coverage ignore next 7 */
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
export {
|
|
261
|
+
GraphAtomVal,
|
|
262
|
+
AcyclicFuncVal,
|
|
263
|
+
InverseFuncVal,
|
|
264
|
+
}
|
package/src/val/HideFuncVal.ts
CHANGED
package/src/val/JunctionVal.ts
CHANGED
|
@@ -33,7 +33,30 @@ abstract class JunctionVal extends FeatureVal {
|
|
|
33
33
|
|
|
34
34
|
clone(ctx: AontuContext, spec?: ValSpec): Val {
|
|
35
35
|
let out = (super.clone(ctx, spec) as JunctionVal)
|
|
36
|
-
|
|
36
|
+
// A JUNCTION'S MEMBERS SIT AT THE JUNCTION'S OWN POSITION. That is
|
|
37
|
+
// the rule `repathInstance` (Val.ts) states for the instance walk
|
|
38
|
+
// -- a conjunct's members occupy the conjunct's position, which is
|
|
39
|
+
// what `A & B` means -- and it holds for every clone, not only for
|
|
40
|
+
// marked ones.
|
|
41
|
+
//
|
|
42
|
+
// Val.clone's ctx cut cannot derive it: MapVal.clone hands a child
|
|
43
|
+
// its path through the SPEC rather than by descending the ctx, so
|
|
44
|
+
// a member left to the cut takes the DRIVING context's path -- the
|
|
45
|
+
// map's -- and loses the field key it sits under. A conjunct
|
|
46
|
+
// member reached through a reference into a position at least as
|
|
47
|
+
// deep as its definition then carried the entity's path, and every
|
|
48
|
+
// reader of `Val.path` was told the wrong position: a rel()-minted
|
|
49
|
+
// link took the ENTITY's key as its predicate, so `inverse(n)`
|
|
50
|
+
// looked for a mirror under a relation nobody declared and
|
|
51
|
+
// reported a written mirror missing.
|
|
52
|
+
//
|
|
53
|
+
// The instantiation flag still descends with the mark (ADR-005).
|
|
54
|
+
// Go states the same invariant directly (go/clone.go, cloneAt), so
|
|
55
|
+
// this restores parity rather than inventing a behaviour.
|
|
56
|
+
const childspec: any = spec?.mark || spec?.dup ?
|
|
57
|
+
{ mark: spec?.mark, dup: spec?.dup, path: out.path }
|
|
58
|
+
: { path: out.path }
|
|
59
|
+
out.peg = this.peg.map((entry: Val) => entry.clone(ctx, childspec))
|
|
37
60
|
return out
|
|
38
61
|
}
|
|
39
62
|
|
package/src/val/KeyFuncVal.ts
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from '../ctx'
|
|
13
13
|
|
|
14
14
|
import { StringVal } from '../val/StringVal'
|
|
15
|
-
import { ConjunctVal } from '../val/ConjunctVal'
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
|
|
@@ -41,39 +40,13 @@ class KeyFuncVal extends FuncBaseVal {
|
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (peer.isTop || (peer.id === this.id)) {
|
|
52
|
-
// TODO: clone needed to avoid triggering unify_cycle - find a better way
|
|
53
|
-
out = this.clone(ctx)
|
|
54
|
-
}
|
|
55
|
-
else if (peer.isNil) {
|
|
56
|
-
out = peer
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
if (
|
|
60
|
-
peer.isKeyFunc
|
|
61
|
-
&& peer.path.join('.') === this.path.join('.')
|
|
62
|
-
&& peer.peg?.[0]?.peg === this.peg?.[0]?.peg
|
|
63
|
-
) {
|
|
64
|
-
out = this
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
out = new ConjunctVal({ peg: [this, peer] }, ctx)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
out = super.unify(peer, ctx)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return out
|
|
76
|
-
}
|
|
43
|
+
// `key()` is the first value to take THE STAGING RULE (G8 phase 0,
|
|
44
|
+
// see AontuContext.settle): its answer is a segment of its own path,
|
|
45
|
+
// so it must not answer while a spread, a reference or a `move` can
|
|
46
|
+
// still move it. It residuates until the model stops changing, and
|
|
47
|
+
// fires on the settle pass. The residuation itself is FuncBaseVal's,
|
|
48
|
+
// shared with the generation combinators.
|
|
49
|
+
staged = true
|
|
77
50
|
|
|
78
51
|
|
|
79
52
|
resolve(ctx: AontuContext, _args: Val[]) {
|
|
@@ -113,7 +86,38 @@ class KeyFuncVal extends FuncBaseVal {
|
|
|
113
86
|
}
|
|
114
87
|
}
|
|
115
88
|
|
|
116
|
-
|
|
89
|
+
// THE PATH IS THE ONE IT IS BEING DRIVEN AT, not the one it
|
|
90
|
+
// remembers. `this.path` is a cache that the residuation clone
|
|
91
|
+
// refreshes each pass, and it is right for a key() the bag walk
|
|
92
|
+
// reaches directly -- but a key() nested inside a function or
|
|
93
|
+
// operator ARGUMENT is never reached that way: it is driven by its
|
|
94
|
+
// enclosing call, which re-paths nothing, so it kept the position
|
|
95
|
+
// the SOURCE TEXT put it at. Inside a template that is fatal: the
|
|
96
|
+
// source position of `&: {k: "x" + key()}` (or of `pack`'s
|
|
97
|
+
// template) is the template, not any of the destinations, and the
|
|
98
|
+
// parse-time path of a function argument is not a document
|
|
99
|
+
// position at all.
|
|
100
|
+
// A stored path is only usable if it IS one: a path segment that is
|
|
101
|
+
// not a key is not a position, and the parse-time path of a value
|
|
102
|
+
// written inside a function ARGUMENT carries exactly that -- the
|
|
103
|
+
// argument has no key, so its segment is not a string. Those values
|
|
104
|
+
// are also the ones the bag walk never re-paths (a call re-paths
|
|
105
|
+
// nothing it holds), which is why the stored path stays wrong
|
|
106
|
+
// forever rather than being refreshed on the next pass. For them
|
|
107
|
+
// the driving context is the only truth. For everything else the
|
|
108
|
+
// stored path stays authoritative, because a TRANSPLANTED value
|
|
109
|
+
// (move(), a shared clone) must answer for where it was put, not
|
|
110
|
+
// for whichever driver happened to reach it first.
|
|
111
|
+
let positioned = true
|
|
112
|
+
for (const seg of this.path) {
|
|
113
|
+
if ('string' !== typeof seg) {
|
|
114
|
+
positioned = false
|
|
115
|
+
break
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const here = positioned ? this.path : ctx.path
|
|
120
|
+
const key = here[here.length - (1 + move)] ?? ''
|
|
117
121
|
// console.log('KEY', this.path, move, key)
|
|
118
122
|
|
|
119
123
|
out = new StringVal({ peg: key })
|
package/src/val/ListVal.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { unite } from '../unify'
|
|
|
17
17
|
|
|
18
18
|
import {
|
|
19
19
|
propagateMarks,
|
|
20
|
+
canonRiders,
|
|
20
21
|
explainOpen,
|
|
21
22
|
ec,
|
|
22
23
|
explainClose,
|
|
@@ -32,6 +33,8 @@ import {
|
|
|
32
33
|
import { ConjunctVal } from './ConjunctVal'
|
|
33
34
|
import { NilVal } from './NilVal'
|
|
34
35
|
import { BagVal } from './BagVal'
|
|
36
|
+
import { repathInstance, spreadId } from './Val'
|
|
37
|
+
import { markSpread } from '../provenance'
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
class ListVal extends BagVal {
|
|
@@ -55,7 +58,10 @@ class ListVal extends BagVal {
|
|
|
55
58
|
if (spread) {
|
|
56
59
|
if ('&' === spread.o) {
|
|
57
60
|
|
|
58
|
-
//
|
|
61
|
+
// Multiple same-level spreads conjoin; an unequal spread from
|
|
62
|
+
// another statement meets this one in unify's combination
|
|
63
|
+
// below (see the MapVal constructor note — the combined
|
|
64
|
+
// template is stateless, BUGS.md §6-§7).
|
|
59
65
|
this.spread.cj =
|
|
60
66
|
Array.isArray(spread.v) ?
|
|
61
67
|
1 < spread.v.length ?
|
|
@@ -73,6 +79,12 @@ class ListVal extends BagVal {
|
|
|
73
79
|
// NOTE: order of keys is not preserved!
|
|
74
80
|
// not possible in any case - consider {a,b} unify {b,a}
|
|
75
81
|
unify(peer: Val, ctx: AontuContext): Val {
|
|
82
|
+
// A rel() peer drives: the relation constraint rewrites this list
|
|
83
|
+
// leaf by leaf (RELATIONS.0.md §3.2); see the twin arm in MapVal.
|
|
84
|
+
if (true === (peer as any)?.isRel) {
|
|
85
|
+
return (peer as any).unify(this, ctx)
|
|
86
|
+
}
|
|
87
|
+
|
|
76
88
|
const TOP = top()
|
|
77
89
|
peer = peer ?? TOP
|
|
78
90
|
|
|
@@ -86,6 +98,19 @@ class ListVal extends BagVal {
|
|
|
86
98
|
return peer.unify(this, ctx)
|
|
87
99
|
}
|
|
88
100
|
|
|
101
|
+
// A DISJUNCT ALTERNATIVE MATCHES ITS OWN LENGTH (BUGS.md §52
|
|
102
|
+
// regime 4, the X-C3 adjudication): in a trial, a literal list
|
|
103
|
+
// with no spread admits only a peer list of the same length -- a
|
|
104
|
+
// spread makes it variadic. Outside trials the ordinary
|
|
105
|
+
// elementwise merge stands (two statements of one list are one
|
|
106
|
+
// list), so `[] | [&: T]` stops admitting every list through the
|
|
107
|
+
// empty arm while `a: [] a: [1]` still merges.
|
|
108
|
+
if (true === ctx._trialMode && true === (peer as any).isList
|
|
109
|
+
&& null == this.spread.cj && null == (peer as any).spread.cj
|
|
110
|
+
&& this.peg.length !== (peer as any).peg.length) {
|
|
111
|
+
return makeNilErr(ctx, 'list_length', this, peer)
|
|
112
|
+
}
|
|
113
|
+
|
|
89
114
|
const te = ctx.explain && explainOpen(ctx, ctx.explain, 'List', this, peer)
|
|
90
115
|
let done: boolean = true
|
|
91
116
|
let exit = false
|
|
@@ -124,21 +149,63 @@ class ListVal extends BagVal {
|
|
|
124
149
|
// Always unify children first
|
|
125
150
|
for (let key in this.peg) {
|
|
126
151
|
const keyctx = ctx.descend(key)
|
|
127
|
-
const key_spread_cj = spread_cj.spreadClone(keyctx)
|
|
128
152
|
const child = this.peg[key]
|
|
129
153
|
|
|
130
154
|
propagateMarks(this, child)
|
|
131
155
|
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
156
|
+
// APPLIED ONCE PER ELEMENT, the guard MapVal has carried since
|
|
157
|
+
// the spread was written: an element that already holds this
|
|
158
|
+
// template's contribution is progressed by self-unification
|
|
159
|
+
// instead of having the template met into it a second time.
|
|
160
|
+
// Re-applying is the identity for a template that has already
|
|
161
|
+
// RESOLVED, which is why the missing guard went unnoticed here
|
|
162
|
+
// — but a template that residuates (`&: {k: key(1)}`, G8 phase
|
|
163
|
+
// 0) is not yet a value to be idempotent about, so each pass
|
|
164
|
+
// conjoined another copy and the element's canon DOUBLED per
|
|
165
|
+
// pass. The old `ctx.cc < 3` key delay hid it by ending the
|
|
166
|
+
// growth at three passes; the staging rule waits for the model
|
|
167
|
+
// to settle, and a model whose canon doubles every pass never
|
|
168
|
+
// does.
|
|
169
|
+
let oval: Val
|
|
170
|
+
if (!spread_cj.isTop
|
|
171
|
+
&& (child as any)._spr === spreadId(spread_cj)) {
|
|
172
|
+
oval = child.done ? child :
|
|
173
|
+
unite(te ? keyctx.clone({ explain: ec(te, 'PEG:' + key) }) : keyctx,
|
|
174
|
+
child, TOP, 'list-own')
|
|
175
|
+
; (oval as any)._spr = spreadId(spread_cj)
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const key_spread_cj = spread_cj.spreadClone(keyctx)
|
|
179
|
+
// The spread mark the provenance recorder reads (G7 phase 3),
|
|
180
|
+
// as in MapVal: this is where a template becomes a per-element
|
|
181
|
+
// contribution. Instrumented runs only.
|
|
182
|
+
if (undefined !== keyctx.prov) {
|
|
183
|
+
markSpread(key_spread_cj)
|
|
184
|
+
}
|
|
140
185
|
|
|
141
|
-
|
|
186
|
+
// child is non-nullish: propagateMarks above dereferences it.
|
|
187
|
+
oval =
|
|
188
|
+
child.isNil ? child :
|
|
189
|
+
key_spread_cj.isNil ? key_spread_cj :
|
|
190
|
+
// The no-op meet is SKIPPED on the normal path (it is the
|
|
191
|
+
// identity) but TAKEN while recording: a value written once
|
|
192
|
+
// and never met is still a contribution the author wants
|
|
193
|
+
// pointed at, and the Go port's unite sees that meet (G7
|
|
194
|
+
// phase 4). Instrumented runs pay knowingly.
|
|
195
|
+
key_spread_cj.isTop && child.done && undefined === keyctx.prov
|
|
196
|
+
? child :
|
|
197
|
+
child.isTop && key_spread_cj.done ? key_spread_cj :
|
|
198
|
+
unite(te ? keyctx.clone({ explain: ec(te, 'PEG:' + key) }) : keyctx,
|
|
199
|
+
child, key_spread_cj, 'list-own')
|
|
200
|
+
|
|
201
|
+
if (!spread_cj.isTop && !oval.isNil) {
|
|
202
|
+
; (oval as any)._spr = spreadId(spread_cj)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
out.peg[key] = oval
|
|
207
|
+
|
|
208
|
+
done = (done && DONE === oval.dc)
|
|
142
209
|
}
|
|
143
210
|
|
|
144
211
|
const allowedKeys: string[] = this.closed ? Object.keys(this.peg) : []
|
|
@@ -171,6 +238,9 @@ class ListVal extends BagVal {
|
|
|
171
238
|
|
|
172
239
|
if (this.spread.cj) {
|
|
173
240
|
let key_spread_cj = spread_cj.spreadClone(peerctx)
|
|
241
|
+
if (undefined !== peerctx.prov) {
|
|
242
|
+
markSpread(key_spread_cj)
|
|
243
|
+
}
|
|
174
244
|
|
|
175
245
|
oval = out.peg[peerkey] =
|
|
176
246
|
unite(te ? peerctx.clone({ explain: ec(te, 'PSP:' + peerkey) }) : peerctx,
|
|
@@ -182,6 +252,12 @@ class ListVal extends BagVal {
|
|
|
182
252
|
done = (done && DONE === oval.dc)
|
|
183
253
|
}
|
|
184
254
|
}
|
|
255
|
+
else if (true === (peer as any).isContainerKind) {
|
|
256
|
+
// The container KIND delegates to its own arm, exactly as a
|
|
257
|
+
// scalar delegates to a ScalarKindVal peer (MapVal has the
|
|
258
|
+
// same arm).
|
|
259
|
+
out = peer.unify(this, ctx) as any
|
|
260
|
+
}
|
|
185
261
|
else if (!peer.isTop) {
|
|
186
262
|
out = makeNilErr(ctx, 'list', this, peer)
|
|
187
263
|
}
|
|
@@ -226,7 +302,11 @@ class ListVal extends BagVal {
|
|
|
226
302
|
}
|
|
227
303
|
|
|
228
304
|
if (!allScalarKind) {
|
|
229
|
-
|
|
305
|
+
// A full instance (`dup`, ADR-005), paths normalised to the
|
|
306
|
+
// destination: see Val.spreadClone and repathInstance.
|
|
307
|
+
const out = this.clone(ctx, { dup: true })
|
|
308
|
+
repathInstance(out, out.path)
|
|
309
|
+
return out
|
|
230
310
|
}
|
|
231
311
|
|
|
232
312
|
let out = (super.clone(ctx) as ListVal)
|
|
@@ -249,12 +329,16 @@ class ListVal extends BagVal {
|
|
|
249
329
|
|
|
250
330
|
clone(ctx: AontuContext, spec?: ValSpec): Val {
|
|
251
331
|
let out = (super.clone(ctx, spec) as ListVal)
|
|
332
|
+
// The instantiation flag descends with the mark (ADR-005): a
|
|
333
|
+
// template's elements are part of the instance.
|
|
334
|
+
const childspec = spec?.mark || spec?.dup ?
|
|
335
|
+
{ mark: spec?.mark, dup: spec?.dup } : {}
|
|
252
336
|
for (let entry of Object.entries(this.peg)) {
|
|
253
337
|
out.peg[entry[0]] =
|
|
254
|
-
(entry[1] as any)?.isVal ? (entry[1] as Val).clone(ctx,
|
|
338
|
+
(entry[1] as any)?.isVal ? (entry[1] as Val).clone(ctx, childspec) : entry[1]
|
|
255
339
|
}
|
|
256
340
|
if (this.spread.cj) {
|
|
257
|
-
out.spread.cj = this.spread.cj.clone(ctx,
|
|
341
|
+
out.spread.cj = this.spread.cj.clone(ctx, childspec)
|
|
258
342
|
}
|
|
259
343
|
|
|
260
344
|
out.closed = this.closed
|
|
@@ -280,7 +364,9 @@ class ListVal extends BagVal {
|
|
|
280
364
|
// key. The Go port's ListVal.Canon has no such arm either, and the
|
|
281
365
|
// two canons must agree -- a canon is round-trippable, and a marker
|
|
282
366
|
// on an element the grammar cannot produce would not reparse.
|
|
283
|
-
|
|
367
|
+
// canonRiders, not .canon: a deprecated element renders
|
|
368
|
+
// back as its `deprecate(x, m)` call, reparseably (G3).
|
|
369
|
+
keys.map(k => canonRiders(this.peg[k])).join(',') +
|
|
284
370
|
']'
|
|
285
371
|
}
|
|
286
372
|
} /* node:coverage ignore next 8 */
|
package/src/val/LowerFuncVal.ts
CHANGED