@bablr/agast-helpers 0.10.9 → 0.11.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/README.md +1 -1
- package/lib/b-list-keyed.js +1 -0
- package/lib/b-list.js +1 -0
- package/lib/b-map.js +1 -0
- package/lib/b-set.js +1 -0
- package/lib/builders.js +916 -120
- package/lib/debug.js +39 -0
- package/lib/debug.register.js +5 -0
- package/lib/iterable.js +170 -0
- package/lib/object.js +52 -3
- package/lib/parse.js +30 -0
- package/lib/path.js +584 -635
- package/lib/print.js +45 -22
- package/lib/shorthand.js +4 -30
- package/lib/spans.js +0 -163
- package/lib/stream.js +345 -196
- package/lib/symbols.js +1 -0
- package/lib/tags.js +256 -77
- package/lib/template.js +19 -16
- package/lib/tree.js +49 -44
- package/package.json +14 -8
- package/lib/btree.js +0 -1
package/lib/path.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as BList from './b-list.js';
|
|
2
2
|
import * as Tags from './tags.js';
|
|
3
3
|
import {
|
|
4
4
|
ReferenceTag,
|
|
@@ -14,28 +14,43 @@ import {
|
|
|
14
14
|
TreeNode,
|
|
15
15
|
NullNode,
|
|
16
16
|
GapNode,
|
|
17
|
-
Document,
|
|
18
17
|
} from './symbols.js';
|
|
19
18
|
import {
|
|
20
19
|
immSet,
|
|
21
|
-
isPlainObject,
|
|
22
20
|
isString,
|
|
23
21
|
has as objHas,
|
|
24
22
|
get as objGet,
|
|
25
23
|
isObject,
|
|
24
|
+
isArray,
|
|
26
25
|
isSymbol,
|
|
26
|
+
recordValues,
|
|
27
|
+
freezeClass,
|
|
27
28
|
} from './object.js';
|
|
28
29
|
import {
|
|
29
|
-
buildReferenceTag,
|
|
30
30
|
buildChild,
|
|
31
31
|
buildProperty,
|
|
32
|
-
buildGapTag,
|
|
33
32
|
buildNullTag,
|
|
34
33
|
buildOpenNodeTag,
|
|
35
34
|
buildShift,
|
|
36
35
|
buildPropertyTag,
|
|
37
36
|
buildPathFrame,
|
|
37
|
+
buildBounds,
|
|
38
|
+
parseOpenNodeTag,
|
|
39
|
+
parseTag,
|
|
40
|
+
parseTagType,
|
|
41
|
+
buildTag,
|
|
42
|
+
buildFullOpenNodeTag,
|
|
43
|
+
tokenFlags,
|
|
44
|
+
parseObject,
|
|
38
45
|
} from './builders.js';
|
|
46
|
+
import { printObject, printTag } from './print.js';
|
|
47
|
+
import { arrayValues, map } from './iterable.js';
|
|
48
|
+
import { freezeRecord } from '@bablr/record';
|
|
49
|
+
|
|
50
|
+
let { hasOwn, freeze } = Object;
|
|
51
|
+
let { getTags } = Tags;
|
|
52
|
+
|
|
53
|
+
let arrayLast = (arr) => arr[arr.length - 1];
|
|
39
54
|
|
|
40
55
|
export const incrementShift = (shift) => {
|
|
41
56
|
if (!shift) return buildShift(1, 3);
|
|
@@ -43,74 +58,82 @@ export const incrementShift = (shift) => {
|
|
|
43
58
|
return buildShift(shift.index + 1, shift.height + 1);
|
|
44
59
|
};
|
|
45
60
|
|
|
46
|
-
export const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
export const stringName = (name) => {
|
|
62
|
+
switch (typeof name) {
|
|
63
|
+
case 'symbol':
|
|
64
|
+
return name.description;
|
|
65
|
+
case 'string':
|
|
66
|
+
return name;
|
|
67
|
+
case 'null':
|
|
68
|
+
case 'undefined':
|
|
69
|
+
return null;
|
|
70
|
+
default:
|
|
71
|
+
throw new Error();
|
|
72
|
+
}
|
|
51
73
|
};
|
|
52
74
|
|
|
53
75
|
export const buildNode = (tags) => {
|
|
54
76
|
if (isArray(tags) && !Number.isFinite(tags[0])) throw new Error();
|
|
55
|
-
if (!isArray(tags) && !isSymbol(tags.type)) throw new Error();
|
|
56
|
-
let tags_ = isArray(tags) ? tags : Tags.fromValues([tags]);
|
|
77
|
+
if (!isArray(tags) && !isString(tags) && !isSymbol(tags.type)) throw new Error();
|
|
78
|
+
let tags_ = isArray(tags) ? tags : Tags.fromValues([printTag(tags)]);
|
|
57
79
|
|
|
58
80
|
if (!Number.isFinite(tags_[0])) throw new Error();
|
|
59
81
|
if (!isArray(tags_[1]) || !tags_[1].length) throw new Error();
|
|
60
82
|
|
|
61
83
|
let openTag = tags_[1][0];
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
} else {
|
|
91
|
-
throw new Error();
|
|
84
|
+
|
|
85
|
+
switch (parseTagType(openTag)) {
|
|
86
|
+
case GapTag:
|
|
87
|
+
return buildTag(GapNode, { tags: Tags.fromValues([openTag]) });
|
|
88
|
+
case NullTag:
|
|
89
|
+
return buildTag(NullNode, { tags: Tags.fromValues([openTag]) });
|
|
90
|
+
case OpenNodeTag: {
|
|
91
|
+
let { flags, type, name, attributes } = parseOpenNodeTag(openTag).value;
|
|
92
|
+
|
|
93
|
+
let children = tags_[1][1] || Tags.fromValues([]);
|
|
94
|
+
|
|
95
|
+
if (!Tags.isNode(children)) throw new Error();
|
|
96
|
+
|
|
97
|
+
return freezeRecord({
|
|
98
|
+
type: TreeNode,
|
|
99
|
+
value: freezeRecord({
|
|
100
|
+
flags,
|
|
101
|
+
type,
|
|
102
|
+
name,
|
|
103
|
+
attributes: parseObject(attributes),
|
|
104
|
+
tags: tags_,
|
|
105
|
+
children,
|
|
106
|
+
bounds: buildBoundsFromTags(tags_),
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
throw new Error();
|
|
92
112
|
}
|
|
93
113
|
};
|
|
94
114
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
let gapFrame = buildPathFrame(
|
|
116
|
+
buildPropertyTag(
|
|
117
|
+
BList.fromValues([Tags.fromValues([]), Tags.fromValues([]), buildNode('<//>')], 1),
|
|
118
|
+
),
|
|
119
|
+
null,
|
|
120
|
+
true,
|
|
121
|
+
);
|
|
101
122
|
|
|
102
|
-
|
|
123
|
+
export const buildBoundsFromTags = (tags) => {
|
|
124
|
+
let leading = BList.fromValues([gapFrame]);
|
|
125
|
+
let trailing = leading;
|
|
103
126
|
let firstProperty, lastProperty;
|
|
104
127
|
let firstPropertyIndex, lastPropertyIndex;
|
|
105
128
|
|
|
106
|
-
if (Tags.getAt(-1, tags)
|
|
107
|
-
return
|
|
129
|
+
if (parseTagType(Tags.getAt(-1, tags)) !== CloseNodeTag) {
|
|
130
|
+
return buildBounds(leading, trailing);
|
|
108
131
|
}
|
|
109
132
|
|
|
110
133
|
for (let i = 1; i < Tags.getSize(tags); i++) {
|
|
111
134
|
let tag = Tags.getAt(i, tags);
|
|
112
135
|
|
|
113
|
-
if (tag
|
|
136
|
+
if (parseTagType(tag) === Property && !isNullNode(tag.value.node)) {
|
|
114
137
|
firstProperty = tag;
|
|
115
138
|
firstPropertyIndex = i;
|
|
116
139
|
break;
|
|
@@ -120,107 +143,90 @@ export const buildBoundsFromTags = (tags) => {
|
|
|
120
143
|
for (let i = Tags.getSize(tags) - 2; i >= 0; i--) {
|
|
121
144
|
let tag = Tags.getAt(i, tags);
|
|
122
145
|
|
|
123
|
-
if (tag
|
|
146
|
+
if (parseTagType(tag) === Property && !isNullNode(tag.value.node)) {
|
|
124
147
|
lastProperty = tag;
|
|
125
148
|
lastPropertyIndex = i;
|
|
126
149
|
break;
|
|
127
150
|
}
|
|
128
151
|
}
|
|
129
152
|
|
|
130
|
-
let { 0: openStack, 1: closeStack } = bounds;
|
|
131
|
-
|
|
132
153
|
if (firstProperty && firstProperty.value.node.type === TreeNode) {
|
|
133
|
-
|
|
154
|
+
leading = firstProperty.value.node.value.bounds.leading;
|
|
134
155
|
|
|
135
|
-
let rootFrame =
|
|
156
|
+
let rootFrame = BList.getAt(1, leading);
|
|
136
157
|
|
|
137
|
-
|
|
158
|
+
leading = BList.replaceAt(0, buildPathFrame(firstProperty), leading);
|
|
138
159
|
if (rootFrame) {
|
|
139
|
-
|
|
140
|
-
1,
|
|
141
|
-
openStack,
|
|
142
|
-
buildPathFrame(rootFrame.property, firstPropertyIndex),
|
|
143
|
-
);
|
|
160
|
+
leading = BList.replaceAt(1, buildPathFrame(rootFrame.property, firstPropertyIndex), leading);
|
|
144
161
|
}
|
|
145
|
-
|
|
162
|
+
leading = BList.unshift(gapFrame, leading);
|
|
146
163
|
}
|
|
147
164
|
|
|
148
|
-
if (lastProperty && lastProperty.value.type === TreeNode) {
|
|
165
|
+
if (lastProperty && lastProperty.value.node.type === TreeNode) {
|
|
149
166
|
if (!lastProperty.value.node) throw new Error();
|
|
150
167
|
|
|
151
|
-
|
|
168
|
+
trailing = lastProperty.value.node.value.bounds.trailing;
|
|
152
169
|
|
|
153
|
-
let rootFrame =
|
|
170
|
+
let rootFrame = BList.getAt(1, trailing);
|
|
154
171
|
|
|
155
|
-
|
|
172
|
+
trailing = BList.replaceAt(0, buildPathFrame(lastProperty), trailing);
|
|
156
173
|
if (rootFrame) {
|
|
157
|
-
|
|
174
|
+
trailing = BList.replaceAt(
|
|
158
175
|
1,
|
|
159
|
-
closeStack,
|
|
160
176
|
buildPathFrame(rootFrame.property, lastPropertyIndex),
|
|
177
|
+
trailing,
|
|
161
178
|
);
|
|
162
179
|
}
|
|
163
|
-
|
|
180
|
+
trailing = BList.unshift(gapFrame, trailing);
|
|
164
181
|
}
|
|
165
182
|
|
|
166
|
-
|
|
167
|
-
bounds[1] = closeStack;
|
|
168
|
-
|
|
169
|
-
return freeze(bounds);
|
|
183
|
+
return buildBounds(leading, trailing);
|
|
170
184
|
};
|
|
171
185
|
|
|
172
186
|
export const isNode = (value) => {
|
|
173
|
-
return [TreeNode, NullNode, GapNode].includes(value?.type);
|
|
187
|
+
return isObject(value) && [TreeNode, NullNode, GapNode].includes(value?.type);
|
|
174
188
|
};
|
|
175
189
|
|
|
176
190
|
export const endsNode = (tag) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
);
|
|
191
|
+
let tagType = parseTagType(tag);
|
|
192
|
+
if ([CloseNodeTag, NullTag, GapTag].includes(tagType)) return true;
|
|
193
|
+
|
|
194
|
+
return tagType === OpenNodeTag ? parseTag(tag).value.selfClosing : false;
|
|
181
195
|
};
|
|
182
196
|
|
|
183
197
|
export const propertyIsFull = (tag) => {
|
|
184
|
-
if (tag.type !== Property) return true;
|
|
198
|
+
if (isString(tag) || tag.type !== Property) return true;
|
|
185
199
|
|
|
186
200
|
let { tags } = tag.value;
|
|
187
201
|
|
|
188
|
-
return tags.length === 3;
|
|
202
|
+
return tags[1].length === 3;
|
|
189
203
|
};
|
|
190
204
|
|
|
191
205
|
export const nodeIsComplete = (node) => {
|
|
192
|
-
let sigilTag = getOpenTag(node);
|
|
193
|
-
return sigilTag.type !== OpenNodeTag || sigilTag.value.selfClosing
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
export const getTags = (node) => {
|
|
197
|
-
switch (node.type) {
|
|
198
|
-
case TreeNode:
|
|
199
|
-
return node.value.tags;
|
|
200
|
-
case NullNode:
|
|
201
|
-
return node.value.tags;
|
|
202
|
-
case GapNode:
|
|
203
|
-
return node.value.tags;
|
|
204
|
-
case Document:
|
|
205
|
-
return getTags(node.value.tree);
|
|
206
|
-
default:
|
|
207
|
-
throw new Error();
|
|
208
|
-
}
|
|
206
|
+
let sigilTag = parseTag(getOpenTag(node));
|
|
207
|
+
return sigilTag.type !== OpenNodeTag || sigilTag.value.selfClosing
|
|
208
|
+
? true
|
|
209
|
+
: !!getCloseNodeTag(node);
|
|
209
210
|
};
|
|
210
211
|
|
|
211
212
|
export const offsetForTag = (tag) => {
|
|
212
|
-
switch (tag
|
|
213
|
+
switch (parseTagType(tag)) {
|
|
213
214
|
case ReferenceTag:
|
|
214
215
|
case ShiftTag:
|
|
215
216
|
return [0];
|
|
216
217
|
case BindingTag:
|
|
217
218
|
return [1, -1];
|
|
219
|
+
case TreeNode:
|
|
220
|
+
case NullNode:
|
|
221
|
+
case GapNode:
|
|
222
|
+
return [2];
|
|
218
223
|
default:
|
|
219
224
|
return [];
|
|
220
225
|
}
|
|
221
226
|
};
|
|
222
227
|
|
|
223
228
|
export const isNodeTag = (tag) => {
|
|
229
|
+
if (isString(tag)) return false;
|
|
224
230
|
switch (tag.type) {
|
|
225
231
|
case TreeNode:
|
|
226
232
|
case NullNode:
|
|
@@ -259,13 +265,13 @@ export const getRootProperty = (node) => {
|
|
|
259
265
|
if (node == null || !isCover(node)) {
|
|
260
266
|
return null;
|
|
261
267
|
}
|
|
262
|
-
let idx =
|
|
268
|
+
let idx = Tags.getIndex(buildFullPathSegment('_', null), node.value.tags);
|
|
263
269
|
|
|
264
270
|
if (idx == null) return null;
|
|
265
271
|
|
|
266
272
|
let tag = Tags.getAt(idx, getTags(node));
|
|
267
273
|
|
|
268
|
-
if (tag.type !== Property) throw new Error();
|
|
274
|
+
if (isString(tag) || tag.type !== Property) throw new Error();
|
|
269
275
|
return tag;
|
|
270
276
|
};
|
|
271
277
|
|
|
@@ -288,15 +294,15 @@ export const getSigilTag = (node) => {
|
|
|
288
294
|
|
|
289
295
|
export const getOpenTag = (node) => {
|
|
290
296
|
let tag = Tags.getValues(getTags(node))[0];
|
|
291
|
-
return tag
|
|
297
|
+
return parseTagType(tag) === OpenNodeTag ? tag : null;
|
|
292
298
|
};
|
|
293
299
|
|
|
294
|
-
export const
|
|
300
|
+
export const getCloseNodeTag = (node) => {
|
|
295
301
|
return Tags.getValues(getTags(node))[2];
|
|
296
302
|
};
|
|
297
303
|
|
|
298
304
|
export const isNullNode = (node) => {
|
|
299
|
-
return node && Tags.getAt(0, getTags(node))
|
|
305
|
+
return node && parseTagType(Tags.getAt(0, getTags(node))) === NullTag;
|
|
300
306
|
};
|
|
301
307
|
|
|
302
308
|
export const isCover = (node) => {
|
|
@@ -316,197 +322,17 @@ export const isMultiFragment = (node) => {
|
|
|
316
322
|
};
|
|
317
323
|
|
|
318
324
|
export const isGapNode = (node) => {
|
|
319
|
-
return node && Tags.getAt(0, getTags(node))
|
|
325
|
+
return node && parseTagType(Tags.getAt(0, getTags(node))) === GapTag;
|
|
320
326
|
};
|
|
321
327
|
|
|
322
328
|
export const isStubNode = (node) => {
|
|
323
|
-
return node && [GapTag, NullTag].includes(Tags.getAt(0, getTags(node))
|
|
329
|
+
return node && [GapTag, NullTag].includes(parseTagType(Tags.getAt(0, getTags(node))));
|
|
324
330
|
};
|
|
325
331
|
|
|
326
332
|
export const isStubTag = (tag) => {
|
|
327
|
-
return [GapTag, NullTag].includes(tag
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
export const getChildPropertyIndex = (agAstNode, tagsIndex) => {
|
|
331
|
-
let child = Tags.getAt(tagsIndex, agAstNode.value.tags);
|
|
332
|
-
|
|
333
|
-
if (child.type !== Property) return null;
|
|
334
|
-
|
|
335
|
-
let tag = child.value.tags[0];
|
|
336
|
-
|
|
337
|
-
let refIndex = tag.type === ShiftTag ? tagsIndex - tag.value.index : tagsIndex;
|
|
338
|
-
|
|
339
|
-
let stack = Tags.findPath(refIndex, agAstNode.value.tags);
|
|
340
|
-
let { node, index: leafIdx } = stack.value;
|
|
341
|
-
let leaf = Tags.getAt(leafIdx, node);
|
|
342
|
-
|
|
343
|
-
if (leaf.type !== Property) {
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
let leafRefTag = leaf.value.tags[0];
|
|
348
|
-
|
|
349
|
-
if (leafRefTag.type !== ReferenceTag) return null;
|
|
350
|
-
|
|
351
|
-
let { name, flags } = leafRefTag.value;
|
|
352
|
-
let count = -1;
|
|
353
|
-
|
|
354
|
-
if (!name) throw new Error();
|
|
355
|
-
|
|
356
|
-
if (!flags.array) return null;
|
|
357
|
-
|
|
358
|
-
for (let i = leafIdx; i >= 0; i--) {
|
|
359
|
-
let value = Tags.getAt(i, node);
|
|
360
|
-
if (value.type === Property) {
|
|
361
|
-
let firstTag = value.value.tags[0];
|
|
362
|
-
|
|
363
|
-
if (firstTag.type === ReferenceTag && firstTag.value.name === name) {
|
|
364
|
-
count++;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
stack = stack.pop();
|
|
369
|
-
|
|
370
|
-
if (!stack.size) return count - 1;
|
|
371
|
-
|
|
372
|
-
({ node, index: leafIdx } = stack.value);
|
|
373
|
-
|
|
374
|
-
do {
|
|
375
|
-
for (let i = leafIdx - 1; i >= 0; i--) {
|
|
376
|
-
let value = Tags.getValues(node)[i];
|
|
377
|
-
|
|
378
|
-
if (Array.isArray(value)) {
|
|
379
|
-
let childNode = value;
|
|
380
|
-
let { names } = Tags.getSums(childNode);
|
|
381
|
-
|
|
382
|
-
let res;
|
|
383
|
-
if ((res = Tags.getAtName(name, names))) {
|
|
384
|
-
count += res;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
stack = stack.pop();
|
|
389
|
-
if (stack.size) {
|
|
390
|
-
({ node, index: leafIdx } = stack.value);
|
|
391
|
-
}
|
|
392
|
-
} while (stack.size);
|
|
393
|
-
|
|
394
|
-
// the initializer doesn't matter to us
|
|
395
|
-
// also we're going from fenceposts to gaps
|
|
396
|
-
return count - 1;
|
|
333
|
+
return [GapTag, NullTag].includes(parseTagType(tag));
|
|
397
334
|
};
|
|
398
335
|
|
|
399
|
-
export const getPropertyTagsIndex = (agAstNode, type, name, index, shiftIndex) => {
|
|
400
|
-
let firstPropsIndex = __getPropertyTagsIndex(agAstNode, type, name, 0);
|
|
401
|
-
let prop = firstPropsIndex == null ? null : Tags.getAt(firstPropsIndex, getTags(agAstNode));
|
|
402
|
-
let ref = prop?.value.reference;
|
|
403
|
-
let sums = Tags.getSums(agAstNode.value.tags);
|
|
404
|
-
let counts = name ? sums.names : sums.types;
|
|
405
|
-
|
|
406
|
-
if (ref?.flags.array) {
|
|
407
|
-
if (index < 0) {
|
|
408
|
-
index = Tags.getAtName(type, counts) + index;
|
|
409
|
-
} else if (index == null) {
|
|
410
|
-
index = Tags.getAtName(name, counts) - 1;
|
|
411
|
-
|
|
412
|
-
if (index < 0) return null;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
let parentIndex = __getPropertyTagsIndex(agAstNode, type, name, index ?? 0);
|
|
417
|
-
|
|
418
|
-
if (parentIndex != null && ref?.flags.expression) {
|
|
419
|
-
let shiftIndex_ = shiftIndex == null ? -1 : shiftIndex;
|
|
420
|
-
if (shiftIndex_ < 0) {
|
|
421
|
-
let shifts = 0;
|
|
422
|
-
// TODO speed this up for deeply nested shifts
|
|
423
|
-
// algorithm: make big jump forward, then look at shift index to see if we overshot completely
|
|
424
|
-
// works because we know the size of the thing and a bigger thing doesn't fit in a smaller one
|
|
425
|
-
while (Tags.getAt(parentIndex + shifts, agAstNode.value.children)?.value.shift) {
|
|
426
|
-
shifts++;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (-shiftIndex_ > shifts + 1) return null;
|
|
430
|
-
|
|
431
|
-
return parentIndex + shifts + shiftIndex_ + 1;
|
|
432
|
-
} else {
|
|
433
|
-
if (parentIndex + shiftIndex_ >= Tags.getSize(agAstNode.value.tags)) {
|
|
434
|
-
return null;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return parentIndex + shiftIndex_;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return parentIndex;
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
const __getPropertyTagsIndex = (agAstNode, type, name, index) => {
|
|
445
|
-
let nameCount = 0;
|
|
446
|
-
let node = Tags.getValues(agAstNode.value.tags)[1];
|
|
447
|
-
let idx = -1;
|
|
448
|
-
|
|
449
|
-
// drill into subtrees, passing over subtrees with too few references of the desired name
|
|
450
|
-
outer: while (node) {
|
|
451
|
-
let sums = Tags.getSums(node);
|
|
452
|
-
|
|
453
|
-
if (!sums) return null;
|
|
454
|
-
|
|
455
|
-
let valueNameCount =
|
|
456
|
-
name != null ? Tags.getAtName(name, sums.names) : Tags.getAtName(type, sums.types);
|
|
457
|
-
|
|
458
|
-
if (nameCount + valueNameCount < index) {
|
|
459
|
-
return null;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
for (const value of Tags.getValues(node)) {
|
|
463
|
-
if (!isArray(value)) {
|
|
464
|
-
idx++;
|
|
465
|
-
let tag = value;
|
|
466
|
-
if (tag.type === Property) {
|
|
467
|
-
let { tags, reference } = tag.value;
|
|
468
|
-
if (tags[0].type === ReferenceTag) {
|
|
469
|
-
if (
|
|
470
|
-
(name != null && reference.name === name) ||
|
|
471
|
-
(type != null && reference.type === type)
|
|
472
|
-
) {
|
|
473
|
-
nameCount += 1;
|
|
474
|
-
if (nameCount > index) {
|
|
475
|
-
return idx + 1;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
} else {
|
|
481
|
-
let valueSums = Tags.getSums(value);
|
|
482
|
-
if (
|
|
483
|
-
nameCount +
|
|
484
|
-
(name != null
|
|
485
|
-
? Tags.getAtName(name, valueSums.names)
|
|
486
|
-
: Tags.getAtName(type, valueSums.types)) >
|
|
487
|
-
index
|
|
488
|
-
) {
|
|
489
|
-
node = value;
|
|
490
|
-
continue outer;
|
|
491
|
-
} else {
|
|
492
|
-
nameCount +=
|
|
493
|
-
(name != null
|
|
494
|
-
? Tags.getAtName(name, valueSums.names)
|
|
495
|
-
: Tags.getAtName(type, valueSums.types)) ?? 0;
|
|
496
|
-
idx += Tags.getSize(value);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
return null;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return null;
|
|
505
|
-
};
|
|
506
|
-
|
|
507
|
-
const { hasOwn, freeze } = Object;
|
|
508
|
-
const { isArray } = Array;
|
|
509
|
-
|
|
510
336
|
export const getOriginalFirstNode = (node) => {
|
|
511
337
|
if (node.type !== TreeNode) return;
|
|
512
338
|
|
|
@@ -529,7 +355,10 @@ export const getFirstNodeProperty = (node) => {
|
|
|
529
355
|
if (!ref.flags.expression) {
|
|
530
356
|
return child;
|
|
531
357
|
} else {
|
|
532
|
-
let tagsIndex =
|
|
358
|
+
let tagsIndex = Tags.getIndex(
|
|
359
|
+
buildFullPathSegment(ref.type, ref.name, 0, -1),
|
|
360
|
+
node.value.tags,
|
|
361
|
+
);
|
|
533
362
|
return Tags.getAt(tagsIndex, getTags(node), 2)?.value;
|
|
534
363
|
}
|
|
535
364
|
// is it shifted?
|
|
@@ -538,22 +367,6 @@ export const getFirstNodeProperty = (node) => {
|
|
|
538
367
|
return null;
|
|
539
368
|
};
|
|
540
369
|
|
|
541
|
-
export const referenceIsSingular = (ref) => {
|
|
542
|
-
return (ref.name && !['#', '@'].includes(ref.type)) || ref.type === '_';
|
|
543
|
-
};
|
|
544
|
-
|
|
545
|
-
export const referencesAreEqual = (a, b) => {
|
|
546
|
-
return (
|
|
547
|
-
a === b ||
|
|
548
|
-
(a.type === b.type &&
|
|
549
|
-
a.name === b.name &&
|
|
550
|
-
a.flags.array === b.flags.array &&
|
|
551
|
-
a.flags.intrinsic === b.flags.intrinsic &&
|
|
552
|
-
a.flags.hasGap === b.flags.hasGap &&
|
|
553
|
-
a.flags.expression === b.flags.expression)
|
|
554
|
-
);
|
|
555
|
-
};
|
|
556
|
-
|
|
557
370
|
export const isDefined = (obj, key) => hasOwn(obj, key) && obj[key] !== undefined;
|
|
558
371
|
export const isUndefined = (obj, key) => !hasOwn(obj, key) || obj[key] === undefined;
|
|
559
372
|
|
|
@@ -570,10 +383,8 @@ export const getProperty = (pathSegment, node) => {
|
|
|
570
383
|
|
|
571
384
|
if (pathSegment == null) throw new Error('Bad path segment');
|
|
572
385
|
|
|
573
|
-
let
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
let propIndex = getPropertyTagsIndex(node, type, name, index, shiftIndex);
|
|
386
|
+
let segment = typeof pathSegment === 'string' ? buildPathSegment(pathSegment) : pathSegment;
|
|
387
|
+
let propIndex = Tags.getIndex(segment, node.value.tags);
|
|
577
388
|
|
|
578
389
|
if (propIndex == null) return null;
|
|
579
390
|
|
|
@@ -638,7 +449,12 @@ export const getOr = (defaultValue, path, node) => {
|
|
|
638
449
|
return isNullNode(result) ? null : result;
|
|
639
450
|
};
|
|
640
451
|
|
|
452
|
+
export const set = (path, value, node) => {
|
|
453
|
+
return Path.from(node).replaceAt(path, value).node;
|
|
454
|
+
};
|
|
455
|
+
|
|
641
456
|
export function* list(name, node) {
|
|
457
|
+
if (isArray(name)) throw new Error('not supported');
|
|
642
458
|
let count = countList(name, node);
|
|
643
459
|
|
|
644
460
|
for (let i = 0; i < count; i++) {
|
|
@@ -651,10 +467,10 @@ export const countList = (name, node) => {
|
|
|
651
467
|
|
|
652
468
|
if (name == null) throw new Error('Bad path');
|
|
653
469
|
|
|
654
|
-
return Tags.
|
|
470
|
+
return Tags.findStats(name, Tags.getSums(getTags(node)).names);
|
|
655
471
|
};
|
|
656
472
|
|
|
657
|
-
export function* allTagPathsFor(range, options = {}) {
|
|
473
|
+
export function* allTagPathsFor(range, options = freeze({})) {
|
|
658
474
|
if (range == null) return;
|
|
659
475
|
|
|
660
476
|
if (range[0] && !(range[0] instanceof TagPath)) throw new Error();
|
|
@@ -666,7 +482,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
666
482
|
let path = startPath;
|
|
667
483
|
|
|
668
484
|
while (path) {
|
|
669
|
-
if (path.inner && path.previousSibling.
|
|
485
|
+
if (path.inner && path.previousSibling.type === ReferenceTag) {
|
|
670
486
|
path = TagPath.from(path.inner, 0);
|
|
671
487
|
}
|
|
672
488
|
|
|
@@ -684,7 +500,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
684
500
|
|
|
685
501
|
if (
|
|
686
502
|
endPath &&
|
|
687
|
-
path.
|
|
503
|
+
path.type === CloseNodeTag &&
|
|
688
504
|
gapPath &&
|
|
689
505
|
gapPath.tagsIndex === endPath.tagsIndex &&
|
|
690
506
|
gapPath.path.node === endPath.path.node
|
|
@@ -695,7 +511,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
695
511
|
}
|
|
696
512
|
}
|
|
697
513
|
|
|
698
|
-
export function* allTagsFor(range, options = {}) {
|
|
514
|
+
export function* allTagsFor(range, options = freeze({})) {
|
|
699
515
|
for (let path of allTagPathsFor(range, options)) {
|
|
700
516
|
yield path.tag;
|
|
701
517
|
}
|
|
@@ -786,51 +602,27 @@ export const getAttributes = (node) => {
|
|
|
786
602
|
};
|
|
787
603
|
|
|
788
604
|
export const isSelfClosingTag = (tag) => {
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
export let pathForTagPath = (tagPath) => {
|
|
797
|
-
let refTagPath = tagPath;
|
|
798
|
-
let isShift = tagPath.tag.type === ShiftTag;
|
|
799
|
-
|
|
800
|
-
if (isShift) {
|
|
801
|
-
refTagPath = tagPath.siblingAt(tagPath.tagsIndex - tagPath.tag.value.index);
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
let { type, name } = refTagPath.tag.value;
|
|
805
|
-
|
|
806
|
-
if (refTagPath.tag.type !== ReferenceTag) throw new Error();
|
|
807
|
-
|
|
808
|
-
let index = getChildPropertyIndex(tagPath.node, refTagPath.tagsIndex);
|
|
809
|
-
let shiftIndex = isShift ? (tagPath.tag.value.index ?? 0) + 1 : null;
|
|
810
|
-
|
|
811
|
-
return [{ type, name, index, shiftIndex }];
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
let getSigilTag_ = (tag) => {
|
|
815
|
-
switch (tag.type) {
|
|
816
|
-
case Property:
|
|
817
|
-
return getTags(tag.value.property.node)[1][0];
|
|
818
|
-
case TreeNode:
|
|
819
|
-
case NullNode:
|
|
820
|
-
case GapNode:
|
|
821
|
-
return getTags(tag)[1][0];
|
|
822
|
-
case OpenNodeTag:
|
|
823
|
-
case GapTag:
|
|
824
|
-
case NullTag:
|
|
825
|
-
return tag;
|
|
826
|
-
}
|
|
605
|
+
if (!tag) return false;
|
|
606
|
+
let tagType = parseTagType(tag);
|
|
607
|
+
if ([NullTag, GapTag].includes(tagType)) return true;
|
|
608
|
+
if (tagType !== OpenNodeTag) return false;
|
|
609
|
+
let tag_ = isString(tag) ? parseOpenNodeTag(tag) : tag;
|
|
610
|
+
return tag_.value.selfClosing;
|
|
827
611
|
};
|
|
828
612
|
|
|
829
613
|
const parents = new WeakMap();
|
|
830
614
|
|
|
831
615
|
export const Path = class AgastPath {
|
|
832
616
|
static from(node) {
|
|
833
|
-
return
|
|
617
|
+
return (
|
|
618
|
+
node &&
|
|
619
|
+
new Path(
|
|
620
|
+
null,
|
|
621
|
+
buildPathFrame(
|
|
622
|
+
buildPropertyTag(BList.fromValues([Tags.fromValues([]), Tags.fromValues([]), node], 1)),
|
|
623
|
+
),
|
|
624
|
+
)
|
|
625
|
+
);
|
|
834
626
|
}
|
|
835
627
|
|
|
836
628
|
static wrap(frames) {
|
|
@@ -841,17 +633,17 @@ export const Path = class AgastPath {
|
|
|
841
633
|
return Path.from(buildNode(openTag));
|
|
842
634
|
}
|
|
843
635
|
|
|
844
|
-
static set(
|
|
636
|
+
static set(path, value, node) {
|
|
845
637
|
return Path.from(node).replaceAt(path, value).node;
|
|
846
638
|
}
|
|
847
639
|
|
|
848
|
-
static get(
|
|
640
|
+
static get(path, node) {
|
|
849
641
|
return Path.from(node).get(path).node;
|
|
850
642
|
}
|
|
851
643
|
|
|
852
644
|
constructor(parent, frame) {
|
|
853
645
|
if (!frame) throw new Error();
|
|
854
|
-
let frame_ = isArray(frame) ?
|
|
646
|
+
let frame_ = isArray(frame) ? BList.getAt(-1, frame) : frame;
|
|
855
647
|
let { property, parentIndex, isGap } = frame_;
|
|
856
648
|
let { node } = property.value;
|
|
857
649
|
|
|
@@ -868,13 +660,13 @@ export const Path = class AgastPath {
|
|
|
868
660
|
parents.set(this, parent);
|
|
869
661
|
}
|
|
870
662
|
|
|
871
|
-
this.depth = parent ? parent.depth + 1 : isArray(frame) ?
|
|
663
|
+
this.depth = parent ? parent.depth + 1 : isArray(frame) ? BList.getSize(frame) - 1 : 0;
|
|
872
664
|
this.frame = frame_;
|
|
873
665
|
this.frames = !parent
|
|
874
666
|
? isArray(frame)
|
|
875
667
|
? frame
|
|
876
|
-
:
|
|
877
|
-
:
|
|
668
|
+
: BList.fromValues([frame])
|
|
669
|
+
: BList.push(frame, parent.frames);
|
|
878
670
|
|
|
879
671
|
buildSkips(this);
|
|
880
672
|
|
|
@@ -888,18 +680,10 @@ export const Path = class AgastPath {
|
|
|
888
680
|
throw new Error();
|
|
889
681
|
}
|
|
890
682
|
|
|
891
|
-
if (
|
|
892
|
-
parentIndex != null &&
|
|
893
|
-
!parent?.node.value.flags.token &&
|
|
894
|
-
(!this.referenceTag || ![ReferenceTag, ShiftTag].includes(this.referenceTag.type))
|
|
895
|
-
) {
|
|
896
|
-
throw new Error();
|
|
897
|
-
}
|
|
898
|
-
|
|
899
683
|
if (
|
|
900
684
|
parent_ &&
|
|
901
685
|
(isGap
|
|
902
|
-
?
|
|
686
|
+
? BList.getAt(0, parent_.node.value.bounds.leading).property
|
|
903
687
|
: parent_.tagPathAt(parentIndex).tag) !== property
|
|
904
688
|
) {
|
|
905
689
|
throw new Error('Path not reachable');
|
|
@@ -914,12 +698,12 @@ export const Path = class AgastPath {
|
|
|
914
698
|
|
|
915
699
|
push(tagsIndex, isGap) {
|
|
916
700
|
let tag = isGap
|
|
917
|
-
?
|
|
701
|
+
? BList.getAt(0, this.node.value.bounds.leading).property
|
|
918
702
|
: tagsIndex != null
|
|
919
703
|
? Tags.getAt(tagsIndex, this.tags)
|
|
920
704
|
: null;
|
|
921
705
|
|
|
922
|
-
if (!tag || tag
|
|
706
|
+
if (!tag || parseTagType(tag) !== Property) {
|
|
923
707
|
return null;
|
|
924
708
|
}
|
|
925
709
|
|
|
@@ -940,7 +724,7 @@ export const Path = class AgastPath {
|
|
|
940
724
|
return parent;
|
|
941
725
|
}
|
|
942
726
|
|
|
943
|
-
parent = new Path(null,
|
|
727
|
+
parent = new Path(null, BList.pop(frames));
|
|
944
728
|
|
|
945
729
|
parents.set(this, parent);
|
|
946
730
|
|
|
@@ -959,6 +743,10 @@ export const Path = class AgastPath {
|
|
|
959
743
|
return this.frame.property.value.node;
|
|
960
744
|
}
|
|
961
745
|
|
|
746
|
+
get value() {
|
|
747
|
+
return this.node.value;
|
|
748
|
+
}
|
|
749
|
+
|
|
962
750
|
get name() {
|
|
963
751
|
let { node } = this;
|
|
964
752
|
return node.type === TreeNode ? node.value.name : null;
|
|
@@ -986,6 +774,7 @@ export const Path = class AgastPath {
|
|
|
986
774
|
getChild(childrenIndex) {
|
|
987
775
|
let { node } = this;
|
|
988
776
|
if (isStubNode(node)) return null;
|
|
777
|
+
|
|
989
778
|
return Tags.getAt(childrenIndex, getChildren(node)) || null;
|
|
990
779
|
}
|
|
991
780
|
|
|
@@ -999,7 +788,7 @@ export const Path = class AgastPath {
|
|
|
999
788
|
|
|
1000
789
|
getPropertyTagPath(childrenIndex) {
|
|
1001
790
|
let tagPath = this.tagPathAt(childrenIndex + 1);
|
|
1002
|
-
return tagPath && tagPath.
|
|
791
|
+
return tagPath && tagPath.type === Property ? tagPath : null;
|
|
1003
792
|
}
|
|
1004
793
|
|
|
1005
794
|
getReferenceTagPath(childrenIndex) {
|
|
@@ -1025,12 +814,12 @@ export const Path = class AgastPath {
|
|
|
1025
814
|
|
|
1026
815
|
get openTagPath() {
|
|
1027
816
|
let tagPath = TagPath.from(this, 0);
|
|
1028
|
-
return tagPath.
|
|
817
|
+
return tagPath.type === OpenNodeTag ? tagPath : null;
|
|
1029
818
|
}
|
|
1030
819
|
|
|
1031
820
|
get closeTagPath() {
|
|
1032
821
|
let tagPath = TagPath.from(this, -1);
|
|
1033
|
-
return tagPath.
|
|
822
|
+
return tagPath.type === CloseNodeTag ? tagPath : null;
|
|
1034
823
|
}
|
|
1035
824
|
|
|
1036
825
|
get openTag() {
|
|
@@ -1038,7 +827,7 @@ export const Path = class AgastPath {
|
|
|
1038
827
|
}
|
|
1039
828
|
|
|
1040
829
|
get open() {
|
|
1041
|
-
return this.openTag.value;
|
|
830
|
+
return parseOpenNodeTag(this.openTag).value;
|
|
1042
831
|
}
|
|
1043
832
|
|
|
1044
833
|
get closeTag() {
|
|
@@ -1050,11 +839,12 @@ export const Path = class AgastPath {
|
|
|
1050
839
|
}
|
|
1051
840
|
|
|
1052
841
|
get bindingTags() {
|
|
1053
|
-
return this.parentPropertyPath?.tag.value.tags[1];
|
|
842
|
+
return this.parentPropertyPath?.tag.value.tags[1][1];
|
|
1054
843
|
}
|
|
1055
844
|
|
|
1056
845
|
get reference() {
|
|
1057
|
-
|
|
846
|
+
let { referenceTag } = this;
|
|
847
|
+
return referenceTag && parseTag(referenceTag)?.value;
|
|
1058
848
|
}
|
|
1059
849
|
|
|
1060
850
|
get referenceTag() {
|
|
@@ -1080,8 +870,8 @@ export const Path = class AgastPath {
|
|
|
1080
870
|
return null;
|
|
1081
871
|
}
|
|
1082
872
|
let path = TagPath.from(this.parent, this.parentIndex);
|
|
1083
|
-
if (path.
|
|
1084
|
-
path = TagPath.from(this.parent, this.parentIndex - path.
|
|
873
|
+
if (path.next?.type === ShiftTag) {
|
|
874
|
+
path = TagPath.from(this.parent, this.parentIndex - path.value.shift.index);
|
|
1085
875
|
}
|
|
1086
876
|
return path;
|
|
1087
877
|
}
|
|
@@ -1096,7 +886,7 @@ export const Path = class AgastPath {
|
|
|
1096
886
|
|
|
1097
887
|
get firstPropertyTagPath() {
|
|
1098
888
|
let tagPath = this.tagPathAt(0);
|
|
1099
|
-
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.
|
|
889
|
+
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.value.node))) {
|
|
1100
890
|
tagPath = tagPath.nextSibling;
|
|
1101
891
|
if (tagPath?.propertyPath) {
|
|
1102
892
|
tagPath = tagPath.propertyPath;
|
|
@@ -1107,7 +897,7 @@ export const Path = class AgastPath {
|
|
|
1107
897
|
|
|
1108
898
|
get lastPropertyTagPath() {
|
|
1109
899
|
let tagPath = this.tagPathAt(-1);
|
|
1110
|
-
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.
|
|
900
|
+
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.value.node))) {
|
|
1111
901
|
tagPath = tagPath.previousSibling;
|
|
1112
902
|
if (tagPath?.propertyPath) {
|
|
1113
903
|
tagPath = tagPath.propertyPath;
|
|
@@ -1140,7 +930,9 @@ export const Path = class AgastPath {
|
|
|
1140
930
|
while (!pathInst.node.value.name && pathInst.node.value.type === Symbol.for('_')) {
|
|
1141
931
|
if (pathInst.depth) throw new Error();
|
|
1142
932
|
skippedRootFragment = true;
|
|
1143
|
-
pathInst = pathInst.push(
|
|
933
|
+
pathInst = pathInst.push(
|
|
934
|
+
Tags.getIndex(buildFullPathSegment('_', null, 0), pathInst.node.value.tags),
|
|
935
|
+
);
|
|
1144
936
|
}
|
|
1145
937
|
}
|
|
1146
938
|
|
|
@@ -1160,12 +952,9 @@ export const Path = class AgastPath {
|
|
|
1160
952
|
|
|
1161
953
|
if (i === 0 && seg.type === '_' && skippedRootFragment) continue;
|
|
1162
954
|
|
|
1163
|
-
let tagsIndex =
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
seg.name,
|
|
1167
|
-
seg.index,
|
|
1168
|
-
seg.shiftIndex,
|
|
955
|
+
let tagsIndex = Tags.getIndex(
|
|
956
|
+
buildFullPathSegment(seg.type, seg.name, seg.index, seg.shiftIndex),
|
|
957
|
+
pathInst.node.value.tags,
|
|
1169
958
|
);
|
|
1170
959
|
|
|
1171
960
|
if (tagsIndex == null) return null;
|
|
@@ -1177,9 +966,9 @@ export const Path = class AgastPath {
|
|
|
1177
966
|
}
|
|
1178
967
|
|
|
1179
968
|
replaceWith(node, bindingTags) {
|
|
1180
|
-
let bindings = bindingTags?.map((tag) => tag.value); // TODO improve here
|
|
969
|
+
let bindings = bindingTags?.map((tag) => parseTag(tag).value); // TODO improve here
|
|
1181
970
|
if (bindings != null && !isArray(bindings)) throw new Error();
|
|
1182
|
-
if (!
|
|
971
|
+
if (!isNode(node)) throw new Error();
|
|
1183
972
|
|
|
1184
973
|
if (!node) throw new Error();
|
|
1185
974
|
|
|
@@ -1191,7 +980,7 @@ export const Path = class AgastPath {
|
|
|
1191
980
|
let path = this.parent;
|
|
1192
981
|
let replacementPath = [];
|
|
1193
982
|
|
|
1194
|
-
let targetShift_ = this.parent?.parentProperty?.value.tags[0];
|
|
983
|
+
let targetShift_ = this.parent?.parentProperty?.value.tags[1][0];
|
|
1195
984
|
let targetShift = targetShift_ && (targetShift_.type === ReferenceTag ? null : targetShift_);
|
|
1196
985
|
let targetReference = this.reference;
|
|
1197
986
|
let targetBindings = bindings == null ? this.bindings : bindings;
|
|
@@ -1206,24 +995,29 @@ export const Path = class AgastPath {
|
|
|
1206
995
|
|
|
1207
996
|
let { tags, shift } = Tags.getAt(targetParentIndex, getTags(path.node)).value;
|
|
1208
997
|
|
|
1209
|
-
let firstTag = tags[0];
|
|
998
|
+
let firstTag = tags[1][0];
|
|
1210
999
|
let newFirstTag = firstTag;
|
|
1211
1000
|
if (shift) {
|
|
1212
1001
|
newFirstTag = buildChild(ReferenceTag, targetReference);
|
|
1213
1002
|
}
|
|
1214
1003
|
|
|
1215
|
-
let tags_ =
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1004
|
+
let tags_ = BList.fromValues(
|
|
1005
|
+
[
|
|
1006
|
+
firstTag,
|
|
1007
|
+
Tags.fromValues(
|
|
1008
|
+
map((binding) => buildChild(BindingTag, binding), arrayValues(targetBindings)),
|
|
1009
|
+
),
|
|
1010
|
+
value,
|
|
1011
|
+
],
|
|
1012
|
+
1,
|
|
1013
|
+
);
|
|
1220
1014
|
|
|
1221
1015
|
if (!held && !shift) {
|
|
1222
1016
|
built = buildNode(
|
|
1223
1017
|
Tags.replaceAt(
|
|
1224
1018
|
targetParentIndex,
|
|
1225
|
-
built.value.tags,
|
|
1226
1019
|
buildChild(Property, buildProperty(tags_)),
|
|
1020
|
+
built.value.tags,
|
|
1227
1021
|
),
|
|
1228
1022
|
);
|
|
1229
1023
|
replacementPath.push(targetParentIndex);
|
|
@@ -1234,16 +1028,18 @@ export const Path = class AgastPath {
|
|
|
1234
1028
|
let nextShift = nextProperty?.type === Property && nextProperty.value.shift;
|
|
1235
1029
|
|
|
1236
1030
|
if (nextShift) {
|
|
1237
|
-
let { reference, bindings } =
|
|
1238
|
-
|
|
1031
|
+
let { reference, bindings } = BList.getAt(
|
|
1032
|
+
-1,
|
|
1033
|
+
nextProperty.value.node.value.bounds.leading,
|
|
1034
|
+
).property.value;
|
|
1239
1035
|
|
|
1240
1036
|
path = path.push(i);
|
|
1241
1037
|
|
|
1242
1038
|
built = buildNode(
|
|
1243
1039
|
Tags.replaceAt(
|
|
1244
1040
|
targetParentIndex - shift.index,
|
|
1245
|
-
built.value.tags,
|
|
1246
1041
|
buildChild(Property, buildProperty(tags_)),
|
|
1042
|
+
built.value.tags,
|
|
1247
1043
|
),
|
|
1248
1044
|
);
|
|
1249
1045
|
|
|
@@ -1252,17 +1048,14 @@ export const Path = class AgastPath {
|
|
|
1252
1048
|
built = buildNode(Tags.removeAt(targetParentIndex + 1, built.value.tags));
|
|
1253
1049
|
}
|
|
1254
1050
|
|
|
1255
|
-
tags_ = [newFirstTag, tags_[1], tags_[2]];
|
|
1051
|
+
tags_ = BList.fromValues([newFirstTag, tags_[1][1], tags_[1][2]], 1);
|
|
1256
1052
|
|
|
1257
1053
|
targetShift = null;
|
|
1258
1054
|
targetReference = reference;
|
|
1259
1055
|
targetBindings = bindings;
|
|
1260
|
-
targetParentIndex =
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
reference.name,
|
|
1264
|
-
0,
|
|
1265
|
-
0,
|
|
1056
|
+
targetParentIndex = Tags.getIndex(
|
|
1057
|
+
buildFullPathSegment(reference.type, reference.name, 0, 0),
|
|
1058
|
+
nextProperty.value.node.value.tags,
|
|
1266
1059
|
);
|
|
1267
1060
|
held = null;
|
|
1268
1061
|
|
|
@@ -1272,8 +1065,8 @@ export const Path = class AgastPath {
|
|
|
1272
1065
|
built = buildNode(
|
|
1273
1066
|
Tags.replaceAt(
|
|
1274
1067
|
targetParentIndex,
|
|
1275
|
-
getTags(built),
|
|
1276
1068
|
buildChild(Property, buildProperty(tags_, shift)),
|
|
1069
|
+
getTags(built),
|
|
1277
1070
|
),
|
|
1278
1071
|
);
|
|
1279
1072
|
replacementPath.push(targetParentIndex);
|
|
@@ -1283,7 +1076,7 @@ export const Path = class AgastPath {
|
|
|
1283
1076
|
held = targetShift ? value : null;
|
|
1284
1077
|
heldCount = held ? heldCount + 1 : 0;
|
|
1285
1078
|
|
|
1286
|
-
targetShift_ = path?.parentProperty?.value.tags[0];
|
|
1079
|
+
targetShift_ = path?.parentProperty?.value.tags[1][0];
|
|
1287
1080
|
targetShift = targetShift_ && (targetShift_.type === ReferenceTag ? null : targetShift_);
|
|
1288
1081
|
targetReference = path.reference;
|
|
1289
1082
|
targetBindings = path.bindings;
|
|
@@ -1295,7 +1088,131 @@ export const Path = class AgastPath {
|
|
|
1295
1088
|
}
|
|
1296
1089
|
|
|
1297
1090
|
replaceAt(path, node, bindings) {
|
|
1298
|
-
return this.get(path).replaceWith(node, bindings).atDepth(
|
|
1091
|
+
return this.get(path).replaceWith(node, bindings).atDepth(this.depth);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
removeAt(path) {
|
|
1095
|
+
if (!this.depth && !path.length) {
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
let built = null;
|
|
1100
|
+
let lastPath = this.get(path);
|
|
1101
|
+
let path_ = lastPath.parent;
|
|
1102
|
+
let replacementPath = [];
|
|
1103
|
+
|
|
1104
|
+
let targetShift_ = lastPath.parent?.parentProperty?.value.tags[1][0];
|
|
1105
|
+
let targetShift = targetShift_ && (targetShift_.type === ReferenceTag ? null : targetShift_);
|
|
1106
|
+
let targetReference = lastPath.reference;
|
|
1107
|
+
let targetBindings = lastPath.bindings;
|
|
1108
|
+
let targetParentIndex = lastPath.parentIndex;
|
|
1109
|
+
let held = null;
|
|
1110
|
+
let heldCount = 0;
|
|
1111
|
+
let value;
|
|
1112
|
+
|
|
1113
|
+
while (path_) {
|
|
1114
|
+
value = built;
|
|
1115
|
+
built = buildNode(getTags(path_.node));
|
|
1116
|
+
|
|
1117
|
+
let { tags, shift } = Tags.getAt(targetParentIndex, getTags(path_.node)).value;
|
|
1118
|
+
|
|
1119
|
+
let firstTag = tags[1][0];
|
|
1120
|
+
let newFirstTag = firstTag;
|
|
1121
|
+
if (shift) {
|
|
1122
|
+
newFirstTag = buildChild(ReferenceTag, targetReference);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
let tags_ =
|
|
1126
|
+
value &&
|
|
1127
|
+
BList.fromValues(
|
|
1128
|
+
[
|
|
1129
|
+
firstTag,
|
|
1130
|
+
Tags.fromValues(
|
|
1131
|
+
map((binding) => buildChild(BindingTag, binding), arrayValues(targetBindings)),
|
|
1132
|
+
),
|
|
1133
|
+
value,
|
|
1134
|
+
],
|
|
1135
|
+
1,
|
|
1136
|
+
);
|
|
1137
|
+
|
|
1138
|
+
if (!held && !shift) {
|
|
1139
|
+
if (tags_) {
|
|
1140
|
+
built = buildNode(
|
|
1141
|
+
Tags.replaceAt(
|
|
1142
|
+
targetParentIndex,
|
|
1143
|
+
buildChild(Property, buildProperty(tags_)),
|
|
1144
|
+
built.value.tags,
|
|
1145
|
+
),
|
|
1146
|
+
);
|
|
1147
|
+
} else {
|
|
1148
|
+
built = buildNode(Tags.removeAt(targetParentIndex, built.value.tags));
|
|
1149
|
+
}
|
|
1150
|
+
replacementPath.push(targetParentIndex);
|
|
1151
|
+
} else {
|
|
1152
|
+
let i = targetParentIndex + 1;
|
|
1153
|
+
let nextProperty = Tags.getAt(i, built.value.tags);
|
|
1154
|
+
|
|
1155
|
+
let nextShift = nextProperty?.type === Property && nextProperty.value.shift;
|
|
1156
|
+
|
|
1157
|
+
if (nextShift) {
|
|
1158
|
+
let { reference, bindings } = BList.getAt(
|
|
1159
|
+
-1,
|
|
1160
|
+
nextProperty.value.node.value.bounds.leading,
|
|
1161
|
+
).property.value;
|
|
1162
|
+
|
|
1163
|
+
path_ = path_.push(i);
|
|
1164
|
+
|
|
1165
|
+
built = buildNode(
|
|
1166
|
+
Tags.replaceAt(
|
|
1167
|
+
targetParentIndex - shift.index,
|
|
1168
|
+
buildChild(Property, buildProperty(tags_)),
|
|
1169
|
+
built.value.tags,
|
|
1170
|
+
),
|
|
1171
|
+
);
|
|
1172
|
+
|
|
1173
|
+
targetParentIndex -= shift.index;
|
|
1174
|
+
for (let i = shift.index - 1; i >= 0; i--) {
|
|
1175
|
+
built = buildNode(Tags.removeAt(targetParentIndex + 1, built.value.tags));
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
tags_ = BList.fromValues([newFirstTag, tags_[1][1], tags_[1][2]], 1);
|
|
1179
|
+
|
|
1180
|
+
targetShift = null;
|
|
1181
|
+
targetReference = reference;
|
|
1182
|
+
targetBindings = bindings;
|
|
1183
|
+
targetParentIndex = Tags.getIndex(
|
|
1184
|
+
buildFullPathSegment(reference.type, reference.name, 0, 0),
|
|
1185
|
+
nextProperty.value.node.value.tags,
|
|
1186
|
+
);
|
|
1187
|
+
held = null;
|
|
1188
|
+
|
|
1189
|
+
replacementPath.push(targetParentIndex);
|
|
1190
|
+
continue;
|
|
1191
|
+
} else {
|
|
1192
|
+
built = buildNode(
|
|
1193
|
+
Tags.replaceAt(
|
|
1194
|
+
targetParentIndex,
|
|
1195
|
+
buildChild(Property, buildProperty(tags_, shift)),
|
|
1196
|
+
getTags(built),
|
|
1197
|
+
),
|
|
1198
|
+
);
|
|
1199
|
+
replacementPath.push(targetParentIndex);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
held = targetShift ? value : null;
|
|
1204
|
+
heldCount = held ? heldCount + 1 : 0;
|
|
1205
|
+
|
|
1206
|
+
targetShift_ = path_?.parentProperty?.value.tags[1][0];
|
|
1207
|
+
targetShift = targetShift_ && (targetShift_.type === ReferenceTag ? null : targetShift_);
|
|
1208
|
+
targetReference = path_.reference;
|
|
1209
|
+
targetBindings = path_.bindings;
|
|
1210
|
+
targetParentIndex = path_.parentIndex;
|
|
1211
|
+
lastPath = path_;
|
|
1212
|
+
path_ = path_.parent;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
return Path.from(built);
|
|
1299
1216
|
}
|
|
1300
1217
|
|
|
1301
1218
|
mapOnto(rootNode) {
|
|
@@ -1321,19 +1238,19 @@ export const Path = class AgastPath {
|
|
|
1321
1238
|
let { parent, node } = this;
|
|
1322
1239
|
let sigilTag = getSigilTag(node);
|
|
1323
1240
|
|
|
1324
|
-
return !parent && sigilTag && !!(isSelfClosingTag(sigilTag) ||
|
|
1241
|
+
return !parent && sigilTag && !!(isSelfClosingTag(sigilTag) || getCloseNodeTag(node));
|
|
1325
1242
|
}
|
|
1326
1243
|
|
|
1327
1244
|
get held() {
|
|
1328
1245
|
let tagPath = this.tagPathAt(-1);
|
|
1329
1246
|
|
|
1330
1247
|
// TODO is this safe
|
|
1331
|
-
if (tagPath.
|
|
1248
|
+
if (tagPath.type !== Property) return null;
|
|
1332
1249
|
|
|
1333
|
-
let { tags } = tagPath.
|
|
1250
|
+
let { tags } = tagPath.value;
|
|
1334
1251
|
|
|
1335
|
-
if (tags[0]?.type === ShiftTag && !tags[2]) {
|
|
1336
|
-
return TagPath.from(tagPath.path, tagPath.tagsIndex - 1).
|
|
1252
|
+
if (tags[1][0]?.type === ShiftTag && !tags[1][2]) {
|
|
1253
|
+
return TagPath.from(tagPath.path, tagPath.tagsIndex - 1).value;
|
|
1337
1254
|
}
|
|
1338
1255
|
|
|
1339
1256
|
// if we're not at the left side, we aren't held
|
|
@@ -1350,8 +1267,8 @@ export const Path = class AgastPath {
|
|
|
1350
1267
|
for (;;) {
|
|
1351
1268
|
let refPath = coverParent.propertyKeyTagPath;
|
|
1352
1269
|
|
|
1353
|
-
if (refPath?.
|
|
1354
|
-
return TagPath.from(refPath.path, refPath.tagsIndex - 1).
|
|
1270
|
+
if (refPath?.type === ShiftTag) {
|
|
1271
|
+
return TagPath.from(refPath.path, refPath.tagsIndex - 1).value;
|
|
1355
1272
|
}
|
|
1356
1273
|
|
|
1357
1274
|
coverParent = coverParent.parent;
|
|
@@ -1364,57 +1281,24 @@ export const Path = class AgastPath {
|
|
|
1364
1281
|
advance(tag) {
|
|
1365
1282
|
if (!tag) throw new Error();
|
|
1366
1283
|
|
|
1367
|
-
let tagPath = this.tagPathAt(-1,
|
|
1284
|
+
let tagPath = this.tagPathAt(-1, -1);
|
|
1368
1285
|
|
|
1369
|
-
if (tagPath?.
|
|
1286
|
+
if (tagPath?.type === Property ? tagPath?.nextSibling : tagPath?.next) throw new Error();
|
|
1370
1287
|
|
|
1371
1288
|
if (this.done) throw new Error();
|
|
1372
1289
|
|
|
1373
1290
|
let resultPath = this;
|
|
1374
1291
|
|
|
1375
|
-
|
|
1376
|
-
case BindingTag: {
|
|
1377
|
-
if (!this.lastPropertyTagPath) {
|
|
1378
|
-
resultPath = this.advanceUnwrapped(buildReferenceTag()).path;
|
|
1379
|
-
}
|
|
1380
|
-
break;
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
case TreeNode:
|
|
1384
|
-
case NullNode:
|
|
1385
|
-
case GapNode:
|
|
1386
|
-
case NullTag:
|
|
1387
|
-
case GapTag:
|
|
1388
|
-
case OpenNodeTag: {
|
|
1389
|
-
let sigilTag = getSigilTag_(tag);
|
|
1390
|
-
|
|
1391
|
-
if (sigilTag.type === OpenNodeTag && sigilTag.value.type === Symbol.for('__')) {
|
|
1392
|
-
break;
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
let lastTagPath = this.lastPropertyTagPath;
|
|
1396
|
-
let newProperty = !lastTagPath || propertyIsFull(lastTagPath.tag);
|
|
1397
|
-
let reference = lastTagPath?.referenceTagPath.tag.value;
|
|
1292
|
+
let tag_ = isNode(tag) ? tag : parseTag(tag);
|
|
1398
1293
|
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
if (newProperty || !lastTagPath.tag.value.tags.length) {
|
|
1402
|
-
resultPath = this.advanceUnwrapped(buildReferenceTag()).path;
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
break;
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
if (tag.type === Property) {
|
|
1411
|
-
resultPath = Path.from(buildNode(Tags.push(getTags(resultPath.node), tag)));
|
|
1294
|
+
if (tag_.type === Property) {
|
|
1295
|
+
resultPath = Path.from(buildNode(Tags.push(tag, getTags(resultPath.node))));
|
|
1412
1296
|
} else {
|
|
1413
|
-
resultPath = resultPath.advanceUnwrapped(tag).path;
|
|
1297
|
+
resultPath = resultPath.advanceUnwrapped(printTag(tag)).path;
|
|
1414
1298
|
}
|
|
1415
1299
|
|
|
1416
1300
|
if (
|
|
1417
|
-
(
|
|
1301
|
+
(tag_.type === CloseNodeTag || (tag_.type === OpenNodeTag && tag_.value.selfClosing)) &&
|
|
1418
1302
|
resultPath.depth
|
|
1419
1303
|
) {
|
|
1420
1304
|
return resultPath.parent;
|
|
@@ -1424,14 +1308,13 @@ export const Path = class AgastPath {
|
|
|
1424
1308
|
}
|
|
1425
1309
|
|
|
1426
1310
|
advanceUnwrapped(tag) {
|
|
1427
|
-
if (!tag) throw new Error();
|
|
1311
|
+
if (!isString(tag) && !isNode(tag)) throw new Error();
|
|
1312
|
+
let tag_ = isString(tag) ? parseTag(tag) : tag;
|
|
1428
1313
|
|
|
1429
1314
|
let tagPath = this.tagPathAt(-1, [-1, -1]);
|
|
1430
1315
|
|
|
1431
1316
|
if (
|
|
1432
|
-
[TreeNode, NullNode, GapNode].includes(tagPath?.
|
|
1433
|
-
? tagPath?.nextSibling
|
|
1434
|
-
: tagPath?.next
|
|
1317
|
+
[TreeNode, NullNode, GapNode].includes(tagPath?.type) ? tagPath?.nextSibling : tagPath?.next
|
|
1435
1318
|
)
|
|
1436
1319
|
throw new Error();
|
|
1437
1320
|
|
|
@@ -1439,11 +1322,11 @@ export const Path = class AgastPath {
|
|
|
1439
1322
|
|
|
1440
1323
|
let targetPath = tagPath && endsNode(tagPath.tag) ? this.parent : this;
|
|
1441
1324
|
|
|
1442
|
-
switch (
|
|
1325
|
+
switch (tag_.type) {
|
|
1443
1326
|
case ReferenceTag: {
|
|
1444
|
-
let { type, name, flags } =
|
|
1327
|
+
let { type, name, flags } = tag_.value;
|
|
1445
1328
|
|
|
1446
|
-
if ([ReferenceTag, ShiftTag, BindingTag].includes(targetPath.tagPathAt(-1, -1)?.
|
|
1329
|
+
if ([ReferenceTag, ShiftTag, BindingTag].includes(targetPath.tagPathAt(-1, -1)?.type))
|
|
1447
1330
|
throw new Error('invalid location for reference');
|
|
1448
1331
|
if (!name && !type) throw new Error();
|
|
1449
1332
|
|
|
@@ -1456,22 +1339,25 @@ export const Path = class AgastPath {
|
|
|
1456
1339
|
if (targetPath.open.type === Symbol.for('_') && !['_', '#'].includes(type))
|
|
1457
1340
|
throw new Error();
|
|
1458
1341
|
|
|
1459
|
-
if (
|
|
1460
|
-
let property = getProperty(
|
|
1342
|
+
if (tag_.value.name) {
|
|
1343
|
+
let property = getProperty(tag_.value.name, targetPath.node);
|
|
1461
1344
|
if (
|
|
1462
|
-
getOr(null,
|
|
1345
|
+
getOr(null, tag_.value.name, targetPath.node) &&
|
|
1463
1346
|
!property.value.shift &&
|
|
1464
|
-
!referencesAreEqual(
|
|
1347
|
+
!Tags.referencesAreEqual(tag_.value, property.value.reference)
|
|
1465
1348
|
) {
|
|
1466
1349
|
throw new Error('mismatched references');
|
|
1467
1350
|
}
|
|
1468
|
-
} else if (
|
|
1469
|
-
let rootIdx =
|
|
1351
|
+
} else if (tag_.value.type === '_') {
|
|
1352
|
+
let rootIdx = Tags.getIndex(
|
|
1353
|
+
buildFullPathSegment('_', null, 0),
|
|
1354
|
+
targetPath.node.value.tags,
|
|
1355
|
+
);
|
|
1470
1356
|
|
|
1471
1357
|
if (
|
|
1472
1358
|
rootIdx != null &&
|
|
1473
|
-
!referencesAreEqual(
|
|
1474
|
-
|
|
1359
|
+
!Tags.referencesAreEqual(
|
|
1360
|
+
tag_.value,
|
|
1475
1361
|
Tags.getAt(rootIdx, getTags(targetPath.node)).value.reference,
|
|
1476
1362
|
)
|
|
1477
1363
|
) {
|
|
@@ -1479,43 +1365,42 @@ export const Path = class AgastPath {
|
|
|
1479
1365
|
}
|
|
1480
1366
|
}
|
|
1481
1367
|
|
|
1482
|
-
let property = buildChild(Property, buildProperty([tag]));
|
|
1368
|
+
let property = buildChild(Property, buildProperty(BList.fromValues([printTag(tag)])));
|
|
1483
1369
|
|
|
1484
1370
|
targetPath = targetPath.replaceWith(
|
|
1485
|
-
buildNode(Tags.push(getTags(targetPath.node)
|
|
1371
|
+
buildNode(Tags.push(property, getTags(targetPath.node))),
|
|
1486
1372
|
);
|
|
1487
1373
|
break;
|
|
1488
1374
|
}
|
|
1489
1375
|
|
|
1490
1376
|
case BindingTag: {
|
|
1491
|
-
if (![ReferenceTag, ShiftTag].includes(this.tagPathAt(-1, -1)
|
|
1377
|
+
if (![ReferenceTag, ShiftTag].includes(parseTagType(this.tagPathAt(-1, -1)))) {
|
|
1492
1378
|
throw new Error('Invalid location for BindingTag');
|
|
1493
1379
|
}
|
|
1494
|
-
if (!tag.value.segments) throw new Error();
|
|
1495
1380
|
|
|
1496
1381
|
let refPath = this.tagPathAt(-1, 0);
|
|
1497
1382
|
let propPath = TagPath.from(refPath.path, refPath.tagsIndex);
|
|
1498
1383
|
|
|
1499
|
-
let { shift } = propPath.
|
|
1384
|
+
let { shift } = propPath.value;
|
|
1500
1385
|
|
|
1501
|
-
if (![ReferenceTag, ShiftTag].includes(refPath.
|
|
1386
|
+
if (![ReferenceTag, ShiftTag].includes(refPath.type)) throw new Error();
|
|
1502
1387
|
|
|
1503
|
-
if (refPath.
|
|
1388
|
+
if (refPath.type === ShiftTag) {
|
|
1504
1389
|
refPath = TagPath.from(refPath.path, refPath.tagsIndex - shift.index, 0);
|
|
1505
1390
|
}
|
|
1506
1391
|
|
|
1507
|
-
let { 0: firstTag, 1: bindingTags = [] } = propPath.
|
|
1508
|
-
let tags = [firstTag,
|
|
1392
|
+
let { 0: firstTag, 1: bindingTags = [] } = propPath.value.tags[1];
|
|
1393
|
+
let tags = BList.fromValues([firstTag, Tags.from(...bindingTags, tag_)], 1);
|
|
1509
1394
|
let property = buildChild(Property, buildProperty(tags, shift));
|
|
1510
1395
|
|
|
1511
1396
|
targetPath = this.replaceWith(
|
|
1512
|
-
buildNode(Tags.replaceAt(propPath.tagsIndex, getTags(this.node)
|
|
1397
|
+
buildNode(Tags.replaceAt(propPath.tagsIndex, property, getTags(this.node))),
|
|
1513
1398
|
);
|
|
1514
1399
|
break;
|
|
1515
1400
|
}
|
|
1516
1401
|
|
|
1517
1402
|
case OpenNodeTag: {
|
|
1518
|
-
let { literalValue, flags, type } =
|
|
1403
|
+
let { literalValue, flags, type, name, attributes } = tag_.value;
|
|
1519
1404
|
|
|
1520
1405
|
if (this.held && flags.token) throw new Error();
|
|
1521
1406
|
|
|
@@ -1524,22 +1409,36 @@ export const Path = class AgastPath {
|
|
|
1524
1409
|
}
|
|
1525
1410
|
|
|
1526
1411
|
let parentProp = this.node && Tags.getAt(-1, getChildren(this.node));
|
|
1527
|
-
|
|
1412
|
+
|
|
1413
|
+
if (parentProp && propertyIsFull(parentProp)) {
|
|
1414
|
+
parentProp = null;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
let ref = parentProp?.value.shift
|
|
1528
1418
|
? this.node &&
|
|
1529
|
-
|
|
1530
|
-
.value
|
|
1531
|
-
|
|
1419
|
+
parseTag(
|
|
1420
|
+
Tags.getAt(-1 - parentProp.value.shift.index, getChildren(this.node)).value
|
|
1421
|
+
.tags[1][0],
|
|
1422
|
+
).value
|
|
1423
|
+
: parentProp?.value.reference;
|
|
1532
1424
|
|
|
1533
|
-
|
|
1425
|
+
let parentFlags = parentProp?.value.shift ? flags : this.node.value.flags;
|
|
1534
1426
|
|
|
1535
|
-
|
|
1427
|
+
if (parentFlags.token && ref?.type !== '@') throw new Error();
|
|
1536
1428
|
|
|
1429
|
+
let node;
|
|
1537
1430
|
if (literalValue && !flags.token) {
|
|
1538
|
-
|
|
1431
|
+
let newOpenTag = buildFullOpenNodeTag(flags, type, name, null, attributes);
|
|
1432
|
+
let literalNode = Path.fromTag(
|
|
1433
|
+
buildFullOpenNodeTag(tokenFlags, null, null, literalValue),
|
|
1434
|
+
).node;
|
|
1435
|
+
|
|
1436
|
+
node = Path.fromTag(newOpenTag).advance(literalNode).advance('</>').node;
|
|
1437
|
+
} else {
|
|
1438
|
+
node = buildNode(tag_);
|
|
1539
1439
|
}
|
|
1540
1440
|
|
|
1541
1441
|
targetPath = this.advanceUnwrapped(node).path;
|
|
1542
|
-
|
|
1543
1442
|
targetPath = targetPath.tagPathAt(-1).inner;
|
|
1544
1443
|
|
|
1545
1444
|
break;
|
|
@@ -1548,11 +1447,11 @@ export const Path = class AgastPath {
|
|
|
1548
1447
|
case GapTag:
|
|
1549
1448
|
case NullTag: {
|
|
1550
1449
|
// if (getSigilTag(this.node)) throw new Error();
|
|
1551
|
-
if (this.tagPathAt(-1, 0)
|
|
1450
|
+
if (parseTagType(this.tagPathAt(-1, 0)) !== ReferenceTag) {
|
|
1552
1451
|
throw new Error('Invalid location for NullTag');
|
|
1553
1452
|
}
|
|
1554
1453
|
|
|
1555
|
-
let node = buildNode(
|
|
1454
|
+
let node = buildNode(tag_);
|
|
1556
1455
|
|
|
1557
1456
|
targetPath = this.advanceUnwrapped(node).path;
|
|
1558
1457
|
// targetPath = targetPath.tagPathAt(-1).inner; // ?
|
|
@@ -1565,21 +1464,22 @@ export const Path = class AgastPath {
|
|
|
1565
1464
|
|
|
1566
1465
|
let lastChild = targetPath.getChild(-1);
|
|
1567
1466
|
|
|
1568
|
-
if (lastChild?.type === Property && !propertyIsFull(lastChild))
|
|
1467
|
+
if (isObject(lastChild) && lastChild?.type === Property && !propertyIsFull(lastChild))
|
|
1468
|
+
throw new Error();
|
|
1569
1469
|
|
|
1570
1470
|
let openTag = getOpenTag(node);
|
|
1571
1471
|
|
|
1572
1472
|
if (!openTag) throw new Error();
|
|
1573
|
-
if (openTag.value.selfClosing) throw new Error();
|
|
1473
|
+
if (parseTag(openTag).value.selfClosing) throw new Error();
|
|
1574
1474
|
|
|
1575
|
-
targetPath = targetPath.replaceWith(buildNode(Tags.push(getTags(node)
|
|
1475
|
+
targetPath = targetPath.replaceWith(buildNode(Tags.push(tag_, getTags(node))));
|
|
1576
1476
|
break;
|
|
1577
1477
|
}
|
|
1578
1478
|
|
|
1579
1479
|
case NullNode:
|
|
1580
1480
|
case GapNode:
|
|
1581
1481
|
case TreeNode: {
|
|
1582
|
-
let node =
|
|
1482
|
+
let node = tag_;
|
|
1583
1483
|
let parentPath = targetPath;
|
|
1584
1484
|
let { node: parentNode } = parentPath;
|
|
1585
1485
|
|
|
@@ -1588,12 +1488,12 @@ export const Path = class AgastPath {
|
|
|
1588
1488
|
if (isMultiFragment(node)) {
|
|
1589
1489
|
let existingProperty = tagPath;
|
|
1590
1490
|
|
|
1591
|
-
while (existingProperty?.
|
|
1592
|
-
existingProperty = existingProperty.
|
|
1491
|
+
while (existingProperty?.type === AttributeDefinition) {
|
|
1492
|
+
existingProperty = tagPath.siblingAt(existingProperty.tagsIndex - 1);
|
|
1593
1493
|
}
|
|
1594
1494
|
|
|
1595
1495
|
if (
|
|
1596
|
-
existingProperty.
|
|
1496
|
+
existingProperty.type !== OpenNodeTag &&
|
|
1597
1497
|
existingProperty.tag &&
|
|
1598
1498
|
!propertyIsFull(existingProperty.tag)
|
|
1599
1499
|
) {
|
|
@@ -1603,7 +1503,7 @@ export const Path = class AgastPath {
|
|
|
1603
1503
|
let newPath = Path.from(buildNode(this.node.value.tags));
|
|
1604
1504
|
|
|
1605
1505
|
for (let tag of Tags.traverse(node.value.children)) {
|
|
1606
|
-
if (tag
|
|
1506
|
+
if (parseTagType(tag) === Property) {
|
|
1607
1507
|
newPath = newPath.advance(tag);
|
|
1608
1508
|
} else {
|
|
1609
1509
|
newPath = newPath.advanceUnwrapped(tag).path.atDepth(0);
|
|
@@ -1614,11 +1514,11 @@ export const Path = class AgastPath {
|
|
|
1614
1514
|
break;
|
|
1615
1515
|
}
|
|
1616
1516
|
|
|
1617
|
-
let shift = tagPath.
|
|
1517
|
+
let shift = tagPath.type === Property ? tagPath.value.shift : undefined;
|
|
1618
1518
|
let { held } = this;
|
|
1619
1519
|
|
|
1620
1520
|
if (held) {
|
|
1621
|
-
// let heldProperty = this.tagPathAt(-2, 2).
|
|
1521
|
+
// let heldProperty = this.tagPathAt(-2, 2).value;
|
|
1622
1522
|
let matchesHeld = isGapNode(node);
|
|
1623
1523
|
if (getRoot(node) && nodeIsComplete(node)) {
|
|
1624
1524
|
matchesHeld =
|
|
@@ -1626,8 +1526,10 @@ export const Path = class AgastPath {
|
|
|
1626
1526
|
isGapNode(node) ||
|
|
1627
1527
|
held.node === node ||
|
|
1628
1528
|
held.node ===
|
|
1629
|
-
|
|
1630
|
-
.
|
|
1529
|
+
BList.getAt(
|
|
1530
|
+
-BList.getSize(held.node.value.bounds.leading),
|
|
1531
|
+
node.value.bounds.leading,
|
|
1532
|
+
).property.value.node;
|
|
1631
1533
|
if (!matchesHeld) {
|
|
1632
1534
|
// TODO We're passing by the node that shifted if it's a cover!
|
|
1633
1535
|
throw new Error();
|
|
@@ -1636,17 +1538,17 @@ export const Path = class AgastPath {
|
|
|
1636
1538
|
}
|
|
1637
1539
|
|
|
1638
1540
|
if (propertyIsFull(tagPath.tag)) {
|
|
1639
|
-
let tags = [
|
|
1541
|
+
let tags = BList.fromValues([Tags.fromValues([]), Tags.fromValues([]), node], 1);
|
|
1640
1542
|
let property = buildChild(Property, buildProperty(tags, shift));
|
|
1641
1543
|
|
|
1642
|
-
targetPath = this.replaceWith(buildNode(Tags.push(parentNode.value.tags
|
|
1544
|
+
targetPath = this.replaceWith(buildNode(Tags.push(property, parentNode.value.tags)));
|
|
1643
1545
|
} else {
|
|
1644
|
-
let { 0: firstTag, 1: bindingTags = [] } = tagPath.
|
|
1645
|
-
let tags = [firstTag, bindingTags, node];
|
|
1546
|
+
let { 0: firstTag, 1: bindingTags = Tags.fromValues([]) } = tagPath.value.tags[1];
|
|
1547
|
+
let tags = BList.fromValues([firstTag, bindingTags, node], 1);
|
|
1646
1548
|
let property = buildChild(Property, buildProperty(tags, shift));
|
|
1647
1549
|
|
|
1648
1550
|
targetPath = this.replaceWith(
|
|
1649
|
-
buildNode(Tags.replaceAt(tagPath.tagsIndex, parentNode.value.tags
|
|
1551
|
+
buildNode(Tags.replaceAt(tagPath.tagsIndex, property, parentNode.value.tags)),
|
|
1650
1552
|
);
|
|
1651
1553
|
}
|
|
1652
1554
|
|
|
@@ -1662,10 +1564,10 @@ export const Path = class AgastPath {
|
|
|
1662
1564
|
|
|
1663
1565
|
// add undefined attributes from value
|
|
1664
1566
|
let { node } = this;
|
|
1665
|
-
if (
|
|
1567
|
+
if (tag_.type !== AttributeDefinition) throw new Error();
|
|
1666
1568
|
|
|
1667
|
-
let { path, value } =
|
|
1668
|
-
let openTag = getOpenTag(node);
|
|
1569
|
+
let { path, value } = tag_.value;
|
|
1570
|
+
let openTag = parseTag(getOpenTag(node));
|
|
1669
1571
|
let { attributes } = node.value;
|
|
1670
1572
|
|
|
1671
1573
|
if (!objHas(attributes, path) && objGet(attributes, path) !== undefined)
|
|
@@ -1675,10 +1577,10 @@ export const Path = class AgastPath {
|
|
|
1675
1577
|
|
|
1676
1578
|
let { flags, name } = openTag.value;
|
|
1677
1579
|
attributes = immSet(attributes, path, value);
|
|
1678
|
-
let newOpenTag = buildOpenNodeTag(flags, name, null, attributes);
|
|
1580
|
+
let newOpenTag = buildOpenNodeTag(flags, name, null, printObject(attributes));
|
|
1679
1581
|
|
|
1680
1582
|
targetPath = this.replaceWith(
|
|
1681
|
-
buildNode(Tags.push(Tags.replaceAt(0, getTags(node)
|
|
1583
|
+
buildNode(Tags.push(tag_, Tags.replaceAt(0, newOpenTag, getTags(node)))),
|
|
1682
1584
|
);
|
|
1683
1585
|
break;
|
|
1684
1586
|
}
|
|
@@ -1691,7 +1593,7 @@ export const Path = class AgastPath {
|
|
|
1691
1593
|
let { reference, shift: heldShift } = lastPropertyTag.value;
|
|
1692
1594
|
|
|
1693
1595
|
if (!reference) {
|
|
1694
|
-
({ reference } = this.tagPathAt(-1 - (heldShift?.index ?? 0)).
|
|
1596
|
+
({ reference } = this.tagPathAt(-1 - (heldShift?.index ?? 0)).value);
|
|
1695
1597
|
}
|
|
1696
1598
|
|
|
1697
1599
|
if (!reference.flags.expression && reference.type !== '_') throw new Error();
|
|
@@ -1700,55 +1602,114 @@ export const Path = class AgastPath {
|
|
|
1700
1602
|
? buildShift(heldShift.index + 1, heldShift.height + 1)
|
|
1701
1603
|
: buildShift(1, 3);
|
|
1702
1604
|
|
|
1703
|
-
let property = buildChild(Property, buildProperty([tag], shift));
|
|
1605
|
+
let property = buildChild(Property, buildProperty(BList.fromValues([tag]), shift));
|
|
1704
1606
|
|
|
1705
|
-
targetPath = this.replaceWith(buildNode(Tags.push(this.node.value.tags
|
|
1607
|
+
targetPath = this.replaceWith(buildNode(Tags.push(property, this.node.value.tags)));
|
|
1706
1608
|
break;
|
|
1707
1609
|
}
|
|
1708
1610
|
|
|
1709
1611
|
case LiteralTag:
|
|
1710
|
-
if (typeof
|
|
1612
|
+
if (typeof tag_.value !== 'string') throw new Error();
|
|
1711
1613
|
|
|
1712
|
-
targetPath = this.replaceWith(buildNode(Tags.push(this.node.value.tags
|
|
1614
|
+
targetPath = this.replaceWith(buildNode(Tags.push(tag_, this.node.value.tags)));
|
|
1713
1615
|
break;
|
|
1714
1616
|
|
|
1715
1617
|
default:
|
|
1716
1618
|
throw new Error();
|
|
1717
1619
|
}
|
|
1718
1620
|
|
|
1719
|
-
return targetPath && TagPath.from(targetPath, -1,
|
|
1621
|
+
return targetPath && TagPath.from(targetPath, -1, offsetForTag(tag_));
|
|
1720
1622
|
}
|
|
1721
1623
|
};
|
|
1722
1624
|
|
|
1723
|
-
|
|
1625
|
+
freezeClass(Path);
|
|
1724
1626
|
|
|
1725
1627
|
export const tagPathsAreEqual = (a, b) => {
|
|
1726
1628
|
if (a == null || b == null) return b == a;
|
|
1727
1629
|
return a.path.node === b.path.node && a.tagsIndex === b.tagsIndex;
|
|
1728
1630
|
};
|
|
1729
1631
|
|
|
1632
|
+
let resolveIdx = (idx, tree) => {
|
|
1633
|
+
let path = [];
|
|
1634
|
+
let node = tree;
|
|
1635
|
+
|
|
1636
|
+
if (isArray(idx)) {
|
|
1637
|
+
for (let seg of arrayValues(idx)) {
|
|
1638
|
+
let index = typeof seg !== 'object' ? seg : seg.index;
|
|
1639
|
+
if (typeof index === 'string') throw new Error();
|
|
1640
|
+
if (!Tags.isNode(node)) return null;
|
|
1641
|
+
let index_ = index < 0 ? Tags.getSize(node) + index : index;
|
|
1642
|
+
path.push(index_);
|
|
1643
|
+
node = Tags.getValues(node)[index_];
|
|
1644
|
+
if (node && !Tags.isNode(node)) {
|
|
1645
|
+
return path;
|
|
1646
|
+
}
|
|
1647
|
+
if (!node) return null;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
return path;
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1730
1654
|
export class TagPath {
|
|
1731
1655
|
static from(path, tagsIndex, propertyIndex) {
|
|
1732
1656
|
let tags = getTags(path.node);
|
|
1733
1657
|
let size = Tags.getSize(tags);
|
|
1734
1658
|
let index = Number.isFinite(tagsIndex) && tagsIndex < 0 ? size + tagsIndex : tagsIndex;
|
|
1735
|
-
|
|
1736
|
-
let
|
|
1737
|
-
|
|
1738
|
-
let propTag = Tags.getAt(index, tags);
|
|
1659
|
+
let propertyIndex_ = propertyIndex;
|
|
1660
|
+
let propTag_ = Tags.getAt(index, tags);
|
|
1661
|
+
let propTag = propTag_ && parseTag(propTag_);
|
|
1739
1662
|
|
|
1740
1663
|
if (
|
|
1741
1664
|
[OpenNodeTag, CloseNodeTag, LiteralTag, AttributeDefinition, GapTag, NullTag].includes(
|
|
1742
1665
|
propTag?.type,
|
|
1743
1666
|
)
|
|
1744
1667
|
) {
|
|
1745
|
-
propertyIndex_ =
|
|
1668
|
+
propertyIndex_ = null;
|
|
1746
1669
|
}
|
|
1747
1670
|
|
|
1748
|
-
let
|
|
1749
|
-
|
|
1671
|
+
let idx = null;
|
|
1672
|
+
if (propTag?.type === Property) {
|
|
1673
|
+
if (isArray(propertyIndex_)) {
|
|
1674
|
+
if (propertyIndex_.length) {
|
|
1675
|
+
idx = resolveIdx(propertyIndex_, propTag.value.tags);
|
|
1676
|
+
}
|
|
1677
|
+
} else if (propertyIndex_ != null) {
|
|
1678
|
+
let { tags } = propTag.value;
|
|
1679
|
+
let bindingsSize = Tags.getSize(tags[1][1]);
|
|
1680
|
+
let valuesSize = Tags.getValues(tags).length;
|
|
1681
|
+
let tagsSize = valuesSize - (tags[1][1] ? 1 : 0) + bindingsSize;
|
|
1682
|
+
let absoluteIndex = propertyIndex_ < 0 ? propertyIndex_ + tagsSize : propertyIndex_;
|
|
1683
|
+
|
|
1684
|
+
let bindingsStop = 1 + bindingsSize;
|
|
1685
|
+
|
|
1686
|
+
if (absoluteIndex === 0) {
|
|
1687
|
+
idx = [0];
|
|
1688
|
+
} else if (absoluteIndex > bindingsStop) {
|
|
1689
|
+
idx = [2];
|
|
1690
|
+
} else if (tags[1][1]) {
|
|
1691
|
+
let result = Tags.findPath(absoluteIndex - 1, tags[1][1]).map(({ index }) => index);
|
|
1692
|
+
if (Number.isFinite(arrayLast(result))) {
|
|
1693
|
+
idx = [1].concat(result);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
idx ||= [];
|
|
1700
|
+
|
|
1701
|
+
if (idx?.length) {
|
|
1702
|
+
let tag = Tags.getAt(idx, propTag.value.tags);
|
|
1703
|
+
if (isArray(tag)) {
|
|
1704
|
+
idx = [];
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
freezeRecord(idx);
|
|
1750
1709
|
|
|
1751
|
-
|
|
1710
|
+
let pathExists = isArray(propertyIndex_) && propertyIndex_?.length ? idx.length : propTag;
|
|
1711
|
+
|
|
1712
|
+
return pathExists ? new TagPath(path, index, idx) : null;
|
|
1752
1713
|
}
|
|
1753
1714
|
|
|
1754
1715
|
static fromNode(node, tagsIndex, propertyIndex) {
|
|
@@ -1773,28 +1734,26 @@ export class TagPath {
|
|
|
1773
1734
|
if (!Number.isFinite(tagsIndex) || tagsIndex < 0) throw new Error();
|
|
1774
1735
|
if (!isArray(propertyIndex)) throw new Error();
|
|
1775
1736
|
|
|
1776
|
-
let
|
|
1737
|
+
for (let index of recordValues(propertyIndex)) {
|
|
1738
|
+
if (!(index >= 0) || !Number.isFinite(index)) throw new Error();
|
|
1739
|
+
}
|
|
1777
1740
|
|
|
1778
1741
|
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
1779
1742
|
|
|
1780
|
-
if (
|
|
1781
|
-
tag = Tags.getAt(
|
|
1743
|
+
if (propertyIndex.length) {
|
|
1744
|
+
tag = Tags.getAt(propertyIndex, tag.value.tags);
|
|
1782
1745
|
}
|
|
1783
1746
|
|
|
1784
1747
|
if (tag == null || isArray(tag)) throw new Error();
|
|
1785
1748
|
|
|
1786
|
-
for (let segment of propertyIndex_) {
|
|
1787
|
-
if (!isPlainObject(segment) || !(segment.index === 0 || segment.index > 0)) throw new Error();
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
1749
|
this.path = path;
|
|
1791
1750
|
this.tagsIndex = tagsIndex;
|
|
1792
|
-
this.propertyIndex =
|
|
1751
|
+
this.propertyIndex = propertyIndex;
|
|
1793
1752
|
|
|
1794
1753
|
this.node = path.node;
|
|
1795
1754
|
this.tag = tag;
|
|
1796
1755
|
|
|
1797
|
-
if (tag.type === Property &&
|
|
1756
|
+
if (isObject(tag) && tag.type === Property && propertyIndex.length) throw new Error();
|
|
1798
1757
|
|
|
1799
1758
|
freeze(this);
|
|
1800
1759
|
}
|
|
@@ -1802,13 +1761,21 @@ export class TagPath {
|
|
|
1802
1761
|
asPrimitive() {
|
|
1803
1762
|
let { path, tagsIndex, propertyIndex } = this;
|
|
1804
1763
|
|
|
1805
|
-
return
|
|
1764
|
+
return freeze({ path: path.asPrimitive(), tagsIndex, propertyIndex });
|
|
1806
1765
|
}
|
|
1807
1766
|
|
|
1808
1767
|
get child() {
|
|
1809
1768
|
return this.tag;
|
|
1810
1769
|
}
|
|
1811
1770
|
|
|
1771
|
+
get type() {
|
|
1772
|
+
return parseTagType(this.tag);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
get value() {
|
|
1776
|
+
return parseTag(this.tag).value;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1812
1779
|
get parentNode() {
|
|
1813
1780
|
return this.path.parentNode;
|
|
1814
1781
|
}
|
|
@@ -1830,12 +1797,12 @@ export class TagPath {
|
|
|
1830
1797
|
get referenceTagPath() {
|
|
1831
1798
|
let path = TagPath.from(this.path, this.tagsIndex, 0);
|
|
1832
1799
|
if (path && path.propertyPath) {
|
|
1833
|
-
let { shift } = path.propertyPath.
|
|
1800
|
+
let { shift } = path.propertyPath.value;
|
|
1834
1801
|
if (shift) {
|
|
1835
1802
|
path = TagPath.from(this.path, this.tagsIndex - shift.index, 0);
|
|
1836
1803
|
}
|
|
1837
1804
|
}
|
|
1838
|
-
return path?.
|
|
1805
|
+
return path?.type === ReferenceTag ? path : null;
|
|
1839
1806
|
}
|
|
1840
1807
|
|
|
1841
1808
|
get nextProperty() {
|
|
@@ -1843,33 +1810,33 @@ export class TagPath {
|
|
|
1843
1810
|
|
|
1844
1811
|
let nextChild = TagPath.from(path, tagsIndex + 1);
|
|
1845
1812
|
|
|
1846
|
-
return nextChild?.
|
|
1813
|
+
return nextChild?.type === Property ? nextChild : null;
|
|
1847
1814
|
}
|
|
1848
1815
|
|
|
1849
1816
|
get nextSibling() {
|
|
1850
1817
|
let { path, tagsIndex, propertyIndex } = this;
|
|
1851
1818
|
|
|
1852
|
-
let propertyIndex0 = propertyIndex[0]
|
|
1819
|
+
let propertyIndex0 = propertyIndex[0];
|
|
1853
1820
|
|
|
1854
|
-
let nextChildIndex = tagsIndex
|
|
1821
|
+
let nextChildIndex = tagsIndex;
|
|
1855
1822
|
let nextChild = path.getChild(nextChildIndex);
|
|
1856
1823
|
|
|
1857
1824
|
if (propertyIndex0 == null && !nextChild) {
|
|
1858
|
-
return this.
|
|
1825
|
+
return this.type === CloseNodeTag ? null : path.closeTagPath;
|
|
1859
1826
|
}
|
|
1860
1827
|
|
|
1861
1828
|
switch (propertyIndex0) {
|
|
1862
1829
|
case 0:
|
|
1863
1830
|
case 1: {
|
|
1864
1831
|
let childIndex = tagsIndex - 1;
|
|
1865
|
-
let bindingIndex = propertyIndex[1]
|
|
1832
|
+
let bindingIndex = propertyIndex[1] ?? -1;
|
|
1866
1833
|
let binding = path.getBindingTagPath(childIndex, bindingIndex + 1);
|
|
1867
1834
|
if (binding) return binding;
|
|
1868
1835
|
return path.getNodeTagPath(childIndex);
|
|
1869
1836
|
}
|
|
1870
1837
|
case 2:
|
|
1871
1838
|
default: {
|
|
1872
|
-
if (!nextChild || nextChild.type !== Property) {
|
|
1839
|
+
if (!nextChild || nextChild.type !== Property || !propertyIndex.length) {
|
|
1873
1840
|
return path.tagPathAt(tagsIndex + 1);
|
|
1874
1841
|
} else {
|
|
1875
1842
|
let ref = path.getReferenceTagPath(nextChildIndex);
|
|
@@ -1916,38 +1883,34 @@ export class TagPath {
|
|
|
1916
1883
|
get next() {
|
|
1917
1884
|
let { path, tagsIndex, propertyIndex } = this;
|
|
1918
1885
|
|
|
1919
|
-
propertyIndex = [...propertyIndex];
|
|
1886
|
+
propertyIndex = [...recordValues(propertyIndex)];
|
|
1920
1887
|
|
|
1921
1888
|
let leaving = false;
|
|
1922
1889
|
|
|
1923
1890
|
for (;;) {
|
|
1924
|
-
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
1891
|
+
let tag = parseTag(Tags.getAt(tagsIndex, getTags(path.node)));
|
|
1925
1892
|
let propTag = tag;
|
|
1926
1893
|
let lastRef = null;
|
|
1894
|
+
let wasLeaving = leaving;
|
|
1927
1895
|
leaving = false;
|
|
1928
1896
|
|
|
1929
1897
|
if (!tag) return null;
|
|
1930
1898
|
|
|
1931
|
-
if (tag.type === Property) {
|
|
1932
|
-
if (propertyIndex.length === 0
|
|
1933
|
-
|
|
1934
|
-
}
|
|
1899
|
+
if (isObject(tag) && tag.type === Property && !wasLeaving) {
|
|
1900
|
+
if (propertyIndex.length === 0) {
|
|
1901
|
+
let { 0: open, 1: bindings } = tag.value.tags[1];
|
|
1935
1902
|
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1903
|
+
let index = !isArray(open) ? 0 : !isArray(bindings) ? 1 : 2;
|
|
1904
|
+
|
|
1905
|
+
propertyIndex.push({ index, node: tag.value.tags });
|
|
1939
1906
|
}
|
|
1940
|
-
}
|
|
1941
1907
|
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
} else {
|
|
1948
|
-
propertyIndex = [{ index: propertyIndex[0].index + 1, node: tag }];
|
|
1908
|
+
if (propertyIndex != null) {
|
|
1909
|
+
let tag_ = Tags.getAt(propertyIndex, tag.value.tags);
|
|
1910
|
+
propTag = isNode(tag_) ? tag_ : parseTag(tag_);
|
|
1911
|
+
let lastRef_ = Tags.getAt([0], tag.value.tags);
|
|
1912
|
+
lastRef = isArray(lastRef_) ? null : parseTag(lastRef_);
|
|
1949
1913
|
}
|
|
1950
|
-
continue;
|
|
1951
1914
|
}
|
|
1952
1915
|
|
|
1953
1916
|
let isInitialTag =
|
|
@@ -1956,21 +1919,21 @@ export class TagPath {
|
|
|
1956
1919
|
arraysEqual(propertyIndex, this.propertyIndex);
|
|
1957
1920
|
|
|
1958
1921
|
// done
|
|
1959
|
-
if (!isInitialTag && !isNodeTag(propTag)) {
|
|
1922
|
+
if (!isInitialTag && !isNodeTag(propTag) && propTag.type !== Property) {
|
|
1960
1923
|
return TagPath.from(path, tagsIndex, propertyIndex);
|
|
1961
1924
|
}
|
|
1962
1925
|
|
|
1963
1926
|
// shift
|
|
1964
|
-
if (propTag.type === BindingTag && lastRef
|
|
1927
|
+
if (propTag.type === BindingTag && lastRef?.type === ShiftTag) {
|
|
1965
1928
|
let lastProp = Tags.getAt(tagsIndex, path.tags);
|
|
1966
1929
|
let { shift } = lastProp.value;
|
|
1967
1930
|
let refIndex = tagsIndex - shift.index;
|
|
1968
1931
|
if (refIndex < 0) throw new Error();
|
|
1969
|
-
let refTag = Tags.getAt(refIndex, path.tags, 0);
|
|
1932
|
+
let refTag = parseTag(Tags.getAt(refIndex, path.tags, 0));
|
|
1970
1933
|
|
|
1971
1934
|
if (refTag.type !== ReferenceTag) throw new Error();
|
|
1972
1935
|
|
|
1973
|
-
let { node } = tag.value;
|
|
1936
|
+
let { node } = parseTag(tag).value;
|
|
1974
1937
|
if (!node) return null;
|
|
1975
1938
|
|
|
1976
1939
|
path = new Path(path, tagsIndex);
|
|
@@ -1982,66 +1945,47 @@ export class TagPath {
|
|
|
1982
1945
|
continue;
|
|
1983
1946
|
}
|
|
1984
1947
|
|
|
1985
|
-
|
|
1948
|
+
// in
|
|
1949
|
+
if (isNodeTag(propTag)) {
|
|
1950
|
+
let shiftPath = path;
|
|
1951
|
+
|
|
1952
|
+
while (
|
|
1953
|
+
shiftPath.parent &&
|
|
1954
|
+
!Tags.getAt(shiftPath.parentIndex - 1, shiftPath.parent.node.value.children).value.shift
|
|
1955
|
+
) {
|
|
1956
|
+
shiftPath = shiftPath.parent;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
let isGap =
|
|
1960
|
+
path.parent &&
|
|
1961
|
+
tagsIndex === 1 &&
|
|
1962
|
+
shiftPath.parent &&
|
|
1963
|
+
Tags.getAt(shiftPath.parentIndex - 1, shiftPath.parent.node.value.children).value.shift &&
|
|
1964
|
+
tag.value.node ===
|
|
1965
|
+
Tags.getAt(shiftPath.parentIndex - 2, shiftPath.parent.node.value.children).value.node;
|
|
1966
|
+
|
|
1967
|
+
path = path.push(tagsIndex, isGap);
|
|
1968
|
+
tagsIndex = 0;
|
|
1969
|
+
propertyIndex = [];
|
|
1970
|
+
continue;
|
|
1971
|
+
}
|
|
1986
1972
|
|
|
1987
1973
|
// over
|
|
1974
|
+
let { nextSibling } = TagPath.from(path, tagsIndex, freeze([...arrayValues(propertyIndex)]));
|
|
1975
|
+
|
|
1988
1976
|
if (nextSibling) {
|
|
1989
1977
|
({ tagsIndex, propertyIndex } = nextSibling);
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
let shiftPath = path;
|
|
1993
|
-
|
|
1994
|
-
while (
|
|
1995
|
-
shiftPath.parent &&
|
|
1996
|
-
!Tags.getAt(shiftPath.parentIndex - 1, shiftPath.parent.node.value.children).value.shift
|
|
1997
|
-
) {
|
|
1998
|
-
shiftPath = shiftPath.parent;
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
let isGap =
|
|
2002
|
-
path.parent &&
|
|
2003
|
-
tagsIndex === 1 &&
|
|
2004
|
-
shiftPath.parent &&
|
|
2005
|
-
Tags.getAt(shiftPath.parentIndex - 1, shiftPath.parent.node.value.children).value
|
|
2006
|
-
.shift &&
|
|
2007
|
-
tag.value.node ===
|
|
2008
|
-
Tags.getAt(shiftPath.parentIndex - 2, shiftPath.parent.node.value.children).value
|
|
2009
|
-
.node;
|
|
2010
|
-
|
|
2011
|
-
path = path.push(tagsIndex, isGap);
|
|
2012
|
-
tagsIndex = 0;
|
|
2013
|
-
propertyIndex = [];
|
|
2014
|
-
continue;
|
|
2015
|
-
} else {
|
|
2016
|
-
return nextSibling;
|
|
2017
|
-
}
|
|
1978
|
+
propertyIndex = [...arrayValues(propertyIndex)];
|
|
1979
|
+
continue;
|
|
2018
1980
|
}
|
|
2019
1981
|
|
|
2020
1982
|
// out
|
|
2021
1983
|
if (path.parentIndex != null && path.parent) {
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
Tags.getAt(
|
|
2026
|
-
[path.coverBoundary.parentIndex, 0],
|
|
2027
|
-
path.coverBoundary.parent.node.value.tags,
|
|
2028
|
-
)?.type === ShiftTag
|
|
2029
|
-
) {
|
|
2030
|
-
// while
|
|
2031
|
-
tagsIndex =
|
|
2032
|
-
Tags.getSize(path.parent.node.value.tags) > path.parentIndex + 1
|
|
2033
|
-
? path.parentIndex + 1
|
|
2034
|
-
: null;
|
|
2035
|
-
} else {
|
|
2036
|
-
tagsIndex = path.parentIndex + 1;
|
|
2037
|
-
}
|
|
2038
|
-
|
|
2039
|
-
propertyIndex = [];
|
|
2040
|
-
path = path.parent;
|
|
2041
|
-
leaving = true;
|
|
1984
|
+
tagsIndex = path.parentIndex;
|
|
1985
|
+
propertyIndex = [];
|
|
1986
|
+
path = path.parent;
|
|
2042
1987
|
|
|
2043
|
-
|
|
2044
|
-
} while (tagsIndex == null);
|
|
1988
|
+
if (!path) return null;
|
|
2045
1989
|
|
|
2046
1990
|
leaving = true;
|
|
2047
1991
|
continue;
|
|
@@ -2054,21 +1998,23 @@ export class TagPath {
|
|
|
2054
1998
|
get nextUnshifted() {
|
|
2055
1999
|
let { path, tagsIndex, propertyIndex } = this;
|
|
2056
2000
|
|
|
2057
|
-
propertyIndex = [...propertyIndex];
|
|
2001
|
+
propertyIndex = [...arrayValues(propertyIndex)];
|
|
2058
2002
|
|
|
2059
2003
|
let leaving = false;
|
|
2060
2004
|
|
|
2061
2005
|
for (;;) {
|
|
2062
|
-
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
2006
|
+
let tag = parseTag(Tags.getAt(tagsIndex, getTags(path.node)));
|
|
2063
2007
|
let propTag = tag;
|
|
2064
2008
|
let wasLeaving = leaving;
|
|
2065
2009
|
leaving = false;
|
|
2066
2010
|
|
|
2067
2011
|
if (!tag) return null;
|
|
2068
2012
|
|
|
2069
|
-
if (tag.type === Property) {
|
|
2013
|
+
if (isObject(tag) && tag.type === Property) {
|
|
2070
2014
|
if (propertyIndex.length === 0 && !leaving) {
|
|
2071
|
-
|
|
2015
|
+
let { 0: open, 1: bindings } = tag.value.tags[1];
|
|
2016
|
+
let index = !isArray(open) ? 0 : !isArray(bindings) ? 1 : 2;
|
|
2017
|
+
propertyIndex.push({ index, node: tag.value.tags });
|
|
2072
2018
|
}
|
|
2073
2019
|
|
|
2074
2020
|
if (propertyIndex != null) {
|
|
@@ -2077,7 +2023,7 @@ export class TagPath {
|
|
|
2077
2023
|
}
|
|
2078
2024
|
|
|
2079
2025
|
if (isArray(propTag)) {
|
|
2080
|
-
if (propTag
|
|
2026
|
+
if (Tags.getSize(propTag)) {
|
|
2081
2027
|
// enter bindings array
|
|
2082
2028
|
propertyIndex.push({ index: 0, node: propTag });
|
|
2083
2029
|
propTag = propTag[propertyIndex[1].index];
|
|
@@ -2097,7 +2043,7 @@ export class TagPath {
|
|
|
2097
2043
|
tagsIndex === this.tagsIndex &&
|
|
2098
2044
|
arraysEqual(propertyIndex, this.propertyIndex);
|
|
2099
2045
|
|
|
2100
|
-
if (!wasLeaving && propTag
|
|
2046
|
+
if (!wasLeaving && parseTagType(propTag) === ReferenceTag) {
|
|
2101
2047
|
// move past shifts
|
|
2102
2048
|
|
|
2103
2049
|
let shifts = 0;
|
|
@@ -2125,6 +2071,7 @@ export class TagPath {
|
|
|
2125
2071
|
// over
|
|
2126
2072
|
if (nextSibling) {
|
|
2127
2073
|
({ tagsIndex, propertyIndex } = nextSibling);
|
|
2074
|
+
propertyIndex = [...arrayValues(propertyIndex)];
|
|
2128
2075
|
continue;
|
|
2129
2076
|
}
|
|
2130
2077
|
|
|
@@ -2159,7 +2106,7 @@ export class TagPath {
|
|
|
2159
2106
|
|
|
2160
2107
|
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
2161
2108
|
|
|
2162
|
-
return tag.type === Property ? path.tagPathAt(tagsIndex) : null;
|
|
2109
|
+
return isObject(tag) && tag.type === Property ? path.tagPathAt(tagsIndex) : null;
|
|
2163
2110
|
}
|
|
2164
2111
|
|
|
2165
2112
|
get innerNode() {
|
|
@@ -2167,20 +2114,22 @@ export class TagPath {
|
|
|
2167
2114
|
}
|
|
2168
2115
|
|
|
2169
2116
|
get inner() {
|
|
2170
|
-
let { tagsIndex,
|
|
2117
|
+
let { tagsIndex, type } = this;
|
|
2171
2118
|
|
|
2172
2119
|
let node;
|
|
2173
|
-
switch (
|
|
2120
|
+
switch (type) {
|
|
2174
2121
|
case Property: {
|
|
2175
|
-
({ node } = tag.value);
|
|
2122
|
+
({ node } = this.tag.value);
|
|
2176
2123
|
break;
|
|
2177
2124
|
}
|
|
2125
|
+
case GapNode:
|
|
2126
|
+
case NullNode:
|
|
2178
2127
|
case TreeNode: {
|
|
2179
|
-
node = tag;
|
|
2128
|
+
node = this.tag;
|
|
2180
2129
|
break;
|
|
2181
2130
|
}
|
|
2182
2131
|
default:
|
|
2183
|
-
|
|
2132
|
+
node = null;
|
|
2184
2133
|
}
|
|
2185
2134
|
return node && this.path.push(tagsIndex);
|
|
2186
2135
|
}
|
|
@@ -2194,4 +2143,4 @@ export class TagPath {
|
|
|
2194
2143
|
}
|
|
2195
2144
|
}
|
|
2196
2145
|
|
|
2197
|
-
|
|
2146
|
+
freezeClass(TagPath);
|