aontu 0.30.1 → 0.31.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 (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 +90 -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 +162 -0
  22. package/dist/unify.js.map +1 -0
  23. package/dist/utility.d.ts +14 -0
  24. package/dist/utility.js +128 -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 +14 -0
  39. package/dist/val/CopyFuncVal.js +43 -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 +131 -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 +13 -0
  60. package/dist/val/KeyFuncVal.js +64 -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 +233 -0
  70. package/dist/val/MapVal.js.map +1 -0
  71. package/dist/val/MoveFuncVal.d.ts +12 -0
  72. package/dist/val/MoveFuncVal.js +44 -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 +112 -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 +310 -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 +62 -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 +90 -0
  126. package/dist/val/Val.js +205 -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 +129 -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 +233 -0
  147. package/src/utility.ts +185 -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 +82 -0
  153. package/src/val/DisjunctVal.ts +288 -0
  154. package/src/val/FeatureVal.ts +56 -0
  155. package/src/val/FuncBaseVal.ts +204 -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 +103 -0
  160. package/src/val/ListVal.ts +286 -0
  161. package/src/val/LowerFuncVal.ts +73 -0
  162. package/src/val/MapVal.ts +349 -0
  163. package/src/val/MoveFuncVal.ts +83 -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 +170 -0
  173. package/src/val/RefVal.ts +436 -0
  174. package/src/val/ScalarKindVal.ts +125 -0
  175. package/src/val/ScalarVal.ts +107 -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 +318 -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,349 @@
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
+ // console.log('MAPVAL-UNIFY', this.id, this.canon, peer.id, peer.canon)
81
+
82
+ const TOP = top()
83
+ peer = peer ?? TOP
84
+ const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Map', this, peer)
85
+
86
+ let done: boolean = true
87
+ let exit = false
88
+
89
+ // NOTE: not a clone! needs to be constructed.
90
+ let out: MapVal | NilVal = (peer.isTop ? this : new MapVal({ peg: {} }, ctx))
91
+
92
+ out.closed = this.closed
93
+ out.optionalKeys = [...this.optionalKeys]
94
+
95
+ out.spread.cj = this.spread.cj
96
+
97
+ // TODO: some spreads (no path refs etc) could self unified
98
+ /*
99
+ if (out.spread.cj && !out.spread.cj.mark._self_unified) {
100
+ // console.log('MAPVAL-SPR-START', out.spread.cj.mark)
101
+ out.spread.cj = out.spread.cj.unify(TOP, ctx.clone({ explain: ec(te, 'SPR-SELF-UNIFY') }))
102
+ out.spread.cj.mark._self_unified = true
103
+ // console.log('MAPVAL-SU', out.spread.cj.id, out.spread.cj.canon, out.spread.cj.done)
104
+ }
105
+ */
106
+
107
+ if (peer instanceof MapVal) {
108
+ // console.log('MAPVAL-PEER-MAPVAL', this.id, this.canon, this.done, peer.id, peer.canon, peer.done)
109
+
110
+ if (!this.closed && peer.closed) {
111
+ out = peer.unify(this, ctx.clone({ explain: ec(te, 'PMC') })) as MapVal
112
+ exit = true
113
+ }
114
+
115
+ // ensure determinism of unification
116
+ else if (this.closed && peer.closed) {
117
+ const peerkeys = Object.keys(peer.peg)
118
+ const selfkeys = Object.keys(this.peg)
119
+
120
+ if (
121
+ peerkeys.length < selfkeys.length
122
+ || (peerkeys.length === selfkeys.length
123
+ && peerkeys.join('~') < selfkeys.join('~')
124
+ )
125
+ ) {
126
+ out = peer.unify(this, ctx.clone({ explain: ec(te, 'SPC') })) as MapVal
127
+ exit = true
128
+ }
129
+
130
+ }
131
+
132
+ if (!exit) {
133
+ out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
134
+ null == peer.spread.cj ? out.spread.cj : (
135
+ out.spread.cj =
136
+ unite(ctx.clone({ explain: ec(te, 'SPR') }),
137
+ out.spread.cj, peer.spread.cj, 'map-self')
138
+ )
139
+ )
140
+ }
141
+ }
142
+ else {
143
+ // console.log('MAPVAL-PEER-OTHER', this.id, this.canon, this.done, peer.id, peer.canon, peer.done)
144
+ }
145
+
146
+
147
+ if (!exit) {
148
+ out.dc = this.dc + 1
149
+
150
+ // let newtype = this.type || peer.type
151
+
152
+ let spread_cj = out.spread.cj ?? TOP
153
+
154
+ // Always unify own children first
155
+ for (let key in this.peg) {
156
+ const keyctx = ctx.descend(key)
157
+
158
+ const key_spread_cj = spread_cj.clone(keyctx)
159
+ // console.log('MAPVAL-SPREAD', this.id, key, key_spread_cj.id, key_spread_cj.canon, key_spread_cj.done)
160
+
161
+ const child = this.peg[key]
162
+
163
+ propagateMarks(this, child)
164
+
165
+ out.peg[key] =
166
+ undefined === child ? key_spread_cj :
167
+ child.isNil ? child :
168
+ key_spread_cj.isNil ? key_spread_cj :
169
+ key_spread_cj.isTop && child.done ? child :
170
+ child.isTop && key_spread_cj.done ? key_spread_cj :
171
+ unite(keyctx.clone({ explain: ec(te, 'KEY:' + key) }),
172
+ child, key_spread_cj, 'map-own')
173
+
174
+ done = (done && DONE === out.peg[key].dc)
175
+ }
176
+
177
+ const allowedKeys: string[] = this.closed ? Object.keys(this.peg) : []
178
+ let bad: NilVal | undefined = undefined
179
+
180
+ if (peer instanceof MapVal) {
181
+ let upeer: MapVal = (unite(ctx.clone({ explain: ec(te, 'PER') }),
182
+ peer, TOP, 'map-peer-map') as MapVal)
183
+
184
+ for (let peerkey in upeer.peg) {
185
+ let peerchild = upeer.peg[peerkey]
186
+
187
+ if (this.closed && !allowedKeys.includes(peerkey)) {
188
+ bad = makeNilErr(ctx, 'closed', peerchild, undefined)
189
+ }
190
+
191
+ // key optionality is additive
192
+ if (upeer.optionalKeys.includes(peerkey) && !out.optionalKeys.includes(peerkey)) {
193
+ out.optionalKeys.push(peerkey)
194
+ }
195
+
196
+ let child = out.peg[peerkey]
197
+
198
+ let oval = out.peg[peerkey] =
199
+ undefined === child ? peerchild :
200
+ child.isTop && peerchild.done ? peerchild :
201
+ child.isNil ? child :
202
+ peerchild.isNil ? peerchild :
203
+ unite(ctx.descend(peerkey).clone({ explain: ec(te, 'CHD') }),
204
+ child, peerchild, 'map-peer')
205
+
206
+ if (this.spread.cj) {
207
+ let key_ctx = ctx.descend(peerkey)
208
+ let key_spread_cj = spread_cj.clone(key_ctx)
209
+
210
+ // console.log('MAPVAL-PEER-SPR', peerkey, key_spread_cj.id, key_spread_cj.canon, key_spread_cj.done)
211
+
212
+ oval = out.peg[peerkey] =
213
+ unite(key_ctx.clone({ explain: ec(te, 'PSP:' + peerkey) }),
214
+ oval, key_spread_cj, 'map-peer-spread')
215
+ }
216
+
217
+ propagateMarks(this, oval)
218
+
219
+ done = (done && DONE === oval.dc)
220
+ }
221
+ }
222
+ else if (!peer.isTop) {
223
+ out = makeNilErr(ctx, 'map', this, peer)
224
+ }
225
+
226
+ if (null != bad) {
227
+ out = bad
228
+ }
229
+
230
+ if (!out.isNil) {
231
+ out.uh.push(peer.id)
232
+
233
+ out.dc = done ? DONE : out.dc
234
+ propagateMarks(peer, out)
235
+ propagateMarks(this, out)
236
+ }
237
+ }
238
+
239
+ // console.log('MAPVAL-OUT', this.id, this.closed, this.canon, 'P=', (peer as any).closed, peer.canon, '->', (out as any).closed, out.canon)
240
+
241
+ ctx.explain && explainClose(te, out)
242
+
243
+ return out
244
+ }
245
+
246
+
247
+ clone(ctx: AontuContext, spec?: ValSpec): Val {
248
+ let out = (super.clone(ctx, spec) as MapVal)
249
+ out.peg = {}
250
+
251
+ for (let entry of Object.entries(this.peg)) {
252
+ out.peg[entry[0]] =
253
+ (entry[1] as any)?.isVal ?
254
+ // (entry[1] as Val).clone(ctx, spec?.mark ? { mark: spec.mark } : {}) :
255
+ (entry[1] as Val).clone(ctx, {
256
+ mark: spec?.mark ?? {},
257
+ path: [...out.path, entry[0]]
258
+ }) :
259
+ entry[1]
260
+ }
261
+ if (this.spread.cj) {
262
+ out.spread.cj = this.spread.cj.clone(ctx, spec?.mark ? { mark: spec.mark } : {})
263
+ }
264
+
265
+ out.closed = this.closed
266
+ out.optionalKeys = [...this.optionalKeys]
267
+
268
+ // console.log('MAPVAL-CLONE', this.canon, '->', out.canon)
269
+ return out
270
+ }
271
+
272
+
273
+ get canon() {
274
+ let keys = Object.keys(this.peg)
275
+ return '' +
276
+ // this.errcanon() +
277
+ // (this.mark.type ? '<type>' : '') +
278
+ // (this.id + '=') +
279
+ '{' +
280
+ (this.spread.cj ? '&:' + this.spread.cj.canon +
281
+ (0 < keys.length ? ',' : '') : '') +
282
+ keys
283
+ .map(k => [
284
+ JSON.stringify(k) +
285
+ (this.optionalKeys.includes(k) ? '?' : '') +
286
+ ':' +
287
+ (this.peg[k]?.canon ?? this.peg[k])
288
+ ])
289
+ .join(',') +
290
+ '}' // + '<' + (this.mark.hide ? 'H' : '') + '>'
291
+
292
+ }
293
+
294
+
295
+ inspection(d?: number) {
296
+ return this.spread.cj ? '&:' + this.spread.cj.inspect(null == d ? 0 : d + 1) : ''
297
+ }
298
+
299
+
300
+ gen(ctx: AontuContext) {
301
+ let out: any = {}
302
+ if (this.mark.type || this.mark.hide) {
303
+ return undefined
304
+ }
305
+
306
+ for (let p in this.peg) {
307
+ const child = this.peg[p]
308
+ if (child.mark.type || child.mark.hide) {
309
+ continue
310
+ }
311
+
312
+ const optional = this.optionalKeys.includes(p)
313
+
314
+ if (child.isScalar
315
+ || child.isMap
316
+ || child.isList
317
+ || child.isPref
318
+ || child.isRef
319
+ || child.isDisjunct
320
+ || child.isNil
321
+ ) {
322
+ const cval = child.gen(ctx)
323
+
324
+ if (optional && empty(cval)) {
325
+ continue
326
+ }
327
+
328
+ out[p] = cval
329
+ }
330
+ else if (!optional) {
331
+ makeNilErr(
332
+ ctx,
333
+ this.closed ? 'mapval_required' : 'mapval_no_gen',
334
+ child, undefined
335
+ )
336
+ break
337
+ }
338
+
339
+ // else optional so we can ignore it
340
+ }
341
+
342
+ return out
343
+ }
344
+ }
345
+
346
+
347
+ export {
348
+ MapVal
349
+ }