aontu 0.30.1 → 0.30.2

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 (184) hide show
  1. package/dist/ctx.d.ts +51 -0
  2. package/dist/ctx.js +105 -0
  3. package/dist/ctx.js.map +1 -0
  4. package/dist/err.d.ts +12 -0
  5. package/dist/err.js +123 -0
  6. package/dist/err.js.map +1 -0
  7. package/dist/hints.d.ts +8 -0
  8. package/dist/hints.js +84 -0
  9. package/dist/hints.js.map +1 -0
  10. package/dist/lang.d.ts +11 -0
  11. package/dist/lang.js +569 -0
  12. package/dist/lang.js.map +1 -0
  13. package/dist/site.d.ts +12 -0
  14. package/dist/site.js +27 -0
  15. package/dist/site.js.map +1 -0
  16. package/dist/tsconfig.tsbuildinfo +1 -0
  17. package/dist/type.d.ts +32 -0
  18. package/dist/type.js +16 -0
  19. package/dist/type.js.map +1 -0
  20. package/dist/unify.d.ts +14 -0
  21. package/dist/unify.js +156 -0
  22. package/dist/unify.js.map +1 -0
  23. package/dist/utility.d.ts +14 -0
  24. package/dist/utility.js +122 -0
  25. package/dist/utility.js.map +1 -0
  26. package/dist/val/BagVal.d.ts +10 -0
  27. package/dist/val/BagVal.js +15 -0
  28. package/dist/val/BagVal.js.map +1 -0
  29. package/dist/val/BooleanVal.d.ts +9 -0
  30. package/dist/val/BooleanVal.js +16 -0
  31. package/dist/val/BooleanVal.js.map +1 -0
  32. package/dist/val/CloseFuncVal.d.ts +11 -0
  33. package/dist/val/CloseFuncVal.js +32 -0
  34. package/dist/val/CloseFuncVal.js.map +1 -0
  35. package/dist/val/ConjunctVal.d.ts +14 -0
  36. package/dist/val/ConjunctVal.js +187 -0
  37. package/dist/val/ConjunctVal.js.map +1 -0
  38. package/dist/val/CopyFuncVal.d.ts +13 -0
  39. package/dist/val/CopyFuncVal.js +35 -0
  40. package/dist/val/CopyFuncVal.js.map +1 -0
  41. package/dist/val/DisjunctVal.d.ts +19 -0
  42. package/dist/val/DisjunctVal.js +194 -0
  43. package/dist/val/DisjunctVal.js.map +1 -0
  44. package/dist/val/FeatureVal.d.ts +10 -0
  45. package/dist/val/FeatureVal.js +29 -0
  46. package/dist/val/FeatureVal.js.map +1 -0
  47. package/dist/val/FuncBaseVal.d.ts +15 -0
  48. package/dist/val/FuncBaseVal.js +127 -0
  49. package/dist/val/FuncBaseVal.js.map +1 -0
  50. package/dist/val/HideFuncVal.d.ts +12 -0
  51. package/dist/val/HideFuncVal.js +48 -0
  52. package/dist/val/HideFuncVal.js.map +1 -0
  53. package/dist/val/IntegerVal.d.ts +9 -0
  54. package/dist/val/IntegerVal.js +46 -0
  55. package/dist/val/IntegerVal.js.map +1 -0
  56. package/dist/val/JunctionVal.d.ts +12 -0
  57. package/dist/val/JunctionVal.js +31 -0
  58. package/dist/val/JunctionVal.js.map +1 -0
  59. package/dist/val/KeyFuncVal.d.ts +12 -0
  60. package/dist/val/KeyFuncVal.js +34 -0
  61. package/dist/val/KeyFuncVal.js.map +1 -0
  62. package/dist/val/ListVal.d.ts +17 -0
  63. package/dist/val/ListVal.js +186 -0
  64. package/dist/val/ListVal.js.map +1 -0
  65. package/dist/val/LowerFuncVal.d.ts +12 -0
  66. package/dist/val/LowerFuncVal.js +40 -0
  67. package/dist/val/LowerFuncVal.js.map +1 -0
  68. package/dist/val/MapVal.d.ts +16 -0
  69. package/dist/val/MapVal.js +211 -0
  70. package/dist/val/MapVal.js.map +1 -0
  71. package/dist/val/MoveFuncVal.d.ts +11 -0
  72. package/dist/val/MoveFuncVal.js +41 -0
  73. package/dist/val/MoveFuncVal.js.map +1 -0
  74. package/dist/val/NilVal.d.ts +25 -0
  75. package/dist/val/NilVal.js +92 -0
  76. package/dist/val/NilVal.js.map +1 -0
  77. package/dist/val/NullVal.d.ts +9 -0
  78. package/dist/val/NullVal.js +18 -0
  79. package/dist/val/NullVal.js.map +1 -0
  80. package/dist/val/NumberVal.d.ts +9 -0
  81. package/dist/val/NumberVal.js +44 -0
  82. package/dist/val/NumberVal.js.map +1 -0
  83. package/dist/val/OpBaseVal.d.ts +18 -0
  84. package/dist/val/OpBaseVal.js +152 -0
  85. package/dist/val/OpBaseVal.js.map +1 -0
  86. package/dist/val/OpenFuncVal.d.ts +11 -0
  87. package/dist/val/OpenFuncVal.js +30 -0
  88. package/dist/val/OpenFuncVal.js.map +1 -0
  89. package/dist/val/PathFuncVal.d.ts +13 -0
  90. package/dist/val/PathFuncVal.js +42 -0
  91. package/dist/val/PathFuncVal.js.map +1 -0
  92. package/dist/val/PlusOpVal.d.ts +16 -0
  93. package/dist/val/PlusOpVal.js +59 -0
  94. package/dist/val/PlusOpVal.js.map +1 -0
  95. package/dist/val/PrefFuncVal.d.ts +11 -0
  96. package/dist/val/PrefFuncVal.js +39 -0
  97. package/dist/val/PrefFuncVal.js.map +1 -0
  98. package/dist/val/PrefVal.d.ts +15 -0
  99. package/dist/val/PrefVal.js +104 -0
  100. package/dist/val/PrefVal.js.map +1 -0
  101. package/dist/val/RefVal.d.ts +22 -0
  102. package/dist/val/RefVal.js +276 -0
  103. package/dist/val/RefVal.js.map +1 -0
  104. package/dist/val/ScalarKindVal.d.ts +16 -0
  105. package/dist/val/ScalarKindVal.js +76 -0
  106. package/dist/val/ScalarKindVal.js.map +1 -0
  107. package/dist/val/ScalarVal.d.ts +16 -0
  108. package/dist/val/ScalarVal.js +61 -0
  109. package/dist/val/ScalarVal.js.map +1 -0
  110. package/dist/val/StringVal.d.ts +10 -0
  111. package/dist/val/StringVal.js +19 -0
  112. package/dist/val/StringVal.js.map +1 -0
  113. package/dist/val/SuperFuncVal.d.ts +11 -0
  114. package/dist/val/SuperFuncVal.js +22 -0
  115. package/dist/val/SuperFuncVal.js.map +1 -0
  116. package/dist/val/TopVal.d.ts +16 -0
  117. package/dist/val/TopVal.js +38 -0
  118. package/dist/val/TopVal.js.map +1 -0
  119. package/dist/val/TypeFuncVal.d.ts +12 -0
  120. package/dist/val/TypeFuncVal.js +35 -0
  121. package/dist/val/TypeFuncVal.js.map +1 -0
  122. package/dist/val/UpperFuncVal.d.ts +12 -0
  123. package/dist/val/UpperFuncVal.js +40 -0
  124. package/dist/val/UpperFuncVal.js.map +1 -0
  125. package/dist/val/Val.d.ts +89 -0
  126. package/dist/val/Val.js +186 -0
  127. package/dist/val/Val.js.map +1 -0
  128. package/dist/val/VarVal.d.ts +13 -0
  129. package/dist/val/VarVal.js +109 -0
  130. package/dist/val/VarVal.js.map +1 -0
  131. package/dist/val/top.d.ts +2 -0
  132. package/dist/val/top.js +10 -0
  133. package/dist/val/top.js.map +1 -0
  134. package/dist/val/valutil.d.ts +2 -0
  135. package/dist/val/valutil.js +30 -0
  136. package/dist/val/valutil.js.map +1 -0
  137. package/package.json +3 -5
  138. package/src/aontu.ts +218 -0
  139. package/src/ctx.ts +201 -0
  140. package/src/err.ts +172 -0
  141. package/src/hints.ts +119 -0
  142. package/src/lang.ts +782 -0
  143. package/src/site.ts +34 -0
  144. package/src/tsconfig.json +16 -0
  145. package/src/type.ts +72 -0
  146. package/src/unify.ts +225 -0
  147. package/src/utility.ts +179 -0
  148. package/src/val/BagVal.ts +33 -0
  149. package/src/val/BooleanVal.ts +32 -0
  150. package/src/val/CloseFuncVal.ts +61 -0
  151. package/src/val/ConjunctVal.ts +285 -0
  152. package/src/val/CopyFuncVal.ts +69 -0
  153. package/src/val/DisjunctVal.ts +288 -0
  154. package/src/val/FeatureVal.ts +56 -0
  155. package/src/val/FuncBaseVal.ts +198 -0
  156. package/src/val/HideFuncVal.ts +85 -0
  157. package/src/val/IntegerVal.ts +75 -0
  158. package/src/val/JunctionVal.ts +54 -0
  159. package/src/val/KeyFuncVal.ts +67 -0
  160. package/src/val/ListVal.ts +286 -0
  161. package/src/val/LowerFuncVal.ts +73 -0
  162. package/src/val/MapVal.ts +316 -0
  163. package/src/val/MoveFuncVal.ts +79 -0
  164. package/src/val/NilVal.ts +156 -0
  165. package/src/val/NullVal.ts +38 -0
  166. package/src/val/NumberVal.ts +75 -0
  167. package/src/val/OpBaseVal.ts +231 -0
  168. package/src/val/OpenFuncVal.ts +60 -0
  169. package/src/val/PathFuncVal.ts +75 -0
  170. package/src/val/PlusOpVal.ts +92 -0
  171. package/src/val/PrefFuncVal.ts +73 -0
  172. package/src/val/PrefVal.ts +159 -0
  173. package/src/val/RefVal.ts +384 -0
  174. package/src/val/ScalarKindVal.ts +125 -0
  175. package/src/val/ScalarVal.ts +105 -0
  176. package/src/val/StringVal.ts +37 -0
  177. package/src/val/SuperFuncVal.ts +46 -0
  178. package/src/val/TopVal.ts +69 -0
  179. package/src/val/TypeFuncVal.ts +69 -0
  180. package/src/val/UpperFuncVal.ts +72 -0
  181. package/src/val/Val.ts +294 -0
  182. package/src/val/VarVal.ts +171 -0
  183. package/src/val/top.ts +12 -0
  184. package/src/val/valutil.ts +31 -0
@@ -0,0 +1,286 @@
1
+ /* Copyright (c) 2021-2025 Richard Rodger, MIT License */
2
+
3
+
4
+ import type {
5
+ Val,
6
+ ValList,
7
+ ValSpec,
8
+ } from '../type'
9
+
10
+ import {
11
+ DONE,
12
+ SPREAD,
13
+ } from '../type'
14
+
15
+ import { AontuContext } from '../ctx'
16
+ import { unite } from '../unify'
17
+
18
+ import {
19
+ propagateMarks,
20
+ explainOpen,
21
+ ec,
22
+ explainClose,
23
+ } from '../utility'
24
+
25
+ import { makeNilErr, AontuError } from '../err'
26
+
27
+
28
+ import {
29
+ top
30
+ } from './top'
31
+
32
+ import { ConjunctVal } from './ConjunctVal'
33
+ import { NilVal } from './NilVal'
34
+ import { BagVal } from './BagVal'
35
+ import { empty } from './Val'
36
+
37
+
38
+ class ListVal extends BagVal {
39
+ isList = true
40
+
41
+ spread = {
42
+ cj: (undefined as Val | undefined),
43
+ }
44
+
45
+ constructor(
46
+ spec: {
47
+ peg: ValList
48
+ },
49
+ ctx?: AontuContext
50
+ ) {
51
+ super(spec, ctx)
52
+
53
+ if (null == this.peg) {
54
+ throw new AontuError('ListVal spec.peg undefined')
55
+ }
56
+
57
+ let spread = (this.peg as any)[SPREAD]
58
+ delete (this.peg as any)[SPREAD]
59
+
60
+ if (spread) {
61
+ if ('&' === spread.o) {
62
+
63
+ // TODO: handle existing spread!
64
+ this.spread.cj =
65
+ Array.isArray(spread.v) ?
66
+ 1 < spread.v.length ?
67
+ new ConjunctVal({ peg: spread.v }, ctx) :
68
+ spread.v[0] :
69
+ spread.v
70
+
71
+ // let tmv = Array.isArray(spread.v) ? spread.v : [spread.v]
72
+ // this.spread.cj = new ConjunctVal({ peg: tmv }, ctx)
73
+ }
74
+ }
75
+ }
76
+
77
+
78
+ // NOTE: order of keys is not preserved!
79
+ // not possible in any case - consider {a,b} unify {b,a}
80
+ unify(peer: Val, ctx: AontuContext): Val {
81
+ const TOP = top()
82
+ peer = peer ?? TOP
83
+
84
+ const te = ctx.explain && explainOpen(ctx, ctx.explain, 'List', this, peer)
85
+ let done: boolean = true
86
+ let exit = false
87
+
88
+ // NOTE: not a clone! needs to be constructed.
89
+ let out: ListVal | NilVal = (peer.isTop ? this : new ListVal({ peg: [] }, ctx))
90
+
91
+ out.closed = this.closed
92
+ out.optionalKeys = [...this.optionalKeys]
93
+
94
+ out.spread.cj = this.spread.cj
95
+
96
+ if (peer instanceof ListVal) {
97
+ if (!this.closed && peer.closed) {
98
+ out = peer.unify(this, ctx.clone({ explain: ec(te, 'PMC') })) as ListVal
99
+ exit = true
100
+ }
101
+ else {
102
+ out.closed = out.closed || peer.closed
103
+ out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
104
+ null == peer.spread.cj ? out.spread.cj : (
105
+ out.spread.cj =
106
+ unite(ctx.clone({ explain: ec(te, 'SPR') }),
107
+ out.spread.cj, peer.spread.cj, 'list-peer')
108
+ )
109
+ )
110
+ }
111
+ }
112
+
113
+
114
+ if (!exit) {
115
+ out.dc = this.dc + 1
116
+
117
+ let spread_cj = out.spread.cj || TOP
118
+
119
+ // Always unify children first
120
+ for (let key in this.peg) {
121
+ const keyctx = ctx.descend(key)
122
+ const key_spread_cj = spread_cj.clone(keyctx)
123
+ const child = this.peg[key]
124
+
125
+ propagateMarks(this, child)
126
+
127
+ out.peg[key] =
128
+ undefined === child ? key_spread_cj :
129
+ child.isNil ? child :
130
+ key_spread_cj.isNil ? key_spread_cj :
131
+ key_spread_cj.isTop && child.done ? child :
132
+ child.isTop && key_spread_cj.done ? key_spread_cj :
133
+ unite(keyctx.clone({ explain: ec(te, 'PEG:' + key) }),
134
+ child, key_spread_cj, 'list-own')
135
+
136
+ done = (done && DONE === out.peg[key].dc)
137
+ }
138
+
139
+ const allowedKeys: string[] = this.closed ? Object.keys(this.peg) : []
140
+ let bad: NilVal | undefined = undefined
141
+
142
+ if (peer instanceof ListVal) {
143
+ let upeer: ListVal = (unite(ctx.clone({ explain: ec(te, 'PER') }),
144
+ peer, TOP, 'list-peer-list') as ListVal)
145
+
146
+ // NOTE: peerkey is the index
147
+ for (let peerkey in upeer.peg) {
148
+ let peerchild = upeer.peg[peerkey]
149
+
150
+ if (this.closed && !allowedKeys.includes(peerkey)) {
151
+ bad = makeNilErr(ctx, 'closed', peerchild, undefined)
152
+ }
153
+
154
+ let child = out.peg[peerkey]
155
+
156
+ let oval = out.peg[peerkey] =
157
+ undefined === child ? peerchild :
158
+ child.isTop && peerchild.done ? peerchild :
159
+ child.isNil ? child :
160
+ peerchild.isNil ? peerchild :
161
+ unite(ctx.descend(peerkey).clone({ explain: ec(te, 'CHD') }),
162
+ child, peerchild, 'list-peer')
163
+
164
+ if (this.spread.cj) {
165
+ let key_ctx = ctx.descend(peerkey)
166
+ let key_spread_cj = spread_cj.clone(key_ctx)
167
+
168
+ oval = out.peg[peerkey] =
169
+ unite(key_ctx.clone({ explain: ec(te, 'PSP:' + peerkey) }),
170
+ out.peg[peerkey], key_spread_cj, 'list-spread')
171
+ }
172
+
173
+ propagateMarks(this, oval)
174
+
175
+ done = (done && DONE === oval.dc)
176
+ }
177
+ }
178
+ else if (!peer.isTop) {
179
+ out = makeNilErr(ctx, 'list', this, peer)
180
+ }
181
+
182
+ if (null != bad) {
183
+ out = bad
184
+ }
185
+
186
+ if (!out.isNil) {
187
+ out.uh.push(peer.id)
188
+
189
+ out.dc = done ? DONE : out.dc
190
+ propagateMarks(peer, out)
191
+ propagateMarks(this, out)
192
+ }
193
+ }
194
+
195
+ ctx.explain && explainClose(te, out)
196
+
197
+ return out
198
+ }
199
+
200
+
201
+ clone(ctx: AontuContext, spec?: ValSpec): Val {
202
+ let out = (super.clone(ctx, spec) as ListVal)
203
+ for (let entry of Object.entries(this.peg)) {
204
+ out.peg[entry[0]] =
205
+ (entry[1] as any)?.isVal ? (entry[1] as Val).clone(ctx, spec?.mark ? { mark: spec.mark } : {}) : entry[1]
206
+ }
207
+ if (this.spread.cj) {
208
+ out.spread.cj = this.spread.cj.clone(ctx, spec?.mark ? { mark: spec.mark } : {})
209
+ }
210
+
211
+ out.closed = this.closed
212
+ out.optionalKeys = [...this.optionalKeys]
213
+
214
+ // console.log('LISTVAL-CLONE', this.canon, '->', out.canon)
215
+ return out
216
+ }
217
+
218
+
219
+ get canon() {
220
+ // console.log('LISTVAL-CANON', this.optionalKeys)
221
+ let keys = Object.keys(this.peg)
222
+ return '' +
223
+ // this.errcanon() +
224
+ '[' +
225
+ (this.spread.cj ? '&:' + this.spread.cj.canon +
226
+ (0 < keys.length ? ',' : '') : '') +
227
+ keys
228
+ .map(k => this.optionalKeys.includes(k) ?
229
+ k + '?:' + this.peg[k].canon :
230
+ this.peg[k].canon).join(',') +
231
+ ']'
232
+ }
233
+
234
+
235
+ gen(ctx: AontuContext) {
236
+ let out: any = []
237
+ if (this.mark.type || this.mark.hide) {
238
+ return undefined
239
+ }
240
+
241
+ for (let i = 0; i < this.peg.length; i++) {
242
+ const child = this.peg[i]
243
+
244
+ const optional = this.optionalKeys.includes('' + i)
245
+
246
+ if (child.isScalar
247
+ || child.isMap
248
+ || child.isList
249
+ || child.isPref
250
+ || child.isRef
251
+ || child.isDisjunct
252
+ || child.isNil
253
+ ) {
254
+ const cval = child.gen(ctx)
255
+
256
+ if (optional && empty(cval)) {
257
+ continue
258
+ }
259
+
260
+ out.push(cval)
261
+ }
262
+ else if (child.isNil) {
263
+ ctx.adderr(child)
264
+ }
265
+ else if (!this.optionalKeys.includes('' + i)) {
266
+ makeNilErr(
267
+ ctx,
268
+ this.closed ? 'listval_required' : 'listval_no_gen',
269
+ child, undefined
270
+ )
271
+ break
272
+ }
273
+
274
+ // else optional so we can ignore it
275
+ }
276
+
277
+ return out
278
+ }
279
+ }
280
+
281
+
282
+
283
+
284
+ export {
285
+ ListVal,
286
+ }
@@ -0,0 +1,73 @@
1
+ /* Copyright (c) 2021-2025 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 { makeNilErr } from '../err'
14
+
15
+
16
+ import { NilVal } from '../val/NilVal'
17
+ import { ScalarKindVal } from '../val/ScalarKindVal'
18
+ import { makeScalar } from '../val/valutil'
19
+
20
+
21
+
22
+ import { FuncBaseVal } from './FuncBaseVal'
23
+
24
+
25
+ class LowerFuncVal extends FuncBaseVal {
26
+ isLower = true
27
+
28
+ constructor(
29
+ spec: ValSpec,
30
+ ctx?: AontuContext
31
+ ) {
32
+ super(spec, ctx)
33
+ }
34
+
35
+
36
+ make(_ctx: AontuContext, spec: ValSpec): Val {
37
+ return new LowerFuncVal(spec)
38
+ }
39
+
40
+ funcname() {
41
+ return 'lower'
42
+ }
43
+
44
+
45
+ resolve(ctx: AontuContext | undefined, args: Val[]) {
46
+ const oldpeg = args?.[0].peg
47
+ const peg = 'string' === typeof oldpeg ? oldpeg.toLowerCase() :
48
+ 'number' === typeof oldpeg ? Math.floor(oldpeg) :
49
+ undefined
50
+ const out = this.place(
51
+ null == peg ?
52
+ makeNilErr(ctx, 'invalid-arg', this) :
53
+ makeScalar(peg)
54
+ )
55
+ return out
56
+ }
57
+
58
+
59
+ superior() {
60
+ const arg = this.peg?.[0]
61
+ return arg?.isScalar ?
62
+ this.place(new ScalarKindVal({
63
+ peg: arg.kind
64
+ })) :
65
+ super.superior()
66
+ }
67
+
68
+ }
69
+
70
+
71
+ export {
72
+ LowerFuncVal,
73
+ }
@@ -0,0 +1,316 @@
1
+ /* Copyright (c) 2021-2025 Richard Rodger, MIT License */
2
+
3
+
4
+
5
+ import type {
6
+ Val,
7
+ ValSpec,
8
+ } from '../type'
9
+
10
+ import {
11
+ DONE,
12
+ SPREAD,
13
+ } from '../type'
14
+
15
+ import { AontuContext } from '../ctx'
16
+ import { unite } from '../unify'
17
+
18
+ import {
19
+ propagateMarks,
20
+ explainOpen,
21
+ ec,
22
+ explainClose,
23
+ } from '../utility'
24
+
25
+ import { makeNilErr, AontuError } from '../err'
26
+
27
+ import {
28
+ top
29
+ } from './top'
30
+
31
+
32
+ import { ConjunctVal } from './ConjunctVal'
33
+ import { NilVal } from './NilVal'
34
+ import { BagVal } from './BagVal'
35
+ import { empty } from './Val'
36
+
37
+
38
+ class MapVal extends BagVal {
39
+ isMap = true
40
+
41
+ spread = {
42
+ cj: (undefined as Val | undefined),
43
+ }
44
+
45
+ constructor(
46
+ spec: ValSpec,
47
+ ctx?: AontuContext
48
+ ) {
49
+ super(spec, ctx)
50
+
51
+ if (null == this.peg) {
52
+ throw new AontuError('MapVal spec.peg undefined')
53
+ }
54
+
55
+ this.mark.type = !!spec.mark?.type
56
+ this.mark.hide = !!spec.mark?.hide
57
+
58
+ let spread = (this.peg as any)[SPREAD]
59
+ delete (this.peg as any)[SPREAD]
60
+
61
+ if (spread) {
62
+ if ('&' === spread.o) {
63
+ // TODO: handle existing spread!
64
+ this.spread.cj =
65
+ Array.isArray(spread.v) ?
66
+ 1 < spread.v.length ?
67
+ new ConjunctVal({ peg: spread.v }, ctx) :
68
+ spread.v[0] :
69
+ spread.v
70
+ }
71
+ }
72
+
73
+ // console.log('MAPVAL-ctor', this.type, spec)
74
+ }
75
+
76
+
77
+ // NOTE: order of keys is not preserved!
78
+ // not possible in any case - consider {a,b} unify {b,a}
79
+ unify(peer: Val, ctx: AontuContext): Val {
80
+ const TOP = top()
81
+ peer = peer ?? TOP
82
+ const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Map', this, peer)
83
+
84
+ let done: boolean = true
85
+ let exit = false
86
+
87
+ // NOTE: not a clone! needs to be constructed.
88
+ let out: MapVal | NilVal = (peer.isTop ? this : new MapVal({ peg: {} }, ctx))
89
+
90
+ out.closed = this.closed
91
+ out.optionalKeys = [...this.optionalKeys]
92
+
93
+ out.spread.cj = this.spread.cj
94
+
95
+ if (peer instanceof MapVal) {
96
+ if (!this.closed && peer.closed) {
97
+ out = peer.unify(this, ctx.clone({ explain: ec(te, 'PMC') })) as MapVal
98
+ exit = true
99
+ }
100
+
101
+ // ensure determinism of unification
102
+ else if (this.closed && peer.closed) {
103
+ const peerkeys = Object.keys(peer.peg)
104
+ const selfkeys = Object.keys(this.peg)
105
+
106
+ if (
107
+ peerkeys.length < selfkeys.length
108
+ || (peerkeys.length === selfkeys.length
109
+ && peerkeys.join('~') < selfkeys.join('~')
110
+ )
111
+ ) {
112
+ out = peer.unify(this, ctx.clone({ explain: ec(te, 'SPC') })) as MapVal
113
+ exit = true
114
+ }
115
+
116
+ }
117
+
118
+ if (!exit) {
119
+ out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
120
+ null == peer.spread.cj ? out.spread.cj : (
121
+ out.spread.cj =
122
+ unite(ctx.clone({ explain: ec(te, 'SPR') }), out.spread.cj, peer.spread.cj, 'map-self')
123
+ )
124
+ )
125
+ }
126
+ }
127
+
128
+ if (!exit) {
129
+ out.dc = this.dc + 1
130
+
131
+ // let newtype = this.type || peer.type
132
+
133
+ let spread_cj = out.spread.cj ?? TOP
134
+
135
+ // Always unify own children first
136
+ for (let key in this.peg) {
137
+ const keyctx = ctx.descend(key)
138
+ const key_spread_cj = spread_cj.clone(keyctx)
139
+ const child = this.peg[key]
140
+
141
+ propagateMarks(this, child)
142
+
143
+ out.peg[key] =
144
+ undefined === child ? key_spread_cj :
145
+ child.isNil ? child :
146
+ key_spread_cj.isNil ? key_spread_cj :
147
+ key_spread_cj.isTop && child.done ? child :
148
+ child.isTop && key_spread_cj.done ? key_spread_cj :
149
+ unite(keyctx.clone({ explain: ec(te, 'PEG:' + key) }),
150
+ child, key_spread_cj, 'map-own')
151
+
152
+ done = (done && DONE === out.peg[key].dc)
153
+ }
154
+
155
+ const allowedKeys: string[] = this.closed ? Object.keys(this.peg) : []
156
+ let bad: NilVal | undefined = undefined
157
+
158
+ if (peer instanceof MapVal) {
159
+ let upeer: MapVal = (unite(ctx.clone({ explain: ec(te, 'PER') }),
160
+ peer, TOP, 'map-peer-map') as MapVal)
161
+
162
+ for (let peerkey in upeer.peg) {
163
+ let peerchild = upeer.peg[peerkey]
164
+
165
+ if (this.closed && !allowedKeys.includes(peerkey)) {
166
+ bad = makeNilErr(ctx, 'closed', peerchild, undefined)
167
+ }
168
+
169
+ // key optionality is additive
170
+ if (upeer.optionalKeys.includes(peerkey) && !out.optionalKeys.includes(peerkey)) {
171
+ out.optionalKeys.push(peerkey)
172
+ }
173
+
174
+ let child = out.peg[peerkey]
175
+
176
+ let oval = out.peg[peerkey] =
177
+ undefined === child ? peerchild :
178
+ child.isTop && peerchild.done ? peerchild :
179
+ child.isNil ? child :
180
+ peerchild.isNil ? peerchild :
181
+ unite(ctx.descend(peerkey).clone({ explain: ec(te, 'CHD') }),
182
+ child, peerchild, 'map-peer')
183
+
184
+ if (this.spread.cj) {
185
+ let key_ctx = ctx.descend(peerkey)
186
+ let key_spread_cj = spread_cj.clone(key_ctx)
187
+ oval = out.peg[peerkey] =
188
+ unite(key_ctx.clone({ explain: ec(te, 'PSP:' + peerkey) }),
189
+ oval, key_spread_cj, 'map-peer-spread')
190
+ }
191
+
192
+ propagateMarks(this, oval)
193
+
194
+ done = (done && DONE === oval.dc)
195
+ }
196
+ }
197
+ else if (!peer.isTop) {
198
+ out = makeNilErr(ctx, 'map', this, peer)
199
+ }
200
+
201
+ if (null != bad) {
202
+ out = bad
203
+ }
204
+
205
+ if (!out.isNil) {
206
+ out.uh.push(peer.id)
207
+
208
+ out.dc = done ? DONE : out.dc
209
+ propagateMarks(peer, out)
210
+ propagateMarks(this, out)
211
+ }
212
+ }
213
+
214
+ // console.log('MAPVAL-OUT', this.id, this.closed, this.canon, 'P=', (peer as any).closed, peer.canon, '->', (out as any).closed, out.canon)
215
+
216
+ ctx.explain && explainClose(te, out)
217
+
218
+ return out
219
+ }
220
+
221
+
222
+ clone(ctx: AontuContext, spec?: ValSpec): Val {
223
+ let out = (super.clone(ctx, spec) as MapVal)
224
+ out.peg = {}
225
+ for (let entry of Object.entries(this.peg)) {
226
+ out.peg[entry[0]] =
227
+ (entry[1] as any)?.isVal ? (entry[1] as Val).clone(ctx, spec?.mark ? { mark: spec.mark } : {}) : entry[1]
228
+ }
229
+ if (this.spread.cj) {
230
+ out.spread.cj = this.spread.cj.clone(ctx, spec?.mark ? { mark: spec.mark } : {})
231
+ }
232
+
233
+ out.closed = this.closed
234
+ out.optionalKeys = [...this.optionalKeys]
235
+
236
+ // console.log('MAPVAL-CLONE', this.canon, '->', out.canon)
237
+ return out
238
+ }
239
+
240
+
241
+ get canon() {
242
+ let keys = Object.keys(this.peg)
243
+ return '' +
244
+ // this.errcanon() +
245
+ // (this.mark.type ? '<type>' : '') +
246
+ // (this.id + '=') +
247
+ '{' +
248
+ (this.spread.cj ? '&:' + this.spread.cj.canon +
249
+ (0 < keys.length ? ',' : '') : '') +
250
+ keys
251
+ .map(k => [
252
+ JSON.stringify(k) +
253
+ (this.optionalKeys.includes(k) ? '?' : '') +
254
+ ':' +
255
+ (this.peg[k]?.canon ?? this.peg[k])
256
+ ])
257
+ .join(',') +
258
+ '}'
259
+ }
260
+
261
+
262
+ inspection(inspect: Function) {
263
+ return this.spread.cj ? '&:' + inspect(this.spread.cj) : ''
264
+ }
265
+
266
+
267
+ gen(ctx: AontuContext) {
268
+ let out: any = {}
269
+ if (this.mark.type || this.mark.hide) {
270
+ return undefined
271
+ }
272
+
273
+ for (let p in this.peg) {
274
+ const child = this.peg[p]
275
+ if (child.mark.type || child.mark.hide) {
276
+ continue
277
+ }
278
+
279
+ const optional = this.optionalKeys.includes(p)
280
+
281
+ if (child.isScalar
282
+ || child.isMap
283
+ || child.isList
284
+ || child.isPref
285
+ || child.isRef
286
+ || child.isDisjunct
287
+ || child.isNil
288
+ ) {
289
+ const cval = child.gen(ctx)
290
+
291
+ if (optional && empty(cval)) {
292
+ continue
293
+ }
294
+
295
+ out[p] = cval
296
+ }
297
+ else if (!optional) {
298
+ makeNilErr(
299
+ ctx,
300
+ this.closed ? 'mapval_required' : 'mapval_no_gen',
301
+ child, undefined
302
+ )
303
+ break
304
+ }
305
+
306
+ // else optional so we can ignore it
307
+ }
308
+
309
+ return out
310
+ }
311
+ }
312
+
313
+
314
+ export {
315
+ MapVal
316
+ }