aontu 0.11.0 → 0.13.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 (73) hide show
  1. package/aontu.ts +13 -6
  2. package/dist/aontu.d.ts +3 -0
  3. package/dist/aontu.js +10 -4
  4. package/dist/aontu.js.map +1 -1
  5. package/dist/aontu.min.js +1 -1
  6. package/dist/lib/err.js +1 -1
  7. package/dist/lib/err.js.map +1 -1
  8. package/dist/lib/lang.d.ts +1 -2
  9. package/dist/lib/lang.js +130 -38
  10. package/dist/lib/lang.js.map +1 -1
  11. package/dist/lib/op/disjunct.js +2 -2
  12. package/dist/lib/op/disjunct.js.map +1 -1
  13. package/dist/lib/op/op.js +1 -1
  14. package/dist/lib/op/op.js.map +1 -1
  15. package/dist/lib/op/unite.js +36 -6
  16. package/dist/lib/op/unite.js.map +1 -1
  17. package/dist/lib/type.d.ts +10 -8
  18. package/dist/lib/type.js +2 -27
  19. package/dist/lib/type.js.map +1 -1
  20. package/dist/lib/unify.d.ts +7 -4
  21. package/dist/lib/unify.js +17 -29
  22. package/dist/lib/unify.js.map +1 -1
  23. package/dist/lib/val/ConjunctVal.d.ts +7 -4
  24. package/dist/lib/val/ConjunctVal.js +62 -31
  25. package/dist/lib/val/ConjunctVal.js.map +1 -1
  26. package/dist/lib/val/DisjunctVal.d.ts +5 -2
  27. package/dist/lib/val/DisjunctVal.js +15 -7
  28. package/dist/lib/val/DisjunctVal.js.map +1 -1
  29. package/dist/lib/val/ListVal.d.ts +5 -2
  30. package/dist/lib/val/ListVal.js +39 -19
  31. package/dist/lib/val/ListVal.js.map +1 -1
  32. package/dist/lib/val/MapVal.d.ts +5 -2
  33. package/dist/lib/val/MapVal.js +59 -30
  34. package/dist/lib/val/MapVal.js.map +1 -1
  35. package/dist/lib/val/Nil.d.ts +3 -2
  36. package/dist/lib/val/Nil.js +19 -5
  37. package/dist/lib/val/Nil.js.map +1 -1
  38. package/dist/lib/val/PrefVal.d.ts +6 -2
  39. package/dist/lib/val/PrefVal.js +18 -8
  40. package/dist/lib/val/PrefVal.js.map +1 -1
  41. package/dist/lib/val/RefVal.d.ts +11 -5
  42. package/dist/lib/val/RefVal.js +187 -39
  43. package/dist/lib/val/RefVal.js.map +1 -1
  44. package/dist/lib/val/ValBase.d.ts +10 -9
  45. package/dist/lib/val/ValBase.js +25 -6
  46. package/dist/lib/val/ValBase.js.map +1 -1
  47. package/dist/lib/val/VarVal.d.ts +14 -0
  48. package/dist/lib/val/VarVal.js +68 -0
  49. package/dist/lib/val/VarVal.js.map +1 -0
  50. package/dist/lib/val.d.ts +42 -8
  51. package/dist/lib/val.js +64 -18
  52. package/dist/lib/val.js.map +1 -1
  53. package/lib/err.ts +1 -1
  54. package/lib/lang.ts +168 -43
  55. package/lib/op/disjunct.ts +10 -3
  56. package/lib/op/op.ts +1 -1
  57. package/lib/op/unite.ts +44 -4
  58. package/lib/type.ts +12 -40
  59. package/lib/unify.ts +70 -29
  60. package/lib/val/ConjunctVal.ts +83 -46
  61. package/lib/val/DisjunctVal.ts +35 -12
  62. package/lib/val/ListVal.ts +57 -22
  63. package/lib/val/MapVal.ts +82 -51
  64. package/lib/val/Nil.ts +29 -9
  65. package/lib/val/PrefVal.ts +38 -14
  66. package/lib/val/RefVal.ts +254 -55
  67. package/lib/val/ValBase.ts +33 -28
  68. package/lib/val/VarVal.ts +139 -0
  69. package/lib/val.ts +116 -25
  70. package/package.json +8 -8
  71. package/dist/lib/common.d.ts +0 -8
  72. package/dist/lib/common.js +0 -3
  73. package/dist/lib/common.js.map +0 -1
package/lib/unify.ts CHANGED
@@ -1,11 +1,15 @@
1
- /* Copyright (c) 2021 Richard Rodger, MIT License */
1
+ /* Copyright (c) 2021-2023 Richard Rodger, MIT License */
2
2
 
3
3
 
4
4
  import type { Val } from './type'
5
5
 
6
- import { DONE, TOP } from './type'
6
+ import { DONE, } from './type'
7
7
 
8
8
 
9
+ import {
10
+ TOP
11
+ } from './val'
12
+
9
13
  import {
10
14
  Lang
11
15
  } from './lang'
@@ -16,8 +20,10 @@ import {
16
20
 
17
21
 
18
22
 
19
- import { MapVal } from '../lib/val/MapVal'
20
- import { RefVal } from '../lib/val/RefVal'
23
+
24
+
25
+ // import { MapVal } from '../lib/val/MapVal'
26
+ // import { RefVal } from '../lib/val/RefVal'
21
27
  import { Nil } from '../lib/val/Nil'
22
28
 
23
29
 
@@ -30,18 +36,27 @@ class Context {
30
36
  path: Path // Path to current Val.
31
37
  err: Nil[] // Nil error log of current unify.
32
38
  vc: number // Val counter to create unique val ids.
39
+ cc: number = -1
40
+ var: Record<string, Val> = {}
33
41
 
34
42
  constructor(cfg: {
35
- root: Val
43
+ root: Val,
44
+ path?: Path,
36
45
  err?: Nil[],
37
- vc?: number
46
+ vc?: number,
47
+ cc?: number,
48
+ var?: Record<string, Val>
38
49
  }) {
39
50
  this.root = cfg.root
40
- this.path = []
51
+ this.path = cfg.path || []
41
52
  this.err = cfg.err || []
42
53
 
43
54
  // Multiple unify passes will keep incrementing Val counter.
44
55
  this.vc = null == cfg.vc ? 1_000_000_000 : cfg.vc
56
+
57
+ this.cc = null == cfg.cc ? this.cc : cfg.cc
58
+
59
+ this.var = cfg.var || this.var
45
60
  }
46
61
 
47
62
 
@@ -52,8 +67,11 @@ class Context {
52
67
  }): Context {
53
68
  return new Context({
54
69
  root: cfg.root || this.root,
70
+ path: cfg.path,
55
71
  err: cfg.err || this.err,
56
72
  vc: this.vc,
73
+ cc: this.cc,
74
+ var: { ...this.var },
57
75
  })
58
76
  }
59
77
 
@@ -66,27 +84,49 @@ class Context {
66
84
  }
67
85
 
68
86
 
69
- find(ref: RefVal) {
87
+ // TODO: move to RefVal
88
+ /*
89
+ xfind(ref: RefVal) {
70
90
  // TODO: relative paths
71
91
  // if (this.root instanceof MapVal && ref.absolute) {
92
+
93
+ // NOTE: path *to* the ref, not the ref itself!
94
+ let fullpath = ref.path
95
+
72
96
  if (ref.absolute) {
73
- let node = this.root
74
- let pI = 0
75
- for (; pI < ref.parts.length; pI++) {
76
- let part = ref.parts[pI]
77
- if (node instanceof MapVal) {
78
- node = node.peg[part]
79
- }
80
- else {
81
- break;
82
- }
83
- }
97
+ fullpath = ref.parts.slice(1) // ignore '$' at start
98
+ }
99
+ else {
100
+ fullpath = fullpath.concat(ref.parts)
101
+ }
102
+
103
+ console.log('FP', ref.absolute, ref.parts, fullpath)
84
104
 
85
- if (pI === ref.parts.length) {
86
- return node
105
+ let node = this.root
106
+ let pI = 0
107
+ for (; pI < ref.parts.length; pI++) {
108
+ let part = ref.parts[pI]
109
+ if (node instanceof MapVal) {
110
+ node = node.peg[part]
111
+ }
112
+ else {
113
+ // console.log(
114
+ // 'FIND', ref.parts, pI, node.constructor.name,
115
+ // node.peg.map(
116
+ // (n: any) =>
117
+ // n.constructor.name + ':' + n.done +
118
+ // ' {' + Object.keys(n.peg) + '}'
119
+ // )
120
+ // )
121
+ break;
87
122
  }
88
123
  }
89
- }
124
+
125
+ if (pI === ref.parts.length) {
126
+ return node
127
+ }
128
+ }
129
+ */
90
130
  }
91
131
 
92
132
 
@@ -94,10 +134,10 @@ class Unify {
94
134
  root: Val
95
135
  res: Val
96
136
  err: Nil[]
97
- dc: number
137
+ cc: number
98
138
  lang: Lang
99
139
 
100
- constructor(root: Val | string, lang?: Lang) {
140
+ constructor(root: Val | string, lang?: Lang, ctx?: Context) {
101
141
  this.lang = lang || new Lang()
102
142
  if ('string' === typeof root) {
103
143
  root = this.lang.parse(root)
@@ -108,7 +148,8 @@ class Unify {
108
148
  this.err = []
109
149
 
110
150
  let res = root
111
- let ctx: Context = new Context({
151
+
152
+ ctx = ctx || new Context({
112
153
  root: res,
113
154
  err: this.err,
114
155
  })
@@ -118,13 +159,13 @@ class Unify {
118
159
  // perhaps parse should count intial vals, paths, etc?
119
160
 
120
161
 
121
- let maxdc = 999
122
- for (this.dc = 0; this.dc < maxdc && DONE !== res.done; this.dc++) {
162
+ let maxdc = 9 // 99
163
+ for (this.cc = 0; this.cc < maxdc && DONE !== res.done; this.cc++) {
164
+ // console.log('\n\nRES', this.dc)
123
165
  // console.log('\n\nRES', this.dc, res.canon)
124
166
  // console.dir(res, { depth: null })
125
-
167
+ ctx.cc = this.cc
126
168
  res = unite(ctx, res, TOP)
127
- // console.log('U', this.dc, res.canon)
128
169
  ctx = ctx.clone({ root: res })
129
170
  }
130
171
 
@@ -1,49 +1,47 @@
1
- /* Copyright (c) 2021-2022 Richard Rodger, MIT License */
1
+ /* Copyright (c) 2021-2023 Richard Rodger, MIT License */
2
2
 
3
3
 
4
4
  import type {
5
5
  Val,
6
- ValMap,
7
- ValList,
6
+ ValSpec,
8
7
  } from '../type'
9
8
 
10
9
  import {
11
10
  DONE,
12
- TOP,
13
11
  } from '../type'
14
12
 
15
- import {
16
- ValBase,
17
- } from '../val/ValBase'
18
-
19
- import {
20
- Nil,
21
- } from '../val/Nil'
22
-
23
- import { RefVal } from '../val/RefVal'
24
- import { MapVal } from '../val/MapVal'
25
13
 
26
14
  import {
27
15
  Context,
28
16
  } from '../unify'
29
17
 
30
18
 
31
- import {
32
- Site
33
- } from '../lang'
34
-
35
19
 
36
20
  import {
37
21
  unite
38
22
  } from '../op/op'
39
23
 
40
24
 
25
+ import { TOP } from '../val'
26
+ import { DisjunctVal } from '../val/DisjunctVal'
27
+ import { ListVal } from '../val/ListVal'
28
+ import { MapVal } from '../val/MapVal'
29
+ import { Nil } from '../val/Nil'
30
+ import { PrefVal } from '../val/PrefVal'
31
+ import { RefVal } from '../val/RefVal'
32
+ import { ValBase } from '../val/ValBase'
41
33
 
42
34
 
43
35
  // TODO: move main logic to op/conjunct
44
36
  class ConjunctVal extends ValBase {
45
- constructor(peg: Val[], ctx?: Context) {
46
- super(peg, ctx)
37
+
38
+ constructor(
39
+ spec: {
40
+ peg: Val[]
41
+ },
42
+ ctx?: Context
43
+ ) {
44
+ super(spec, ctx)
47
45
  }
48
46
 
49
47
  // NOTE: mutation!
@@ -53,6 +51,11 @@ class ConjunctVal extends ValBase {
53
51
  }
54
52
 
55
53
  unify(peer: Val, ctx: Context): Val {
54
+ // console.log('CONJUNCT UNIFY', this.done, this.path.join('.'), this.canon,
55
+ // 'P', peer.top || peer.constructor.name,
56
+ // peer.done, peer.path.join('.'), peer.canon)
57
+
58
+
56
59
  const mark = (Math.random() * 1e7) % 1e6 | 0
57
60
  // console.log('CONJUNCT unify', mark, this.done, this.canon, 'peer=', peer.canon)
58
61
 
@@ -61,10 +64,12 @@ class ConjunctVal extends ValBase {
61
64
  // Unify each term of conjunct against peer
62
65
  let upeer: Val[] = []
63
66
 
67
+
68
+ // console.log('CJa' + mark, this.peg.map((p: Val) => p.canon), 'p=', peer.canon)
64
69
  for (let vI = 0; vI < this.peg.length; vI++) {
65
- upeer[vI] = unite(ctx, this.peg[vI], peer)
70
+ upeer[vI] = unite(ctx, this.peg[vI], peer, 'cj-own' + mark)
66
71
 
67
- let prevdone = done
72
+ // let prevdone = done
68
73
  done = done && (DONE === upeer[vI].done)
69
74
 
70
75
  // console.log('CONJUNCT pud', mark, vI, done, prevdone, '|', upeer[vI].done, upeer[vI].canon)
@@ -87,12 +92,19 @@ class ConjunctVal extends ValBase {
87
92
  let outvals: Val[] = []
88
93
  let val: Val
89
94
 
95
+ // let mark = Math.random()
96
+
97
+ // console.log('CJ upeer', mark, upeer.map(v => v.canon))
98
+
99
+ let t0 = upeer[0]
100
+
90
101
  next_term:
91
102
  for (let pI = 0; pI < upeer.length; pI++) {
92
- let t0 = upeer[pI]
103
+ // let t0 = upeer[pI]
104
+ // console.log('CJ TERM t0', pI, t0.done, t0.canon)
93
105
 
94
106
  if (DONE !== t0.done) {
95
- let u0 = unite(ctx, t0, TOP)
107
+ let u0 = unite(ctx, t0, TOP, 'cj-peer-t0')
96
108
 
97
109
  if (
98
110
  DONE !== u0.done
@@ -107,6 +119,7 @@ class ConjunctVal extends ValBase {
107
119
 
108
120
  // console.log('CONJUNCT PUSH A', u0.id, u0.canon)
109
121
  outvals.push(u0)
122
+ // console.log('CJ outvals A', outvals.map(v => v.canon))
110
123
  continue next_term
111
124
  }
112
125
  else {
@@ -115,41 +128,50 @@ class ConjunctVal extends ValBase {
115
128
  }
116
129
 
117
130
  let t1 = upeer[pI + 1]
131
+ // console.log('CJ TERM t1', pI + 1, t1?.done, t1?.canon)
118
132
 
119
133
  if (null == t1) {
120
134
  // console.log('CONJUNCT PUSH B', t0.canon)
121
135
  outvals.push(t0)
136
+ // console.log('CJ outvals B', outvals.map(v => v.canon))
122
137
  }
123
138
 
124
139
  // Can't unite with a RefVal, unless also a RefVal with same path.
125
140
  else if (t0 instanceof RefVal && !(t1 instanceof RefVal)) {
126
141
  // console.log('CONJUNCT PUSH D', t0.canon)
127
142
  outvals.push(t0)
143
+ t0 = t1
144
+ // console.log('CJ outvals C', outvals.map(v => v.canon))
128
145
  }
129
146
 
130
147
  else {
131
- val = unite(ctx, t0, t1)
148
+ val = unite(ctx, t0, t1, 'cj-peer-t0t1')
132
149
  done = done && DONE === val.done
133
150
 
151
+ // Unite was just a conjunt anyway, so discard.
134
152
  if (val instanceof ConjunctVal) {
135
- if (t0.id === val.peg[0].id) {
136
- val = t0
137
- }
153
+ // if (t0.id === val.peg[0].id) {
154
+ // val = t0
155
+ outvals.push(t0)
156
+ t0 = t1
157
+ // console.log('CJ outvals D', outvals.map(v => v.canon))
158
+ //}
138
159
  }
139
160
  else if (val instanceof Nil) {
140
161
  return val
141
162
  }
142
-
163
+ else {
164
+ t0 = val
165
+ }
143
166
  // TODO: t0 should become this to avoid unnecessary repasses
144
167
  // console.log('CONJUNCT PUSH C', val.canon)
145
- outvals.push(val)
168
+ // outvals.push(val)
146
169
 
147
- pI++
170
+ // pI++
148
171
  }
149
172
  }
150
173
 
151
-
152
- // console.log('CONJUNCT outvals', mark, outvals.map(v => v.canon))
174
+ // console.log('CJ outvals', mark, outvals.map(v => v.canon))
153
175
 
154
176
  let out: Val
155
177
 
@@ -164,37 +186,52 @@ class ConjunctVal extends ValBase {
164
186
  out = outvals[0]
165
187
  }
166
188
  else {
167
- out = new ConjunctVal(outvals, ctx)
189
+ out = new ConjunctVal({ peg: outvals }, ctx)
168
190
  }
169
191
 
170
192
  out.done = done ? DONE : this.done + 1
171
193
 
172
- // console.log('CONJUNCT out', mark, out.done, out.canon)
194
+ // console.log('CJ out', out.done, out.canon)
173
195
 
174
196
  return out
175
197
  }
176
198
 
199
+
200
+ clone(spec?: ValSpec, ctx?: Context): Val {
201
+ let out = (super.clone(spec, ctx) as ConjunctVal)
202
+ out.peg = this.peg.map((entry: Val) => entry.clone(null, ctx))
203
+ return out
204
+ }
205
+
206
+
177
207
  // TODO: need a well-defined val order so conjunt canon is always the same
178
208
  get canon() {
209
+ // return ' C( ' + this.peg.map((v: Val) => v.canon).join('&') + ' ) '
179
210
  return this.peg.map((v: Val) => v.canon).join('&')
180
211
  }
181
212
 
213
+
182
214
  gen(ctx?: Context) {
183
- if (0 < this.peg.length) {
215
+ throw new Error('ConjuntVal-gen')
184
216
 
185
- // Default is just the first term - does this work?
186
- // TODO: maybe use a PrefVal() ?
187
- let v: Val = this.peg[0]
217
+ // if (0 < this.peg.length) {
188
218
 
219
+ // // Default is just the first term - does this work?
220
+ // // TODO: maybe use a PrefVal() ?
221
+ // let v: Val = this.peg[0]
189
222
 
190
- let out = undefined
191
- if (undefined !== v && !(v instanceof Nil)) {
192
- out = v.gen(ctx)
193
- }
194
- return out
195
- }
196
223
 
197
- return undefined
224
+ // let out = undefined
225
+ // if (undefined !== v && !(v instanceof Nil)) {
226
+ // out = v.gen(ctx)
227
+ // }
228
+ // return out
229
+ // }
230
+ // else {
231
+ // throw new Error('ConjuntVal-gen')
232
+ // }
233
+
234
+ // return undefined
198
235
  }
199
236
  }
200
237
 
@@ -1,8 +1,10 @@
1
- /* Copyright (c) 2021-2022 Richard Rodger, MIT License */
1
+ /* Copyright (c) 2021-2023 Richard Rodger, MIT License */
2
+
2
3
 
3
4
 
4
5
  import type {
5
6
  Val,
7
+ ValSpec,
6
8
  } from '../type'
7
9
 
8
10
  import {
@@ -24,15 +26,16 @@ import {
24
26
  } from '../op/op'
25
27
 
26
28
 
27
- import {
28
- ValBase,
29
- } from '../val/ValBase'
30
-
31
-
32
- import { Nil } from './Nil'
33
- import { PrefVal } from './PrefVal'
34
29
 
35
30
 
31
+ import { TOP } from '../val'
32
+ import { ConjunctVal } from '../val/ConjunctVal'
33
+ import { ListVal } from '../val/ListVal'
34
+ import { MapVal } from '../val/MapVal'
35
+ import { Nil } from '../val/Nil'
36
+ import { PrefVal } from '../val/PrefVal'
37
+ import { RefVal } from '../val/RefVal'
38
+ import { ValBase } from '../val/ValBase'
36
39
 
37
40
 
38
41
 
@@ -40,8 +43,14 @@ import { PrefVal } from './PrefVal'
40
43
  // TODO: move main logic to op/disjunct
41
44
  class DisjunctVal extends ValBase {
42
45
  // TODO: sites from normalization of orginal Disjuncts, as well as child pegs
43
- constructor(peg: Val[], ctx?: Context, _sites?: Site[]) {
44
- super(peg, ctx)
46
+ constructor(
47
+ spec: {
48
+ peg: Val[]
49
+ },
50
+ ctx?: Context,
51
+ _sites?: Site[]
52
+ ) {
53
+ super(spec, ctx)
45
54
  }
46
55
 
47
56
  // NOTE: mutation!
@@ -102,16 +111,27 @@ class DisjunctVal extends ValBase {
102
111
  return Nil.make(ctx, '|:empty', this)
103
112
  }
104
113
  else {
105
- out = new DisjunctVal(oval, ctx)
114
+ out = new DisjunctVal({ peg: oval }, ctx)
106
115
  }
107
116
 
108
117
  out.done = done ? DONE : this.done + 1
109
118
 
110
119
  return out
111
120
  }
121
+
122
+
123
+ clone(spec?: ValSpec, ctx?: Context): Val {
124
+ let out = (super.clone(spec, ctx) as DisjunctVal)
125
+ out.peg = this.peg.map((entry: Val) => entry.clone(null, ctx))
126
+ return out
127
+ }
128
+
129
+
112
130
  get canon() {
113
131
  return this.peg.map((v: Val) => v.canon).join('|')
114
132
  }
133
+
134
+
115
135
  gen(ctx?: Context) {
116
136
 
117
137
  // TODO: this is not right - unresolved Disjuncts eval to undef
@@ -126,7 +146,10 @@ class DisjunctVal extends ValBase {
126
146
  let val = vals[0]
127
147
 
128
148
  for (let vI = 1; vI < this.peg.length; vI++) {
129
- val = val.unify(this.peg[vI], ctx)
149
+ // val = val.unify(this.peg[vI], ctx)
150
+ let valnext = val.unify(this.peg[vI], ctx)
151
+ // console.log(valnext.canon, val.canon, this.peg[vI].canon, val, this.peg[vI])
152
+ val = valnext
130
153
  }
131
154
 
132
155
  return val.gen(ctx)
@@ -3,13 +3,12 @@
3
3
 
4
4
  import type {
5
5
  Val,
6
- ValMap,
7
6
  ValList,
7
+ ValSpec,
8
8
  } from '../type'
9
9
 
10
10
  import {
11
11
  DONE,
12
- TOP,
13
12
  } from '../type'
14
13
 
15
14
  import {
@@ -26,13 +25,17 @@ import {
26
25
  unite
27
26
  } from '../op/op'
28
27
 
29
- import { Nil } from '../val/Nil'
30
28
 
31
- import {
32
- ValBase,
33
- } from '../val/ValBase'
34
29
 
30
+
31
+ import { TOP } from '../val'
35
32
  import { ConjunctVal } from '../val/ConjunctVal'
33
+ import { DisjunctVal } from '../val/DisjunctVal'
34
+ import { MapVal } from '../val/MapVal'
35
+ import { Nil } from '../val/Nil'
36
+ import { PrefVal } from '../val/PrefVal'
37
+ import { RefVal } from '../val/RefVal'
38
+ import { ValBase } from '../val/ValBase'
36
39
 
37
40
 
38
41
 
@@ -45,8 +48,17 @@ class ListVal extends ValBase {
45
48
  cj: (undefined as Val | undefined),
46
49
  }
47
50
 
48
- constructor(peg: ValList, ctx?: Context) {
49
- super(peg, ctx)
51
+ constructor(
52
+ spec: {
53
+ peg: ValList
54
+ },
55
+ ctx?: Context
56
+ ) {
57
+ super(spec, ctx)
58
+
59
+ if (null == this.peg) {
60
+ throw new Error('ListVal spec.peg undefined')
61
+ }
50
62
 
51
63
  let spread = (this.peg as any)[ListVal.SPREAD]
52
64
  delete (this.peg as any)[ListVal.SPREAD]
@@ -54,24 +66,26 @@ class ListVal extends ValBase {
54
66
  if (spread) {
55
67
  if ('&' === spread.o) {
56
68
  // TODO: handle existing spread!
57
- this.spread.cj =
58
- new ConjunctVal(Array.isArray(spread.v) ? spread.v : [spread.v], ctx)
69
+ let tmv = Array.isArray(spread.v) ? spread.v : [spread.v]
70
+ this.spread.cj = new ConjunctVal({ peg: tmv }, ctx)
59
71
  }
60
72
  }
61
73
  }
62
74
 
75
+
63
76
  // NOTE: order of keys is not preserved!
64
77
  // not possible in any case - consider {a,b} unify {b,a}
65
78
  unify(peer: Val, ctx: Context): Val {
66
79
  let done: boolean = true
67
- let out: ListVal = TOP === peer ? this : new ListVal([], ctx)
80
+ let out: ListVal = TOP === peer ? this : new ListVal({ peg: [] }, ctx)
68
81
 
69
82
  out.spread.cj = this.spread.cj
70
83
 
71
84
  if (peer instanceof ListVal) {
72
85
  out.spread.cj = null == out.spread.cj ? peer.spread.cj : (
73
86
  null == peer.spread.cj ? out.spread.cj : (
74
- out.spread.cj = new ConjunctVal([out.spread.cj, peer.spread.cj], ctx)
87
+ out.spread.cj =
88
+ new ConjunctVal({ peg: [out.spread.cj, peer.spread.cj] }, ctx)
75
89
  )
76
90
  )
77
91
  }
@@ -79,25 +93,28 @@ class ListVal extends ValBase {
79
93
 
80
94
  out.done = this.done + 1
81
95
 
82
- if (this.spread.cj) {
83
- out.spread.cj =
84
- DONE !== this.spread.cj.done ? unite(ctx, this.spread.cj) :
85
- this.spread.cj
86
- }
96
+ // if (this.spread.cj) {
97
+ // out.spread.cj =
98
+ // DONE !== this.spread.cj.done ? unite(ctx, this.spread.cj) :
99
+ // this.spread.cj
100
+ // }
87
101
 
88
102
  let spread_cj = out.spread.cj || TOP
89
103
 
90
104
  // Always unify children first
91
105
  for (let key in this.peg) {
92
- out.peg[key] =
93
- unite(ctx.descend(key), this.peg[key], spread_cj)
106
+ let keyctx = ctx.descend(key)
107
+ let key_spread_cj = spread_cj.clone(null, keyctx)
94
108
 
109
+ out.peg[key] = unite(keyctx, this.peg[key], key_spread_cj, 'list-own')
95
110
  done = (done && DONE === out.peg[key].done)
96
111
  }
97
112
 
113
+
98
114
  if (peer instanceof ListVal) {
99
- let upeer: ListVal = (unite(ctx, peer) as ListVal)
115
+ let upeer: ListVal = (unite(ctx, peer, undefined, 'list-peer-list') as ListVal)
100
116
 
117
+ // NOTE: peerkey is the index
101
118
  for (let peerkey in upeer.peg) {
102
119
  let peerchild = upeer.peg[peerkey]
103
120
  let child = out.peg[peerkey]
@@ -106,10 +123,17 @@ class ListVal extends ValBase {
106
123
  undefined === child ? peerchild :
107
124
  child instanceof Nil ? child :
108
125
  peerchild instanceof Nil ? peerchild :
109
- unite(ctx.descend(peerkey), child, peerchild)
126
+ unite(ctx.descend(peerkey), child, peerchild, 'list-peer')
110
127
 
111
128
  if (this.spread.cj) {
112
- out.peg[peerkey] = unite(ctx, out.peg[peerkey], spread_cj)
129
+ let key_ctx = ctx.descend(peerkey)
130
+ let key_spread_cj = spread_cj.clone(null, key_ctx)
131
+
132
+ // out.peg[peerkey] = unite(ctx, out.peg[peerkey], spread_cj)
133
+ out.peg[peerkey] =
134
+ new ConjunctVal({ peg: [out.peg[peerkey], key_spread_cj] }, key_ctx)
135
+ done = false
136
+
113
137
  }
114
138
 
115
139
  done = (done && DONE === oval.done)
@@ -124,6 +148,17 @@ class ListVal extends ValBase {
124
148
  return out
125
149
  }
126
150
 
151
+
152
+ clone(spec?: ValSpec, ctx?: Context): Val {
153
+ let out = (super.clone(spec, ctx) as ListVal)
154
+ out.peg = this.peg.map((entry: Val) => entry.clone(null, ctx))
155
+ if (this.spread.cj) {
156
+ out.spread.cj = this.spread.cj.clone(null, ctx)
157
+ }
158
+ return out
159
+ }
160
+
161
+
127
162
  get canon() {
128
163
  let keys = Object.keys(this.peg)
129
164
  return '[' +