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
package/src/val/MapVal.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { unite } from '../unify'
|
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
propagateMarks,
|
|
19
|
+
canonRiders,
|
|
19
20
|
walk,
|
|
20
21
|
explainOpen,
|
|
21
22
|
ec,
|
|
@@ -27,12 +28,15 @@ import { makeNilErr, AontuError } from '../err'
|
|
|
27
28
|
import {
|
|
28
29
|
top
|
|
29
30
|
} from './top'
|
|
31
|
+
import { pendingMarkWrapper } from './RefVal'
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
import { ConjunctVal } from './ConjunctVal'
|
|
33
35
|
import { NilVal } from './NilVal'
|
|
34
36
|
import { BagVal } from './BagVal'
|
|
37
|
+
import { repathInstance, spreadId } from './Val'
|
|
35
38
|
import { cmpCodePoint } from '../keyorder'
|
|
39
|
+
import { markSpread } from '../provenance'
|
|
36
40
|
|
|
37
41
|
|
|
38
42
|
// Structural snapshots of ref spreads (see MapVal.unify), keyed by the
|
|
@@ -60,10 +64,21 @@ function snapshotRefSpread(cj: any, ctx: AontuContext): Val | undefined {
|
|
|
60
64
|
const sk = spreadSnapKey(cj)
|
|
61
65
|
let snap: Val | undefined = snapmap.get(sk)
|
|
62
66
|
if (undefined === snap) {
|
|
63
|
-
|
|
67
|
+
// snap mode: the pending-mark-wrapper defer in find must not
|
|
68
|
+
// apply here — the snapshot WANTS the pre-resolution structure.
|
|
69
|
+
let tgt: Val | undefined = cj.find(ctx, true)
|
|
64
70
|
// A ref to a type() resolves to its inner template — snapshot that,
|
|
65
71
|
// so a type-wrapped ref behaves like a plain-map ref spread.
|
|
66
72
|
if (tgt && (tgt as any).isTypeFunc) tgt = (tgt as any).peg?.[0]
|
|
73
|
+
// A pending type()/hide() CALL is not yet a value to snapshot
|
|
74
|
+
// (ADR-005, the same rule find's non-snap path defers on): cached
|
|
75
|
+
// here it resolves at every destination and STAMPS marks the
|
|
76
|
+
// clearing walk ran too early to clear -- a mutual recursive
|
|
77
|
+
// schema's members vanished from generation this way. No cache;
|
|
78
|
+
// retry once the wrapper has resolved at its own field.
|
|
79
|
+
if (tgt && pendingMarkWrapper(tgt)) {
|
|
80
|
+
return undefined
|
|
81
|
+
}
|
|
67
82
|
// Only snapshot a found, path-dependent target. If the target is not
|
|
68
83
|
// present yet (it may be introduced by a later conjunct/merge), do
|
|
69
84
|
// NOT cache — retry on the next fixpoint pass.
|
|
@@ -104,7 +119,12 @@ class MapVal extends BagVal {
|
|
|
104
119
|
|
|
105
120
|
if (spread) {
|
|
106
121
|
if ('&' === spread.o) {
|
|
107
|
-
//
|
|
122
|
+
// Multiple same-level spreads arrive as an array and conjoin;
|
|
123
|
+
// an unequal spread arriving from ANOTHER statement meets this
|
|
124
|
+
// one in unify's spread combination below — sound since the
|
|
125
|
+
// combined template became stateless (pure ExpectVal, BUGS.md
|
|
126
|
+
// §6-§7): each child meets the combined constraint
|
|
127
|
+
// independently and children never meet each other's data.
|
|
108
128
|
this.spread.cj =
|
|
109
129
|
Array.isArray(spread.v) ?
|
|
110
130
|
1 < spread.v.length ?
|
|
@@ -120,7 +140,34 @@ class MapVal extends BagVal {
|
|
|
120
140
|
|
|
121
141
|
// NOTE: order of keys is not preserved!
|
|
122
142
|
// not possible in any case - consider {a,b} unify {b,a}
|
|
143
|
+
// ALIAS DECLARATIONS MUST SIT AT THE DOCUMENT ROOT. Stated on the
|
|
144
|
+
// VALUE rather than at the parse, because the parse cannot see it: an
|
|
145
|
+
// INCLUDED file's declarations are at the root of their own text, and
|
|
146
|
+
// only once the loaded map is placed does it become apparent that
|
|
147
|
+
// root is not the document's. `%name` is spelled as a reference from
|
|
148
|
+
// the document root, so an included file's own `%b` would otherwise
|
|
149
|
+
// reach the INCLUDER's `%b` -- cross-file capture, the hazard the
|
|
150
|
+
// sigil exists to prevent, one level up.
|
|
151
|
+
//
|
|
152
|
+
// P1 is single-file by construction; carrying a name ACROSS files is
|
|
153
|
+
// what `export` and the destructure are for (P2, not built), and this
|
|
154
|
+
// refusal is what keeps the two from being confused meanwhile. Pathed
|
|
155
|
+
// at the DECLARATION, which is what is wrong, not at the map.
|
|
156
|
+
aliasDeclarationsAreRooted(ctx: AontuContext): Val | undefined {
|
|
157
|
+
if (0 === this.aliasKeys.length || 0 === this.path.length) {
|
|
158
|
+
return undefined
|
|
159
|
+
}
|
|
160
|
+
const nv: any = new NilVal({ why: 'alias_not_toplevel' }, ctx)
|
|
161
|
+
nv.site = this.site
|
|
162
|
+
nv.path = [...this.path, this.aliasKeys[0]]
|
|
163
|
+
return nv
|
|
164
|
+
}
|
|
165
|
+
|
|
123
166
|
unify(peer: Val, ctx: AontuContext): Val {
|
|
167
|
+
const arooted = this.aliasDeclarationsAreRooted(ctx)
|
|
168
|
+
if (undefined !== arooted) {
|
|
169
|
+
return arooted
|
|
170
|
+
}
|
|
124
171
|
// console.log('MAPVAL-UNIFY', this.id, this.canon, peer.id, peer.canon)
|
|
125
172
|
|
|
126
173
|
const TOP = top()
|
|
@@ -146,9 +193,18 @@ class MapVal extends BagVal {
|
|
|
146
193
|
|
|
147
194
|
out.closed = this.closed
|
|
148
195
|
out.optionalKeys = [...this.optionalKeys]
|
|
196
|
+
out.aliasKeys = [...this.aliasKeys]
|
|
149
197
|
out.spread.cj = this.spread.cj
|
|
150
198
|
out.site = this.site
|
|
151
199
|
|
|
200
|
+
// A rel() peer DRIVES whichever side the fold hands it on: the
|
|
201
|
+
// relation constraint rewrites this container leaf by leaf
|
|
202
|
+
// (RELATIONS.0.md §3.2), exactly as a sizing residual takes the
|
|
203
|
+
// driver's seat above.
|
|
204
|
+
if (true === (peer as any)?.isRel) {
|
|
205
|
+
return peer.unify(this, te ? ctx.clone({ explain: ec(te, 'REL') }) : ctx)
|
|
206
|
+
}
|
|
207
|
+
|
|
152
208
|
if (peer instanceof MapVal) {
|
|
153
209
|
if (!this.closed && peer.closed) {
|
|
154
210
|
out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'PMC') }) : ctx) as MapVal
|
|
@@ -184,6 +240,13 @@ class MapVal extends BagVal {
|
|
|
184
240
|
// combined here). unite resolves key()/path() at each destination via
|
|
185
241
|
// spreadClone below, so nested + sibling key() cases stay correct
|
|
186
242
|
// (test/spec/spread-nested-key, spread-key-all).
|
|
243
|
+
//
|
|
244
|
+
// The combined template must stay STATELESS: this meet wraps a
|
|
245
|
+
// key present in only one side as an ExpectVal, the combined
|
|
246
|
+
// map is shared across destinations when path-independent
|
|
247
|
+
// (spreadClone tier 1), and a stateful expect accumulated the
|
|
248
|
+
// first sibling's data and met it into the next (BUGS.md
|
|
249
|
+
// §6-§7). ExpectVal.unify is pure for exactly this reason.
|
|
187
250
|
out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
|
|
188
251
|
null == peer.spread.cj ? out.spread.cj :
|
|
189
252
|
out.spread.cj.canon === peer.spread.cj.canon ? out.spread.cj :
|
|
@@ -243,31 +306,46 @@ class MapVal extends BagVal {
|
|
|
243
306
|
// No `undefined !== child` here: propagateMarks above already
|
|
244
307
|
// dereferenced it, so a missing child would have thrown there.
|
|
245
308
|
if (!spread_cj.isTop
|
|
246
|
-
&& (child as any)._spr === (spread_cj
|
|
309
|
+
&& (child as any)._spr === spreadId(spread_cj)) {
|
|
247
310
|
oval = child.done ? child :
|
|
248
311
|
unite(te ? keyctx.clone({ explain: ec(te, 'KEY:' + key) }) : keyctx,
|
|
249
312
|
child, TOP, 'map-own')
|
|
250
|
-
; (oval as any)._spr = (spread_cj
|
|
313
|
+
; (oval as any)._spr = spreadId(spread_cj)
|
|
251
314
|
}
|
|
252
315
|
else {
|
|
253
316
|
const key_spread_cj = spread_cj.spreadClone(keyctx)
|
|
254
317
|
|
|
318
|
+
// The one place a spread is APPLIED, so the one place that
|
|
319
|
+
// knows a contribution came from a template rather than
|
|
320
|
+
// from the key itself (G7 phase 3). Only when someone is
|
|
321
|
+
// recording: the walk is O(template) per key per pass.
|
|
322
|
+
if (undefined !== keyctx.prov) {
|
|
323
|
+
markSpread(key_spread_cj)
|
|
324
|
+
}
|
|
325
|
+
|
|
255
326
|
// child is non-nullish: propagateMarks above dereferences it.
|
|
256
327
|
oval =
|
|
257
328
|
child.isNil ? child :
|
|
258
329
|
key_spread_cj.isNil ? key_spread_cj :
|
|
259
|
-
|
|
330
|
+
// The no-op meet is SKIPPED on the normal path (it is the
|
|
331
|
+
// identity) but TAKEN while recording: a value written once
|
|
332
|
+
// and never met is still a contribution the author wants
|
|
333
|
+
// pointed at, and the Go port's unite sees that meet (G7
|
|
334
|
+
// phase 4). Instrumented runs pay knowingly.
|
|
335
|
+
key_spread_cj.isTop && child.done && undefined === keyctx.prov
|
|
336
|
+
? child :
|
|
260
337
|
child.isTop && key_spread_cj.done ? key_spread_cj :
|
|
261
338
|
unite(te ? keyctx.clone({ explain: ec(te, 'KEY:' + key) }) : keyctx,
|
|
262
339
|
child, key_spread_cj, 'map-own')
|
|
263
340
|
|
|
264
341
|
if (!spread_cj.isTop && !oval.isNil) {
|
|
265
|
-
; (oval as any)._spr = (spread_cj
|
|
342
|
+
; (oval as any)._spr = spreadId(spread_cj)
|
|
266
343
|
}
|
|
267
344
|
}
|
|
268
345
|
|
|
269
346
|
out.peg[key] = oval
|
|
270
347
|
|
|
348
|
+
|
|
271
349
|
done = (done && DONE === oval.dc)
|
|
272
350
|
}
|
|
273
351
|
|
|
@@ -291,12 +369,31 @@ class MapVal extends BagVal {
|
|
|
291
369
|
out.optionalKeys.push(peerkey)
|
|
292
370
|
}
|
|
293
371
|
|
|
372
|
+
// ... and so is an alias declaration, for the same reason:
|
|
373
|
+
// two statements for one map are one map, and a name declared
|
|
374
|
+
// in either is declared in the result.
|
|
375
|
+
if (upeer.aliasKeys.includes(peerkey) && !out.aliasKeys.includes(peerkey)) {
|
|
376
|
+
out.aliasKeys.push(peerkey)
|
|
377
|
+
}
|
|
378
|
+
|
|
294
379
|
let child = out.peg[peerkey]
|
|
295
380
|
|
|
296
381
|
const peerctx = ctx.descend(peerkey)
|
|
297
382
|
|
|
298
383
|
let oval = out.peg[peerkey] =
|
|
299
|
-
|
|
384
|
+
// A peer-only key is CARRIED, not met — except on an
|
|
385
|
+
// instrumented run, where the identity meet is taken so
|
|
386
|
+
// the recorder sees where the value came from. The Go port
|
|
387
|
+
// unites a genable peer-only child with TOP unconditionally
|
|
388
|
+
// (go/mapval.go), and the difference was invisible until
|
|
389
|
+
// G4's identity merge brought a peer whose children the
|
|
390
|
+
// recorder counts as WRITTEN: `why $.b.k` on two positions
|
|
391
|
+
// of one entity named the site in Go and answered "nothing
|
|
392
|
+
// met here" in TypeScript.
|
|
393
|
+
undefined === child
|
|
394
|
+
? (undefined !== peerctx.prov && peerchild.isGenable
|
|
395
|
+
? unite(peerctx, peerchild, TOP, 'map-peer-only')
|
|
396
|
+
: this.handleExpectedVal(peerkey, peerchild, this, ctx)) :
|
|
300
397
|
child.isTop && peerchild.done ? peerchild :
|
|
301
398
|
child.isNil ? child :
|
|
302
399
|
peerchild.isNil ? peerchild :
|
|
@@ -307,15 +404,27 @@ class MapVal extends BagVal {
|
|
|
307
404
|
// Same apply-once discipline as the own-key loop: once the
|
|
308
405
|
// constraint is merged into the value (marked with the
|
|
309
406
|
// constraint's id), later passes only self-unify.
|
|
310
|
-
if ((oval as any)._spr !== (spread_cj
|
|
407
|
+
if ((oval as any)._spr !== spreadId(spread_cj)) {
|
|
311
408
|
let key_spread_cj = spread_cj.spreadClone(peerctx)
|
|
312
409
|
|
|
410
|
+
// A SPREAD IS A SPREAD FROM EITHER SIDE. The own-key loop
|
|
411
|
+
// above marks its template so `why` can say the
|
|
412
|
+
// contribution came from `&:` rather than from the key;
|
|
413
|
+
// this arm did not, so the SAME document reported the
|
|
414
|
+
// role or dropped it depending on whether the template
|
|
415
|
+
// and the keys were written in one statement or two --
|
|
416
|
+
// `services: &: {..}` plus `services: {web:{}}` took the
|
|
417
|
+
// peer path and lost `(spread)` (use-cases/BUGS.md §55).
|
|
418
|
+
if (undefined !== peerctx.prov) {
|
|
419
|
+
markSpread(key_spread_cj)
|
|
420
|
+
}
|
|
421
|
+
|
|
313
422
|
oval = out.peg[peerkey] =
|
|
314
423
|
unite(te ? peerctx.clone({ explain: ec(te, 'PSP:' + peerkey) }) : peerctx,
|
|
315
424
|
oval, key_spread_cj, 'map-peer-spread')
|
|
316
425
|
|
|
317
426
|
if (!spread_cj.isTop && !oval.isNil) {
|
|
318
|
-
; (oval as any)._spr = (spread_cj
|
|
427
|
+
; (oval as any)._spr = spreadId(spread_cj)
|
|
319
428
|
}
|
|
320
429
|
}
|
|
321
430
|
}
|
|
@@ -325,6 +434,12 @@ class MapVal extends BagVal {
|
|
|
325
434
|
done = (done && DONE === oval.dc)
|
|
326
435
|
}
|
|
327
436
|
}
|
|
437
|
+
else if (true === (peer as any).isContainerKind) {
|
|
438
|
+
// The container KIND delegates to its own arm, exactly as a
|
|
439
|
+
// scalar delegates to a ScalarKindVal peer: the kind knows to
|
|
440
|
+
// admit this map, and this map knows nothing about kinds.
|
|
441
|
+
out = peer.unify(this, ctx) as any
|
|
442
|
+
}
|
|
328
443
|
else if (!peer.isTop) {
|
|
329
444
|
out = makeNilErr(ctx, 'map', this, peer)
|
|
330
445
|
}
|
|
@@ -382,7 +497,11 @@ class MapVal extends BagVal {
|
|
|
382
497
|
}
|
|
383
498
|
|
|
384
499
|
if (!allScalarKind) {
|
|
385
|
-
|
|
500
|
+
// A full instance (`dup`, ADR-005), paths normalised to the
|
|
501
|
+
// destination: see Val.spreadClone and repathInstance.
|
|
502
|
+
const out = this.clone(ctx, { dup: true })
|
|
503
|
+
repathInstance(out, out.path)
|
|
504
|
+
return out
|
|
386
505
|
}
|
|
387
506
|
|
|
388
507
|
let out = (super.clone(ctx) as MapVal)
|
|
@@ -399,6 +518,7 @@ class MapVal extends BagVal {
|
|
|
399
518
|
|
|
400
519
|
out.closed = this.closed
|
|
401
520
|
out.optionalKeys = [...this.optionalKeys]
|
|
521
|
+
out.aliasKeys = [...this.aliasKeys]
|
|
402
522
|
|
|
403
523
|
return out
|
|
404
524
|
}
|
|
@@ -414,16 +534,22 @@ class MapVal extends BagVal {
|
|
|
414
534
|
// (entry[1] as Val).clone(ctx, spec?.mark ? { mark: spec.mark } : {}) :
|
|
415
535
|
(entry[1] as Val).clone(ctx, {
|
|
416
536
|
mark: spec?.mark ?? {},
|
|
417
|
-
path: [...out.path, entry[0]]
|
|
537
|
+
path: [...out.path, entry[0]],
|
|
538
|
+
// The instantiation flag descends (ADR-005): a template's
|
|
539
|
+
// children are part of the instance.
|
|
540
|
+
dup: spec?.dup,
|
|
418
541
|
}) :
|
|
419
542
|
entry[1]
|
|
420
543
|
}
|
|
421
544
|
if (this.spread.cj) {
|
|
422
|
-
out.spread.cj = this.spread.cj.clone(ctx,
|
|
545
|
+
out.spread.cj = this.spread.cj.clone(ctx,
|
|
546
|
+
spec?.mark || spec?.dup ?
|
|
547
|
+
{ mark: spec?.mark, dup: spec?.dup } : {})
|
|
423
548
|
}
|
|
424
549
|
|
|
425
550
|
out.closed = this.closed
|
|
426
551
|
out.optionalKeys = [...this.optionalKeys]
|
|
552
|
+
out.aliasKeys = [...this.aliasKeys]
|
|
427
553
|
|
|
428
554
|
// out.from = this.from
|
|
429
555
|
|
|
@@ -437,7 +563,14 @@ class MapVal extends BagVal {
|
|
|
437
563
|
// independent of insertion/unification order and matches the Go
|
|
438
564
|
// port. A bare .sort() is UTF-16 code-unit order, which puts an
|
|
439
565
|
// astral key ahead of everything in U+E000-U+FFFF -- see cmpCodePoint.
|
|
440
|
-
|
|
566
|
+
// An alias declaration is not part of the document, so canon does
|
|
567
|
+
// not render it: a document with aliases and the document with
|
|
568
|
+
// every alias written out longhand must produce the same text and
|
|
569
|
+
// therefore the same `aon1-` hash. That is the sharpest statement
|
|
570
|
+
// of what an alias IS -- a name for a value, and nothing more.
|
|
571
|
+
let keys = Object.keys(this.peg)
|
|
572
|
+
.filter(k => !this.aliasKeys.includes(k))
|
|
573
|
+
.sort(cmpCodePoint)
|
|
441
574
|
return '' +
|
|
442
575
|
// this.errcanon() +
|
|
443
576
|
// (this.mark.type ? '<type>' : '') +
|
|
@@ -450,7 +583,13 @@ class MapVal extends BagVal {
|
|
|
450
583
|
JSON.stringify(k) +
|
|
451
584
|
(this.optionalKeys.includes(k) ? '?' : '') +
|
|
452
585
|
':' +
|
|
453
|
-
|
|
586
|
+
// canonRiders, not .canon: a deprecated field renders
|
|
587
|
+
// back as its `deprecate(x, m)` call, reparseably (G3). The
|
|
588
|
+
// guard is the isVal FLAG, never the canon getter: computing
|
|
589
|
+
// canon in the guard and again in the render doubles the
|
|
590
|
+
// recursion per level, which is 2^depth on a nested document.
|
|
591
|
+
(true === this.peg[k]?.isVal
|
|
592
|
+
? canonRiders(this.peg[k]) : this.peg[k])
|
|
454
593
|
])
|
|
455
594
|
.join(',') +
|
|
456
595
|
'}' // + '<' + (this.mark.hide ? 'H' : '') + '>'
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
// GENERATION: `match(v, p1, r1, p2, r2, …, d?)` (G8 phase 2,
|
|
4
|
+
// docs/capability-review/g8-generation.md). A BOUNDED conditional:
|
|
5
|
+
// alternating pattern/result arguments and an optional trailing
|
|
6
|
+
// default. The first pattern IN ARGUMENT ORDER that `v` unifies with
|
|
7
|
+
// SELECTS its result, and the result is the answer.
|
|
8
|
+
//
|
|
9
|
+
// The design said the answer was `v & p & r` -- the scrutinee narrowed
|
|
10
|
+
// by the arm rather than replaced by it. That cannot be what a match
|
|
11
|
+
// is for: it makes every arm whose result is not already a `v` a
|
|
12
|
+
// contradiction, and the design's own example
|
|
13
|
+
// (`match($.tier, small, {cpu:1}, …)`, a string scrutinee and map
|
|
14
|
+
// results) cannot be evaluated at all under it. A match MAPS a value
|
|
15
|
+
// to another value; a document that wants the scrutinee kept can say
|
|
16
|
+
// so, because the scrutinee is a value it can name.
|
|
17
|
+
//
|
|
18
|
+
// size: match($.tier, small, {cpu:1}, large, {cpu:8}, {cpu:2})
|
|
19
|
+
//
|
|
20
|
+
// WHAT KEEPS IT FROM BECOMING A CONDITIONAL LANGUAGE. The scrutinee is
|
|
21
|
+
// matched by UNIFIABILITY only: no boolean guards, no comparisons
|
|
22
|
+
// beyond what the constraint atoms already are, no fallthrough (first
|
|
23
|
+
// match wins, in a spec-pinned order), and no way to write a pattern
|
|
24
|
+
// that is not an ordinary Aontu value. The whole form is total.
|
|
25
|
+
//
|
|
26
|
+
// NO MATCH AND NO DEFAULT IS AN ERROR, not an empty answer, and the
|
|
27
|
+
// report names the patterns that were tried -- the admissible-
|
|
28
|
+
// alternatives shape (G2's error contract). A default is how a
|
|
29
|
+
// document says it meant to allow the rest.
|
|
30
|
+
//
|
|
31
|
+
// A RESULT IS NOT EVALUATED UNTIL IT IS SELECTED. Only the scrutinee
|
|
32
|
+
// and the patterns are driven; an unselected result never runs, so a
|
|
33
|
+
// broken arm nobody takes is not an error the document has to carry
|
|
34
|
+
// (which multi-error collection, G2 phase 6, would otherwise report).
|
|
35
|
+
|
|
36
|
+
import type {
|
|
37
|
+
Val,
|
|
38
|
+
ValSpec,
|
|
39
|
+
} from '../type'
|
|
40
|
+
|
|
41
|
+
import {
|
|
42
|
+
AontuContext,
|
|
43
|
+
} from '../ctx'
|
|
44
|
+
|
|
45
|
+
import { makeNilErr } from '../err'
|
|
46
|
+
import { top } from './top'
|
|
47
|
+
import { prefInnerPeg } from './PrefVal'
|
|
48
|
+
import { FuncBaseVal, trialUnify } from './FuncBaseVal'
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// THE DEFAULTED-SCRUTINEE RULE (ADR-004, use-cases/BUGS.md §5). The
|
|
52
|
+
// generation-effective view of a settled scrutinee: a preference — or
|
|
53
|
+
// a disjunction carrying one — means "this value unless something
|
|
54
|
+
// overrides it", and by resolve time the model has SETTLED (staging
|
|
55
|
+
// rule), so nothing will. The value generation is about to emit is
|
|
56
|
+
// therefore the value the patterns must be tested against. Testing
|
|
57
|
+
// against the still-open preference instead let a pattern SELECT an
|
|
58
|
+
// arm by overriding the default: `side_effect:*readonly|write|
|
|
59
|
+
// destructive` beside `match(.side_effect, destructive, true, false)`
|
|
60
|
+
// answered `true` while generating "readonly" next to it — a derived
|
|
61
|
+
// value contradicting the very value it derives from, exit 0.
|
|
62
|
+
// A pref-free scrutinee (open disjunction included) is untouched:
|
|
63
|
+
// matching by unifiability is its documented meaning.
|
|
64
|
+
// Exported for the multi-pref unit test (ADR-002, the subsumeNode
|
|
65
|
+
// precedent): rankPrefs leaves a settled disjunct at most one pref, so
|
|
66
|
+
// the min-rank scan below cannot be reached through a document.
|
|
67
|
+
export function effectiveScrutinee(v: Val): Val {
|
|
68
|
+
let out: any = v
|
|
69
|
+
if (true === out?.isDisjunct && Array.isArray(out.peg)) {
|
|
70
|
+
const prefs = out.peg.filter((m: any) => true === m?.isPref)
|
|
71
|
+
if (0 === prefs.length) {
|
|
72
|
+
return v
|
|
73
|
+
}
|
|
74
|
+
// Generation picks the LOWEST rank (effectiveDefault in
|
|
75
|
+
// subsume.ts; `a:**1|*2` generates 2). rankPrefs leaves at most
|
|
76
|
+
// one pref standing in a settled disjunct, so the scan is
|
|
77
|
+
// defensive.
|
|
78
|
+
out = prefs.reduce((a: any, b: any) => b.rank < a.rank ? b : a)
|
|
79
|
+
}
|
|
80
|
+
return prefInnerPeg(out)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class MatchFuncVal extends FuncBaseVal {
|
|
85
|
+
isMatchFunc = true
|
|
86
|
+
|
|
87
|
+
// THE STAGING RULE (G8 phase 0). A scrutinee that is still being
|
|
88
|
+
// narrowed can match an EARLIER pattern than the one it will end up
|
|
89
|
+
// matching, and the arm a match takes is not a thing to guess at.
|
|
90
|
+
staged = true
|
|
91
|
+
|
|
92
|
+
constructor(
|
|
93
|
+
spec: ValSpec,
|
|
94
|
+
ctx?: AontuContext
|
|
95
|
+
) {
|
|
96
|
+
super(spec, ctx)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
funcname() {
|
|
101
|
+
return 'match'
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
prepare(_ctx: AontuContext, _args: Val[]) {
|
|
106
|
+
return null
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
// The scrutinee is argument 0 and the patterns are the odd
|
|
111
|
+
// arguments; the results are the even ones after 0, and the last
|
|
112
|
+
// argument is a DEFAULT when the count is even. Written once, read
|
|
113
|
+
// by both the driver below and resolve.
|
|
114
|
+
hasDefault() {
|
|
115
|
+
return 0 === this.peg.length % 2
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
unify(peer: Val, ctx: AontuContext): Val {
|
|
120
|
+
// The scrutinee and the PATTERNS are driven; the results are not
|
|
121
|
+
// (see the header). driveStagedArgs takes a prefix, so the odd
|
|
122
|
+
// positions are driven one at a time.
|
|
123
|
+
let ready = this.driveStagedArgs(ctx, 1)
|
|
124
|
+
const last = this.peg.length - (this.hasDefault() ? 1 : 0)
|
|
125
|
+
for (let i = 1; i < last; i += 2) {
|
|
126
|
+
const arg: Val = this.peg[i]
|
|
127
|
+
if (!arg.done) {
|
|
128
|
+
this.peg[i] = arg.unify(top(), ctx)
|
|
129
|
+
}
|
|
130
|
+
ready = ready && true === this.peg[i].done
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!ready || !ctx.settle) {
|
|
134
|
+
return this.residuate(peer, ctx)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return super.unify(peer, ctx)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
resolve(ctx: AontuContext, args: Val[]) {
|
|
142
|
+
const scrutinee: Val = effectiveScrutinee(args[0])
|
|
143
|
+
const dflt: Val | undefined = this.hasDefault() ?
|
|
144
|
+
args[args.length - 1] : undefined
|
|
145
|
+
const last = args.length - (undefined === dflt ? 0 : 1)
|
|
146
|
+
|
|
147
|
+
const tried: string[] = []
|
|
148
|
+
|
|
149
|
+
for (let i = 1; i < last; i += 2) {
|
|
150
|
+
const pattern: Val = args[i]
|
|
151
|
+
tried.push(pattern.canon)
|
|
152
|
+
|
|
153
|
+
// The trial is against CLONES: `unite` refines a bag in place
|
|
154
|
+
// against a TOP peer, and a pattern that failed must be
|
|
155
|
+
// untouched for the next document that reads its canon.
|
|
156
|
+
if (undefined !== trialUnify(ctx, scrutinee.clone(ctx), pattern.clone(ctx))) {
|
|
157
|
+
return args[i + 1].clone(ctx)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (undefined !== dflt) {
|
|
162
|
+
return dflt.clone(ctx)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return makeNilErr(ctx, 'match_none', this, undefined, 'resolve', {
|
|
166
|
+
value: scrutinee.canon,
|
|
167
|
+
tried: tried.join(' '),
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
} /* node:coverage ignore next 5 */
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
export {
|
|
175
|
+
MatchFuncVal,
|
|
176
|
+
}
|
package/src/val/MoveFuncVal.ts
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
|
|
13
13
|
import { makeNilErr } from '../err'
|
|
14
14
|
|
|
15
|
-
import { NilVal } from '../val/NilVal'
|
|
16
15
|
|
|
17
16
|
import {
|
|
18
17
|
walk
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
import { FuncBaseVal } from './FuncBaseVal'
|
|
24
|
-
import { CopyFuncVal } from './CopyFuncVal'
|
|
25
23
|
import { PrefFuncVal } from './PrefFuncVal'
|
|
26
24
|
|
|
27
25
|
|
package/src/val/NilVal.ts
CHANGED
|
@@ -79,6 +79,31 @@ class NilVal extends Val {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// THE PATH IS WHERE THE MEET IS, NOT WHERE THE OPERAND WAS WRITTEN
|
|
83
|
+
// (use-cases/BUGS.md §41). The operand path above decides the SITE
|
|
84
|
+
// correctly and the path only by accident: a value that arrives by
|
|
85
|
+
// REFERENCE is re-pathed to the referring field, and its children
|
|
86
|
+
// are re-pathed to that same field rather than rebased under it, so
|
|
87
|
+
// every conflict inside `q: $.M` reported `$.q` — the enclosing
|
|
88
|
+
// record, not the key to edit, and the SAME path for every one of
|
|
89
|
+
// its fields. The context has descended to the child by the time
|
|
90
|
+
// the meet fails, and Go reads the path off the tree position for
|
|
91
|
+
// exactly this reason.
|
|
92
|
+
//
|
|
93
|
+
// Only EXTENDS, never redirects: the context path is taken when the
|
|
94
|
+
// operand's path is a PREFIX of it, so a nil minted away from the
|
|
95
|
+
// descent (a func resolving an argument, a generator's own probe,
|
|
96
|
+
// an anchored `--at` run whose operand is already correctly placed)
|
|
97
|
+
// keeps the path its operand carries. Taking the context path
|
|
98
|
+
// unconditionally was tried and reverted -- it moved the closed-key,
|
|
99
|
+
// spread-template and every `--at` finding to the driving location,
|
|
100
|
+
// which is not where those belong.
|
|
101
|
+
if (null != ctx?.path && null != nil.path &&
|
|
102
|
+
nil.path.length < ctx.path.length &&
|
|
103
|
+
nil.path.every((p, i) => p === ctx.path[i])) {
|
|
104
|
+
nil.path = [...ctx.path]
|
|
105
|
+
}
|
|
106
|
+
|
|
82
107
|
if (ctx) {
|
|
83
108
|
ctx.adderr(nil)
|
|
84
109
|
}
|
package/src/val/OpBaseVal.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
|
|
32
32
|
import { ConjunctVal } from './ConjunctVal'
|
|
33
33
|
import { FeatureVal } from './FeatureVal'
|
|
34
|
+
import { hasPlace, fillPlace } from './PlaceVal'
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
|
|
@@ -66,6 +67,17 @@ class OpBaseVal extends FeatureVal {
|
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
unify(peer: Val, ctx: AontuContext): Val {
|
|
70
|
+
|
|
71
|
+
// THE PLACEHOLDER (G8 phase 3, see PlaceVal), on the operator side:
|
|
72
|
+
// `x: {&: {m: _ + 2}}` meeting `1` is `3`. Same rule as
|
|
73
|
+
// FuncBaseVal's -- the peer fills the hole and the operation is
|
|
74
|
+
// what answers.
|
|
75
|
+
if (!peer.isTop && !peer.isNil && this.id !== peer.id && hasPlace(this)) {
|
|
76
|
+
if (hasPlace(peer)) {
|
|
77
|
+
return makeNilErr(ctx, 'place_pair', this, peer)
|
|
78
|
+
}
|
|
79
|
+
return fillPlace(this, peer, ctx).unify(top(), ctx)
|
|
80
|
+
}
|
|
69
81
|
const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Op:' + this.opname(), this, peer)
|
|
70
82
|
// Declared without an initial value: every arm below assigns it, and
|
|
71
83
|
// seeding it with `this` made the two arms that stand the op read as
|
|
@@ -165,10 +177,17 @@ class OpBaseVal extends FeatureVal {
|
|
|
165
177
|
}
|
|
166
178
|
|
|
167
179
|
|
|
168
|
-
clone(ctx: AontuContext,
|
|
180
|
+
clone(ctx: AontuContext, spec?: ValSpec): Val {
|
|
169
181
|
let out = (super.clone(ctx, {
|
|
170
182
|
peg: this.peg,
|
|
171
183
|
}) as OpBaseVal)
|
|
184
|
+
// THE PER-DESTINATION INSTANTIATION RULE (ADR-005): an operation
|
|
185
|
+
// inside a template clones its operands as instances — the
|
|
186
|
+
// default clone shares them (see FuncBaseVal.clone). Every
|
|
187
|
+
// operand is a Val by construction, as in the Go twin's []Val.
|
|
188
|
+
if (true === spec?.dup) {
|
|
189
|
+
out.peg = this.peg.map((a: Val) => a.clone(ctx, { dup: true }))
|
|
190
|
+
}
|
|
172
191
|
return out
|
|
173
192
|
}
|
|
174
193
|
|
package/src/val/OpenFuncVal.ts
CHANGED
|
@@ -14,7 +14,6 @@ import { makeNilErr } from '../err'
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
import { FuncBaseVal } from './FuncBaseVal'
|
|
17
|
-
import { NilVal } from '../val/NilVal'
|
|
18
17
|
import { BagVal } from '../val/BagVal'
|
|
19
18
|
|
|
20
19
|
|
|
@@ -39,13 +38,16 @@ class OpenFuncVal extends FuncBaseVal {
|
|
|
39
38
|
|
|
40
39
|
|
|
41
40
|
resolve(ctx: AontuContext | undefined, args: Val[]) {
|
|
42
|
-
|
|
41
|
+
let argval: any = args[0]
|
|
43
42
|
|
|
44
43
|
if (null == argval) {
|
|
45
44
|
return makeNilErr(ctx, 'no_first_arg', this, undefined, 'close')
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
if (argval.isMap || argval.isList) {
|
|
48
|
+
// In place, for the reason CloseFuncVal.resolve gives: the
|
|
49
|
+
// instantiation rule (ADR-005) makes the argument this call's
|
|
50
|
+
// own wherever the call is multiplied.
|
|
49
51
|
(argval as BagVal).closed = false
|
|
50
52
|
}
|
|
51
53
|
|