@bablr/bablr-vm 0.22.1 → 0.23.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.
- package/lib/context.js +2 -44
- package/lib/evaluate.js +147 -378
- package/lib/facades.js +34 -0
- package/lib/match.js +468 -325
- package/lib/source.js +9 -58
- package/lib/spans.js +29 -68
- package/lib/state.js +58 -336
- package/lib/utils/pattern.js +58 -28
- package/package.json +11 -8
- package/lib/node.js +0 -327
package/lib/node.js
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildBindingTag,
|
|
3
|
-
buildCloseNodeTag,
|
|
4
|
-
buildGapTag,
|
|
5
|
-
buildOpenNodeTag,
|
|
6
|
-
buildReferenceTag,
|
|
7
|
-
buildStubNode,
|
|
8
|
-
fragmentFlags,
|
|
9
|
-
isNullNode,
|
|
10
|
-
} from '@bablr/agast-helpers/tree';
|
|
11
|
-
import { NullTag, OpenNodeTag, PropertyWrapper, ReferenceTag } from '@bablr/agast-helpers/symbols';
|
|
12
|
-
import {
|
|
13
|
-
buildFullPathSegment,
|
|
14
|
-
buildFullRange,
|
|
15
|
-
buildPathSegment,
|
|
16
|
-
buildTypePathSegment,
|
|
17
|
-
} from '@bablr/agast-helpers/path';
|
|
18
|
-
import { hasOwn, isArray } from '@bablr/helpers/object';
|
|
19
|
-
|
|
20
|
-
export const states = new WeakMap();
|
|
21
|
-
|
|
22
|
-
export const isFragmentNode = (node) => {
|
|
23
|
-
return node.type === null && node.sigilTag.type === OpenNodeTag;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const FragmentFacade = class BABLRFragmentFacade {
|
|
27
|
-
static wrapNode(
|
|
28
|
-
node,
|
|
29
|
-
context,
|
|
30
|
-
transparent = false,
|
|
31
|
-
tagsIndexRange = null,
|
|
32
|
-
dotPropertyReference = null,
|
|
33
|
-
dotPropertyIndex = null,
|
|
34
|
-
) {
|
|
35
|
-
return (
|
|
36
|
-
node &&
|
|
37
|
-
new FragmentFacade(
|
|
38
|
-
node,
|
|
39
|
-
context,
|
|
40
|
-
transparent,
|
|
41
|
-
false,
|
|
42
|
-
tagsIndexRange,
|
|
43
|
-
dotPropertyReference,
|
|
44
|
-
dotPropertyIndex,
|
|
45
|
-
)
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static wrap(
|
|
50
|
-
node,
|
|
51
|
-
context,
|
|
52
|
-
transparent = false,
|
|
53
|
-
tagsIndexRange = null,
|
|
54
|
-
dotPropertyReference = null,
|
|
55
|
-
dotPropertyIndex = null,
|
|
56
|
-
) {
|
|
57
|
-
return (
|
|
58
|
-
node &&
|
|
59
|
-
new FragmentFacade(
|
|
60
|
-
node,
|
|
61
|
-
context,
|
|
62
|
-
transparent,
|
|
63
|
-
true,
|
|
64
|
-
tagsIndexRange,
|
|
65
|
-
dotPropertyReference,
|
|
66
|
-
dotPropertyIndex,
|
|
67
|
-
)
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
constructor(
|
|
72
|
-
node,
|
|
73
|
-
context,
|
|
74
|
-
transparent = false,
|
|
75
|
-
isFragmentFacade = true,
|
|
76
|
-
tagsIndexRange = null,
|
|
77
|
-
dotPropertyReference = null,
|
|
78
|
-
dotPropertyIndex = null,
|
|
79
|
-
) {
|
|
80
|
-
if (!node || hasOwn(node, 'tags')) throw new Error();
|
|
81
|
-
if (isNaN(dotPropertyIndex)) throw new Error();
|
|
82
|
-
|
|
83
|
-
if (tagsIndexRange && (tagsIndexRange[0] == null || !tagsIndexRange[1] == null)) {
|
|
84
|
-
throw new Error();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (!context) throw new Error();
|
|
88
|
-
|
|
89
|
-
if (dotPropertyReference && !node.properties.get(dotPropertyReference.name)) throw new Error();
|
|
90
|
-
|
|
91
|
-
if (dotPropertyReference?.isArray && dotPropertyIndex == null) throw new Error();
|
|
92
|
-
|
|
93
|
-
let resolvedNode = node;
|
|
94
|
-
let fragmentNode = node;
|
|
95
|
-
|
|
96
|
-
if (dotPropertyReference) {
|
|
97
|
-
let { type, name } = dotPropertyReference;
|
|
98
|
-
|
|
99
|
-
resolvedNode = fragmentNode.get(buildFullPathSegment(type, name, dotPropertyIndex));
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (dotPropertyReference?.value) throw new Error();
|
|
103
|
-
|
|
104
|
-
states.set(this, {
|
|
105
|
-
context,
|
|
106
|
-
openTag: buildOpenNodeTag(fragmentFlags),
|
|
107
|
-
closeTag: buildCloseNodeTag(),
|
|
108
|
-
node: resolvedNode,
|
|
109
|
-
fragmentNode,
|
|
110
|
-
transparent,
|
|
111
|
-
isFragmentFacade,
|
|
112
|
-
tagsIndexRange,
|
|
113
|
-
dotPropertyReference,
|
|
114
|
-
dotPropertyIndex,
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
Object.freeze(this);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
get dotPropertyName() {
|
|
121
|
-
return states.get(this).dotPropertyReference?.value.name;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
get isTransparent() {
|
|
125
|
-
return states.get(this).transparent;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
get isNull() {
|
|
129
|
-
let { node } = states.get(this);
|
|
130
|
-
return node.sigilTag.type === NullTag;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
get tagsInner() {
|
|
134
|
-
let { node, isFragmentNode, transparent, tagsIndexRange } = states.get(this);
|
|
135
|
-
|
|
136
|
-
tagsIndexRange = isFragmentNode || !tagsIndexRange ? buildFullRange(node) : tagsIndexRange;
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
*[Symbol.iterator]() {
|
|
140
|
-
for (let tag of node.tags) {
|
|
141
|
-
if (tag.type === PropertyWrapper) {
|
|
142
|
-
let { property, tags } = tag.value;
|
|
143
|
-
if (transparent || !property.reference.flags.hasGap) {
|
|
144
|
-
yield* tags;
|
|
145
|
-
} else {
|
|
146
|
-
yield buildReferenceTag(property.reference);
|
|
147
|
-
yield buildBindingTag();
|
|
148
|
-
yield buildGapTag();
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
getRootIndex() {
|
|
157
|
-
const { node, dotPropertyName, tagsIndexRange } = states.get(this);
|
|
158
|
-
|
|
159
|
-
if (!tagsIndexRange) return null;
|
|
160
|
-
|
|
161
|
-
if (tagsIndexRange[0] > tagsIndexRange[1]) throw new Error();
|
|
162
|
-
|
|
163
|
-
for (let i = tagsIndexRange[0]; i <= tagsIndexRange[1]; i++) {
|
|
164
|
-
let tag = node.tags.at(i);
|
|
165
|
-
if (tag.type === ReferenceTag) {
|
|
166
|
-
const { name, isArray } = tag.value;
|
|
167
|
-
let resolvedTagName = name === '.' ? dotPropertyName : name;
|
|
168
|
-
|
|
169
|
-
if (resolvedTagName === dotPropertyName) {
|
|
170
|
-
return i;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
get flags() {
|
|
179
|
-
const { node } = states.get(this);
|
|
180
|
-
let openTag = node.sigilTag;
|
|
181
|
-
|
|
182
|
-
return openTag?.value.flags;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
get type() {
|
|
186
|
-
let { node } = states.get(this);
|
|
187
|
-
let openTag = node.sigilTag;
|
|
188
|
-
|
|
189
|
-
return openTag?.value.type;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
get attributes() {
|
|
193
|
-
let { node } = states.get(this);
|
|
194
|
-
let openTag = node.sigilTag;
|
|
195
|
-
|
|
196
|
-
return openTag?.value.attributes;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
get openTag() {
|
|
200
|
-
const { node, openTag, isFragmentFacade } = states.get(this);
|
|
201
|
-
|
|
202
|
-
return isFragmentNode(node) ? node.tags.at(1) : isFragmentFacade ? openTag : node.tags.at(0);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
get closeTag() {
|
|
206
|
-
const { node, closeTag, isFragmentFacade } = states.get(this);
|
|
207
|
-
|
|
208
|
-
return isFragmentFacade ? (isFragmentNode(node) ? node.closeTag : closeTag) : node.tags.at(-1);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
merge(targetFragment) {
|
|
212
|
-
let {
|
|
213
|
-
fragmentNode,
|
|
214
|
-
context,
|
|
215
|
-
transparent,
|
|
216
|
-
isFragmentFacade,
|
|
217
|
-
dotPropertyReference,
|
|
218
|
-
dotPropertyIndex,
|
|
219
|
-
} = states.get(this);
|
|
220
|
-
const { fragmentNode: targetFragmentNode, tagsIndexRange: targetTagsIndexRange } =
|
|
221
|
-
states.get(targetFragment);
|
|
222
|
-
if (fragmentNode === targetFragmentNode) {
|
|
223
|
-
// TODO restrict what is legal here
|
|
224
|
-
|
|
225
|
-
return new FragmentFacade(
|
|
226
|
-
fragmentNode,
|
|
227
|
-
context,
|
|
228
|
-
transparent,
|
|
229
|
-
isFragmentFacade,
|
|
230
|
-
targetTagsIndexRange,
|
|
231
|
-
dotPropertyReference,
|
|
232
|
-
dotPropertyIndex,
|
|
233
|
-
);
|
|
234
|
-
} else {
|
|
235
|
-
throw new Error('not implemented');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
get(path) {
|
|
240
|
-
let {
|
|
241
|
-
node: ownNode,
|
|
242
|
-
context,
|
|
243
|
-
transparent,
|
|
244
|
-
isFragmentFacade,
|
|
245
|
-
tagsIndexRange,
|
|
246
|
-
dotPropertyReference: dotReference,
|
|
247
|
-
dotPropertyIndex: dotIndex,
|
|
248
|
-
} = states.get(this);
|
|
249
|
-
|
|
250
|
-
if (typeof path === 'string') {
|
|
251
|
-
path = [path];
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (!isArray(path)) throw new Error();
|
|
255
|
-
|
|
256
|
-
let node = ownNode;
|
|
257
|
-
let ref = dotReference;
|
|
258
|
-
let index = dotIndex;
|
|
259
|
-
let outerNode;
|
|
260
|
-
|
|
261
|
-
for (let i = 0; i < path.length; i++) {
|
|
262
|
-
let name = path[i];
|
|
263
|
-
let seg = typeof name === 'string' ? buildPathSegment(name) : name;
|
|
264
|
-
outerNode = node;
|
|
265
|
-
|
|
266
|
-
node = node.get(seg);
|
|
267
|
-
if (node?.sigilTag.type === NullTag) {
|
|
268
|
-
node = null;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (!node) break;
|
|
272
|
-
let refIndex = outerNode.getPropertyTagsIndex(null, seg.name, seg.index);
|
|
273
|
-
tagsIndexRange = [refIndex, refIndex];
|
|
274
|
-
|
|
275
|
-
let boundRef = outerNode.properties.referenceAt(seg.name, seg.index);
|
|
276
|
-
|
|
277
|
-
if (!node) return null;
|
|
278
|
-
|
|
279
|
-
let arraySize = outerNode.countList(seg.name);
|
|
280
|
-
|
|
281
|
-
ref = boundRef;
|
|
282
|
-
index = seg.index < 0 ? arraySize + seg.index : seg.index;
|
|
283
|
-
|
|
284
|
-
node =
|
|
285
|
-
(ref && ref.type === ReferenceTag && !ref.flags.hasGap) || transparent
|
|
286
|
-
? node
|
|
287
|
-
: buildStubNode(buildGapTag());
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return !node || isNullNode(node)
|
|
291
|
-
? null
|
|
292
|
-
: new FragmentFacade(
|
|
293
|
-
outerNode,
|
|
294
|
-
context,
|
|
295
|
-
transparent,
|
|
296
|
-
isFragmentFacade,
|
|
297
|
-
tagsIndexRange,
|
|
298
|
-
ref,
|
|
299
|
-
index,
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
has(path) {
|
|
304
|
-
let node = states.get(this).node;
|
|
305
|
-
let path_ = path;
|
|
306
|
-
if (typeof path === 'string') {
|
|
307
|
-
path_ = [path];
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (!isArray(path_)) throw new Error();
|
|
311
|
-
|
|
312
|
-
for (let i = 0; i < path_.length; i++) {
|
|
313
|
-
if (!node.properties.has(path_[i])) return false;
|
|
314
|
-
if (i < path.length - 1) {
|
|
315
|
-
node = node.properties.get(path_[i]);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return true;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
hasRoot() {
|
|
323
|
-
return this.type != null ? false : !!states.get(this).node.get([buildTypePathSegment('.')]);
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
Object.seal(FragmentFacade);
|