aontu 0.61.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/README.md +4 -4
  2. package/dist/agentsmd.d.ts +1 -0
  3. package/dist/agentsmd.js +7 -28
  4. package/dist/agentsmd.js.map +1 -1
  5. package/dist/alias.js.map +1 -1
  6. package/dist/allow.d.ts +23 -0
  7. package/dist/allow.js +138 -0
  8. package/dist/allow.js.map +1 -0
  9. package/dist/aontu.d.ts +4 -2
  10. package/dist/aontu.js +4 -80
  11. package/dist/aontu.js.map +1 -1
  12. package/dist/aontumodel.d.ts +4 -0
  13. package/dist/aontumodel.js +33 -0
  14. package/dist/aontumodel.js.map +1 -0
  15. package/dist/cli.d.ts +10 -1
  16. package/dist/cli.js +877 -479
  17. package/dist/cli.js.map +1 -1
  18. package/dist/ctx.js +0 -48
  19. package/dist/ctx.js.map +1 -1
  20. package/dist/diff.js +0 -32
  21. package/dist/diff.js.map +1 -1
  22. package/dist/err.js +0 -40
  23. package/dist/err.js.map +1 -1
  24. package/dist/escape.js +0 -45
  25. package/dist/escape.js.map +1 -1
  26. package/dist/exactjson.d.ts +0 -35
  27. package/dist/exactjson.js +0 -131
  28. package/dist/exactjson.js.map +1 -1
  29. package/dist/format.js +55 -189
  30. package/dist/format.js.map +1 -1
  31. package/dist/grammar.d.ts +9 -0
  32. package/dist/grammar.js +54 -0
  33. package/dist/grammar.js.map +1 -0
  34. package/dist/graph.js +0 -26
  35. package/dist/graph.js.map +1 -1
  36. package/dist/hcanon.js +0 -82
  37. package/dist/hcanon.js.map +1 -1
  38. package/dist/helpdoc.d.ts +16 -0
  39. package/dist/helpdoc.js +59 -0
  40. package/dist/helpdoc.js.map +1 -0
  41. package/dist/hints.d.ts +0 -6
  42. package/dist/hints.js +59 -47
  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 +32 -877
  50. package/dist/lang.js.map +1 -1
  51. package/dist/lower.d.ts +3 -0
  52. package/dist/lower.js +14 -61
  53. package/dist/lower.js.map +1 -1
  54. package/dist/lsp-server.js +0 -16
  55. package/dist/lsp-server.js.map +1 -1
  56. package/dist/lsp.d.ts +1 -1
  57. package/dist/lsp.js +12 -159
  58. package/dist/lsp.js.map +1 -1
  59. package/dist/mcp-server.js +0 -26
  60. package/dist/mcp-server.js.map +1 -1
  61. package/dist/mcp.js +0 -113
  62. package/dist/mcp.js.map +1 -1
  63. package/dist/mod-tool.js +0 -130
  64. package/dist/mod-tool.js.map +1 -1
  65. package/dist/mod.js +0 -162
  66. package/dist/mod.js.map +1 -1
  67. package/dist/patch.js +0 -217
  68. package/dist/patch.js.map +1 -1
  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.d.ts +2 -0
  76. package/dist/relation.js +3 -58
  77. package/dist/relation.js.map +1 -1
  78. package/dist/render.js +33 -143
  79. package/dist/render.js.map +1 -1
  80. package/dist/report-sarif.d.ts +0 -11
  81. package/dist/report-sarif.js +0 -28
  82. package/dist/report-sarif.js.map +1 -1
  83. package/dist/sig.js +0 -35
  84. package/dist/sig.js.map +1 -1
  85. package/dist/sigdecl.js +1 -1
  86. package/dist/sigdecl.js.map +1 -1
  87. package/dist/siggate.js +0 -4
  88. package/dist/siggate.js.map +1 -1
  89. package/dist/site.js +3 -29
  90. package/dist/site.js.map +1 -1
  91. package/dist/subsume.d.ts +0 -10
  92. package/dist/subsume.js +0 -137
  93. package/dist/subsume.js.map +1 -1
  94. package/dist/template.d.ts +2 -1
  95. package/dist/template.js +58 -138
  96. package/dist/template.js.map +1 -1
  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 +12 -242
  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 +20 -0
  125. package/dist/val/CmpFuncVal.js +188 -0
  126. package/dist/val/CmpFuncVal.js.map +1 -0
  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.d.ts +1 -2
  141. package/dist/val/EachFuncVal.js +12 -29
  142. package/dist/val/EachFuncVal.js.map +1 -1
  143. package/dist/val/EmitFuncVal.d.ts +1 -1
  144. package/dist/val/EmitFuncVal.js +6 -119
  145. package/dist/val/EmitFuncVal.js.map +1 -1
  146. package/dist/val/ExpectVal.js +0 -62
  147. package/dist/val/ExpectVal.js.map +1 -1
  148. package/dist/val/FilterFuncVal.js +0 -25
  149. package/dist/val/FilterFuncVal.js.map +1 -1
  150. package/dist/val/FuncBaseVal.d.ts +1 -0
  151. package/dist/val/FuncBaseVal.js +7 -127
  152. package/dist/val/FuncBaseVal.js.map +1 -1
  153. package/dist/val/GraphAtomVal.js +0 -15
  154. package/dist/val/GraphAtomVal.js.map +1 -1
  155. package/dist/val/HideFuncVal.js +0 -13
  156. package/dist/val/HideFuncVal.js.map +1 -1
  157. package/dist/val/IntegerVal.js +0 -61
  158. package/dist/val/IntegerVal.js.map +1 -1
  159. package/dist/val/JunctionVal.js +0 -20
  160. package/dist/val/JunctionVal.js.map +1 -1
  161. package/dist/val/KeyFuncVal.js +0 -46
  162. package/dist/val/KeyFuncVal.js.map +1 -1
  163. package/dist/val/ListVal.js +0 -57
  164. package/dist/val/ListVal.js.map +1 -1
  165. package/dist/val/LowerFuncVal.js +11 -6
  166. package/dist/val/LowerFuncVal.js.map +1 -1
  167. package/dist/val/MapVal.js +0 -151
  168. package/dist/val/MapVal.js.map +1 -1
  169. package/dist/val/MatchFuncVal.js +0 -27
  170. package/dist/val/MatchFuncVal.js.map +1 -1
  171. package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
  172. package/dist/val/MaybeFuncVal.js +50 -0
  173. package/dist/val/MaybeFuncVal.js.map +1 -0
  174. package/dist/val/MoveFuncVal.js +0 -18
  175. package/dist/val/MoveFuncVal.js.map +1 -1
  176. package/dist/val/NilVal.js +2 -36
  177. package/dist/val/NilVal.js.map +1 -1
  178. package/dist/val/NomFuncVal.d.ts +12 -0
  179. package/dist/val/NomFuncVal.js +153 -0
  180. package/dist/val/NomFuncVal.js.map +1 -0
  181. package/dist/val/NumberVal.js +0 -15
  182. package/dist/val/NumberVal.js.map +1 -1
  183. package/dist/val/OpBaseVal.d.ts +1 -0
  184. package/dist/val/OpBaseVal.js +3 -15
  185. package/dist/val/OpBaseVal.js.map +1 -1
  186. package/dist/val/PackFuncVal.js +0 -34
  187. package/dist/val/PackFuncVal.js.map +1 -1
  188. package/dist/val/PathFuncVal.js +0 -6
  189. package/dist/val/PathFuncVal.js.map +1 -1
  190. package/dist/val/PathVal.js +0 -41
  191. package/dist/val/PathVal.js.map +1 -1
  192. package/dist/val/PlaceVal.js +0 -25
  193. package/dist/val/PlaceVal.js.map +1 -1
  194. package/dist/val/PlusOpVal.d.ts +1 -7
  195. package/dist/val/PlusOpVal.js +13 -74
  196. package/dist/val/PlusOpVal.js.map +1 -1
  197. package/dist/val/PrefFuncVal.js +0 -1
  198. package/dist/val/PrefFuncVal.js.map +1 -1
  199. package/dist/val/PrefVal.js +0 -167
  200. package/dist/val/PrefVal.js.map +1 -1
  201. package/dist/val/RecurseVal.js +0 -55
  202. package/dist/val/RecurseVal.js.map +1 -1
  203. package/dist/val/RefVal.js +0 -282
  204. package/dist/val/RefVal.js.map +1 -1
  205. package/dist/val/ReferFuncVal.js +0 -232
  206. package/dist/val/ReferFuncVal.js.map +1 -1
  207. package/dist/val/ScalarKindVal.js +0 -49
  208. package/dist/val/ScalarKindVal.js.map +1 -1
  209. package/dist/val/ScalarVal.js +0 -11
  210. package/dist/val/ScalarVal.js.map +1 -1
  211. package/dist/val/StrFuncVal.js +0 -18
  212. package/dist/val/StrFuncVal.js.map +1 -1
  213. package/dist/val/SuperFuncVal.js +0 -32
  214. package/dist/val/SuperFuncVal.js.map +1 -1
  215. package/dist/val/TopVal.js +0 -1
  216. package/dist/val/TopVal.js.map +1 -1
  217. package/dist/val/TranslateFuncVal.d.ts +12 -0
  218. package/dist/val/TranslateFuncVal.js +99 -0
  219. package/dist/val/TranslateFuncVal.js.map +1 -0
  220. package/dist/val/UpperFuncVal.js +11 -6
  221. package/dist/val/UpperFuncVal.js.map +1 -1
  222. package/dist/val/Val.d.ts +1 -0
  223. package/dist/val/Val.js +2 -133
  224. package/dist/val/Val.js.map +1 -1
  225. package/dist/val/VarVal.js +0 -12
  226. package/dist/val/VarVal.js.map +1 -1
  227. package/dist/val/arith.js +0 -37
  228. package/dist/val/arith.js.map +1 -1
  229. package/dist/val/caserange.d.ts +3 -0
  230. package/dist/val/caserange.js +49 -0
  231. package/dist/val/caserange.js.map +1 -0
  232. package/dist/val/members.js +0 -6
  233. package/dist/val/members.js.map +1 -1
  234. package/dist/val/numcmp.js +0 -11
  235. package/dist/val/numcmp.js.map +1 -1
  236. package/dist/val/numkind.js +0 -145
  237. package/dist/val/numkind.js.map +1 -1
  238. package/dist/val/valutil.js +0 -16
  239. package/dist/val/valutil.js.map +1 -1
  240. package/dist/vet.d.ts +12 -0
  241. package/dist/vet.js +159 -412
  242. package/dist/vet.js.map +1 -1
  243. package/dist/view.js +0 -414
  244. package/dist/view.js.map +1 -1
  245. package/dist/walk.js +0 -41
  246. package/dist/walk.js.map +1 -1
  247. package/grammar/aontu.abnf +9 -7
  248. package/grammar/aontu.gbnf +5 -5
  249. package/grammar/aontu.lark +5 -5
  250. package/grammar/aontu.tmLanguage.json +1 -1
  251. package/package.json +4 -2
  252. package/skill/SKILL.md +8 -0
  253. package/skill/init/check.sh +28 -0
  254. package/skill/init/data.aon +12 -0
  255. package/skill/init/model.aon +19 -0
  256. package/skill/tasks.md +151 -0
  257. package/src/agentsmd.ts +8 -32
  258. package/src/alias.ts +0 -39
  259. package/src/allow.ts +221 -0
  260. package/src/aontu.ts +10 -108
  261. package/src/aontumodel.ts +32 -0
  262. package/src/cli.ts +1009 -540
  263. package/src/ctx.ts +0 -103
  264. package/src/diff.ts +0 -40
  265. package/src/err.ts +0 -40
  266. package/src/escape.ts +0 -46
  267. package/src/exactjson.ts +0 -131
  268. package/src/format.ts +63 -234
  269. package/src/grammar.ts +72 -0
  270. package/src/graph.ts +0 -61
  271. package/src/hcanon.ts +0 -82
  272. package/src/helpdoc.ts +77 -0
  273. package/src/hints.ts +72 -49
  274. package/src/jsonschema.ts +0 -123
  275. package/src/keyorder.ts +0 -42
  276. package/src/lang.ts +39 -895
  277. package/src/lower.ts +15 -65
  278. package/src/lsp-server.ts +0 -16
  279. package/src/lsp.ts +12 -180
  280. package/src/mcp-server.ts +0 -31
  281. package/src/mcp.ts +0 -130
  282. package/src/mod-tool.ts +0 -158
  283. package/src/mod.ts +0 -178
  284. package/src/patch.ts +0 -232
  285. package/src/provenance.ts +0 -183
  286. package/src/query.ts +0 -84
  287. package/src/reach.ts +0 -53
  288. package/src/relation.ts +7 -71
  289. package/src/render.ts +33 -180
  290. package/src/report-sarif.ts +0 -48
  291. package/src/sig.ts +0 -35
  292. package/src/sigdecl.ts +1 -1
  293. package/src/siggate.ts +0 -30
  294. package/src/site.ts +3 -29
  295. package/src/subsume.ts +1 -161
  296. package/src/template.ts +69 -140
  297. package/src/trim.ts +0 -53
  298. package/src/type.ts +2 -45
  299. package/src/unify.ts +13 -251
  300. package/src/utility.ts +0 -31
  301. package/src/val/AbnfFuncVal.ts +181 -0
  302. package/src/val/AbsentVal.ts +54 -0
  303. package/src/val/AggFuncVal.ts +152 -188
  304. package/src/val/ArithFuncVal.ts +0 -20
  305. package/src/val/BagVal.ts +1 -78
  306. package/src/val/BigDecimalVal.ts +0 -16
  307. package/src/val/BigIntegerVal.ts +0 -16
  308. package/src/val/CloseFuncVal.ts +0 -9
  309. package/src/val/CmpFuncVal.ts +249 -0
  310. package/src/val/ConjunctVal.ts +0 -33
  311. package/src/val/ConstraintVal.ts +2 -537
  312. package/src/val/ContainerKindVal.ts +0 -18
  313. package/src/val/CopyFuncVal.ts +0 -5
  314. package/src/val/Decimal.ts +1 -185
  315. package/src/val/DeprecateFuncVal.ts +0 -10
  316. package/src/val/DisjunctVal.ts +0 -157
  317. package/src/val/EachFuncVal.ts +12 -53
  318. package/src/val/EmitFuncVal.ts +8 -208
  319. package/src/val/ExpectVal.ts +0 -62
  320. package/src/val/FilterFuncVal.ts +0 -55
  321. package/src/val/FuncBaseVal.ts +9 -130
  322. package/src/val/GraphAtomVal.ts +0 -42
  323. package/src/val/HideFuncVal.ts +0 -15
  324. package/src/val/IntegerVal.ts +0 -61
  325. package/src/val/JunctionVal.ts +0 -20
  326. package/src/val/KeyFuncVal.ts +0 -48
  327. package/src/val/ListVal.ts +0 -59
  328. package/src/val/LowerFuncVal.ts +12 -7
  329. package/src/val/MapVal.ts +0 -151
  330. package/src/val/MatchFuncVal.ts +0 -59
  331. package/src/val/MaybeFuncVal.ts +86 -0
  332. package/src/val/MoveFuncVal.ts +0 -20
  333. package/src/val/NilVal.ts +2 -36
  334. package/src/val/NomFuncVal.ts +200 -0
  335. package/src/val/NumberVal.ts +0 -16
  336. package/src/val/OpBaseVal.ts +4 -17
  337. package/src/val/PackFuncVal.ts +0 -63
  338. package/src/val/PathFuncVal.ts +0 -32
  339. package/src/val/PathVal.ts +0 -66
  340. package/src/val/PlaceVal.ts +0 -45
  341. package/src/val/PlusOpVal.ts +18 -75
  342. package/src/val/PrefFuncVal.ts +0 -1
  343. package/src/val/PrefVal.ts +0 -179
  344. package/src/val/RecurseVal.ts +0 -81
  345. package/src/val/RefVal.ts +1 -285
  346. package/src/val/ReferFuncVal.ts +0 -255
  347. package/src/val/ScalarKindVal.ts +0 -50
  348. package/src/val/ScalarVal.ts +0 -12
  349. package/src/val/StrFuncVal.ts +0 -44
  350. package/src/val/SuperFuncVal.ts +0 -42
  351. package/src/val/TopVal.ts +0 -1
  352. package/src/val/TranslateFuncVal.ts +132 -0
  353. package/src/val/UpperFuncVal.ts +12 -7
  354. package/src/val/Val.ts +3 -192
  355. package/src/val/VarVal.ts +0 -15
  356. package/src/val/arith.ts +0 -92
  357. package/src/val/caserange.ts +53 -0
  358. package/src/val/members.ts +0 -23
  359. package/src/val/numcmp.ts +1 -27
  360. package/src/val/numkind.ts +0 -149
  361. package/src/val/valutil.ts +0 -16
  362. package/src/vet.ts +209 -504
  363. package/src/view.ts +0 -507
  364. package/src/walk.ts +0 -41
  365. package/dist/std.d.ts +0 -3
  366. package/dist/std.js +0 -637
  367. package/dist/std.js.map +0 -1
  368. package/dist/val/FormFuncVal.js +0 -55
  369. package/dist/val/FormFuncVal.js.map +0 -1
  370. package/src/std.ts +0 -648
  371. package/src/val/FormFuncVal.ts +0 -119
@@ -1,26 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
2
 
3
- // GENERATION: `each(data, tmpl)` (G8 phase 1,
4
- // docs/capability-review/g8-generation.md). One element of the result
5
- // list per child of `data`, each of them that child met with `tmpl`.
6
- // Written with one argument, `each(m)` is a map's children as a list.
7
- //
8
- // ports: {http: 80, https: 443}
9
- // open: each($.ports, integer) -> [80, 443]
10
- //
11
- // ORDER IS FIXED, and fixed the way canon already fixes it: source
12
- // order for a list, sorted-key order for a map (`cmpCodePoint`, the
13
- // comparator `MapVal.canon` and the Go port's marshalling use). A
14
- // generated list whose order depended on insertion history would differ
15
- // between two runs of the same document, and between the two ports --
16
- // the one thing the shared spec exists to prevent.
17
- //
18
- // The element is the source child CLONED, not shared: it is a second
19
- // position holding that value, and a position is where path-dependent
20
- // content resolves. What the clone keeps is the identity, if the child
21
- // carries one (G4 phase 1) -- a listed entity is still that entity, and
22
- // the merge that follows is the point.
23
-
24
3
  import type {
25
4
  Val,
26
5
  ValSpec,
@@ -30,7 +9,6 @@ import {
30
9
  AontuContext,
31
10
  } from '../ctx'
32
11
 
33
- import { unite } from '../unify'
34
12
  import { makeNilErr } from '../err'
35
13
  import { ListVal } from './ListVal'
36
14
  import { FuncBaseVal } from './FuncBaseVal'
@@ -39,19 +17,11 @@ import { fillPlace } from './PlaceVal'
39
17
  import { memberVals } from './members'
40
18
 
41
19
 
42
- // The members a data bag holds, in the order the result must carry
43
- // them -- what generation would emit (./members.ts, BUGS.md §79) --
44
- // or the code naming what is wrong with the argument.
45
- function dataValues(data: Val | undefined, ctx: AontuContext): Val[] | string {
46
- const vals = memberVals(data, ctx)
47
- return undefined === vals ? 'each_data' : vals
48
- }
49
-
50
-
51
20
  class EachFuncVal extends FuncBaseVal {
52
21
  isEachFunc = true
53
22
 
54
- // THE STAGING RULE, for the reason given in PackFuncVal.
23
+ // THE STAGING RULE, for the reason given in PackFuncVal: the data
24
+ // is not settled merely by being `done` once.
55
25
  staged = true
56
26
 
57
27
  constructor(
@@ -62,7 +32,6 @@ class EachFuncVal extends FuncBaseVal {
62
32
  }
63
33
 
64
34
 
65
-
66
35
  funcname() {
67
36
  return 'each'
68
37
  }
@@ -76,8 +45,7 @@ class EachFuncVal extends FuncBaseVal {
76
45
 
77
46
  unify(peer: Val, ctx: AontuContext): Val {
78
47
  // ONE argument is driven: the data. The template is not (see
79
- // prepare above), and driveStagedArgs answers whether the data has
80
- // settled -- the other half of "ready to fire".
48
+ // prepare above).
81
49
  if (!this.stagedReady(peer, ctx, 1)) {
82
50
  return this.residuate(peer, ctx)
83
51
  }
@@ -87,37 +55,28 @@ class EachFuncVal extends FuncBaseVal {
87
55
 
88
56
 
89
57
  resolve(ctx: AontuContext, args: Val[]) {
90
- const vals = dataValues(args?.[0], ctx)
91
- if ('string' === typeof vals) {
92
- return makeNilErr(ctx, vals, this)
58
+ const vals = memberVals(args?.[0], ctx)
59
+ if (undefined === vals) {
60
+ return makeNilErr(ctx, 'each_data', this)
93
61
  }
94
62
 
95
- const tmpl: Val | undefined = args?.[1]
63
+ // Arity is checked at parse (funcArity), so the template is here.
64
+ const tmpl: Val = args[1]
96
65
  const peg: Val[] = []
97
66
 
98
67
  for (let i = 0; i < vals.length; i++) {
99
68
  const elctx = ctx.descend(String(i))
100
- const el = vals[i].clone(elctx)
101
- // The template is CLONED per element, never shared — a FULL
102
- // instance to the leaves (`dup`, ADR-005): see PackFuncVal.resolve.
103
- // `_` inside the template binds the source child (G8 phase 3),
104
- // which for `each` is the element itself.
105
- let inst: Val | undefined = undefined
106
- if (undefined !== tmpl) {
107
- inst = tmpl.clone(elctx, { dup: true })
108
- repathInstance(inst, inst.path)
109
- }
110
- peg.push(undefined === inst ? el :
111
- unite(elctx, el, fillPlace(inst, vals[i], elctx), 'each'))
69
+ const inst = tmpl.clone(elctx, { dup: true })
70
+ repathInstance(inst, inst.path)
71
+ peg.push(fillPlace(inst, vals[i], elctx))
112
72
  }
113
73
 
114
74
  return new ListVal({ peg }, ctx)
115
75
  }
116
76
 
117
- } /* node:coverage ignore next 7 */
77
+ } /* node:coverage ignore next 6 */
118
78
 
119
79
 
120
80
  export {
121
- dataValues,
122
81
  EachFuncVal,
123
82
  }
@@ -1,86 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
2
 
3
- // TRANSFORMATION: `emit(select, table)` (G9 phase 6,
4
- // docs/design/EMIT.0.md). Apply-templates, with the dispatch in the
5
- // engine and none of it in user space.
6
- //
7
- // emit($.services, [
8
- // {match: {kind: sqs}, body: [`listen(` + .pin + `)`]}
9
- // {match: {kind: http}, body: [`serve(` + .path + `)`]}
10
- // ])
11
- //
12
- // For every node of `select`, in order, the first template whose
13
- // `match` the node unifies with is taken and its `body` instantiated
14
- // AGAINST THAT NODE. The result is one flat list.
15
- //
16
- // WHY THIS CANNOT BE WRITTEN IN THE DOCUMENT (EMIT.0.md, "What it
17
- // takes"). A rule table held as a value cannot be dispatched against:
18
- // a body referenced by path resolves its relative references AT THE
19
- // DEFINITION SITE, and the positional resolution that does exist is a
20
- // dot COUNT that does not survive being consumed by a second dispatch.
21
- // The builtin instantiates a body at the node it matched -- a NAMED
22
- // origin -- which is the whole capability.
23
- //
24
- // THE BODY'S RELATIVE REFERENCES ARE BOUND TO THE NODE. `.pin` inside
25
- // a body is the matched node's `pin`, and `_` is the node itself, as
26
- // it is in every other generator. The binding is done HERE rather than
27
- // left to path resolution: a relative path is a COUNT taken wherever
28
- // the value comes to rest, and the nodes of a computed selection
29
- // (`filter(...)`) come to rest nowhere -- there is no position for a
30
- // count to be taken from. An ABSOLUTE reference is untouched and still
31
- // reads the document root.
32
- //
33
- // The binding stops at a nested generator's own binding argument
34
- // (boundArgStart): a rule table nested in a body is the INNER emit's
35
- // to bind, so `.x` inside it is the inner node. What crosses the
36
- // boundary is the nested call's SELECTOR, which is argument 0 and is
37
- // bound here -- the selector is the channel.
38
- //
39
- // THE RESULT IS FLAT, and that is a constraint rather than a
40
- // convenience: the fragment algebra is flat because the nested
41
- // spelling refuses even a valid instance in both ports, so a dispatch
42
- // returning a tree would undo that ruling. A body element that is
43
- // itself a list SPLICES, which is what makes a nested emit compose.
44
- //
45
- // A VALUE REACHES THE BODY THROUGH `replace`, NOT A DELIMITER
46
- // (docs/design/TEMPLATE.0.md D3, D4; RENDER.0.md P6). A template may
47
- // carry a `replace` map whose key is an exact string the body already
48
- // holds as ordinary target text and whose value is evaluated against
49
- // the matched node, and an `esc` naming the convention every value is
50
- // escaped by -- the C/JSON escape when absent, `none` the one opt-out.
51
- // Three rules: a single left-to-right scan of a literal line taking
52
- // the longest key at each position; a substituted value is never
53
- // re-scanned, so no value can introduce a key; and a template's
54
- // replacements touch its own literal text only, never a result spliced
55
- // in from a nested dispatch. Two checks run on the template before any
56
- // node: a key inside another key (replace_overlap) and a key the body
57
- // does not hold (replace_unused). There is no hole syntax, and that is
58
- // the point: any inline delimiter is somebody's syntax.
59
- //
60
- // NO MATCH IS AN ERROR (`emit_none`). XSLT's built-in rule copies an
61
- // unhandled node's string value into the result, which for code output
62
- // means model data landing silently in the middle of a source file.
63
- // That is the single worst default in the prior art and it is refused.
64
- // An EMPTY selection, by contrast, emits nothing -- which is the whole
65
- // conditional mechanism, and why no `when` directive exists.
66
- //
67
- // A NAMED TABLE IS A PLACEHELD `emit` (`%wire = emit(_, T)`). A table
68
- // written at a document position is DRIVEN there, so its bodies'
69
- // relative references resolve against wherever it sits and miss;
70
- // nothing in the language holds a value unevaluated at such a
71
- // position, and what does hold one is a CALL's template argument.
72
- // `emit(.listen, %wire)` follows the reference and reads the table out
73
- // of the placeheld call; `.listen & %wire` fills the hole. Both are
74
- // the same dispatch, and it is what lets a rule set name ITSELF.
75
- //
76
- // TERMINATION IS THE SELECTION'S. Unlike `pack` and `each`, this one
77
- // recurses -- a nested model walked into nested output is the
78
- // capability the rule layer exists to add -- so the bound is not "it
79
- // cannot call itself" but "each dispatch descends into a finite bag
80
- // that already exists, and a selection that empties emits nothing". A
81
- // rule set that walks into itself WITHOUT descending is charged to the
82
- // depth budget and refused as `unify_cycle`, like any other runaway
83
- // descent.
84
3
 
85
4
  import type {
86
5
  Val,
@@ -106,12 +25,6 @@ import { plusText } from './PlusOpVal'
106
25
  import { bagMembers } from './members'
107
26
 
108
27
 
109
- // One entry of the rule table: the pattern to try, the body to
110
- // instantiate, and -- TEMPLATE.0.md D3 and D4 -- the `replace` map and
111
- // the `esc` convention its values take, with the literal spots of the
112
- // body the replacements are written into. A table is a LIST of these;
113
- // a single template map is that list of one, told apart by kind,
114
- // exactly as match() tells its patterns apart.
115
28
  type Template = {
116
29
  match: Val,
117
30
  body: Val,
@@ -125,8 +38,8 @@ type Template = {
125
38
 
126
39
 
127
40
  // One literal string of a body: element `i`, and within a map element
128
- // the `of` index or the `text` key, with the text itself.
129
- type LitSpot = { i: number, of?: number, text?: boolean, s: string }
41
+ // the `n` index or the `text` key, with the text itself.
42
+ type LitSpot = { i: number, n?: number, text?: boolean, s: string }
130
43
 
131
44
 
132
45
  // What is wrong with a table, with the detail the message carries.
@@ -148,15 +61,6 @@ function isRefusal(x: any): x is Refusal {
148
61
  function tableTemplates(table: Val | undefined): Template[] | Refusal {
149
62
  const t: any = table
150
63
 
151
- // A NAMED TABLE IS A PLACEHELD `emit`, and its table is the table.
152
- // A table written at a document position is DRIVEN there -- a body's
153
- // relative references resolve against wherever it sits and miss --
154
- // so the position that holds one unevaluated is the one position the
155
- // language already never drives: a call's template argument.
156
- // `%wire = emit(_, [ … ])` is that position with the selection left
157
- // open, and it reads as what it is, an apply-templates waiting for
158
- // its nodes: `emit(.listen, %wire)` passes them, `.listen & %wire`
159
- // fills the hole, and both are the same dispatch.
160
64
  if (true === t?.isEmitFunc) {
161
65
  return tableTemplates(t.peg[1])
162
66
  }
@@ -186,12 +90,6 @@ function tableTemplates(table: Val | undefined): Template[] | Refusal {
186
90
  }
187
91
 
188
92
 
189
- // One rule. Both keys are required: a template with no pattern would
190
- // match everything by accident, and one with no body would emit
191
- // nothing while claiming a node. The two optional keys -- a `replace`
192
- // map and an `esc` naming the convention its values are escaped by,
193
- // `none` the one opt-out -- are the template's shape too, and D3's two
194
- // static checks run here, on the template alone, before any node.
195
93
  function oneTemplate(m: any, idx: number): Template | Refusal {
196
94
  const match: Val = m.peg.match
197
95
  const body: any = m.peg.body
@@ -235,12 +133,6 @@ function textOf(v: any): string | undefined {
235
133
  }
236
134
 
237
135
 
238
- // The literal strings of a body -- a string element, and the strings
239
- // written directly in a map element's `of` list or `text` -- which are
240
- // the text the template wrote. A string an expression or a nested
241
- // dispatch computes is not one: D3's third rule (a spliced result is
242
- // finished) and its second (a substituted value is never re-scanned)
243
- // both follow from substituting at these spots and nowhere else.
244
136
  function literalSpots(elems: Val[]): LitSpot[] {
245
137
  const out: LitSpot[] = []
246
138
  elems.forEach((el: any, i: number) => {
@@ -252,12 +144,12 @@ function literalSpots(elems: Val[]): LitSpot[] {
252
144
  if (true !== el?.isMap) {
253
145
  return
254
146
  }
255
- const of: any = el.peg.of
256
- if (true === of?.isList) {
257
- (of.peg as any[]).forEach((p: any, j: number) => {
147
+ const chunks: any = el.peg.n
148
+ if (true === chunks?.isList) {
149
+ (chunks.peg as any[]).forEach((p: any, j: number) => {
258
150
  const ps = textOf(p)
259
151
  if (undefined !== ps) {
260
- out.push({ i, of: j, s: ps })
152
+ out.push({ i, n: j, s: ps })
261
153
  }
262
154
  })
263
155
  }
@@ -270,11 +162,6 @@ function literalSpots(elems: Val[]): LitSpot[] {
270
162
  }
271
163
 
272
164
 
273
- // D3's two static checks, on the template alone and before any node:
274
- // a key inside another is ambiguous whatever the order
275
- // (replace_overlap), and a key no literal holds means the template
276
- // drifted from its map (replace_unused). Keys are visited in code
277
- // point order, so both ports name the same pair.
278
165
  function checkReplace(keys: string[], lits: LitSpot[]): Refusal | undefined {
279
166
  const sorted = [...keys].sort(cmpCodePoint)
280
167
  for (const a of sorted) {
@@ -293,10 +180,6 @@ function checkReplace(keys: string[], lits: LitSpot[]): Refusal | undefined {
293
180
  }
294
181
 
295
182
 
296
- // D3's first two rules as one scan: at each position the longest key
297
- // that matches is taken and its value written out whole, and the scan
298
- // moves past the KEY -- the value is never looked at again, so no
299
- // value can introduce a key.
300
183
  function substitute(text: string, pairs: Pair[]): string {
301
184
  let out = ''
302
185
  let i = 0
@@ -315,11 +198,6 @@ function substitute(text: string, pairs: Pair[]): string {
315
198
  }
316
199
 
317
200
 
318
- // The instance with the template's literal text at element `i`
319
- // rewritten through the pairs -- on the fresh instance, where the
320
- // structure is exactly the template's, and before any binding, so a
321
- // value written in is never scanned again and a spliced result is
322
- // never touched.
323
201
  function substituted(
324
202
  inst: Val, i: number, lits: LitSpot[], pairs: Pair[], ctx: AontuContext
325
203
  ): Val {
@@ -328,8 +206,8 @@ function substituted(
328
206
  continue
329
207
  }
330
208
  const sv = new StringVal({ peg: substitute(l.s, pairs) }, ctx)
331
- if (undefined !== l.of) {
332
- (inst as any).peg.of.peg[l.of] = sv
209
+ if (undefined !== l.n) {
210
+ (inst as any).peg.n.peg[l.n] = sv
333
211
  }
334
212
  else if (true === l.text) {
335
213
  (inst as any).peg.text = sv
@@ -374,14 +252,6 @@ function bindNode(v: any, node: Val, ctx: AontuContext, fail: Fail): Val {
374
252
  return v
375
253
  }
376
254
  const out = found.clone(ctx)
377
- // A RELATIVE REFERENCE IS A READ TOO (RENDER.0.md P7), and the one
378
- // read no reference resolution sees: the binding answers it here,
379
- // from the matched node, rather than letting a path resolve at a
380
- // position the body never occupies. Without this a nested rule set
381
- // whose selection is `.handlers` reported its nodes at the address
382
- // they came to rest, which is in the OUTPUT. A node carries an
383
- // address only under an instrumented run, which is what makes the
384
- // second test the whole guard.
385
255
  if (null == (out as any).origin && null != (node as any).origin) {
386
256
  ; (out as any).origin = (node as any).origin +
387
257
  (v.peg as string[]).map((seg: string) => '.' + seg).join('')
@@ -430,12 +300,6 @@ function bindNode(v: any, node: Val, ctx: AontuContext, fail: Fail): Val {
430
300
  }
431
301
 
432
302
 
433
- // The field of `node` a reference names, or undefined when it names
434
- // none. Only a chain of plain NAMES is a field: a parent step has no
435
- // answer at a node that is an origin rather than a position, and a
436
- // variable segment is not a name until something resolves it -- both
437
- // are refused here rather than left to resolve somewhere else, which
438
- // is the failure mode the binding exists to remove.
439
303
  function nodeField(ref: any, node: Val): Val | undefined {
440
304
  let cur: any = node
441
305
  for (const seg of ref.peg as any[]) {
@@ -455,21 +319,6 @@ function nodeField(ref: any, node: Val): Val | undefined {
455
319
  }
456
320
 
457
321
 
458
- // The address of one matched node: its own read address when it has
459
- // one, else the SELECTION's read address and the node's key under it
460
- // -- a selection is read once and walked, so its members carry no read
461
- // of their own.
462
- //
463
- // A COMPUTED SELECTION HAS NO ADDRESS, AND THE TRACE SAYS SO: an empty
464
- // node. `filter(...)` builds a bag no path in the document names, and
465
- // the only other thing to report is where the bag came to REST -- a
466
- // position inside a template instance, which is not in the document,
467
- // and which the two ports number differently. Publishing that would
468
- // have made the trace a parity break as well as a fiction. The rule
469
- // address answers the same way: `<table>#<index>` for a table a
470
- // reference reached, and `#<index>` alone for one written inline at the
471
- // call site, which has no address of its own. `#` is in no path, so a
472
- // rule's address can never be read as one.
473
322
  function nodeAddr(sel: string | undefined, key: string, node: any): string {
474
323
  if (null != node.origin) {
475
324
  return node.origin
@@ -534,22 +383,11 @@ class EmitFuncVal extends FuncBaseVal {
534
383
 
535
384
 
536
385
  resolve(ctx: AontuContext, args: Val[]) {
537
- // THE MEMBERS WITH THEIR KEYS, read through the one helper every
538
- // fold reads a bag by (./members.ts): source order for a list,
539
- // sorted-key order for a map, a hidden child and an unfilled
540
- // optional left out. The KEY is what the trace addresses a node by
541
- // -- it is the node's key IN THE SELECTION, which is the only
542
- // thing a walk of a computed bag knows about where a node sits.
543
386
  const nodes = bagMembers(args?.[0], ctx)
544
387
  if (undefined === nodes) {
545
388
  return makeNilErr(ctx, 'emit_data', this)
546
389
  }
547
390
 
548
- // A NAMED TABLE IS REACHED BY REFERENCE, and the reference -- not
549
- // the table -- is what is followed. Followed HERE rather than in
550
- // the staged drive, which waits for a SETTLED target: a table is a
551
- // template, a template holding a hole never settles, and waiting
552
- // for one would mean the dispatch never fires.
553
391
  let table: any = args?.[1]
554
392
  if (true === table?.isRef) {
555
393
  table = table.unify(top(), ctx)
@@ -560,10 +398,6 @@ class EmitFuncVal extends FuncBaseVal {
560
398
  return this.refuse(ctx, templates)
561
399
  }
562
400
 
563
- // THE TRACE'S TWO ADDRESSES (RENDER.0.md D11, P7), computed once
564
- // per dispatch and only when the run is instrumented: the table's
565
- // own, which every rule of it is numbered under, and the
566
- // selection's, which every node of it is keyed under.
567
401
  const rec = undefined !== ctx.reads
568
402
  const tableAddr = rec ? ((table as any)?.origin ?? '') : ''
569
403
  const selAddr = rec ? (args?.[0] as any)?.origin : undefined
@@ -582,11 +416,6 @@ class EmitFuncVal extends FuncBaseVal {
582
416
  const fail: Fail = {}
583
417
  let mark: EmitOrigin | undefined = undefined
584
418
  if (rec) {
585
- // THE NODE KEEPS ITS ADDRESS (P7). A body passes the node on
586
- // through `_`, and a nested rule set dispatching over it can
587
- // then say where it came from -- otherwise the node arrives as
588
- // an element of a list the body wrote, and the only address
589
- // left is where that list came to rest.
590
419
  const naddr = nodeAddr(selAddr, member.key, node)
591
420
  if ('' !== naddr && null == (node as any).origin) {
592
421
  ; (node as any).origin = naddr
@@ -643,14 +472,6 @@ class EmitFuncVal extends FuncBaseVal {
643
472
  }
644
473
 
645
474
 
646
- // The replacement pairs for one node: the template's `replace` map
647
- // instantiated at the node -- bound, filled and driven as a body is
648
- // -- each value as text by the one number-to-text rule (`plusText`,
649
- // the rule `+` and `join` share), escaped by the template's
650
- // convention unless that is `none`, and sorted longest key first so
651
- // the scan takes the longest match at every position (D3's first
652
- // rule). A value that is not text, or has not settled, is
653
- // replace_value.
654
475
  replacements(ctx: AontuContext, node: Val, tmpl: Template, fail: Fail): Pair[] | undefined {
655
476
  if (undefined === tmpl.replace) {
656
477
  return undefined
@@ -676,13 +497,6 @@ class EmitFuncVal extends FuncBaseVal {
676
497
  }
677
498
 
678
499
 
679
- // Instantiate one body at the node and SPLICE its pieces into the
680
- // output. A full instance to the leaves (`dup`, ADR-005), because a
681
- // bare clone shares the inner structure of any call in the body and
682
- // the first node's resolution would answer for every node; the
683
- // template's replacements written into the instance's literal text;
684
- // then the two bindings, relative references and the hole, both to
685
- // the node.
686
500
  instantiate(ctx: AontuContext, node: Val, tmpl: Template,
687
501
  out: Val[], fail: Fail, mark?: EmitOrigin): void {
688
502
  const pairs = this.replacements(ctx, node, tmpl, fail)
@@ -700,24 +514,10 @@ class EmitFuncVal extends FuncBaseVal {
700
514
  }
701
515
  let piece = fillPlace(bindNode(inst, node, elctx, fail), node, elctx)
702
516
 
703
- // A NESTED DISPATCH IS DRIVEN HERE, not left for the next pass.
704
- // Its selection is bound and the model has settled, so it has
705
- // everything it needs -- and it must answer NOW, because what
706
- // makes the result flat is splicing its pieces into this one.
707
- // Left standing, a nested `emit` resolved a pass later, as a
708
- // list INSIDE the list, and the fragment algebra is flat.
709
- // Through `unite` rather than by hand: a rule set that walks
710
- // into itself for ever is charged to the depth budget and
711
- // refused as `unify_cycle`, like any other runaway descent.
712
517
  if (!piece.done) {
713
518
  piece = unite(elctx, piece, top(), 'emit')
714
519
  }
715
520
 
716
- // THE INNERMOST DISPATCH OWNS THE PIECE (P7). A body element
717
- // that is a nested rule set has already stamped what it emitted,
718
- // and those pieces are spliced into this result here: the rule
719
- // that WROTE a line is the one the trace names, so a stamp is
720
- // written only where there is none.
721
521
  const at = out.length
722
522
  splice(piece, out)
723
523
  if (undefined !== mark) {
@@ -34,22 +34,6 @@ class ExpectVal extends FeatureVal {
34
34
  parent?: Val
35
35
  key?: string
36
36
 
37
- // An expectation canons as THE EXPECTATION ITSELF -- the peg the peer
38
- // must satisfy. Val.canon's default was the empty string, which
39
- // rendered a key with no value (`{"r":}`): text that is not a document
40
- // and could not be reparsed, breaking canon's round-trip contract in
41
- // both engines (issue #43).
42
- //
43
- // Not `top`, which was the first fix here and was wrong. An ExpectVal
44
- // is created for EVERY peer-introduced non-generable key, not just for
45
- // `&:` spread children -- `m:{x:1} m:{y:string}` makes one at `y` with
46
- // no spread in sight -- so rendering `top` erased the `string` and the
47
- // canon reparsed into a document that accepts values the original
48
- // rejects. A canon that silently drops a constraint is worse than one
49
- // that fails to parse. Go's ExpectVal.Canon renders the same peg.
50
- //
51
- // Which is why `peg` is kept the WHOLE expectation as peers arrive
52
- // (BUGS.md §48) rather than only what was first written: see unify.
53
37
  get canon() { return this.peg.canon }
54
38
 
55
39
  constructor(
@@ -59,41 +43,15 @@ class ExpectVal extends FeatureVal {
59
43
  super(spec, ctx)
60
44
  }
61
45
 
62
- // PURE, deliberately (the unequal-spread crosswire, BUGS.md §6-§7).
63
- // The old body accumulated `this.peer` IN PLACE, which was invisible
64
- // while an expectation only ever lived at one destination -- but the
65
- // spread-combination meet (MapVal.unify's 'map-self' unite) bakes an
66
- // ExpectVal INTO the combined template, and a path-independent
67
- // template is SHARED across every destination (spreadClone tier 1).
68
- // One stateful node in a shared template unified each sibling's own
69
- // data with the next sibling's ($.w.y.r: "Cannot unify value: 6 with
70
- // value: 5", both values sibling data). An expectation now answers
71
- // with a NEW node when it must keep accumulated state, so a shared
72
- // template's expect stays exactly what was written.
73
46
  unify(peer: Val, ctx: AontuContext): Val {
74
47
  const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Expect', this, peer)
75
48
 
76
49
  let out: Val = this
77
50
 
78
51
  if (!peer.isTop) {
79
- // THE PEER MEETS THE WHOLE EXPECTATION. `peg` already carries
80
- // every peer met so far (see below), so meeting the incoming peer
81
- // against the ACCUMULATED `peer` first -- as this did -- refused
82
- // against only the atom that happened to reject. A conflict with
83
- // `peg` is a conflict with the accumulation too, since peg
84
- // subsumes it, so nothing stops being refused: only the sentence
85
- // changes, to the residual the error's own hint promises
86
- // (BUGS.md §48).
87
52
  const peeru =
88
53
  unite(te ? ctx.clone({ explain: ec(te, 'EXPECT') }) : ctx, peer, this.peg, 'expect-self')
89
54
 
90
- // Accumulated for the `expect` finding's operand. Computed BEFORE
91
- // the escape below, where it has always been: an expectation that
92
- // escapes still passed through here, and moving it after the
93
- // escape leaves the accumulating arm reachable only by a node
94
- // that both carries an accumulation AND fails to escape -- which
95
- // the suite never produces, so it reads as dead code against the
96
- // ADR-002 gate. Go's ExpectVal.Unify keeps the same order.
97
55
  const acc = undefined === this.peer ? peer :
98
56
  unite(te ? ctx.clone({ explain: ec(te, 'PEER') }) : ctx, this.peer, peer, 'expect-peer')
99
57
 
@@ -101,26 +59,6 @@ class ExpectVal extends FeatureVal {
101
59
  out = peeru
102
60
  }
103
61
  else {
104
- // Still an expectation: carry the accumulated peer forward in a
105
- // fresh node stored at THIS destination by the caller, leaving
106
- // `this` -- possibly a shared template's child -- untouched.
107
- //
108
- // THE MEET IS THE NEW PEG (BUGS.md §48). An expectation that
109
- // has met a peer without being freed by it stands for `peg &
110
- // peer` from then on -- that is what a later peer must satisfy,
111
- // and what canon has to state. Rebuilding from the ORIGINAL peg
112
- // dropped the peer everywhere the node was later copied (the
113
- // bag re-wrap, Val.clone), so `b:{z:1} b:{u8:min(0)}
114
- // a:$.b.u8&max(15)` -- whose reference resolves a pass late, so
115
- // `max(15)` arrives as a peer -- canoned as `min(0)`. That text
116
- // reparses into a document admitting 20, which the original
117
- // rejects, and hashed differently in each port. Storing the
118
- // meet in `peg` needs no new field and no carrying: every copy
119
- // site already preserves `peg`.
120
- //
121
- // Purity is untouched -- this is a NEW node, so a shared
122
- // template's own expectation keeps the peg it was written with
123
- // (§6-§7).
124
62
  const e = new ExpectVal({ peg: peeru }, ctx)
125
63
  e.key = this.key
126
64
  e.parent = this.parent
@@ -1,35 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
2
 
3
- // GENERATION: `filter(data, cond)` (G8 phase 2,
4
- // docs/capability-review/g8-generation.md). The children of `data`
5
- // that unify with `cond`, keys preserved for a map and order for a
6
- // list; the children that do not are DROPPED, not refused.
7
- //
8
- // debugged: filter($.services, {debug: true})
9
- // sidecars: pack($.debugged, {image: "acme/debug:1.0"})
10
- //
11
- // A CHILD IS KEPT WHEN THE CONDITION CHANGES NOTHING: the meet
12
- // succeeds AND its answer is the child itself, which is to say the
13
- // child ALREADY satisfies the condition. Mere unifiability is not the
14
- // test, and cannot be: a map is open, so `{p:2}` unifies with
15
- // `{debug:true}` perfectly well by GAINING the key -- and a filter
16
- // that keeps everything that could be made to match keeps everything.
17
- // The design named unifiability; its own example
18
- // (`filter($.services, {debug:true})`) is unsatisfiable under it.
19
- //
20
- // There is no predicate language here and there will not be one:
21
- // `cond` is an ordinary Aontu value, so the constraint atoms compose
22
- // with it for free (`filter($.deploy, {replicas: min(3)})`), and a
23
- // document that can filter can be read by anything that can read a
24
- // document.
25
- //
26
- // A FAILED CHILD IS AN ANSWER, not an error. The meet runs in TRIAL
27
- // MODE -- the mechanism disjunction already uses to try each member
28
- // against a peer (trialUnify in FuncBaseVal) -- so a child that does
29
- // not match costs nothing and reports nothing.
30
- //
31
- // TOTALITY. `filter` iterates a finite, settled bag and cannot call
32
- // itself, exactly as `pack` and `each` cannot.
33
3
 
34
4
  import type {
35
5
  Val,
@@ -72,15 +42,6 @@ class FilterFuncVal extends FuncBaseVal {
72
42
  }
73
43
 
74
44
 
75
- // Neither argument is driven by the base: `unify` below drives the
76
- // DATA by hand, because a staged func must advance the argument it
77
- // is waiting on every pass rather than only on the one it fires.
78
- //
79
- // The CONDITION is not driven at all, and that is deliberate: it is
80
- // a template, tested against each child at that child's position,
81
- // so it may hold a `_` (G8 phase 3, the child it is being tested
82
- // against) or a relative reference — neither of which has an answer
83
- // at the call site. Driving it there would freeze both.
84
45
  prepare(_ctx: AontuContext, _args: Val[]) {
85
46
  return null
86
47
  }
@@ -99,19 +60,7 @@ class FilterFuncVal extends FuncBaseVal {
99
60
  const data: any = args[0]
100
61
  const cond: Val = args[1]
101
62
 
102
- // The trial is run against CLONES: `unite` refines a bag in place,
103
- // and a child that failed the test must reach the result -- when
104
- // it passes -- exactly as it was written.
105
- //
106
- // Canon is the comparison because canon is what "the same value"
107
- // MEANS in this language: it is the form the two ports agree on,
108
- // the form `aontu diff` compares, and the form a hash is taken of.
109
63
  const keeps = (child: Val, kctx: AontuContext): boolean => {
110
- // `_` inside the condition binds the child being tested (G8
111
- // phase 3), so a condition can be about the child as a whole
112
- // rather than only about its shape. The condition is cloned as
113
- // a FULL instance per trial (`dup`, ADR-005) — a bare clone
114
- // shares call/pref innards across trials (see PackFuncVal).
115
64
  const inst = cond.clone(kctx, { dup: true })
116
65
  repathInstance(inst, inst.path)
117
66
  const test = fillPlace(inst, child, kctx)
@@ -136,10 +85,6 @@ class FilterFuncVal extends FuncBaseVal {
136
85
  if (true === data?.isList) {
137
86
  const peg: Val[] = []
138
87
  for (const { val: el } of bagMembers(data, ctx) as Member[]) {
139
- // The element context is the position it will END UP at, which
140
- // is its index in the RESULT: dropping the third of five moves
141
- // the fourth up, and a kept element must be pathed where it
142
- // lands rather than where it came from.
143
88
  const ectx = ctx.descend(String(peg.length))
144
89
  if (keeps(el, ectx)) {
145
90
  peg.push(el.clone(ectx))