@bablr/bablr-vm 0.19.1 → 0.20.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.
package/lib/node.js CHANGED
@@ -4,17 +4,20 @@ import {
4
4
  buildOpenNodeTag,
5
5
  buildReferenceTag,
6
6
  buildStubNode,
7
- isFragmentNode,
8
7
  isNullNode,
9
8
  parseReference,
10
- referenceFlags,
11
9
  } from '@bablr/agast-helpers/tree';
12
10
  import { getStreamIterator } from '@bablr/agast-helpers/stream';
13
11
  import { agast } from '@bablr/agast-vm';
14
- import * as btree from '@bablr/agast-helpers/btree';
12
+ import * as sumtree from '@bablr/agast-helpers/sumtree';
15
13
  import { Pump } from './utils/pump.js';
16
14
  import { OpenNodeTag, ReferenceTag } from '@bablr/agast-helpers/symbols';
17
- import { get, getProperties } from '@bablr/agast-helpers/path';
15
+ import {
16
+ buildFullRange,
17
+ get,
18
+ getProperties,
19
+ getPropertyChildrenIndex,
20
+ } from '@bablr/agast-helpers/path';
18
21
  import { isArray } from '@bablr/helpers/object';
19
22
 
20
23
  export const states = new WeakMap();
@@ -22,18 +25,35 @@ export const internalStates = new WeakMap();
22
25
 
23
26
  const { hasOwn } = Object;
24
27
 
25
- const buildFullRange = (node) => {
26
- const sum = btree.getSum(node.children);
27
- return sum ? [0, sum - 1] : null;
28
- };
29
-
30
28
  export const FragmentFacade = class BABLRFragmentFacade {
29
+ static wrapNode(
30
+ node,
31
+ context,
32
+ transparent = false,
33
+ childrenIndexRange = null,
34
+ dotPropertyReference = null,
35
+ dotPropertyIndex = null,
36
+ ) {
37
+ return (
38
+ node &&
39
+ new FragmentFacade(
40
+ node,
41
+ context,
42
+ transparent,
43
+ false,
44
+ childrenIndexRange,
45
+ dotPropertyReference,
46
+ dotPropertyIndex,
47
+ )
48
+ );
49
+ }
50
+
31
51
  static wrap(
32
52
  node,
33
53
  context,
34
54
  transparent = false,
35
- childrenIndexRange = node && buildFullRange(node),
36
- dotPropertyName = null,
55
+ childrenIndexRange = null,
56
+ dotPropertyReference = null,
37
57
  dotPropertyIndex = null,
38
58
  ) {
39
59
  return (
@@ -42,53 +62,86 @@ export const FragmentFacade = class BABLRFragmentFacade {
42
62
  node,
43
63
  context,
44
64
  transparent,
65
+ true,
45
66
  childrenIndexRange,
46
- dotPropertyName,
67
+ dotPropertyReference,
47
68
  dotPropertyIndex,
48
69
  )
49
70
  );
50
71
  }
51
72
 
52
- constructor(node, context, transparent, childrenIndexRange, dotPropertyName, dotPropertyIndex) {
73
+ constructor(
74
+ node,
75
+ context,
76
+ transparent = false,
77
+ isFragmentNode = true,
78
+ childrenIndexRange = null,
79
+ dotPropertyReference = null,
80
+ dotPropertyIndex = null,
81
+ ) {
82
+ if (!node) throw new Error();
83
+
53
84
  if (childrenIndexRange && (childrenIndexRange[0] == null || !childrenIndexRange[1] == null)) {
54
85
  throw new Error();
55
86
  }
56
87
 
57
88
  if (!context) throw new Error();
58
89
 
59
- if (dotPropertyName && !hasOwn(node.properties, dotPropertyName)) throw new Error();
90
+ if (dotPropertyReference && !hasOwn(node.properties, dotPropertyReference.value.name))
91
+ throw new Error();
92
+
93
+ if (isArray(dotPropertyReference?.value.isArray && dotPropertyIndex == null)) throw new Error();
94
+
95
+ let resolvedNode = node;
96
+ let fragmentNode = node;
97
+
98
+ if (dotPropertyReference) {
99
+ let { name, isArray, flags } = dotPropertyReference.value;
60
100
 
61
- if (isArray(node.properties[dotPropertyName]) && dotPropertyIndex == null) throw new Error();
101
+ let dotReference = buildReferenceTag(name, isArray, flags, dotPropertyIndex);
102
+
103
+ resolvedNode = get(dotReference, fragmentNode);
104
+ }
62
105
 
63
106
  states.set(this, {
64
107
  context,
65
108
  openTag: buildOpenNodeTag(),
66
109
  closeTag: buildCloseNodeTag(),
67
- node,
110
+ node: resolvedNode,
111
+ fragmentNode: node,
68
112
  transparent,
113
+ isFragmentNode,
69
114
  childrenIndexRange,
70
- dotPropertyName,
115
+ dotPropertyReference,
71
116
  dotPropertyIndex,
72
117
  });
73
118
  }
74
119
 
120
+ get dotPropertyName() {
121
+ return states.get(this).dotPropertyReference?.value.name;
122
+ }
123
+
75
124
  get isTransparent() {
76
125
  return states.get(this).transparent;
77
126
  }
78
127
 
79
- get isFragmentNode() {
80
- return isFragmentNode(states.get(this).node);
128
+ get isNull() {
129
+ let { node } = states.get(this);
130
+ return isNullNode(node);
81
131
  }
82
132
 
83
133
  get children() {
84
- const { node, transparent, childrenIndexRange } = states.get(this);
134
+ let { node, isFragmentNode, transparent, childrenIndexRange } = states.get(this);
135
+
136
+ childrenIndexRange =
137
+ isFragmentNode || !childrenIndexRange ? buildFullRange(node) : childrenIndexRange;
85
138
 
86
139
  return {
87
140
  *[Symbol.iterator]() {
88
141
  for (let i = childrenIndexRange[0]; i <= childrenIndexRange[1]; i++) {
89
142
  const interpolated = false; // TODO
90
143
  if (!interpolated || transparent) {
91
- yield btree.getAt(i, node.children);
144
+ yield sumtree.getAt(i, node.children);
92
145
  }
93
146
  }
94
147
  },
@@ -103,7 +156,7 @@ export const FragmentFacade = class BABLRFragmentFacade {
103
156
  if (childrenIndexRange[0] > childrenIndexRange[1]) throw new Error();
104
157
 
105
158
  for (let i = childrenIndexRange[0]; i <= childrenIndexRange[1]; i++) {
106
- let tag = btree.getAt(i, node.children);
159
+ let tag = sumtree.getAt(i, node.children);
107
160
  if (tag.type === ReferenceTag) {
108
161
  const { name, isArray } = tag.value;
109
162
  let resolvedTagName = name === '.' ? dotPropertyName : name;
@@ -124,75 +177,120 @@ export const FragmentFacade = class BABLRFragmentFacade {
124
177
  }
125
178
 
126
179
  get language() {
127
- let { node } = states.get(this);
180
+ let { node, isFragmentNode } = states.get(this);
128
181
 
129
- return node.language;
182
+ return isFragmentNode ? null : node.language;
130
183
  }
131
184
 
132
185
  get type() {
133
- let { node } = states.get(this);
186
+ let { node, isFragmentNode } = states.get(this);
134
187
 
135
- return node.type;
188
+ return isFragmentNode ? null : node.type;
136
189
  }
137
190
 
138
191
  get attributes() {
139
- let { node } = states.get(this);
192
+ let { node, isFragmentNode } = states.get(this);
140
193
 
141
- return node.attributes;
194
+ return isFragmentNode ? {} : node.attributes;
142
195
  }
143
196
 
144
197
  get openTag() {
145
- const state = states.get(this);
146
- const { children } = state.node;
198
+ const { node, openTag, isFragmentNode } = states.get(this);
147
199
 
148
- return state.openTag || btree.getAt(0, children);
200
+ return isFragmentNode ? openTag : sumtree.getAt(0, node.children);
149
201
  }
150
202
 
151
203
  get closeTag() {
152
- const state = states.get(this);
153
- const { children } = state.node;
204
+ const { node, closeTag, isFragmentNode } = states.get(this);
154
205
 
155
- return state.closeTag || btree.getAt(btree.getSum(children) - 1, children);
206
+ return isFragmentNode
207
+ ? closeTag
208
+ : sumtree.getAt(sumtree.getSize(node.children) - 1, node.children);
209
+ }
210
+
211
+ merge(targetFragment) {
212
+ let {
213
+ fragmentNode,
214
+ context,
215
+ transparent,
216
+ isFragmentNode,
217
+ childrenIndexRange,
218
+ dotPropertyReference,
219
+ dotPropertyIndex,
220
+ } = states.get(this);
221
+ const { fragmentNode: targetFragmentNode, childrenIndexRange: targetChildrenIndexRange } =
222
+ states.get(targetFragment);
223
+ if (fragmentNode === targetFragmentNode) {
224
+ // TODO restrict what is legal here
225
+
226
+ return new FragmentFacade(
227
+ fragmentNode,
228
+ context,
229
+ transparent,
230
+ isFragmentNode,
231
+ targetChildrenIndexRange,
232
+ dotPropertyReference,
233
+ dotPropertyIndex,
234
+ );
235
+ } else {
236
+ throw new Error('not implemented');
237
+ }
156
238
  }
157
239
 
158
240
  get(path) {
159
241
  let {
160
- node,
242
+ node: ownNode,
243
+ fragmentNode,
161
244
  context,
162
245
  transparent,
163
- dotPropertyName,
246
+ isFragmentNode,
247
+ childrenIndexRange,
248
+ dotPropertyReference: dotReference,
164
249
  dotPropertyIndex: dotIndex,
165
250
  } = states.get(this);
166
- // let { path: nodePath } = internalStates.get(node);
167
251
  const parsedRef = parseReference(path);
168
- // const resolvedPath = resolvePath(node, path);
169
- // const childNode = getAtPath(resolvedPath, node);
170
252
 
171
- // array resolve
253
+ let node = fragmentNode;
172
254
 
173
- if (dotPropertyName) {
174
- let dotReference = buildReferenceTag(
175
- dotPropertyName,
176
- dotIndex != null,
177
- referenceFlags,
178
- dotIndex,
179
- );
255
+ if (parsedRef.value.name !== '.') {
256
+ if (dotReference) {
257
+ fragmentNode = ownNode;
258
+ dotReference = parsedRef;
180
259
 
181
- node = get(dotReference, node);
182
- }
260
+ isFragmentNode = false;
261
+ } else {
262
+ dotReference = parsedRef;
263
+ dotIndex = parsedRef.value.index;
264
+ }
265
+
266
+ let { name, isArray, flags } = parsedRef.value;
267
+ let resolvedReference = buildReferenceTag(name, isArray, flags, dotIndex);
268
+ let refIndex = getPropertyChildrenIndex(fragmentNode, resolvedReference);
269
+ childrenIndexRange = [refIndex, refIndex + 1];
183
270
 
184
- const binding = getProperties(parsedRef, node.properties);
271
+ const binding = getProperties(parsedRef, fragmentNode.properties);
185
272
 
186
- if (!binding) return null;
273
+ if (!binding) return null;
187
274
 
188
- const ref = binding.reference;
275
+ const ref = binding.reference;
189
276
 
190
- const node_ =
191
- (ref && ref.type === ReferenceTag && !ref.value.flags.hasGap) || transparent
192
- ? binding.node
193
- : buildStubNode(buildGapTag());
277
+ node =
278
+ (ref && ref.type === ReferenceTag && !ref.value.flags.hasGap) || transparent
279
+ ? binding.node
280
+ : buildStubNode(buildGapTag());
281
+ }
194
282
 
195
- return isNullNode(node_) ? null : FragmentFacade.wrap(node_, context, transparent);
283
+ return isNullNode(node)
284
+ ? null
285
+ : new FragmentFacade(
286
+ fragmentNode,
287
+ context,
288
+ transparent,
289
+ isFragmentNode,
290
+ childrenIndexRange,
291
+ dotReference,
292
+ dotIndex,
293
+ );
196
294
  }
197
295
 
198
296
  has(path) {
package/lib/source.js CHANGED
@@ -251,7 +251,9 @@ export const Source = class BABLRSource extends WeakStackFrame {
251
251
  }
252
252
 
253
253
  [Symbol.for('@@streamIterator')]() {
254
- return this.holding ? emptyStreamIterator : this.fork.clone()[Symbol.for('@@streamIterator')]();
254
+ return (this.holding ? emptyStreamIterator() : this.fork.clone())[
255
+ Symbol.for('@@streamIterator')
256
+ ]();
255
257
  }
256
258
 
257
259
  formatIndex() {