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
package/src/val/MapVal.ts CHANGED
@@ -8,6 +8,7 @@ import type {
8
8
 
9
9
  import {
10
10
  DONE,
11
+ SPREAD,
11
12
  } from '../type'
12
13
 
13
14
  import { AontuContext } from '../ctx'
@@ -27,13 +28,13 @@ import {
27
28
  } from './top'
28
29
 
29
30
 
31
+ import { ConjunctVal } from './ConjunctVal'
30
32
  import { NilVal } from './NilVal'
31
33
  import { BagVal } from './BagVal'
32
34
 
33
35
 
34
36
  class MapVal extends BagVal {
35
37
  isMap = true
36
- _canonCache?: string
37
38
 
38
39
  constructor(
39
40
  spec: ValSpec,
@@ -47,6 +48,23 @@ class MapVal extends BagVal {
47
48
 
48
49
  this.mark.type = !!spec.mark?.type
49
50
  this.mark.hide = !!spec.mark?.hide
51
+
52
+ let spread = (this.peg as any)[SPREAD]
53
+ delete (this.peg as any)[SPREAD]
54
+
55
+ if (spread) {
56
+ if ('&' === spread.o) {
57
+ // TODO: handle existing spread!
58
+ this.spread.cj =
59
+ Array.isArray(spread.v) ?
60
+ 1 < spread.v.length ?
61
+ new ConjunctVal({ peg: spread.v }, ctx) :
62
+ spread.v[0] :
63
+ spread.v
64
+ }
65
+ }
66
+
67
+ // console.log('MAPVAL-ctor', this.type, spec)
50
68
  }
51
69
 
52
70
 
@@ -57,23 +75,6 @@ class MapVal extends BagVal {
57
75
 
58
76
  const TOP = top()
59
77
  peer = peer ?? TOP
60
-
61
- // Fast path: both maps done, no spreads, peer's keys are a
62
- // subset of this's keys with the same child references, and
63
- // neither side has type/hide marks. No new information.
64
- if (this.done && peer instanceof MapVal && peer.done
65
- && !this.mark.type && !this.mark.hide
66
- && !peer.mark.type && !peer.mark.hide) {
67
- let canSkip = true
68
- for (const k in peer.peg) {
69
- if (this.peg[k] !== peer.peg[k]) {
70
- canSkip = false
71
- break
72
- }
73
- }
74
- if (canSkip) return this
75
- }
76
-
77
78
  const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Map', this, peer)
78
79
 
79
80
  let done: boolean = true
@@ -83,7 +84,8 @@ class MapVal extends BagVal {
83
84
  let out: MapVal | NilVal = (peer.isTop ? this : new MapVal({ peg: {} }, ctx))
84
85
 
85
86
  out.closed = this.closed
86
- out.optionalKeys = 0 < this.optionalKeys.length ? [...this.optionalKeys] : this.optionalKeys
87
+ out.optionalKeys = [...this.optionalKeys]
88
+ out.spread.cj = this.spread.cj
87
89
  out.site = this.site
88
90
 
89
91
  if (peer instanceof MapVal) {
@@ -106,47 +108,53 @@ class MapVal extends BagVal {
106
108
  out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'SPC') }) : ctx) as MapVal
107
109
  exit = true
108
110
  }
111
+
109
112
  }
113
+
114
+ if (!exit) {
115
+ out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
116
+ null == peer.spread.cj ? out.spread.cj : (
117
+ out.spread.cj =
118
+ unite(te ? ctx.clone({ explain: ec(te, 'SPR') }) : ctx,
119
+ out.spread.cj, peer.spread.cj, 'map-self')
120
+ )
121
+ )
122
+ }
123
+ }
124
+ else {
125
+ // console.log('MAPVAL-PEER-OTHER', this.id, this.canon, this.done, peer.id, peer.canon, peer.done)
110
126
  }
111
127
 
112
128
 
113
129
  if (!exit) {
114
130
  out.dc = this.dc + 1
115
131
 
116
- // Fast path: self-unify with TOP.
117
- // If all children are already done, the map is fully converged.
118
- if (peer.isTop) {
119
- let allChildrenDone = true
120
- for (let key in this.peg) {
121
- if (DONE !== this.peg[key]?.dc) {
122
- allChildrenDone = false
123
- break
124
- }
125
- }
126
- if (allChildrenDone) {
127
- out.dc = DONE
128
- ctx.explain && explainClose(te, out)
129
- return out
130
- }
131
- }
132
+ // let newtype = this.type || peer.type
133
+
134
+ let spread_cj = out.spread.cj ?? TOP
132
135
 
133
- // Unify own children
136
+ // Always unify own children first
134
137
  for (let key in this.peg) {
135
- const child = this.peg[key]
136
138
  const keyctx = ctx.descend(key)
137
139
 
140
+ const key_spread_cj = spread_cj.spreadClone(keyctx)
141
+ const child = this.peg[key]
142
+
138
143
  propagateMarks(this, child)
139
144
 
140
145
  out.peg[key] =
141
- undefined === child ? top() :
146
+ undefined === child ? key_spread_cj :
142
147
  child.isNil ? child :
143
- child.done ? child :
144
- unite(te ? keyctx.clone({ explain: ec(te, 'KEY:' + key) }) : keyctx,
145
- child, top(), 'map-own')
148
+ key_spread_cj.isNil ? key_spread_cj :
149
+ key_spread_cj.isTop && child.done ? child :
150
+ child.isTop && key_spread_cj.done ? key_spread_cj :
151
+ unite(te ? keyctx.clone({ explain: ec(te, 'KEY:' + key) }) : keyctx,
152
+ child, key_spread_cj, 'map-own')
146
153
 
147
154
  done = (done && DONE === out.peg[key].dc)
148
155
  }
149
156
 
157
+ const allowedKeys: string[] = this.closed ? Object.keys(this.peg) : []
150
158
  let bad: NilVal | undefined = undefined
151
159
 
152
160
  if (peer instanceof MapVal) {
@@ -157,14 +165,12 @@ class MapVal extends BagVal {
157
165
  for (let peerkey in upeer.peg) {
158
166
  let peerchild = upeer.peg[peerkey]
159
167
 
160
- if (this.closed && !(peerkey in this.peg)) {
168
+ if (this.closed && !allowedKeys.includes(peerkey)) {
161
169
  bad = makeNilErr(ctx, 'closed', peerchild, undefined)
162
170
  }
163
171
 
164
172
  // key optionality is additive
165
- if (0 < upeer.optionalKeys.length
166
- && upeer.optionalKeys.includes(peerkey)
167
- && !out.optionalKeys.includes(peerkey)) {
173
+ if (upeer.optionalKeys.includes(peerkey) && !out.optionalKeys.includes(peerkey)) {
168
174
  out.optionalKeys.push(peerkey)
169
175
  }
170
176
 
@@ -174,11 +180,19 @@ class MapVal extends BagVal {
174
180
 
175
181
  let oval = out.peg[peerkey] =
176
182
  undefined === child ? this.handleExpectedVal(peerkey, peerchild, this, ctx) :
177
- child.isTop && peerchild.done ? peerchild :
178
- child.isNil ? child :
179
- peerchild.isNil ? peerchild :
180
- unite(te ? peerctx.clone({ explain: ec(te, 'CHD') }) : peerctx,
181
- child, peerchild, 'map-peer')
183
+ child.isTop && peerchild.done ? peerchild :
184
+ child.isNil ? child :
185
+ peerchild.isNil ? peerchild :
186
+ unite(te ? peerctx.clone({ explain: ec(te, 'CHD') }) : peerctx,
187
+ child, peerchild, 'map-peer')
188
+
189
+ if (this.spread.cj) {
190
+ let key_spread_cj = spread_cj.spreadClone(peerctx)
191
+
192
+ oval = out.peg[peerkey] =
193
+ unite(te ? peerctx.clone({ explain: ec(te, 'PSP:' + peerkey) }) : peerctx,
194
+ oval, key_spread_cj, 'map-peer-spread')
195
+ }
182
196
 
183
197
  propagateMarks(this, oval)
184
198
 
@@ -199,41 +213,66 @@ class MapVal extends BagVal {
199
213
  out.dc = done ? DONE : out.dc
200
214
  propagateMarks(peer, out)
201
215
  propagateMarks(this, out)
202
-
203
216
  }
204
217
  }
205
218
 
219
+ // console.log(
220
+ // 'MAPVAL-OUT', out.canon,
221
+ // '\n SELF', this,
222
+ // '\n PEER', peer,
223
+ // '\n OUT', out,
224
+ // '\n FROM', (out as any).spread.cj
225
+ // )
226
+
206
227
  ctx.explain && explainClose(te, out)
207
228
 
208
229
  return out
209
230
  }
210
231
 
211
232
 
212
- // Optimized clone for use as a spread constraint: share
213
- // path-independent children, clone only path-dependent ones.
233
+ // Spread clone: return a Val usable as the per-key spread constraint.
234
+ //
235
+ // Three tiers:
236
+ // 1. tree is path-independent (no RefVal/KeyFuncVal/PathFuncVal/
237
+ // MoveFuncVal/SuperFuncVal anywhere below): return `this` directly.
238
+ // Nothing in the unify path mutates the spread root, and no
239
+ // child depends on its own stored .path, so sharing is safe.
240
+ // 2. top-level children are all ScalarKindVal: shallow clone
241
+ // (share children, fresh MapVal wrapper).
242
+ // 3. otherwise: full deep clone via `this.clone(ctx)`.
243
+ //
244
+ // Tier 1 handles the foo-sdk common case of simple type-constraint
245
+ // spreads like `&:{active: *true | boolean, version: *'0.0.1' | string}`,
246
+ // which are cloned thousands of times per run.
214
247
  spreadClone(ctx: AontuContext): Val {
215
248
  if (!this.isPathDependent) return this
216
249
 
250
+ let allScalarKind = true
251
+ for (let key in this.peg) {
252
+ if (!(this.peg[key] as any)?.isScalarKind) {
253
+ allScalarKind = false
254
+ break
255
+ }
256
+ }
257
+
258
+ if (!allScalarKind) {
259
+ return this.clone(ctx)
260
+ }
261
+
217
262
  let out = (super.clone(ctx) as MapVal)
218
263
  out.peg = {}
219
264
 
220
265
  for (let entry of Object.entries(this.peg)) {
221
- const child = entry[1] as Val
222
- if (child?.isVal && child.isPathDependent) {
223
- out.peg[entry[0]] = child.clone(ctx, { path: [...out.path, entry[0]] })
224
- }
225
- else if (child?.isVal) {
226
- const wrapper = Object.create(child)
227
- wrapper.mark = { ...child.mark }
228
- out.peg[entry[0]] = wrapper
229
- }
230
- else {
231
- out.peg[entry[0]] = child
232
- }
266
+ out.peg[entry[0]] = entry[1]
267
+ }
268
+
269
+ // Must create a new spread object to avoid mutating the original.
270
+ out.spread = {
271
+ cj: this.spread.cj ? this.spread.cj.spreadClone(ctx) : undefined,
233
272
  }
234
273
 
235
274
  out.closed = this.closed
236
- out.optionalKeys = 0 < this.optionalKeys.length ? [...this.optionalKeys] : this.optionalKeys
275
+ out.optionalKeys = [...this.optionalKeys]
237
276
 
238
277
  return out
239
278
  }
@@ -246,25 +285,36 @@ class MapVal extends BagVal {
246
285
  for (let entry of Object.entries(this.peg)) {
247
286
  out.peg[entry[0]] =
248
287
  (entry[1] as any)?.isVal ?
288
+ // (entry[1] as Val).clone(ctx, spec?.mark ? { mark: spec.mark } : {}) :
249
289
  (entry[1] as Val).clone(ctx, {
250
290
  mark: spec?.mark ?? {},
251
291
  path: [...out.path, entry[0]]
252
292
  }) :
253
293
  entry[1]
254
294
  }
295
+ if (this.spread.cj) {
296
+ out.spread.cj = this.spread.cj.clone(ctx, spec?.mark ? { mark: spec.mark } : {})
297
+ }
255
298
 
256
299
  out.closed = this.closed
257
300
  out.optionalKeys = [...this.optionalKeys]
258
301
 
302
+ // out.from = this.from
303
+
304
+ // console.log('MAPVAL-CLONE', this.canon, '->', out.canon)
259
305
  return out
260
306
  }
261
307
 
262
308
 
263
309
  get canon() {
264
- if (this._canonCache !== undefined) return this._canonCache
265
- let keys = Object.keys(this.peg).sort()
266
- const c = '' +
310
+ let keys = Object.keys(this.peg)
311
+ return '' +
312
+ // this.errcanon() +
313
+ // (this.mark.type ? '<type>' : '') +
314
+ // (this.id + '=') +
267
315
  '{' +
316
+ (this.spread.cj ? '&:' + this.spread.cj.canon +
317
+ (0 < keys.length ? ',' : '') : '') +
268
318
  keys
269
319
  .map(k => [
270
320
  JSON.stringify(k) +
@@ -273,19 +323,18 @@ class MapVal extends BagVal {
273
323
  (this.peg[k]?.canon ?? this.peg[k])
274
324
  ])
275
325
  .join(',') +
276
- '}'
277
- if (this.done) this._canonCache = c
278
- return c
326
+ '}' // + '<' + (this.mark.hide ? 'H' : '') + '>'
327
+
279
328
  }
280
329
 
281
330
 
282
- inspection(_d?: number) {
283
- return ''
331
+ inspection(d?: number) {
332
+ return this.spread.cj ? '&:' + this.spread.cj.inspect(null == d ? 0 : d + 1) : ''
284
333
  }
285
334
 
286
335
  }
287
336
 
288
337
 
289
338
  export {
290
- MapVal,
339
+ MapVal
291
340
  }
@@ -13,7 +13,6 @@ import {
13
13
  import { makeNilErr } from '../err'
14
14
 
15
15
  import { NilVal } from '../val/NilVal'
16
- import { PathVal } from '../val/PathVal'
17
16
 
18
17
  import {
19
18
  walk
@@ -27,60 +26,6 @@ import { PrefFuncVal } from './PrefFuncVal'
27
26
 
28
27
 
29
28
 
30
- // Navigate the tree using a PathVal's resolved path and hide the source.
31
- function hideAtPath(root: Val, pv: PathVal) {
32
- // Compute the refpath the same way PathVal.find does
33
- const parts: string[] = []
34
- for (const part of pv.peg) {
35
- if ('string' === typeof part) parts.push(part)
36
- }
37
-
38
- let refpath: string[]
39
- if (pv.absolute) {
40
- refpath = parts
41
- }
42
- else {
43
- refpath = pv.path.slice(0, -1).concat(parts)
44
- }
45
-
46
- // Walk to the source, handling conjuncts/disjuncts
47
- let node: any = root
48
- for (let i = 0; i < refpath.length; i++) {
49
- const part = refpath[i]
50
- if (node?.isMap || node?.isList) {
51
- node = node.peg[part]
52
- }
53
- else if (node?.isConjunct || node?.isDisjunct) {
54
- // Search junction terms for the key
55
- let found = null
56
- const stack = [...node.peg]
57
- while (stack.length > 0) {
58
- const term = stack.pop()
59
- if (term?.isConjunct || term?.isDisjunct) {
60
- stack.push(...term.peg)
61
- }
62
- else if ((term?.isMap || term?.isList) && term.peg[part] != null) {
63
- found = term.peg[part]
64
- break
65
- }
66
- }
67
- node = found
68
- }
69
- else {
70
- return
71
- }
72
- if (node == null) return
73
- }
74
-
75
- // Mark the source value hidden
76
- node.mark.hide = true
77
- walk(node, (_key: string | number | undefined, val: Val) => {
78
- val.mark.hide = true
79
- return val
80
- })
81
- }
82
-
83
-
84
29
  class MoveFuncVal extends FuncBaseVal {
85
30
  isMoveFunc = true
86
31
 
@@ -105,40 +50,30 @@ class MoveFuncVal extends FuncBaseVal {
105
50
  }
106
51
 
107
52
  resolve(ctx: AontuContext, args: Val[]) {
108
- let arg = args[0] ?? makeNilErr(ctx, 'arg', this)
109
- if (arg.isNil) return arg
53
+ let out = args[0] ?? makeNilErr(ctx, 'arg', this)
110
54
 
111
- let src: Val
55
+ const orig = out
112
56
 
113
- if (arg instanceof PathVal) {
114
- // Get clone for the destination
115
- src = arg.find(ctx) as Val
116
- if (src == null || src.isNil) return makeNilErr(ctx, 'arg', this)
57
+ if (!orig.isNil) {
58
+ const src = orig.clone(ctx)
117
59
 
118
- // Hide the source in the tree by navigating to it
119
- hideAtPath(ctx.root as Val, arg)
120
- }
121
- else {
122
- src = arg.clone(ctx)
60
+ if (src.isRef) {
61
+ src.mark._hide_found = true
62
+ }
123
63
 
124
- // Hide the original
125
- arg.mark.hide = true
126
- walk(arg, (_key: string | number | undefined, val: Val) => {
64
+ walk(orig, (_key: string | number | undefined, val: Val) => {
127
65
  val.mark.hide = true
128
66
  return val
129
67
  })
68
+
69
+ // out = new CopyFuncVal({ peg: [src] }, ctx)
70
+ out = new PrefFuncVal({ peg: [src] }, ctx)
71
+ // out = src
130
72
  }
131
73
 
132
- // Clear marks on the clone (like copy)
133
- src.mark.type = false
134
- src.mark.hide = false
135
- walk(src, (_key: string | number | undefined, val: Val) => {
136
- val.mark.type = false
137
- val.mark.hide = false
138
- return val
139
- })
74
+ // console.log('MOVE-resolve', orig, out)
140
75
 
141
- return new PrefFuncVal({ peg: [src] }, ctx)
76
+ return out
142
77
  }
143
78
  }
144
79
 
@@ -6,10 +6,6 @@ import type {
6
6
  ValSpec,
7
7
  } from '../type'
8
8
 
9
- import {
10
- DONE,
11
- } from '../type'
12
-
13
9
  import {
14
10
  AontuContext,
15
11
  } from '../ctx'
@@ -17,7 +13,7 @@ import {
17
13
  import { makeNilErr } from '../err'
18
14
 
19
15
  import { NilVal } from '../val/NilVal'
20
- import { PathVal } from '../val/PathVal'
16
+ import { RefVal } from '../val/RefVal'
21
17
  import { FuncBaseVal } from './FuncBaseVal'
22
18
 
23
19
 
@@ -49,26 +45,12 @@ class PathFuncVal extends FuncBaseVal {
49
45
  let arg = args[0]
50
46
 
51
47
  if (0 === this.prepared) {
52
- if (arg instanceof PathVal) {
53
- // PathVal from dotted arg resolve via find().
54
- const found = arg.find(ctx)
55
- if (found != null && !found.isNil) {
56
- arg = found
57
- }
58
- else {
59
- arg.dc = DONE
60
- }
61
- }
62
- else if (arg.isScalar && arg.peg != null && arg.peg !== ''
63
- && ('string' === typeof arg.peg || arg.isNumber)) {
64
- // String or number arg like path("foo") or path(0.2) — create a path value
65
- arg = this.place(new PathVal({ peg: [arg], absolute: false })) as PathVal
66
- arg.dc = DONE
48
+ if (arg.isScalar) {
49
+ arg = this.place(new RefVal({ peg: [arg], absolute: false }))
67
50
  }
68
- else if (arg.isNil || (arg.isScalar && (arg.peg === '' || arg.peg == null))) {
51
+ else if (!arg.isRef) {
69
52
  arg = makeNilErr(ctx, 'invalid-arg', this)
70
53
  }
71
- // else: already resolved by preprocessing — pass through
72
54
  }
73
55
 
74
56
  args[0] = arg
@@ -82,13 +64,6 @@ class PathFuncVal extends FuncBaseVal {
82
64
  resolve(ctx: AontuContext, args: Val[]) {
83
65
  let out = args[0] ?? makeNilErr(ctx, 'arg', this)
84
66
 
85
- if (out instanceof PathVal) {
86
- const found = out.find(ctx)
87
- if (found != null && !found.isNil) {
88
- out = found
89
- }
90
- }
91
-
92
67
  return out
93
68
  }
94
69
 
@@ -22,7 +22,6 @@ import {
22
22
 
23
23
  import { top } from './top'
24
24
 
25
- import { ConjunctVal } from './ConjunctVal'
26
25
  import { FeatureVal } from './FeatureVal'
27
26
 
28
27
 
@@ -65,13 +64,10 @@ class PrefVal extends FeatureVal {
65
64
  if (!this.peg.done) {
66
65
  const resolved = unite(te ? ctx.clone({ explain: ec(te, 'RES') }) : ctx,
67
66
  this.peg, top(), 'pref/resolve')
67
+ // console.log('PREF-RESOLVED', this.peg.canon, '->', resolved)
68
68
  this.peg = resolved
69
69
  this.superpeg = this.peg.superior()
70
70
  }
71
- else if (this.superpeg.isTop && !this.peg.isTop) {
72
- // Stale superpeg from pre-resolved PathVal — recalculate
73
- this.superpeg = this.peg.superior()
74
- }
75
71
 
76
72
  if (peer instanceof PrefVal) {
77
73
  why += 'pref-'
@@ -110,20 +106,11 @@ class PrefVal extends FeatureVal {
110
106
  else if (!peer.isTop) {
111
107
  why += 'super-'
112
108
 
113
- // If peg is unresolved (e.g. deferred ref), don't decide yet
114
- // preserve both sides so a later pass can resolve.
115
- if (!this.peg.done) {
116
- out = new ConjunctVal({ peg: [this, peer] }, ctx)
117
- done = false
118
- why += 'defer'
119
- }
120
- else {
121
- out = unite(te ? ctx.clone({ explain: ec(te, 'SUPER') }) : ctx,
122
- this.superpeg, peer, 'pref-super/' + this.id)
123
- if (out.same(this.superpeg)) {
124
- out = this.peg
125
- why += 'same'
126
- }
109
+ out = unite(te ? ctx.clone({ explain: ec(te, 'SUPER') }) : ctx,
110
+ this.superpeg, peer, 'pref-super/' + this.id)
111
+ if (out.same(this.superpeg)) {
112
+ out = this.peg
113
+ why += 'same'
127
114
  }
128
115
 
129
116
  // }
@@ -1,6 +1,8 @@
1
1
  /* Copyright (c) 2021-2025 Richard Rodger, MIT License */
2
2
 
3
3
 
4
+ import Util from 'node:util'
5
+
4
6
  import {
5
7
  walk,
6
8
  explainOpen,
@@ -14,7 +16,6 @@ import type {
14
16
  ValSpec,
15
17
  } from '../type'
16
18
 
17
-
18
19
  import {
19
20
  DONE,
20
21
  } from '../type'
@@ -136,23 +137,10 @@ class RefVal extends FeatureVal {
136
137
  unify(peer: Val, ctx: AontuContext): Val {
137
138
  peer = peer ?? top()
138
139
 
139
- // TEMPORARY: nerf RefVals to verify spread-first resolution
140
- return makeNilErr(ctx, 'ref_test_block', this, peer)
141
-
142
140
  const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Ref', this, peer)
143
141
  let out: Val = this
144
142
  let why = 'id'
145
143
 
146
- // Defer ref resolution on first pass and while spreads remain
147
- if (0 === ctx.cc || 0 < ctx.sc) {
148
- if (!peer.isTop && this.id !== peer.id) {
149
- out = new ConjunctVal({ peg: [this, peer] }, ctx)
150
- }
151
- out.dc = DONE === out.dc ? DONE : this.dc + 1
152
- explainClose(te, out)
153
- return out
154
- }
155
-
156
144
  if (this.id !== peer.id) {
157
145
 
158
146
  // TODO: not resolved when all Vals in path are done is an error
@@ -371,30 +359,31 @@ class RefVal extends FeatureVal {
371
359
  if (this.mark.type || this.mark.hide) {
372
360
  out.mark.type = this.mark.type
373
361
  out.mark.hide = this.mark.hide
362
+
363
+ // walk(out, (_key: string | number | undefined, val: Val) => {
364
+ // val.mark.type = this.mark.type
365
+ // val.mark.hide = this.mark.hide
366
+ // return val
367
+ // })
374
368
  }
375
369
 
376
370
  if (this.mark._hide_found) {
377
371
  out.mark.hide = true
378
372
  }
379
373
 
380
- // Cache clone+walk results per (ref, target) per iteration.
381
- const cacheKey = this.id + '|' + out.id
382
- const cache = ctx._refCloneCache
383
- const cached = cache?.get(cacheKey)
384
- if (cached !== undefined) {
385
- out = cached
386
- }
387
- else {
388
- out = out.clone(ctx)
374
+ // console.log('FOUND-B', out)
389
375
 
390
- walk(out, (_key: string | number | undefined, val: Val) => {
391
- val.mark.type = false
392
- val.mark.hide = false
393
- return val
394
- })
376
+ out = out.clone(ctx)
395
377
 
396
- cache?.set(cacheKey, out)
397
- }
378
+ // if (this.mark.type || this.mark.hide) {
379
+ walk(out, (_key: string | number | undefined, val: Val) => {
380
+ val.mark.type = false
381
+ val.mark.hide = false
382
+ return val
383
+ })
384
+ //}
385
+
386
+ // onsole.log('FOUND-C', out)
398
387
  }
399
388
  }
400
389
  }