aontu 0.43.0 → 0.45.1

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 (80) hide show
  1. package/dist/ctx.d.ts +2 -5
  2. package/dist/ctx.js +1 -2
  3. package/dist/ctx.js.map +1 -1
  4. package/dist/lang.d.ts +1 -5
  5. package/dist/lang.js +24 -100
  6. package/dist/lang.js.map +1 -1
  7. package/dist/tsconfig.tsbuildinfo +1 -1
  8. package/dist/type.d.ts +0 -5
  9. package/dist/type.js.map +1 -1
  10. package/dist/unify.js +13 -292
  11. package/dist/unify.js.map +1 -1
  12. package/dist/utility.js +2 -6
  13. package/dist/utility.js.map +1 -1
  14. package/dist/val/BagVal.d.ts +3 -0
  15. package/dist/val/BagVal.js +6 -6
  16. package/dist/val/BagVal.js.map +1 -1
  17. package/dist/val/ConjunctVal.d.ts +1 -1
  18. package/dist/val/ConjunctVal.js +14 -137
  19. package/dist/val/ConjunctVal.js.map +1 -1
  20. package/dist/val/CopyFuncVal.js +2 -3
  21. package/dist/val/CopyFuncVal.js.map +1 -1
  22. package/dist/val/DisjunctVal.js +0 -4
  23. package/dist/val/DisjunctVal.js.map +1 -1
  24. package/dist/val/ExpectVal.js +3 -16
  25. package/dist/val/ExpectVal.js.map +1 -1
  26. package/dist/val/JunctionVal.d.ts +0 -1
  27. package/dist/val/JunctionVal.js +1 -6
  28. package/dist/val/JunctionVal.js.map +1 -1
  29. package/dist/val/KeyFuncVal.js +2 -0
  30. package/dist/val/KeyFuncVal.js.map +1 -1
  31. package/dist/val/ListVal.d.ts +0 -1
  32. package/dist/val/ListVal.js +66 -33
  33. package/dist/val/ListVal.js.map +1 -1
  34. package/dist/val/MapVal.d.ts +2 -3
  35. package/dist/val/MapVal.js +95 -67
  36. package/dist/val/MapVal.js.map +1 -1
  37. package/dist/val/MoveFuncVal.d.ts +1 -2
  38. package/dist/val/MoveFuncVal.js +13 -78
  39. package/dist/val/MoveFuncVal.js.map +1 -1
  40. package/dist/val/PathFuncVal.js +4 -25
  41. package/dist/val/PathFuncVal.js.map +1 -1
  42. package/dist/val/PlusOpVal.d.ts +1 -1
  43. package/dist/val/PrefVal.js +5 -18
  44. package/dist/val/PrefVal.js.map +1 -1
  45. package/dist/val/{PathVal.d.ts → RefVal.d.ts} +3 -4
  46. package/dist/val/{PathVal.js → RefVal.js} +77 -75
  47. package/dist/val/RefVal.js.map +1 -0
  48. package/dist/val/Val.d.ts +1 -2
  49. package/dist/val/Val.js +8 -7
  50. package/dist/val/Val.js.map +1 -1
  51. package/dist/val/VarVal.js +2 -2
  52. package/dist/val/VarVal.js.map +1 -1
  53. package/package.json +6 -5
  54. package/src/ctx.ts +3 -16
  55. package/src/lang.ts +23 -113
  56. package/src/type.ts +0 -5
  57. package/src/unify.ts +13 -310
  58. package/src/utility.ts +2 -5
  59. package/src/val/BagVal.ts +7 -6
  60. package/src/val/ConjunctVal.ts +13 -131
  61. package/src/val/CopyFuncVal.ts +2 -3
  62. package/src/val/DisjunctVal.ts +0 -6
  63. package/src/val/ExpectVal.ts +4 -18
  64. package/src/val/JunctionVal.ts +1 -5
  65. package/src/val/KeyFuncVal.ts +3 -0
  66. package/src/val/ListVal.ts +88 -38
  67. package/src/val/MapVal.ts +124 -75
  68. package/src/val/MoveFuncVal.ts +14 -79
  69. package/src/val/PathFuncVal.ts +4 -29
  70. package/src/val/PrefVal.ts +6 -19
  71. package/src/val/{RefVal.ts.old → RefVal.ts} +19 -30
  72. package/src/val/Val.ts +9 -9
  73. package/src/val/VarVal.ts +2 -2
  74. package/README.md +0 -18
  75. package/dist/val/PathVal.js.map +0 -1
  76. package/dist/val/SpreadVal.d.ts +0 -20
  77. package/dist/val/SpreadVal.js +0 -194
  78. package/dist/val/SpreadVal.js.map +0 -1
  79. package/src/val/PathVal.ts +0 -435
  80. package/src/val/SpreadVal.ts +0 -275
@@ -1,435 +0,0 @@
1
- /* Copyright (c) 2025 Richard Rodger, MIT License */
2
-
3
-
4
- import type {
5
- Val,
6
- ValSpec,
7
- } from '../type'
8
-
9
- import {
10
- DONE,
11
- } from '../type'
12
-
13
- import {
14
- walk,
15
- } from '../utility'
16
-
17
- import { AontuContext } from '../ctx'
18
- import { unite } from '../unify'
19
-
20
- import { makeNilErr } from '../err'
21
-
22
- import {
23
- top
24
- } from './top'
25
-
26
- import { StringVal } from './StringVal'
27
- import { IntegerVal } from './IntegerVal'
28
- import { NumberVal } from './NumberVal'
29
- import { VarVal } from './VarVal'
30
- import { ConjunctVal } from './ConjunctVal'
31
- import { DisjunctVal } from './DisjunctVal'
32
- import { FeatureVal } from './FeatureVal'
33
-
34
-
35
- class PathVal extends FeatureVal {
36
- isPath = true
37
- isGenable = true
38
- cjo = 32500
39
-
40
- absolute: boolean = false
41
- prefix: boolean = false
42
- _resolved: Val | undefined = undefined
43
-
44
- constructor(
45
- spec: {
46
- peg: any[],
47
- absolute?: boolean,
48
- prefix?: boolean
49
- },
50
- ctx?: AontuContext
51
- ) {
52
- super(spec, ctx)
53
- this.peg = []
54
-
55
- this.absolute = true === this.absolute ? true : // absolute sticks
56
- true === spec.absolute ? true : false
57
-
58
- this.prefix = true === spec.prefix
59
-
60
- for (let pI = 0; pI < spec.peg.length; pI++) {
61
- this.append(spec.peg[pI])
62
- }
63
- }
64
-
65
-
66
- append(part: any) {
67
- let partval
68
-
69
- if ('string' === typeof part) {
70
- partval = part
71
- this.peg.push(partval)
72
- }
73
-
74
- else if (part instanceof StringVal) {
75
- partval = part.peg
76
- this.peg.push(partval)
77
- }
78
-
79
- else if (part instanceof IntegerVal) {
80
- partval = part.src
81
- this.peg.push(partval)
82
- }
83
-
84
- else if (part instanceof NumberVal) {
85
- let partvals: string[] = part.src.split('.')
86
- this.peg.push(...partvals)
87
- }
88
-
89
- else if (part instanceof VarVal) {
90
- partval = part
91
- this.peg.push(partval)
92
- }
93
-
94
- else if (part instanceof PathVal) {
95
- if (part.absolute) {
96
- this.absolute = true
97
- }
98
-
99
- if (this.prefix) {
100
- if (part.prefix) {
101
- this.peg.push('.')
102
- }
103
- }
104
- else {
105
- if (part.prefix) {
106
- if (0 === this.peg.length) {
107
- this.prefix = true
108
- }
109
-
110
- else if (0 < this.peg.length) {
111
- this.peg.push('.')
112
- }
113
- }
114
- }
115
-
116
- this.peg.push(...part.peg)
117
- }
118
- }
119
-
120
-
121
- unify(peer: Val, ctx: AontuContext): Val {
122
- peer = peer ?? top()
123
-
124
- // Already resolved (e.g. path value from path() function) — skip find
125
- if (this.done) return this
126
-
127
- let out: Val = this
128
- const found = this.find(ctx)
129
-
130
- if (found != null && !found.isNil) {
131
- out = unite(ctx, found, peer, 'path')
132
- }
133
- else if (found?.isNil) {
134
- out = found
135
- }
136
- else {
137
- // Not yet resolvable — increment dc to signal not done
138
- this.dc = DONE === this.dc ? DONE : this.dc + 1
139
- }
140
-
141
- return out
142
- }
143
-
144
-
145
- find(ctx: AontuContext) {
146
- let out: Val | undefined = undefined
147
-
148
- // Check if self.path starts with peg (cycle detection).
149
- // Element-by-element comparison avoids string join+startsWith allocations.
150
- let isprefixpath = this.peg.length <= this.path.length
151
- if (isprefixpath) {
152
- for (let i = 0; i < this.peg.length; i++) {
153
- if (this.peg[i] !== this.path[i]) {
154
- isprefixpath = false
155
- break
156
- }
157
- }
158
- }
159
- // Degenerate case: peg is all empty strings (e.g. path("")) and path is empty.
160
- if (!isprefixpath && this.peg.length > 0 && this.path.length === 0) {
161
- let allEmpty = true
162
- for (let i = 0; i < this.peg.length; i++) {
163
- if ('' !== this.peg[i]) { allEmpty = false; break }
164
- }
165
- isprefixpath = allEmpty
166
- }
167
-
168
- let refpath: string[] = []
169
- let pI = 0
170
- // let descent = ''
171
-
172
- if (isprefixpath) {
173
- // console.log('SELFPATH', selfpath, 'PEGPATH', pegpath)
174
- out = makeNilErr(ctx, 'path_cycle', this)
175
- }
176
- else {
177
-
178
- let parts: string[] = []
179
-
180
- let modes: string[] = []
181
-
182
- for (let pI = 0; pI < this.peg.length; pI++) {
183
- let part = this.peg[pI]
184
- if (part instanceof VarVal) {
185
- let strval = (part as VarVal).peg
186
- let name = strval ? '' + strval.peg : ''
187
-
188
- if ('KEY' === name) {
189
- if (pI === this.peg.length - 1) {
190
- modes.push(name)
191
- }
192
- else {
193
- // TODO: return a Nil explaining error
194
- return
195
- }
196
- }
197
-
198
- if ('SELF' === name) {
199
- if (pI === 0) {
200
- modes.push(name)
201
- }
202
- else {
203
- // TODO: return a Nil explaining error
204
- return
205
- }
206
- }
207
- else if ('PARENT' === name) {
208
- if (pI === 0) {
209
- modes.push(name)
210
- }
211
- else {
212
- // TODO: return a Nil explaining error
213
- return
214
- }
215
- }
216
- else if (0 === modes.length) {
217
- part = (part as VarVal).unify(top(), ctx)
218
- if (part.isNil) {
219
- // TODO: var not found, so can't find path
220
- return
221
- }
222
- else {
223
- part = '' + part.peg
224
- }
225
- }
226
- }
227
- else {
228
- parts.push(part)
229
- }
230
- }
231
-
232
- if (this.absolute) {
233
- refpath = parts
234
- }
235
- else {
236
- // TODO: deprecate $KEY, etc
237
- refpath = this.path.slice(
238
- 0,
239
- (
240
- modes.includes('SELF') ? 0 :
241
- modes.includes('PARENT') ? -1 :
242
- -1 // siblings
243
- )
244
- ).concat(parts)
245
- }
246
-
247
- let sep = '.'
248
- refpath = refpath
249
- .reduce(((a: string[], p: string) =>
250
- (p === sep ? a.length = a.length - 1 : a.push(p), a)), [])
251
-
252
- if (modes.includes('KEY')) {
253
- let key = this.path[this.path.length - 2]
254
- let sv = new StringVal({ peg: null == key ? '' : key }, ctx)
255
-
256
- // TODO: other props?
257
- sv.dc = DONE
258
- sv.path = this.path
259
-
260
- return sv
261
- }
262
-
263
- let node: Val | null = ctx.root as Val
264
-
265
- let nopath = false
266
-
267
- if (null != node) {
268
- for (; pI < refpath.length; pI++) {
269
- let part = refpath[pI]
270
- // console.log('PART', pI, part, node)
271
-
272
- // descent += (' | ' + pI + '=' + node.canon) // Util.inspect(node))
273
-
274
- if (node.isMap) {
275
- node = node.peg[part]
276
- }
277
- else if (node.isList) {
278
- node = node.peg[part]
279
- }
280
- else if (node.isConjunct || node.isDisjunct) {
281
- // Collect matching children from all junction terms,
282
- // flattening nested conjuncts and disjuncts.
283
- // Spreads match any key — their peg is always included.
284
- const matches: Val[] = []
285
- const stack = [...node.peg]
286
- while (stack.length > 0) {
287
- const term = stack.pop()!
288
- if (term.isConjunct || term.isDisjunct) {
289
- stack.push(...term.peg)
290
- }
291
- else if (term.isSpread) {
292
- matches.push(term.peg)
293
- }
294
- else if ((term.isMap || term.isList) && term.peg[part] != null) {
295
- matches.push(term.peg[part])
296
- }
297
- }
298
- if (matches.length === 1) {
299
- node = matches[0]
300
- }
301
- else if (matches.length > 1) {
302
- node = node.isConjunct
303
- ? new ConjunctVal({ peg: matches })
304
- : new DisjunctVal({ peg: matches })
305
- }
306
- else {
307
- node = null
308
- }
309
- }
310
- else if (node.done) {
311
- nopath = true
312
- break;
313
- }
314
- else {
315
- break;
316
- }
317
-
318
- if (null == node) {
319
- nopath = true
320
- break
321
- }
322
-
323
- }
324
- }
325
-
326
- // console.log('REFPATH', ctx.cc, pI, refpath, nopath, ctx.root, node)
327
-
328
-
329
- if (nopath) {
330
- out = makeNilErr(ctx, 'no_path', this)
331
- }
332
- else if (pI === refpath.length && node != null) {
333
- out = node
334
-
335
- // Types and hidden values are cloned and made concrete
336
- if (null != out) { // && (out.mark.type || out.mark.hide)) {
337
-
338
- // console.log('FOUND-A', out)
339
-
340
- if (this.mark.type || this.mark.hide) {
341
- out.mark.type = this.mark.type
342
- out.mark.hide = this.mark.hide
343
- }
344
-
345
- if (this.mark._hide_found) {
346
- out.mark.hide = true
347
- }
348
-
349
- // Cache clone+walk results per (ref, target) per iteration.
350
- const cacheKey = this.id + '|' + out.id
351
- const cache = ctx._refCloneCache
352
- const cached = cache?.get(cacheKey)
353
- if (cached !== undefined) {
354
- out = cached
355
- }
356
- else {
357
- out = out.clone(ctx)
358
- out.mark.type = false
359
- out.mark.hide = false
360
-
361
- walk(out, (_key: string | number | undefined, val: Val) => {
362
- val.mark.type = false
363
- val.mark.hide = false
364
- return val
365
- })
366
-
367
- cache?.set(cacheKey, out)
368
- }
369
- }
370
- }
371
- }
372
-
373
- // console.log('REF-FIND', ctx.cc, this.id, selfpath, 'PEG=', pegpath, 'RP', pI, refpath.join('.'), descent, 'O=', out?.id, out?.canon, out?.done)
374
-
375
- return out
376
- }
377
-
378
-
379
-
380
- same(peer: Val): boolean {
381
- return null == peer ? false : this.peg === peer.peg
382
- }
383
-
384
-
385
- clone(ctx: AontuContext, spec?: ValSpec): Val {
386
- let out = (super.clone(ctx, {
387
- peg: this.peg,
388
- absolute: this.absolute,
389
- ...(spec || {})
390
- }) as PathVal)
391
- return out
392
- }
393
-
394
-
395
- get canon() {
396
- let str =
397
- (this.absolute ? '$' : '') +
398
- (0 < this.peg.length ? '.' : '') +
399
- this.peg.map((p: any) => '.' === p ? '' :
400
- (p.isVal ? p.canon : '' + p))
401
- .join('.')
402
- return str
403
- }
404
-
405
-
406
- gen(ctx: AontuContext) {
407
- let nil = makeNilErr(
408
- ctx,
409
- 'ref',
410
- this,
411
- undefined,
412
- )
413
-
414
- nil.path = this.path
415
- nil.site.url = this.site.url
416
- nil.site.row = this.site.row
417
- nil.site.col = this.site.col
418
-
419
- return undefined
420
- }
421
-
422
-
423
- inspection() {
424
- return [
425
- this.absolute ? 'absolute' : '',
426
- this.prefix ? 'prefix' : '',
427
- ].filter(p => '' != p).join(',')
428
- }
429
-
430
- }
431
-
432
-
433
- export {
434
- PathVal,
435
- }
@@ -1,275 +0,0 @@
1
- /* Copyright (c) 2025 Richard Rodger, MIT License */
2
-
3
- // SpreadVal represents a spread constraint (&:{...}).
4
- // It owns all spread application logic — MapVal and ListVal know
5
- // nothing about spreads. A parsed `{a:1, &:{x:2}}` becomes
6
- // `ConjunctVal([MapVal({a:1}), SpreadVal({x:2})])`.
7
- //
8
- // SpreadVal.unify applies the constraint to a peer MapVal/ListVal
9
- // by unifying each of the peer's children with a per-key clone of
10
- // the spread constraint.
11
-
12
- import type {
13
- Val,
14
- ValSpec,
15
- } from '../type'
16
-
17
- import {
18
- DONE,
19
- } from '../type'
20
-
21
- import { AontuContext } from '../ctx'
22
- import { unite } from '../unify'
23
-
24
- import {
25
- propagateMarks,
26
- walk,
27
- explainOpen,
28
- ec,
29
- explainClose,
30
- } from '../utility'
31
-
32
- import { makeNilErr } from '../err'
33
-
34
- import {
35
- top
36
- } from './top'
37
-
38
- import { FeatureVal } from './FeatureVal'
39
- import { ConjunctVal } from './ConjunctVal'
40
- import { NilVal } from './NilVal'
41
- import { MapVal } from './MapVal'
42
- import { ListVal } from './ListVal'
43
-
44
-
45
- class SpreadVal extends FeatureVal {
46
- isSpread = true
47
- isGenable = true
48
- cjo = 110000 // Sorts after MapVal/ListVal in ConjunctVal norm
49
-
50
- constructor(spec: ValSpec, ctx?: AontuContext) {
51
- super(spec, ctx)
52
- }
53
-
54
-
55
- unify(peer: Val, ctx: AontuContext): Val {
56
- peer = peer ?? top()
57
-
58
- const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Spread', this, peer)
59
-
60
- let out: Val
61
-
62
- if (peer.isTop) {
63
- // Self-unify: spread is a constraint, not a value that converges.
64
- // Mark done to prevent fixpoint cycling.
65
- out = this
66
- out.dc = DONE
67
- }
68
- else if ((peer as any).isSpread) {
69
- // SpreadVal + SpreadVal: unify the two constraints
70
- const merged = unite(
71
- te ? ctx.clone({ explain: ec(te, 'SPR') }) : ctx,
72
- this.peg, peer.peg, 'spread-merge')
73
- out = new SpreadVal({ peg: merged }, ctx)
74
- out.dc = merged.done ? DONE : this.dc + 1
75
- }
76
- else if (peer.isMap) {
77
- // SpreadVal + MapVal: apply spread to each map key
78
- out = this.applyToMap(peer as any, ctx, te)
79
- }
80
- else if (peer.isList) {
81
- // SpreadVal + ListVal: apply spread to each list element
82
- out = this.applyToList(peer as any, ctx, te)
83
- }
84
- else if (peer.isConjunct) {
85
- // SpreadVal + ConjunctVal: unify with the conjunct.
86
- // The conjunct fold will place us last (high cjo).
87
- out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'SCJ') }) : ctx)
88
- }
89
- else {
90
- // SpreadVal + other: defer by wrapping in ConjunctVal
91
- out = new ConjunctVal({ peg: [peer, this] }, ctx)
92
- out.dc = this.dc + 1
93
- }
94
-
95
- // Track unresolved spread count.
96
- // cc=0: increment for spreads that don't vanish.
97
- // cc>0: decrement when a spread vanishes.
98
- if (0 === ctx.cc) {
99
- if (out.isSpread && !out.done) {
100
- ctx.sc++
101
- }
102
- }
103
- else if (ctx.sc > 0) {
104
- if (!(out.isSpread && !out.done)) {
105
- ctx.sc--
106
- }
107
- }
108
-
109
- ctx.explain && explainClose(te, out)
110
- return out
111
- }
112
-
113
-
114
- // Apply this spread constraint to each key in a MapVal.
115
- // Uses unite() per key with the correct descended context.
116
- applyToMap(map: MapVal, ctx: AontuContext, te: any): Val {
117
- const spread = this.peg
118
-
119
- const mapKeys = Object.keys(map.peg)
120
-
121
- // If map has no keys, preserve the spread for future merges.
122
- // Mark as DONE to prevent fixpoint cycling.
123
- if (mapKeys.length === 0) {
124
- const out = new ConjunctVal({ peg: [map, this] }, ctx)
125
- out.dc = DONE
126
- return out
127
- }
128
-
129
- const out = new MapVal({ peg: {} }, ctx)
130
- out.closed = map.closed
131
- out.optionalKeys = 0 < map.optionalKeys.length
132
- ? [...map.optionalKeys] : map.optionalKeys
133
- out.site = map.site
134
-
135
- let done = true
136
-
137
- for (const key of mapKeys) {
138
- const child = map.peg[key]
139
- const keyctx = ctx.descend(key)
140
- // Clone the spread for this key's context, then resolve any
141
- // path-dependent functions (key(), path(), etc.) by unifying
142
- // with TOP. This ensures the spread values are concrete before
143
- // being merged as peer keys into the child map.
144
- let key_spread = spread.spreadClone(keyctx)
145
- if (!key_spread.done) {
146
- key_spread = unite(keyctx, key_spread, top(), 'spread-resolve')
147
- }
148
-
149
- // Clear type marks on the spread constraint root and its
150
- // direct children — type() constrains but should not mark
151
- // children as type-invisible.
152
- key_spread.mark.type = false
153
- key_spread.mark.hide = false
154
- if (key_spread.isMap) {
155
- for (const k in key_spread.peg) {
156
- if (key_spread.peg[k]?.isVal) {
157
- key_spread.peg[k].mark.type = false
158
- }
159
- }
160
- }
161
-
162
- propagateMarks(map, child)
163
-
164
- out.peg[key] =
165
- undefined === child ? key_spread :
166
- child.isNil ? child :
167
- key_spread.isNil ? key_spread :
168
- key_spread.isTop && child.done ? child :
169
- child.isTop && key_spread.done ? key_spread :
170
- unite(te ? keyctx.clone({ explain: ec(te, 'SK:' + key) }) : keyctx,
171
- child, key_spread, 'spread-apply')
172
-
173
- done = done && (DONE === out.peg[key].dc)
174
- }
175
-
176
- out.dc = done ? DONE : map.dc + 1
177
-
178
- propagateMarks(map, out)
179
- // NOTE: do not propagate type/hide marks from the spread constraint
180
- // to the output — a type spread constrains children but doesn't
181
- // make them type-invisible.
182
-
183
- return out
184
- }
185
-
186
-
187
- // Apply this spread constraint to each element in a ListVal.
188
- applyToList(list: ListVal, ctx: AontuContext, te: any): Val {
189
- const spread = this.peg
190
-
191
- const listKeys = Object.keys(list.peg)
192
-
193
- if (listKeys.length === 0) {
194
- const out = new ConjunctVal({ peg: [list, this] }, ctx)
195
- out.dc = DONE
196
- return out
197
- }
198
-
199
- const out = new ListVal({ peg: [] }, ctx)
200
- out.closed = list.closed
201
- out.optionalKeys = 0 < list.optionalKeys.length
202
- ? [...list.optionalKeys] : list.optionalKeys
203
- out.site = list.site
204
-
205
- let done = true
206
-
207
- for (const key of listKeys) {
208
- const child = list.peg[key]
209
- const keyctx = ctx.descend(key)
210
- const key_spread = spread.spreadClone(keyctx)
211
-
212
- propagateMarks(list, child)
213
-
214
- out.peg[key as any] =
215
- undefined === child ? key_spread :
216
- child.isNil ? child :
217
- key_spread.isNil ? key_spread :
218
- key_spread.isTop && child.done ? child :
219
- child.isTop && key_spread.done ? key_spread :
220
- unite(te ? keyctx.clone({ explain: ec(te, 'SL:' + key) }) : keyctx,
221
- child, key_spread, 'spread-apply-list')
222
-
223
- done = done && (DONE === out.peg[key as any]?.dc)
224
- }
225
-
226
- out.dc = done ? DONE : list.dc + 1
227
-
228
- propagateMarks(list, out)
229
-
230
- return out
231
- }
232
-
233
-
234
- clone(ctx: AontuContext, spec?: ValSpec): Val {
235
- const out = new SpreadVal({
236
- peg: this.peg.clone(ctx, spec),
237
- ...(spec || {}),
238
- }, ctx)
239
- out.dc = this.done ? DONE : out.dc
240
- out.site = this.site
241
- return out
242
- }
243
-
244
-
245
- spreadClone(ctx: AontuContext): Val {
246
- if (!this.isPathDependent) return this
247
- return this.clone(ctx)
248
- }
249
-
250
-
251
- get canon(): string {
252
- // Use {&:...} for map spreads, [&:...] for list spreads, {&:X} for scalars
253
- const pc = this.peg.canon
254
- if (this.peg.isMap) return '{&:' + pc.slice(1, -1) + '}' // {&:k:v,...}
255
- if (this.peg.isList) return '[&:' + pc.slice(1, -1) + ']' // [&:v,...]
256
- return '{&:' + pc + '}'
257
- }
258
-
259
-
260
- gen(_ctx: AontuContext) {
261
- // Unresolved spread (never applied to a map/list) generates
262
- // as undefined — the spread is a constraint, not a value.
263
- return undefined
264
- }
265
-
266
-
267
- inspection() {
268
- return 'spread'
269
- }
270
- }
271
-
272
-
273
- export {
274
- SpreadVal,
275
- }