aontu 0.62.0 → 0.64.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.
Files changed (373) hide show
  1. package/README.md +7 -7
  2. package/dist/agentsmd.js +0 -27
  3. package/dist/agentsmd.js.map +1 -1
  4. package/dist/alias.js.map +1 -1
  5. package/dist/allow.js +0 -92
  6. package/dist/allow.js.map +1 -1
  7. package/dist/aontu.d.ts +3 -3
  8. package/dist/aontu.js +4 -84
  9. package/dist/aontu.js.map +1 -1
  10. package/dist/aontumodel.d.ts +4 -0
  11. package/dist/aontumodel.js +27 -0
  12. package/dist/aontumodel.js.map +1 -0
  13. package/dist/casing.d.ts +5 -0
  14. package/dist/casing.js +90 -0
  15. package/dist/casing.js.map +1 -0
  16. package/dist/cli.d.ts +2 -2
  17. package/dist/cli.js +228 -935
  18. package/dist/cli.js.map +1 -1
  19. package/dist/ctx.js +0 -48
  20. package/dist/ctx.js.map +1 -1
  21. package/dist/diff.js +0 -32
  22. package/dist/diff.js.map +1 -1
  23. package/dist/err.js +0 -40
  24. package/dist/err.js.map +1 -1
  25. package/dist/escape.js +0 -45
  26. package/dist/escape.js.map +1 -1
  27. package/dist/exactjson.d.ts +0 -35
  28. package/dist/exactjson.js +0 -131
  29. package/dist/exactjson.js.map +1 -1
  30. package/dist/format.js +13 -203
  31. package/dist/format.js.map +1 -1
  32. package/dist/grammar.d.ts +9 -0
  33. package/dist/grammar.js +54 -0
  34. package/dist/grammar.js.map +1 -0
  35. package/dist/graph.js +0 -26
  36. package/dist/graph.js.map +1 -1
  37. package/dist/hcanon.js +0 -82
  38. package/dist/hcanon.js.map +1 -1
  39. package/dist/helpdoc.js +2 -2
  40. package/dist/helpdoc.js.map +1 -1
  41. package/dist/hints.d.ts +0 -6
  42. package/dist/hints.js +57 -55
  43. package/dist/hints.js.map +1 -1
  44. package/dist/jsonschema.js +0 -114
  45. package/dist/jsonschema.js.map +1 -1
  46. package/dist/keyorder.d.ts +0 -7
  47. package/dist/keyorder.js +0 -41
  48. package/dist/keyorder.js.map +1 -1
  49. package/dist/lang.js +17 -915
  50. package/dist/lang.js.map +1 -1
  51. package/dist/lsp-server.js +0 -16
  52. package/dist/lsp-server.js.map +1 -1
  53. package/dist/lsp.d.ts +1 -1
  54. package/dist/lsp.js +12 -159
  55. package/dist/lsp.js.map +1 -1
  56. package/dist/mcp-server.js +0 -26
  57. package/dist/mcp-server.js.map +1 -1
  58. package/dist/mcp.js +0 -149
  59. package/dist/mcp.js.map +1 -1
  60. package/dist/mod-tool.js +16 -131
  61. package/dist/mod-tool.js.map +1 -1
  62. package/dist/mod.js +0 -162
  63. package/dist/mod.js.map +1 -1
  64. package/dist/patch.js +0 -217
  65. package/dist/patch.js.map +1 -1
  66. package/dist/profile.d.ts +9 -0
  67. package/dist/profile.js +28 -0
  68. package/dist/profile.js.map +1 -0
  69. package/dist/provenance.js +0 -140
  70. package/dist/provenance.js.map +1 -1
  71. package/dist/query.js +0 -75
  72. package/dist/query.js.map +1 -1
  73. package/dist/reach.js +0 -43
  74. package/dist/reach.js.map +1 -1
  75. package/dist/relation.js +0 -61
  76. package/dist/relation.js.map +1 -1
  77. package/dist/report-sarif.d.ts +0 -11
  78. package/dist/report-sarif.js +0 -28
  79. package/dist/report-sarif.js.map +1 -1
  80. package/dist/sig.js +0 -35
  81. package/dist/sig.js.map +1 -1
  82. package/dist/sigdecl.js +1 -1
  83. package/dist/sigdecl.js.map +1 -1
  84. package/dist/siggate.js +0 -4
  85. package/dist/siggate.js.map +1 -1
  86. package/dist/site.js +3 -29
  87. package/dist/site.js.map +1 -1
  88. package/dist/subsume.d.ts +0 -10
  89. package/dist/subsume.js +0 -137
  90. package/dist/subsume.js.map +1 -1
  91. package/dist/template.d.ts +2 -1
  92. package/dist/template.js +58 -138
  93. package/dist/template.js.map +1 -1
  94. package/dist/trace.d.ts +21 -0
  95. package/dist/trace.js +107 -0
  96. package/dist/trace.js.map +1 -0
  97. package/dist/trim.js +0 -41
  98. package/dist/trim.js.map +1 -1
  99. package/dist/tsconfig.tsbuildinfo +1 -1
  100. package/dist/type.js.map +1 -1
  101. package/dist/unify.js +13 -248
  102. package/dist/unify.js.map +1 -1
  103. package/dist/utility.js +0 -22
  104. package/dist/utility.js.map +1 -1
  105. package/dist/val/AbnfFuncVal.d.ts +18 -0
  106. package/dist/val/AbnfFuncVal.js +132 -0
  107. package/dist/val/AbnfFuncVal.js.map +1 -0
  108. package/dist/val/AbsentVal.d.ts +11 -0
  109. package/dist/val/AbsentVal.js +30 -0
  110. package/dist/val/AbsentVal.js.map +1 -0
  111. package/dist/val/AggFuncVal.d.ts +10 -1
  112. package/dist/val/AggFuncVal.js +104 -116
  113. package/dist/val/AggFuncVal.js.map +1 -1
  114. package/dist/val/ArithFuncVal.js +0 -12
  115. package/dist/val/ArithFuncVal.js.map +1 -1
  116. package/dist/val/BagVal.js +1 -78
  117. package/dist/val/BagVal.js.map +1 -1
  118. package/dist/val/BigDecimalVal.js +0 -16
  119. package/dist/val/BigDecimalVal.js.map +1 -1
  120. package/dist/val/BigIntegerVal.js +0 -16
  121. package/dist/val/BigIntegerVal.js.map +1 -1
  122. package/dist/val/CloseFuncVal.js +0 -9
  123. package/dist/val/CloseFuncVal.js.map +1 -1
  124. package/dist/val/CmpFuncVal.d.ts +2 -0
  125. package/dist/val/CmpFuncVal.js +49 -72
  126. package/dist/val/CmpFuncVal.js.map +1 -1
  127. package/dist/val/ConjunctVal.js +0 -29
  128. package/dist/val/ConjunctVal.js.map +1 -1
  129. package/dist/val/ConstraintVal.js +0 -500
  130. package/dist/val/ConstraintVal.js.map +1 -1
  131. package/dist/val/ContainerKindVal.js +0 -2
  132. package/dist/val/ContainerKindVal.js.map +1 -1
  133. package/dist/val/CopyFuncVal.js +0 -3
  134. package/dist/val/CopyFuncVal.js.map +1 -1
  135. package/dist/val/Decimal.js +0 -179
  136. package/dist/val/Decimal.js.map +1 -1
  137. package/dist/val/DeprecateFuncVal.js.map +1 -1
  138. package/dist/val/DisjunctVal.js +0 -152
  139. package/dist/val/DisjunctVal.js.map +1 -1
  140. package/dist/val/EachFuncVal.js +0 -3
  141. package/dist/val/EachFuncVal.js.map +1 -1
  142. package/dist/val/EmitFuncVal.d.ts +1 -1
  143. package/dist/val/EmitFuncVal.js +6 -119
  144. package/dist/val/EmitFuncVal.js.map +1 -1
  145. package/dist/val/ExpectVal.js +0 -62
  146. package/dist/val/ExpectVal.js.map +1 -1
  147. package/dist/val/FilterFuncVal.js +0 -25
  148. package/dist/val/FilterFuncVal.js.map +1 -1
  149. package/dist/val/FuncBaseVal.d.ts +1 -0
  150. package/dist/val/FuncBaseVal.js +7 -127
  151. package/dist/val/FuncBaseVal.js.map +1 -1
  152. package/dist/val/GraphAtomVal.js +0 -15
  153. package/dist/val/GraphAtomVal.js.map +1 -1
  154. package/dist/val/HideFuncVal.js +0 -13
  155. package/dist/val/HideFuncVal.js.map +1 -1
  156. package/dist/val/IntegerVal.js +0 -61
  157. package/dist/val/IntegerVal.js.map +1 -1
  158. package/dist/val/JunctionVal.js +0 -20
  159. package/dist/val/JunctionVal.js.map +1 -1
  160. package/dist/val/KeyFuncVal.js +0 -46
  161. package/dist/val/KeyFuncVal.js.map +1 -1
  162. package/dist/val/ListVal.js +0 -57
  163. package/dist/val/ListVal.js.map +1 -1
  164. package/dist/val/LowerFuncVal.js +0 -11
  165. package/dist/val/LowerFuncVal.js.map +1 -1
  166. package/dist/val/MapVal.js +0 -151
  167. package/dist/val/MapVal.js.map +1 -1
  168. package/dist/val/MatchFuncVal.js +0 -27
  169. package/dist/val/MatchFuncVal.js.map +1 -1
  170. package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
  171. package/dist/val/MaybeFuncVal.js +50 -0
  172. package/dist/val/MaybeFuncVal.js.map +1 -0
  173. package/dist/val/MoveFuncVal.js +0 -18
  174. package/dist/val/MoveFuncVal.js.map +1 -1
  175. package/dist/val/NilVal.js +0 -60
  176. package/dist/val/NilVal.js.map +1 -1
  177. package/dist/val/NomFuncVal.js +18 -54
  178. package/dist/val/NomFuncVal.js.map +1 -1
  179. package/dist/val/NumberVal.js +0 -15
  180. package/dist/val/NumberVal.js.map +1 -1
  181. package/dist/val/OpBaseVal.d.ts +1 -0
  182. package/dist/val/OpBaseVal.js +3 -15
  183. package/dist/val/OpBaseVal.js.map +1 -1
  184. package/dist/val/PackFuncVal.js +0 -34
  185. package/dist/val/PackFuncVal.js.map +1 -1
  186. package/dist/val/PathFuncVal.js +0 -6
  187. package/dist/val/PathFuncVal.js.map +1 -1
  188. package/dist/val/PathVal.js +0 -41
  189. package/dist/val/PathVal.js.map +1 -1
  190. package/dist/val/PlaceVal.js +0 -25
  191. package/dist/val/PlaceVal.js.map +1 -1
  192. package/dist/val/PlusOpVal.d.ts +1 -7
  193. package/dist/val/PlusOpVal.js +13 -74
  194. package/dist/val/PlusOpVal.js.map +1 -1
  195. package/dist/val/PrefFuncVal.js +0 -1
  196. package/dist/val/PrefFuncVal.js.map +1 -1
  197. package/dist/val/PrefVal.js +0 -167
  198. package/dist/val/PrefVal.js.map +1 -1
  199. package/dist/val/RecurseVal.js +0 -55
  200. package/dist/val/RecurseVal.js.map +1 -1
  201. package/dist/val/RefVal.js +0 -282
  202. package/dist/val/RefVal.js.map +1 -1
  203. package/dist/val/ReferFuncVal.js +3 -232
  204. package/dist/val/ReferFuncVal.js.map +1 -1
  205. package/dist/val/ScalarKindVal.js +0 -49
  206. package/dist/val/ScalarKindVal.js.map +1 -1
  207. package/dist/val/ScalarVal.js +0 -11
  208. package/dist/val/ScalarVal.js.map +1 -1
  209. package/dist/val/StrFuncVal.js +0 -18
  210. package/dist/val/StrFuncVal.js.map +1 -1
  211. package/dist/val/SuperFuncVal.js +0 -32
  212. package/dist/val/SuperFuncVal.js.map +1 -1
  213. package/dist/val/TopVal.js +0 -1
  214. package/dist/val/TopVal.js.map +1 -1
  215. package/dist/val/TranslateFuncVal.js +1 -3
  216. package/dist/val/TranslateFuncVal.js.map +1 -1
  217. package/dist/val/UpperFuncVal.js +0 -11
  218. package/dist/val/UpperFuncVal.js.map +1 -1
  219. package/dist/val/Val.d.ts +1 -0
  220. package/dist/val/Val.js +2 -133
  221. package/dist/val/Val.js.map +1 -1
  222. package/dist/val/VarVal.js +0 -12
  223. package/dist/val/VarVal.js.map +1 -1
  224. package/dist/val/arith.js +0 -37
  225. package/dist/val/arith.js.map +1 -1
  226. package/dist/val/caserange.js +0 -61
  227. package/dist/val/caserange.js.map +1 -1
  228. package/dist/val/members.js +0 -6
  229. package/dist/val/members.js.map +1 -1
  230. package/dist/val/numcmp.js +0 -11
  231. package/dist/val/numcmp.js.map +1 -1
  232. package/dist/val/numkind.js +0 -145
  233. package/dist/val/numkind.js.map +1 -1
  234. package/dist/val/valutil.js +0 -16
  235. package/dist/val/valutil.js.map +1 -1
  236. package/dist/vet.js +0 -461
  237. package/dist/vet.js.map +1 -1
  238. package/dist/view.js +0 -414
  239. package/dist/view.js.map +1 -1
  240. package/dist/walk.js +0 -41
  241. package/dist/walk.js.map +1 -1
  242. package/grammar/aontu.abnf +8 -6
  243. package/grammar/aontu.gbnf +4 -4
  244. package/grammar/aontu.lark +4 -4
  245. package/grammar/aontu.tmLanguage.json +1 -1
  246. package/package.json +4 -2
  247. package/skill/tasks.md +9 -7
  248. package/src/agentsmd.ts +0 -35
  249. package/src/alias.ts +0 -39
  250. package/src/allow.ts +1 -96
  251. package/src/aontu.ts +4 -116
  252. package/src/aontumodel.ts +26 -0
  253. package/src/casing.ts +95 -0
  254. package/src/cli.ts +258 -1024
  255. package/src/ctx.ts +0 -103
  256. package/src/diff.ts +0 -40
  257. package/src/err.ts +0 -40
  258. package/src/escape.ts +0 -46
  259. package/src/exactjson.ts +0 -131
  260. package/src/format.ts +14 -257
  261. package/src/grammar.ts +72 -0
  262. package/src/graph.ts +0 -61
  263. package/src/hcanon.ts +0 -82
  264. package/src/helpdoc.ts +2 -2
  265. package/src/hints.ts +69 -57
  266. package/src/jsonschema.ts +0 -123
  267. package/src/keyorder.ts +0 -42
  268. package/src/lang.ts +19 -931
  269. package/src/lsp-server.ts +0 -16
  270. package/src/lsp.ts +12 -180
  271. package/src/mcp-server.ts +0 -31
  272. package/src/mcp.ts +0 -169
  273. package/src/mod-tool.ts +18 -159
  274. package/src/mod.ts +0 -178
  275. package/src/patch.ts +0 -232
  276. package/src/profile.ts +42 -0
  277. package/src/provenance.ts +0 -183
  278. package/src/query.ts +0 -84
  279. package/src/reach.ts +0 -53
  280. package/src/relation.ts +0 -84
  281. package/src/report-sarif.ts +0 -48
  282. package/src/sig.ts +0 -35
  283. package/src/sigdecl.ts +1 -1
  284. package/src/siggate.ts +0 -30
  285. package/src/site.ts +3 -29
  286. package/src/subsume.ts +1 -161
  287. package/src/template.ts +69 -140
  288. package/src/trace.ts +157 -0
  289. package/src/trim.ts +0 -53
  290. package/src/type.ts +2 -45
  291. package/src/unify.ts +14 -257
  292. package/src/utility.ts +0 -31
  293. package/src/val/AbnfFuncVal.ts +181 -0
  294. package/src/val/AbsentVal.ts +54 -0
  295. package/src/val/AggFuncVal.ts +152 -188
  296. package/src/val/ArithFuncVal.ts +0 -20
  297. package/src/val/BagVal.ts +1 -78
  298. package/src/val/BigDecimalVal.ts +0 -16
  299. package/src/val/BigIntegerVal.ts +0 -16
  300. package/src/val/CloseFuncVal.ts +0 -9
  301. package/src/val/CmpFuncVal.ts +68 -184
  302. package/src/val/ConjunctVal.ts +0 -33
  303. package/src/val/ConstraintVal.ts +2 -537
  304. package/src/val/ContainerKindVal.ts +0 -18
  305. package/src/val/CopyFuncVal.ts +0 -5
  306. package/src/val/Decimal.ts +1 -185
  307. package/src/val/DeprecateFuncVal.ts +0 -10
  308. package/src/val/DisjunctVal.ts +0 -157
  309. package/src/val/EachFuncVal.ts +0 -40
  310. package/src/val/EmitFuncVal.ts +8 -208
  311. package/src/val/ExpectVal.ts +0 -62
  312. package/src/val/FilterFuncVal.ts +0 -55
  313. package/src/val/FuncBaseVal.ts +9 -130
  314. package/src/val/GraphAtomVal.ts +0 -42
  315. package/src/val/HideFuncVal.ts +0 -15
  316. package/src/val/IntegerVal.ts +0 -61
  317. package/src/val/JunctionVal.ts +0 -20
  318. package/src/val/KeyFuncVal.ts +0 -48
  319. package/src/val/ListVal.ts +0 -59
  320. package/src/val/LowerFuncVal.ts +0 -12
  321. package/src/val/MapVal.ts +0 -151
  322. package/src/val/MatchFuncVal.ts +0 -59
  323. package/src/val/MaybeFuncVal.ts +86 -0
  324. package/src/val/MoveFuncVal.ts +0 -20
  325. package/src/val/NilVal.ts +0 -60
  326. package/src/val/NomFuncVal.ts +10 -99
  327. package/src/val/NumberVal.ts +0 -16
  328. package/src/val/OpBaseVal.ts +4 -17
  329. package/src/val/PackFuncVal.ts +0 -63
  330. package/src/val/PathFuncVal.ts +0 -32
  331. package/src/val/PathVal.ts +0 -66
  332. package/src/val/PlaceVal.ts +0 -45
  333. package/src/val/PlusOpVal.ts +18 -75
  334. package/src/val/PrefFuncVal.ts +0 -1
  335. package/src/val/PrefVal.ts +0 -179
  336. package/src/val/RecurseVal.ts +0 -81
  337. package/src/val/RefVal.ts +1 -285
  338. package/src/val/ReferFuncVal.ts +4 -255
  339. package/src/val/ScalarKindVal.ts +0 -50
  340. package/src/val/ScalarVal.ts +0 -12
  341. package/src/val/StrFuncVal.ts +0 -44
  342. package/src/val/SuperFuncVal.ts +0 -42
  343. package/src/val/TopVal.ts +0 -1
  344. package/src/val/TranslateFuncVal.ts +1 -51
  345. package/src/val/UpperFuncVal.ts +0 -12
  346. package/src/val/Val.ts +3 -192
  347. package/src/val/VarVal.ts +0 -15
  348. package/src/val/arith.ts +0 -92
  349. package/src/val/caserange.ts +0 -62
  350. package/src/val/members.ts +0 -23
  351. package/src/val/numcmp.ts +1 -27
  352. package/src/val/numkind.ts +0 -149
  353. package/src/val/valutil.ts +0 -16
  354. package/src/vet.ts +1 -582
  355. package/src/view.ts +0 -507
  356. package/src/walk.ts +0 -41
  357. package/dist/lower.d.ts +0 -23
  358. package/dist/lower.js +0 -578
  359. package/dist/lower.js.map +0 -1
  360. package/dist/render.d.ts +0 -53
  361. package/dist/render.js +0 -547
  362. package/dist/render.js.map +0 -1
  363. package/dist/std.d.ts +0 -3
  364. package/dist/std.js +0 -672
  365. package/dist/std.js.map +0 -1
  366. package/dist/val/FormFuncVal.js +0 -55
  367. package/dist/val/FormFuncVal.js.map +0 -1
  368. package/dist/val/NamerFuncVal.d.ts +0 -12
  369. package/dist/val/NamerFuncVal.js +0 -176
  370. package/dist/val/NamerFuncVal.js.map +0 -1
  371. package/src/lower.ts +0 -636
  372. package/src/render.ts +0 -732
  373. package/src/std.ts +0 -683
@@ -69,8 +69,6 @@ class ListVal extends BagVal {
69
69
  spread.v[0] :
70
70
  spread.v
71
71
 
72
- // let tmv = Array.isArray(spread.v) ? spread.v : [spread.v]
73
- // this.spread.cj = new ConjunctVal({ peg: tmv }, ctx)
74
72
  }
75
73
  }
76
74
  }
@@ -88,23 +86,10 @@ class ListVal extends BagVal {
88
86
  const TOP = top()
89
87
  peer = peer ?? TOP
90
88
 
91
- // A sizing residual (`length`, `unique`) sorts AFTER containers in a
92
- // conjunct so that it counts the MERGED list rather than the first
93
- // fragment (SIZING_CJO in ConstraintVal.ts). That makes the list the
94
- // accumulator and the constraint its peer, the reverse of the usual
95
- // order — and the reading belongs to the constraint either way, so
96
- // hand it straight back.
97
89
  if (true === (peer as any).isConstraint) {
98
90
  return peer.unify(this, ctx)
99
91
  }
100
92
 
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
93
  if (true === ctx._trialMode && true === (peer as any).isList
109
94
  && null == this.spread.cj && null == (peer as any).spread.cj
110
95
  && this.peg.length !== (peer as any).peg.length) {
@@ -153,19 +138,6 @@ class ListVal extends BagVal {
153
138
 
154
139
  propagateMarks(this, child)
155
140
 
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
141
  let oval: Val
170
142
  if (!spread_cj.isTop
171
143
  && (child as any)._spr === spreadId(spread_cj)) {
@@ -187,11 +159,6 @@ class ListVal extends BagVal {
187
159
  oval =
188
160
  child.isNil ? child :
189
161
  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
162
  key_spread_cj.isTop && child.done && undefined === keyctx.prov
196
163
  ? child :
197
164
  child.isTop && key_spread_cj.done ? key_spread_cj :
@@ -281,13 +248,6 @@ class ListVal extends BagVal {
281
248
  }
282
249
 
283
250
 
284
- // Spread clone: only deep-clone children that are path-dependent
285
- // (isFunc, isRef). Share all other children directly.
286
- // Spread clone: when all children are ScalarKindVal (simple type
287
- // constraints like `string`, `number`), share them directly to avoid
288
- // N x M allocations. ScalarKindVal is safe to share: it is immutable,
289
- // always done, never path-dependent, and never has marks mutated.
290
- // For anything more complex, fall back to full deep clone.
291
251
  spreadClone(ctx: AontuContext): Val {
292
252
  // B1: share directly when the spread tree has no path-dependent
293
253
  // leaves. See MapVal.spreadClone for rationale.
@@ -337,11 +297,6 @@ class ListVal extends BagVal {
337
297
  out.peg[entry[0]] =
338
298
  (entry[1] as any)?.isVal ? (entry[1] as Val).clone(ctx, {
339
299
  ...childspec,
340
- // AN ELEMENT IS A POSITION, exactly as a map's child is
341
- // (MapVal.clone). Without this an explicitly pathed clone
342
- // rebased the list and left every element at its source
343
- // path -- the Go twin descends by index (go/clone.go, the
344
- // *ListVal arm of clonePathKind).
345
300
  path: [...out.path, entry[0]],
346
301
  }) : entry[1]
347
302
  }
@@ -352,36 +307,22 @@ class ListVal extends BagVal {
352
307
  out.closed = this.closed
353
308
  out.optionalKeys = [...this.optionalKeys]
354
309
 
355
- // console.log('LISTVAL-CLONE', this.canon, '->', out.canon)
356
310
  return out
357
311
  }
358
312
 
359
313
 
360
314
  get canon() {
361
- // console.log('LISTVAL-CANON', this.optionalKeys)
362
315
  let keys = Object.keys(this.peg)
363
316
  return '' +
364
- // this.errcanon() +
365
317
  '[' +
366
318
  (this.spread.cj ? '&:' + this.spread.cj.canon +
367
319
  (0 < keys.length ? ',' : '') : '') +
368
- // No optional-element rendering. A list HAS no optional elements to
369
- // render: a key:value pair in list position contributes no element
370
- // at all, in either spelling and whatever its key (issue #40), so
371
- // nothing a source can write reaches this method with an optional
372
- // key. The Go port's ListVal.Canon has no such arm either, and the
373
- // two canons must agree -- a canon is round-trippable, and a marker
374
- // on an element the grammar cannot produce would not reparse.
375
- // canonRiders, not .canon: a deprecated element renders
376
- // back as its `deprecate(x, m)` call, reparseably (G3).
377
320
  keys.map(k => canonRiders(this.peg[k])).join(',') +
378
321
  ']'
379
322
  }
380
323
  } /* node:coverage ignore next 8 */
381
324
 
382
325
 
383
-
384
-
385
326
  export {
386
327
  ListVal,
387
328
  }
@@ -19,7 +19,6 @@ import { Decimal } from '../val/Decimal'
19
19
  import { caseRange, rangeArg } from './caserange'
20
20
 
21
21
 
22
-
23
22
  import { FuncBaseVal } from './FuncBaseVal'
24
23
 
25
24
 
@@ -51,12 +50,6 @@ class LowerFuncVal extends FuncBaseVal {
51
50
  const arg = args?.[0]
52
51
  const oldpeg = arg?.peg
53
52
 
54
- // THE RANGE (ts/src/val/caserange.ts): `start` names the first
55
- // character of the run when it is zero or positive and the last
56
- // when it is negative; `len` of -1, and the absent argument, are
57
- // the source's length. Refused on a NUMBER, where a run of
58
- // characters means nothing -- the numeric arm below is a ceiling,
59
- // not a case mapping.
60
53
  const start = rangeArg(args?.[1])
61
54
  const len = rangeArg(args?.[2])
62
55
  const ranged = undefined !== start || undefined !== len
@@ -68,11 +61,6 @@ class LowerFuncVal extends FuncBaseVal {
68
61
  const peg = 'string' === typeof oldpeg ?
69
62
  caseRange(oldpeg, start ?? 0, len ?? -1, false) :
70
63
  'number' === typeof oldpeg ? Math.floor(oldpeg) :
71
- // The exact leaves take an EXACT floor and keep their kind: a
72
- // biginteger is already integral so it is its own floor, and a
73
- // bigdecimal floors by coefficient arithmetic. Math.floor is not
74
- // an option for either — it would round the value into binary64
75
- // first, which is the loss the `0d` leaves exist to refuse.
76
64
  'bigint' === typeof oldpeg ? oldpeg :
77
65
  oldpeg instanceof Decimal ? oldpeg.floor() :
78
66
  undefined
package/src/val/MapVal.ts CHANGED
@@ -39,20 +39,10 @@ import { cmpCodePoint } from '../keyorder'
39
39
  import { markSpread } from '../provenance'
40
40
 
41
41
 
42
- // Structural snapshots of ref spreads (see MapVal.unify), keyed by the
43
- // ref's canon + source site rather than object identity: spread
44
- // application clones templates (and the refs inside them) freely, and a
45
- // clone must find the snapshot its parse-origin ref captured on an early
46
- // pass. The map lives on the unify root ctx (see Unify), so it persists
47
- // across fixpoint passes and is GC'd with the run.
48
42
  function spreadSnapKey(cj: any): string {
49
43
  return cj.spelling + '~' + cj.site.row + ':' + cj.site.col
50
44
  }
51
45
 
52
- // Snapshot a path-dependent ref spread to its structural target once,
53
- // while inner key()/path() funcs in the target are still unresolved (see
54
- // the call site comments in MapVal.unify). Shared by the direct
55
- // application path and the deferred-spread early-snapshot walk.
56
46
  function snapshotRefSpread(cj: any, ctx: AontuContext): Val | undefined {
57
47
  let snapmap: Map<string, Val> | undefined = (ctx as any).snapmap
58
48
  if (undefined === snapmap) {
@@ -70,12 +60,6 @@ function snapshotRefSpread(cj: any, ctx: AontuContext): Val | undefined {
70
60
  // A ref to a type() resolves to its inner template — snapshot that,
71
61
  // so a type-wrapped ref behaves like a plain-map ref spread.
72
62
  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
63
  if (tgt && pendingMarkWrapper(tgt)) {
80
64
  return undefined
81
65
  }
@@ -119,12 +103,6 @@ class MapVal extends BagVal {
119
103
 
120
104
  if (spread) {
121
105
  if ('&' === spread.o) {
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.
128
106
  this.spread.cj =
129
107
  Array.isArray(spread.v) ?
130
108
  1 < spread.v.length ?
@@ -134,25 +112,9 @@ class MapVal extends BagVal {
134
112
  }
135
113
  }
136
114
 
137
- // console.log('MAPVAL-ctor', this.type, spec)
138
115
  }
139
116
 
140
117
 
141
- // NOTE: order of keys is not preserved!
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
118
  aliasDeclarationsAreRooted(ctx: AontuContext): Val | undefined {
157
119
  if (0 === this.aliasKeys.length || 0 === this.path.length) {
158
120
  return undefined
@@ -168,17 +130,10 @@ class MapVal extends BagVal {
168
130
  if (undefined !== arooted) {
169
131
  return arooted
170
132
  }
171
- // console.log('MAPVAL-UNIFY', this.id, this.canon, peer.id, peer.canon)
172
133
 
173
134
  const TOP = top()
174
135
  peer = peer ?? TOP
175
136
 
176
- // A sizing residual (`length`, `unique`) sorts AFTER containers in a
177
- // conjunct so that it counts the MERGED map rather than the first
178
- // fragment (SIZING_CJO in ConstraintVal.ts). That makes the map the
179
- // accumulator and the constraint its peer, the reverse of the usual
180
- // order — and the reading belongs to the constraint either way, so
181
- // hand it straight back.
182
137
  if (true === (peer as any).isConstraint) {
183
138
  return peer.unify(this, ctx)
184
139
  }
@@ -197,10 +152,6 @@ class MapVal extends BagVal {
197
152
  out.spread.cj = this.spread.cj
198
153
  out.site = this.site
199
154
 
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
155
  if (true === (peer as any)?.isRel) {
205
156
  return peer.unify(this, te ? ctx.clone({ explain: ec(te, 'REL') }) : ctx)
206
157
  }
@@ -229,24 +180,6 @@ class MapVal extends BagVal {
229
180
  }
230
181
 
231
182
  if (!exit) {
232
- // Combine two spread constraints. Identical templates (same canon)
233
- // collapse to one: re-unifying them resolves key()/path() at the
234
- // shared intermediate path, producing spurious values (f1bb1063).
235
- // Distinct templates are unified in place — unite is idempotent,
236
- // whereas deferring the distinct case into a fresh ConjunctVal (as
237
- // f1bb1063 did) re-wraps every fixpoint pass, growing the conjunct
238
- // without bound and non-terminating on real models (the apidef +
239
- // sdkgen entity schemas each contribute a `&:` spread with name:key(),
240
- // combined here). unite resolves key()/path() at each destination via
241
- // spreadClone below, so nested + sibling key() cases stay correct
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.
250
183
  out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
251
184
  null == peer.spread.cj ? out.spread.cj :
252
185
  out.spread.cj.canon === peer.spread.cj.canon ? out.spread.cj :
@@ -256,32 +189,20 @@ class MapVal extends BagVal {
256
189
  }
257
190
  }
258
191
  else {
259
- // console.log('MAPVAL-PEER-OTHER', this.id, this.canon, this.done, peer.id, peer.canon, peer.done)
260
192
  }
261
193
 
262
194
 
263
195
  if (!exit) {
264
196
  out.dc = this.dc + 1
265
197
 
266
- // let newtype = this.type || peer.type
267
198
 
268
199
  let spread_cj = out.spread.cj ?? TOP
269
200
 
270
- // Snapshot a path-dependent *ref* spread to its structural target
271
- // once (while inner key()/path() funcs are still unresolved), so
272
- // later fixpoint passes don't re-resolve the ref against the mutated
273
- // tree and capture the target's own resolved key()/path() literals,
274
- // which would leak the source key into the spread destination.
275
201
  if (spread_cj.isRef && (spread_cj as any).find) {
276
202
  const snap = snapshotRefSpread(spread_cj, ctx)
277
203
  if (snap) spread_cj = snap
278
204
  }
279
205
 
280
- // A type() used as a spread applies as its inner template: emit the
281
- // (constrained) values at each destination rather than marking the
282
- // destination as a type. I.e. `&:type({k:key(),x:number})` behaves
283
- // like the non-type spread `&:{k:key(),x:number}` — key() resolves
284
- // to the destination key, kinds constrain, fields are emitted.
285
206
  if ((spread_cj as any).isTypeFunc) {
286
207
  spread_cj = (spread_cj as any).peg?.[0] ?? TOP
287
208
  }
@@ -293,15 +214,6 @@ class MapVal extends BagVal {
293
214
 
294
215
  propagateMarks(this, child)
295
216
 
296
- // Apply the spread constraint ONCE per child (marked with the
297
- // constraint's id below): the first application merges the
298
- // template into the child (with key()/path() placeholders that
299
- // resolve in place on later passes), so the constraint content
300
- // is inside the child from then on and only self-unification is
301
- // needed to progress it. Re-applying on every fixpoint pass and
302
- // every conjunct-fold step is the identity (unite is idempotent)
303
- // but costs O(keys) deep template clones per pass on large
304
- // models — the dominant cost on generated-SDK model trees.
305
217
  let oval: Val
306
218
  // No `undefined !== child` here: propagateMarks above already
307
219
  // dereferenced it, so a missing child would have thrown there.
@@ -327,11 +239,6 @@ class MapVal extends BagVal {
327
239
  oval =
328
240
  child.isNil ? child :
329
241
  key_spread_cj.isNil ? key_spread_cj :
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
242
  key_spread_cj.isTop && child.done && undefined === keyctx.prov
336
243
  ? child :
337
244
  child.isTop && key_spread_cj.done ? key_spread_cj :
@@ -369,9 +276,6 @@ class MapVal extends BagVal {
369
276
  out.optionalKeys.push(peerkey)
370
277
  }
371
278
 
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
279
  if (upeer.aliasKeys.includes(peerkey) && !out.aliasKeys.includes(peerkey)) {
376
280
  out.aliasKeys.push(peerkey)
377
281
  }
@@ -381,15 +285,6 @@ class MapVal extends BagVal {
381
285
  const peerctx = ctx.descend(peerkey)
382
286
 
383
287
  let oval = out.peg[peerkey] =
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
288
  undefined === child
394
289
  ? (undefined !== peerctx.prov && peerchild.isGenable
395
290
  ? unite(peerctx, peerchild, TOP, 'map-peer-only')
@@ -407,14 +302,6 @@ class MapVal extends BagVal {
407
302
  if ((oval as any)._spr !== spreadId(spread_cj)) {
408
303
  let key_spread_cj = spread_cj.spreadClone(peerctx)
409
304
 
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
305
  if (undefined !== peerctx.prov) {
419
306
  markSpread(key_spread_cj)
420
307
  }
@@ -457,13 +344,6 @@ class MapVal extends BagVal {
457
344
  }
458
345
  }
459
346
 
460
- // console.log(
461
- // 'MAPVAL-OUT', out.canon,
462
- // '\n SELF', this,
463
- // '\n PEER', peer,
464
- // '\n OUT', out,
465
- // '\n FROM', (out as any).spread.cj
466
- // )
467
347
 
468
348
  ctx.explain && explainClose(te, out)
469
349
 
@@ -471,20 +351,6 @@ class MapVal extends BagVal {
471
351
  }
472
352
 
473
353
 
474
- // Spread clone: return a Val usable as the per-key spread constraint.
475
- //
476
- // Three tiers:
477
- // 1. tree is path-independent (no RefVal/KeyFuncVal/PathFuncVal/
478
- // MoveFuncVal/SuperFuncVal anywhere below): return `this` directly.
479
- // Nothing in the unify path mutates the spread root, and no
480
- // child depends on its own stored .path, so sharing is safe.
481
- // 2. top-level children are all ScalarKindVal: shallow clone
482
- // (share children, fresh MapVal wrapper).
483
- // 3. otherwise: full deep clone via `this.clone(ctx)`.
484
- //
485
- // Tier 1 handles the foo-sdk common case of simple type-constraint
486
- // spreads like `&:{active: *true | boolean, version: *'0.0.1' | string}`,
487
- // which are cloned thousands of times per run.
488
354
  spreadClone(ctx: AontuContext): Val {
489
355
  if (!this.isPathDependent) return this
490
356
 
@@ -531,7 +397,6 @@ class MapVal extends BagVal {
531
397
  for (let entry of Object.entries(this.peg)) {
532
398
  out.peg[entry[0]] =
533
399
  (entry[1] as any)?.isVal ?
534
- // (entry[1] as Val).clone(ctx, spec?.mark ? { mark: spec.mark } : {}) :
535
400
  (entry[1] as Val).clone(ctx, {
536
401
  mark: spec?.mark ?? {},
537
402
  path: [...out.path, entry[0]],
@@ -551,23 +416,12 @@ class MapVal extends BagVal {
551
416
  out.optionalKeys = [...this.optionalKeys]
552
417
  out.aliasKeys = [...this.aliasKeys]
553
418
 
554
- // out.from = this.from
555
419
 
556
- // console.log('MAPVAL-CLONE', this.canon, '->', out.canon)
557
420
  return out
558
421
  }
559
422
 
560
423
 
561
424
  get canon() {
562
- // Keys are emitted in CODE POINT order so the canonical form is
563
- // independent of insertion/unification order and matches the Go
564
- // port. A bare .sort() is UTF-16 code-unit order, which puts an
565
- // astral key ahead of everything in U+E000-U+FFFF -- see cmpCodePoint.
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
425
  let keys = Object.keys(this.peg)
572
426
  .filter(k => !this.aliasKeys.includes(k))
573
427
  .sort(cmpCodePoint)
@@ -583,11 +437,6 @@ class MapVal extends BagVal {
583
437
  JSON.stringify(k) +
584
438
  (this.optionalKeys.includes(k) ? '?' : '') +
585
439
  ':' +
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
440
  (true === this.peg[k]?.isVal
592
441
  ? canonRiders(this.peg[k]) : this.peg[k])
593
442
  ])
@@ -1,37 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
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
3
 
36
4
  import type {
37
5
  Val,
@@ -48,22 +16,6 @@ import { prefInnerPeg } from './PrefVal'
48
16
  import { FuncBaseVal, trialUnify } from './FuncBaseVal'
49
17
 
50
18
 
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
19
  export function effectiveScrutinee(v: Val): Val {
68
20
  let out: any = v
69
21
  if (true === out?.isDisjunct && Array.isArray(out.peg)) {
@@ -71,10 +23,6 @@ export function effectiveScrutinee(v: Val): Val {
71
23
  if (0 === prefs.length) {
72
24
  return v
73
25
  }
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
26
  out = prefs.reduce((a: any, b: any) => b.rank < a.rank ? b : a)
79
27
  }
80
28
  return prefInnerPeg(out)
@@ -84,9 +32,6 @@ export function effectiveScrutinee(v: Val): Val {
84
32
  class MatchFuncVal extends FuncBaseVal {
85
33
  isMatchFunc = true
86
34
 
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
35
  staged = true
91
36
 
92
37
  constructor(
@@ -107,10 +52,6 @@ class MatchFuncVal extends FuncBaseVal {
107
52
  }
108
53
 
109
54
 
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
55
  hasDefault() {
115
56
  return 0 === this.peg.length % 2
116
57
  }
@@ -0,0 +1,86 @@
1
+ /* Copyright (c) 2026 Richard Rodger, MIT License */
2
+
3
+
4
+ import type {
5
+ Val,
6
+ ValSpec,
7
+ } from '../type'
8
+
9
+ import {
10
+ AontuContext,
11
+ } from '../ctx'
12
+
13
+ import { unite } from '../unify'
14
+ import { AbsentVal } from './AbsentVal'
15
+ import { FuncBaseVal } from './FuncBaseVal'
16
+
17
+
18
+ import {
19
+ top
20
+ } from './top'
21
+
22
+
23
+ class MaybeFuncVal extends FuncBaseVal {
24
+ isMaybeFunc = true
25
+
26
+ forgives = true
27
+
28
+ // A reference that has not resolved YET is not a reference to
29
+ // nothing (ADR-034).
30
+ staged = true
31
+
32
+ constructor(
33
+ spec: ValSpec,
34
+ ctx?: AontuContext
35
+ ) {
36
+ super(spec, ctx)
37
+ }
38
+
39
+
40
+ funcname() {
41
+ return 'maybe'
42
+ }
43
+
44
+
45
+ // Null so the base drives nothing: it would drive on the CALLER's
46
+ // context, where NilVal.make records the miss before resolve runs.
47
+ prepare(_ctx: AontuContext, _args: Val[]) {
48
+ return null
49
+ }
50
+
51
+
52
+ unify(peer: Val, ctx: AontuContext): Val {
53
+ if (!ctx.settle) {
54
+ return this.residuate(peer, ctx)
55
+ }
56
+
57
+ return super.unify(peer, ctx)
58
+ }
59
+
60
+
61
+ resolve(ctx: AontuContext, args: Val[]) {
62
+ // Cloned rather than swapped and restored, which is the
63
+ // own-property hazard trialUnify documents at length.
64
+ const sink: Val[] = []
65
+ const actx = ctx.clone({ err: sink, collect: true })
66
+ const out = unite(actx, args[0], top(), 'maybe')
67
+
68
+ // ONLY a missing referent. A conflict inside the argument stays
69
+ // the document's error.
70
+ if (out.isNil && 'reference' === (out as any).class) {
71
+ return this.place(new AbsentVal({}, ctx))
72
+ }
73
+
74
+ for (const err of sink) {
75
+ ctx.adderr(err as any)
76
+ }
77
+
78
+ return out
79
+ }
80
+
81
+ } /* node:coverage ignore next 6 */
82
+
83
+
84
+ export {
85
+ MaybeFuncVal,
86
+ }