aontu 0.52.1 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/README.md +88 -0
  2. package/bin/aontu-mcp.js +4 -0
  3. package/dist/agentsmd.d.ts +16 -0
  4. package/dist/agentsmd.js +107 -0
  5. package/dist/agentsmd.js.map +1 -0
  6. package/dist/aontu.d.ts +15 -3
  7. package/dist/aontu.js +126 -5
  8. package/dist/aontu.js.map +1 -1
  9. package/dist/cli.d.ts +45 -1
  10. package/dist/cli.js +2845 -69
  11. package/dist/cli.js.map +1 -1
  12. package/dist/ctx.d.ts +18 -0
  13. package/dist/ctx.js +44 -0
  14. package/dist/ctx.js.map +1 -1
  15. package/dist/diff.d.ts +22 -0
  16. package/dist/diff.js +141 -0
  17. package/dist/diff.js.map +1 -0
  18. package/dist/err.d.ts +3 -1
  19. package/dist/err.js +45 -8
  20. package/dist/err.js.map +1 -1
  21. package/dist/graph.d.ts +13 -0
  22. package/dist/graph.js +110 -0
  23. package/dist/graph.js.map +1 -0
  24. package/dist/hcanon.d.ts +3 -0
  25. package/dist/hcanon.js +145 -0
  26. package/dist/hcanon.js.map +1 -0
  27. package/dist/hints.js +235 -8
  28. package/dist/hints.js.map +1 -1
  29. package/dist/jsonschema.d.ts +20 -0
  30. package/dist/jsonschema.js +425 -0
  31. package/dist/jsonschema.js.map +1 -0
  32. package/dist/lang.js +955 -110
  33. package/dist/lang.js.map +1 -1
  34. package/dist/lsp.d.ts +9 -2
  35. package/dist/lsp.js +343 -48
  36. package/dist/lsp.js.map +1 -1
  37. package/dist/mcp-server.d.ts +20 -0
  38. package/dist/mcp-server.js +147 -0
  39. package/dist/mcp-server.js.map +1 -0
  40. package/dist/mcp.d.ts +42 -0
  41. package/dist/mcp.js +941 -0
  42. package/dist/mcp.js.map +1 -0
  43. package/dist/mod-tool.d.ts +58 -0
  44. package/dist/mod-tool.js +532 -0
  45. package/dist/mod-tool.js.map +1 -0
  46. package/dist/mod.d.ts +35 -0
  47. package/dist/mod.js +345 -0
  48. package/dist/mod.js.map +1 -0
  49. package/dist/patch.d.ts +49 -0
  50. package/dist/patch.js +506 -0
  51. package/dist/patch.js.map +1 -0
  52. package/dist/provenance.d.ts +41 -0
  53. package/dist/provenance.js +336 -0
  54. package/dist/provenance.js.map +1 -0
  55. package/dist/query.d.ts +27 -0
  56. package/dist/query.js +294 -0
  57. package/dist/query.js.map +1 -0
  58. package/dist/reach.d.ts +15 -0
  59. package/dist/reach.js +168 -0
  60. package/dist/reach.js.map +1 -0
  61. package/dist/relation.d.ts +23 -0
  62. package/dist/relation.js +230 -0
  63. package/dist/relation.js.map +1 -0
  64. package/dist/report-sarif.d.ts +14 -0
  65. package/dist/report-sarif.js +102 -0
  66. package/dist/report-sarif.js.map +1 -0
  67. package/dist/sig.d.ts +25 -0
  68. package/dist/sig.js +277 -0
  69. package/dist/sig.js.map +1 -0
  70. package/dist/sigdecl.d.ts +2 -0
  71. package/dist/sigdecl.js +11 -0
  72. package/dist/sigdecl.js.map +1 -0
  73. package/dist/siggate.d.ts +4 -0
  74. package/dist/siggate.js +90 -0
  75. package/dist/siggate.js.map +1 -0
  76. package/dist/site.d.ts +4 -0
  77. package/dist/site.js +31 -0
  78. package/dist/site.js.map +1 -1
  79. package/dist/std.d.ts +1 -0
  80. package/dist/std.js +129 -0
  81. package/dist/std.js.map +1 -0
  82. package/dist/subsume.d.ts +39 -0
  83. package/dist/subsume.js +573 -0
  84. package/dist/subsume.js.map +1 -0
  85. package/dist/trim.d.ts +19 -0
  86. package/dist/trim.js +155 -0
  87. package/dist/trim.js.map +1 -0
  88. package/dist/tsconfig.tsbuildinfo +1 -1
  89. package/dist/type.d.ts +17 -1
  90. package/dist/type.js.map +1 -1
  91. package/dist/unify.d.ts +2 -1
  92. package/dist/unify.js +234 -38
  93. package/dist/unify.js.map +1 -1
  94. package/dist/utility.d.ts +8 -1
  95. package/dist/utility.js +68 -1
  96. package/dist/utility.js.map +1 -1
  97. package/dist/val/AggFuncVal.d.ts +44 -0
  98. package/dist/val/AggFuncVal.js +364 -0
  99. package/dist/val/AggFuncVal.js.map +1 -0
  100. package/dist/val/ArithFuncVal.d.ts +31 -0
  101. package/dist/val/ArithFuncVal.js +62 -0
  102. package/dist/val/ArithFuncVal.js.map +1 -0
  103. package/dist/val/BagVal.d.ts +7 -0
  104. package/dist/val/BagVal.js +150 -11
  105. package/dist/val/BagVal.js.map +1 -1
  106. package/dist/val/CloseFuncVal.js +9 -1
  107. package/dist/val/CloseFuncVal.js.map +1 -1
  108. package/dist/val/ConjunctVal.d.ts +1 -1
  109. package/dist/val/ConjunctVal.js +19 -0
  110. package/dist/val/ConjunctVal.js.map +1 -1
  111. package/dist/val/ConstraintVal.d.ts +7 -1
  112. package/dist/val/ConstraintVal.js +523 -45
  113. package/dist/val/ConstraintVal.js.map +1 -1
  114. package/dist/val/ContainerKindVal.d.ts +35 -0
  115. package/dist/val/ContainerKindVal.js +99 -0
  116. package/dist/val/ContainerKindVal.js.map +1 -0
  117. package/dist/val/CopyFuncVal.d.ts +1 -2
  118. package/dist/val/CopyFuncVal.js.map +1 -1
  119. package/dist/val/Decimal.d.ts +1 -0
  120. package/dist/val/Decimal.js +13 -0
  121. package/dist/val/Decimal.js.map +1 -1
  122. package/dist/val/DeprecateFuncVal.d.ts +11 -0
  123. package/dist/val/DeprecateFuncVal.js +47 -0
  124. package/dist/val/DeprecateFuncVal.js.map +1 -0
  125. package/dist/val/DisjunctVal.d.ts +1 -2
  126. package/dist/val/DisjunctVal.js +269 -53
  127. package/dist/val/DisjunctVal.js.map +1 -1
  128. package/dist/val/EachFuncVal.d.ts +15 -0
  129. package/dist/val/EachFuncVal.js +75 -0
  130. package/dist/val/EachFuncVal.js.map +1 -0
  131. package/dist/val/ExpectVal.js +62 -4
  132. package/dist/val/ExpectVal.js.map +1 -1
  133. package/dist/val/FeatureVal.js +1 -1
  134. package/dist/val/FeatureVal.js.map +1 -1
  135. package/dist/val/FilterFuncVal.d.ts +15 -0
  136. package/dist/val/FilterFuncVal.js +91 -0
  137. package/dist/val/FilterFuncVal.js.map +1 -0
  138. package/dist/val/FuncBaseVal.d.ts +7 -1
  139. package/dist/val/FuncBaseVal.js +183 -2
  140. package/dist/val/FuncBaseVal.js.map +1 -1
  141. package/dist/val/GraphAtomVal.d.ts +39 -0
  142. package/dist/val/GraphAtomVal.js +184 -0
  143. package/dist/val/GraphAtomVal.js.map +1 -0
  144. package/dist/val/HideFuncVal.js.map +1 -1
  145. package/dist/val/JunctionVal.js +24 -1
  146. package/dist/val/JunctionVal.js.map +1 -1
  147. package/dist/val/KeyFuncVal.d.ts +1 -1
  148. package/dist/val/KeyFuncVal.js +38 -30
  149. package/dist/val/KeyFuncVal.js.map +1 -1
  150. package/dist/val/ListVal.js +94 -14
  151. package/dist/val/ListVal.js.map +1 -1
  152. package/dist/val/LowerFuncVal.js.map +1 -1
  153. package/dist/val/MapVal.d.ts +1 -0
  154. package/dist/val/MapVal.js +146 -14
  155. package/dist/val/MapVal.js.map +1 -1
  156. package/dist/val/MatchFuncVal.d.ts +15 -0
  157. package/dist/val/MatchFuncVal.js +107 -0
  158. package/dist/val/MatchFuncVal.js.map +1 -0
  159. package/dist/val/MoveFuncVal.js.map +1 -1
  160. package/dist/val/NilVal.js +24 -0
  161. package/dist/val/NilVal.js.map +1 -1
  162. package/dist/val/OpBaseVal.d.ts +1 -1
  163. package/dist/val/OpBaseVal.js +19 -1
  164. package/dist/val/OpBaseVal.js.map +1 -1
  165. package/dist/val/OpenFuncVal.js +4 -1
  166. package/dist/val/OpenFuncVal.js.map +1 -1
  167. package/dist/val/PackFuncVal.d.ts +15 -0
  168. package/dist/val/PackFuncVal.js +108 -0
  169. package/dist/val/PackFuncVal.js.map +1 -0
  170. package/dist/val/PathFuncVal.d.ts +2 -2
  171. package/dist/val/PathFuncVal.js +75 -16
  172. package/dist/val/PathFuncVal.js.map +1 -1
  173. package/dist/val/PathVal.d.ts +25 -0
  174. package/dist/val/PathVal.js +150 -0
  175. package/dist/val/PathVal.js.map +1 -0
  176. package/dist/val/PlaceVal.d.ts +13 -0
  177. package/dist/val/PlaceVal.js +131 -0
  178. package/dist/val/PlaceVal.js.map +1 -0
  179. package/dist/val/PlusOpVal.d.ts +2 -1
  180. package/dist/val/PlusOpVal.js +61 -37
  181. package/dist/val/PlusOpVal.js.map +1 -1
  182. package/dist/val/PrefFuncVal.js.map +1 -1
  183. package/dist/val/PrefVal.d.ts +4 -2
  184. package/dist/val/PrefVal.js +223 -41
  185. package/dist/val/PrefVal.js.map +1 -1
  186. package/dist/val/RecurseVal.d.ts +19 -0
  187. package/dist/val/RecurseVal.js +217 -0
  188. package/dist/val/RecurseVal.js.map +1 -0
  189. package/dist/val/RefVal.d.ts +3 -2
  190. package/dist/val/RefVal.js +181 -66
  191. package/dist/val/RefVal.js.map +1 -1
  192. package/dist/val/ReferFuncVal.d.ts +59 -0
  193. package/dist/val/ReferFuncVal.js +604 -0
  194. package/dist/val/ReferFuncVal.js.map +1 -0
  195. package/dist/val/ScalarKindVal.d.ts +4 -3
  196. package/dist/val/ScalarKindVal.js +12 -12
  197. package/dist/val/ScalarKindVal.js.map +1 -1
  198. package/dist/val/SuperFuncVal.d.ts +4 -2
  199. package/dist/val/SuperFuncVal.js +118 -14
  200. package/dist/val/SuperFuncVal.js.map +1 -1
  201. package/dist/val/TopVal.d.ts +1 -1
  202. package/dist/val/TopVal.js.map +1 -1
  203. package/dist/val/TypeFuncVal.js.map +1 -1
  204. package/dist/val/UpperFuncVal.js.map +1 -1
  205. package/dist/val/Val.d.ts +7 -1
  206. package/dist/val/Val.js +170 -2
  207. package/dist/val/Val.js.map +1 -1
  208. package/dist/val/VarVal.js.map +1 -1
  209. package/dist/val/arith.d.ts +6 -0
  210. package/dist/val/arith.js +173 -0
  211. package/dist/val/arith.js.map +1 -0
  212. package/dist/vet.d.ts +45 -0
  213. package/dist/vet.js +802 -0
  214. package/dist/vet.js.map +1 -0
  215. package/dist/view.d.ts +85 -0
  216. package/dist/view.js +1948 -0
  217. package/dist/view.js.map +1 -0
  218. package/dist/walk.d.ts +2 -0
  219. package/dist/walk.js +91 -0
  220. package/dist/walk.js.map +1 -0
  221. package/grammar/aontu.gbnf +138 -0
  222. package/grammar/aontu.lark +118 -0
  223. package/grammar/aontu.tmLanguage.json +184 -0
  224. package/package.json +30 -8
  225. package/skill/SKILL.md +37 -0
  226. package/skill/error-codes.md +62 -0
  227. package/skill/examples.md +99 -0
  228. package/skill/grammar-card.md +56 -0
  229. package/src/agentsmd.ts +135 -0
  230. package/src/aontu.ts +166 -5
  231. package/src/cli.ts +3324 -72
  232. package/src/ctx.ts +93 -1
  233. package/src/diff.ts +198 -0
  234. package/src/err.ts +50 -8
  235. package/src/graph.ts +185 -0
  236. package/src/hcanon.ts +167 -0
  237. package/src/hints.ts +291 -8
  238. package/src/jsonschema.ts +552 -0
  239. package/src/lang.ts +1049 -110
  240. package/src/lsp.ts +351 -49
  241. package/src/mcp-server.ts +187 -0
  242. package/src/mcp.ts +1130 -0
  243. package/src/mod-tool.ts +718 -0
  244. package/src/mod.ts +453 -0
  245. package/src/patch.ts +628 -0
  246. package/src/provenance.ts +437 -0
  247. package/src/query.ts +381 -0
  248. package/src/reach.ts +213 -0
  249. package/src/relation.ts +298 -0
  250. package/src/report-sarif.ts +137 -0
  251. package/src/sig.ts +345 -0
  252. package/src/sigdecl.ts +11 -0
  253. package/src/siggate.ts +144 -0
  254. package/src/site.ts +36 -1
  255. package/src/std.ts +131 -0
  256. package/src/subsume.ts +739 -0
  257. package/src/trim.ts +195 -0
  258. package/src/tsconfig.json +10 -4
  259. package/src/type.ts +51 -2
  260. package/src/unify.ts +253 -38
  261. package/src/utility.ts +79 -1
  262. package/src/val/AggFuncVal.ts +546 -0
  263. package/src/val/ArithFuncVal.ts +108 -0
  264. package/src/val/BagVal.ts +158 -12
  265. package/src/val/CloseFuncVal.ts +9 -1
  266. package/src/val/ConjunctVal.ts +20 -0
  267. package/src/val/ConstraintVal.ts +576 -48
  268. package/src/val/ContainerKindVal.ts +158 -0
  269. package/src/val/CopyFuncVal.ts +0 -1
  270. package/src/val/Decimal.ts +15 -0
  271. package/src/val/DeprecateFuncVal.ts +84 -0
  272. package/src/val/DisjunctVal.ts +282 -59
  273. package/src/val/EachFuncVal.ts +133 -0
  274. package/src/val/ExpectVal.ts +65 -8
  275. package/src/val/FeatureVal.ts +1 -1
  276. package/src/val/FilterFuncVal.ts +154 -0
  277. package/src/val/FuncBaseVal.ts +206 -2
  278. package/src/val/GraphAtomVal.ts +264 -0
  279. package/src/val/HideFuncVal.ts +0 -2
  280. package/src/val/JunctionVal.ts +24 -1
  281. package/src/val/KeyFuncVal.ts +39 -35
  282. package/src/val/ListVal.ts +101 -15
  283. package/src/val/LowerFuncVal.ts +0 -1
  284. package/src/val/MapVal.ts +153 -14
  285. package/src/val/MatchFuncVal.ts +176 -0
  286. package/src/val/MoveFuncVal.ts +0 -2
  287. package/src/val/NilVal.ts +25 -0
  288. package/src/val/OpBaseVal.ts +20 -1
  289. package/src/val/OpenFuncVal.ts +4 -2
  290. package/src/val/PackFuncVal.ts +175 -0
  291. package/src/val/PathFuncVal.ts +107 -20
  292. package/src/val/PathVal.ts +221 -0
  293. package/src/val/PlaceVal.ts +193 -0
  294. package/src/val/PlusOpVal.ts +67 -39
  295. package/src/val/PrefFuncVal.ts +0 -1
  296. package/src/val/PrefVal.ts +251 -60
  297. package/src/val/RecurseVal.ts +285 -0
  298. package/src/val/RefVal.ts +183 -78
  299. package/src/val/ReferFuncVal.ts +732 -0
  300. package/src/val/ScalarKindVal.ts +12 -13
  301. package/src/val/SuperFuncVal.ts +137 -13
  302. package/src/val/TopVal.ts +1 -2
  303. package/src/val/TypeFuncVal.ts +0 -2
  304. package/src/val/UpperFuncVal.ts +0 -1
  305. package/src/val/Val.ts +216 -4
  306. package/src/val/VarVal.ts +0 -1
  307. package/src/val/arith.ts +319 -0
  308. package/src/vet.ts +1025 -0
  309. package/src/view.ts +2563 -0
  310. package/src/walk.ts +99 -0
@@ -0,0 +1,193 @@
1
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+
3
+ // THE PLACEHOLDER `_` (G8 phase 3,
4
+ // docs/capability-review/g8-generation.md): a HOLE in a call, filled
5
+ // by whatever the call is unified with.
6
+ //
7
+ // x: {&: {m: _ + 2}} x: a: m: 1 -> a: m: 3
8
+ // greeting: upper(_) & hello -> "HELLO"
9
+ //
10
+ // WHY A HOLE AND NOT A FUNCTION PARAMETER. Aontu has no user-defined
11
+ // functions and will not get them (G8's Boundary): a function value
12
+ // crossing into the data plane is the step that makes a configuration
13
+ // language a programming language. A hole is not a parameter -- it
14
+ // cannot be named, passed, or partially applied. It says only "the
15
+ // value that arrives here", which is what a template needs to compute
16
+ // from the value it lands on.
17
+ //
18
+ // ALONE, `_` IS TOP WITH A MARK: it admits everything and is filled by
19
+ // its peer, exactly as TOP is dropped by one. What makes it different
20
+ // is that a CALL can see it, and a call that holds one waits for a
21
+ // peer to fill it instead of resolving around it. Unfilled at
22
+ // generation it is an error, as TOP is -- a hole is not a value.
23
+
24
+ import type {
25
+ Val,
26
+ ValSpec,
27
+ } from '../type'
28
+
29
+ import {
30
+ AontuContext,
31
+ } from '../ctx'
32
+
33
+ import { Val as ValBase } from './Val'
34
+
35
+
36
+ class PlaceVal extends ValBase {
37
+ isPlace = true
38
+
39
+ constructor(
40
+ spec: ValSpec,
41
+ ctx?: AontuContext
42
+ ) {
43
+ super(spec, ctx)
44
+ }
45
+
46
+
47
+ unify(peer: Val, _ctx: AontuContext): Val {
48
+ // The peer FILLS the hole. Against TOP there is nothing to fill it
49
+ // with, so it waits -- and waiting is not done, or a call holding
50
+ // it would resolve around it.
51
+ if (peer.isTop) {
52
+ this.notdone()
53
+ return this
54
+ }
55
+
56
+ return peer
57
+ }
58
+
59
+
60
+ get canon() {
61
+ return '_'
62
+ }
63
+
64
+
65
+ // A hole admits everything, so nothing sits above it -- the same
66
+ // answer TOP gives, for the same reason.
67
+ superior(): Val {
68
+ return this
69
+ }
70
+
71
+
72
+ }
73
+
74
+
75
+ // A HOLE BELONGS TO ITS NEAREST ENCLOSING GENERATOR. A `_` inside a
76
+ // generator's template (pack/each, arg 1) or condition (filter, arg 1)
77
+ // is that generator's to bind — "_ is the source child" — so neither
78
+ // the hole test nor the fill walk may cross into those arguments from
79
+ // outside. Before this boundary, `close(pack(d, _ & t))` reported a
80
+ // hole to the OUTER call, so an ordinary overlay statement was
81
+ // absorbed into the template instead of merging with the generated
82
+ // child (use-cases/BUGS.md §10), and an outer pack's fill pass
83
+ // captured a NESTED pack's hole lexically, binding it to the outer
84
+ // source (§34). The data argument (arg 0) is not a binding position,
85
+ // so it stays visible: a hole there is an outer hole as before.
86
+ function boundArgStart(v: any): number {
87
+ return true === v.isPackFunc || true === v.isEachFunc ||
88
+ true === v.isFilterFunc ? 1 : Infinity
89
+ }
90
+
91
+
92
+ // Does this value CONTAIN a hole? Asked of a call before it resolves:
93
+ // a call holding one must wait for a peer to fill it. Holes inside a
94
+ // generator's own binding arguments are NOT this value's holes — see
95
+ // boundArgStart above.
96
+ function hasPlace(v: Val): boolean {
97
+ if (true === (v as any).isPlace) {
98
+ return true
99
+ }
100
+
101
+ const peg: any = (v as any).peg
102
+ const bound = boundArgStart(v)
103
+
104
+ if (Array.isArray(peg)) {
105
+ for (let cI = 0; cI < peg.length && cI < bound; cI++) {
106
+ const c = peg[cI]
107
+ if (true === c?.isVal && hasPlace(c)) {
108
+ return true
109
+ }
110
+ }
111
+ }
112
+ else if (true === peg?.isVal) {
113
+ return hasPlace(peg)
114
+ }
115
+ else if (null != peg && 'object' === typeof peg) {
116
+ for (const k of Object.keys(peg)) {
117
+ if (true === peg[k]?.isVal && hasPlace(peg[k])) {
118
+ return true
119
+ }
120
+ }
121
+ }
122
+
123
+ return false
124
+ }
125
+
126
+
127
+ // The same tree with every hole filled by `fill`. Answers the value
128
+ // UNCHANGED when it holds no hole, so a caller can test identity to
129
+ // know whether anything was filled -- and so a tree with no hole is
130
+ // never needlessly cloned. A nested generator's binding arguments are
131
+ // left untouched (boundArgStart): those holes are the inner
132
+ // generator's to fill with its OWN source children when it fires.
133
+ function fillPlace(v: Val, fill: Val, ctx: AontuContext): Val {
134
+ if (true === (v as any).isPlace) {
135
+ return fill
136
+ }
137
+
138
+ const peg: any = (v as any).peg
139
+ const bound = boundArgStart(v)
140
+
141
+ if (Array.isArray(peg)) {
142
+ let changed = false
143
+ const out = peg.map((c: any, cI: number) => {
144
+ if (true !== c?.isVal || bound <= cI) {
145
+ return c
146
+ }
147
+ const f = fillPlace(c, fill, ctx)
148
+ changed = changed || f !== c
149
+ return f
150
+ })
151
+ return changed ? rebuild(v, out, ctx) : v
152
+ }
153
+
154
+ if (true === peg?.isVal) {
155
+ const f = fillPlace(peg, fill, ctx)
156
+ return f === peg ? v : rebuild(v, f, ctx)
157
+ }
158
+
159
+ if (null != peg && 'object' === typeof peg) {
160
+ let changed = false
161
+ const out: Record<string, Val> = {}
162
+ for (const k of Object.keys(peg)) {
163
+ const c = peg[k]
164
+ // No isVal guard: a slot holding something that is not a Val
165
+ // answers itself, because fillPlace's own first tests -- is it a
166
+ // hole, has it a peg -- are both false for one.
167
+ const f = fillPlace(c, fill, ctx)
168
+ changed = changed || f !== c
169
+ out[k] = f
170
+ }
171
+ return changed ? rebuild(v, out, ctx) : v
172
+ }
173
+
174
+ return v
175
+ }
176
+
177
+
178
+ // A clone carrying a new peg. `clone` shares the peg by reference (see
179
+ // Val.clone), which is exactly what must NOT happen here: the tree
180
+ // being filled is a template, and the fill is one destination's.
181
+ function rebuild(v: Val, peg: any, ctx: AontuContext): Val {
182
+ const out: any = v.clone(ctx)
183
+ out.peg = peg
184
+ out.dc = 0
185
+ return out
186
+ } /* node:coverage ignore next 8 */
187
+
188
+
189
+ export {
190
+ hasPlace,
191
+ fillPlace,
192
+ PlaceVal,
193
+ }
@@ -59,6 +59,61 @@ function isBig(k: OpKind): boolean {
59
59
  }
60
60
 
61
61
 
62
+ // Only concrete scalar operands are valid: anything else (kinds, maps,
63
+ // lists, null, top, funcs) must not coerce — the JS `+` would leak
64
+ // internals like "[object Object]" into output. A non-scalar operand
65
+ // leaves the op unresolved, which generate() reports.
66
+ //
67
+ // A pref operand contributes its preferred value (`pref(1)+2`), and
68
+ // therefore that value's kind too.
69
+ function operand(v: any) {
70
+ while (v?.isPref) {
71
+ v = v.peg
72
+ }
73
+ return v
74
+ }
75
+
76
+
77
+ // The operand's LEAF, not the JavaScript type of its peg: integer and
78
+ // float share `number`, while the exact leaves are told apart from each
79
+ // other and from everything else by their own flags. The whole ladder in
80
+ // `operate` dispatches on this and never on `typeof`.
81
+ function opkind(v: any): OpKind | undefined {
82
+ if (!(v?.isVal && v.isScalar)) {
83
+ return undefined
84
+ }
85
+ if (v.isBigInteger) {
86
+ return 'biginteger'
87
+ }
88
+ if (v.isBigDecimal) {
89
+ return 'bigdecimal'
90
+ }
91
+ if (v.isInteger) {
92
+ return 'integer'
93
+ }
94
+ const t = typeof v.peg
95
+ return 'number' === t ? 'float' :
96
+ 'string' === t ? 'string' :
97
+ 'boolean' === t ? 'boolean' :
98
+ undefined
99
+ }
100
+
101
+
102
+ // THE TEXT `+` WOULD MAKE OF THIS OPERAND, or undefined if `+` would not
103
+ // take it at all.
104
+ //
105
+ // `join` folds with `+` seeded with `""`, so every member goes through
106
+ // concatenation's string branch — and this is the function that branch
107
+ // calls. Exported so that the fold and the operator cannot drift into
108
+ // two answers to "how does a number become text": there is one
109
+ // rendering, `digits` below, and both reach it here.
110
+ function plusText(v: Val): string | undefined {
111
+ const o: any = operand(v)
112
+ const k = opkind(o)
113
+ return undefined === k ? undefined : digits(o, k)
114
+ }
115
+
116
+
62
117
  class PlusOpVal extends OpBaseVal {
63
118
  isPlusOp = true
64
119
 
@@ -80,43 +135,6 @@ class PlusOpVal extends OpBaseVal {
80
135
 
81
136
 
82
137
  operate(ctx: AontuContext, args: Val[]) {
83
- // Only concrete scalar operands are valid: anything else (kinds,
84
- // maps, lists, null, top, funcs) must not coerce — the JS `+` would
85
- // leak internals like "[object Object]" into output. A non-scalar
86
- // operand leaves the op unresolved, which generate() reports.
87
- const operand = (v: any) => {
88
- // A pref operand contributes its preferred value (`pref(1)+2`),
89
- // and therefore that value's kind too.
90
- while (v?.isPref) {
91
- v = v.peg
92
- }
93
- return v
94
- }
95
-
96
- // The operand's LEAF, not the JavaScript type of its peg: integer
97
- // and float share `number`, while the exact leaves are told apart
98
- // from each other and from everything else by their own flags. The
99
- // whole ladder below dispatches on this and never on `typeof`.
100
- const opkind = (v: any): OpKind | undefined => {
101
- if (!(v?.isVal && v.isScalar)) {
102
- return undefined
103
- }
104
- if (v.isBigInteger) {
105
- return 'biginteger'
106
- }
107
- if (v.isBigDecimal) {
108
- return 'bigdecimal'
109
- }
110
- if (v.isInteger) {
111
- return 'integer'
112
- }
113
- const t = typeof v.peg
114
- return 'number' === t ? 'float' :
115
- 'string' === t ? 'string' :
116
- 'boolean' === t ? 'boolean' :
117
- undefined
118
- }
119
-
120
138
  const av: any = operand(args[0])
121
139
  const bv: any = operand(args[1])
122
140
  const ak = opkind(av)
@@ -157,9 +175,18 @@ class PlusOpVal extends OpBaseVal {
157
175
  }
158
176
 
159
177
  // Float with float or integer: unchanged R5 contagion, binary64
160
- // addition, float result (`1 + 2.0` is `3.0`).
178
+ // addition, float result (`1 + 2.0` is `3.0`) -- but a sum that
179
+ // leaves binary64's finite range is NOT a value. Aontu is a JSON
180
+ // superset and there is no notation for an infinity, so one here
181
+ // used to escape as `[aontu/internal]` in TypeScript and as Go's
182
+ // raw `json: unsupported value: +Inf` with no code at all
183
+ // (use-cases/BUGS.md 39). The same check governs the arithmetic
184
+ // family (float_overflow, ts/src/val/arith.ts).
161
185
  if ('float' === ak || 'float' === bk) {
162
- return new NumberVal({ peg: av.peg + bv.peg })
186
+ const sum = av.peg + bv.peg
187
+ return Number.isFinite(sum) ?
188
+ new NumberVal({ peg: sum }) :
189
+ makeNilErr(ctx, 'float_overflow', this, undefined, 'add')
163
190
  }
164
191
 
165
192
  // Both operands are on the exact ladder: promote to the widest.
@@ -242,4 +269,5 @@ function decimal(v: any, k: OpKind): Decimal {
242
269
 
243
270
  export {
244
271
  PlusOpVal,
272
+ plusText,
245
273
  }
@@ -16,7 +16,6 @@ import {
16
16
  walk
17
17
  } from '../utility'
18
18
 
19
- import { NilVal } from '../val/NilVal'
20
19
  import { PrefVal } from '../val/PrefVal'
21
20
  import { FuncBaseVal } from './FuncBaseVal'
22
21