@bablr/agast-helpers 0.10.10 → 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 +917 -115
- 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 +580 -634
- 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
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;
|
|
397
|
-
};
|
|
398
|
-
|
|
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;
|
|
333
|
+
return [GapTag, NullTag].includes(parseTagType(tag));
|
|
505
334
|
};
|
|
506
335
|
|
|
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,6 +449,10 @@ 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) {
|
|
642
457
|
if (isArray(name)) throw new Error('not supported');
|
|
643
458
|
let count = countList(name, node);
|
|
@@ -652,10 +467,10 @@ export const countList = (name, node) => {
|
|
|
652
467
|
|
|
653
468
|
if (name == null) throw new Error('Bad path');
|
|
654
469
|
|
|
655
|
-
return Tags.
|
|
470
|
+
return Tags.findStats(name, Tags.getSums(getTags(node)).names);
|
|
656
471
|
};
|
|
657
472
|
|
|
658
|
-
export function* allTagPathsFor(range, options = {}) {
|
|
473
|
+
export function* allTagPathsFor(range, options = freeze({})) {
|
|
659
474
|
if (range == null) return;
|
|
660
475
|
|
|
661
476
|
if (range[0] && !(range[0] instanceof TagPath)) throw new Error();
|
|
@@ -667,7 +482,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
667
482
|
let path = startPath;
|
|
668
483
|
|
|
669
484
|
while (path) {
|
|
670
|
-
if (path.inner && path.previousSibling.
|
|
485
|
+
if (path.inner && path.previousSibling.type === ReferenceTag) {
|
|
671
486
|
path = TagPath.from(path.inner, 0);
|
|
672
487
|
}
|
|
673
488
|
|
|
@@ -685,7 +500,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
685
500
|
|
|
686
501
|
if (
|
|
687
502
|
endPath &&
|
|
688
|
-
path.
|
|
503
|
+
path.type === CloseNodeTag &&
|
|
689
504
|
gapPath &&
|
|
690
505
|
gapPath.tagsIndex === endPath.tagsIndex &&
|
|
691
506
|
gapPath.path.node === endPath.path.node
|
|
@@ -696,7 +511,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
696
511
|
}
|
|
697
512
|
}
|
|
698
513
|
|
|
699
|
-
export function* allTagsFor(range, options = {}) {
|
|
514
|
+
export function* allTagsFor(range, options = freeze({})) {
|
|
700
515
|
for (let path of allTagPathsFor(range, options)) {
|
|
701
516
|
yield path.tag;
|
|
702
517
|
}
|
|
@@ -787,51 +602,27 @@ export const getAttributes = (node) => {
|
|
|
787
602
|
};
|
|
788
603
|
|
|
789
604
|
export const isSelfClosingTag = (tag) => {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
export let pathForTagPath = (tagPath) => {
|
|
798
|
-
let refTagPath = tagPath;
|
|
799
|
-
let isShift = tagPath.tag.type === ShiftTag;
|
|
800
|
-
|
|
801
|
-
if (isShift) {
|
|
802
|
-
refTagPath = tagPath.siblingAt(tagPath.tagsIndex - tagPath.tag.value.index);
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
let { type, name } = refTagPath.tag.value;
|
|
806
|
-
|
|
807
|
-
if (refTagPath.tag.type !== ReferenceTag) throw new Error();
|
|
808
|
-
|
|
809
|
-
let index = getChildPropertyIndex(tagPath.node, refTagPath.tagsIndex);
|
|
810
|
-
let shiftIndex = isShift ? (tagPath.tag.value.index ?? 0) + 1 : null;
|
|
811
|
-
|
|
812
|
-
return [{ type, name, index, shiftIndex }];
|
|
813
|
-
};
|
|
814
|
-
|
|
815
|
-
let getSigilTag_ = (tag) => {
|
|
816
|
-
switch (tag.type) {
|
|
817
|
-
case Property:
|
|
818
|
-
return getTags(tag.value.property.node)[1][0];
|
|
819
|
-
case TreeNode:
|
|
820
|
-
case NullNode:
|
|
821
|
-
case GapNode:
|
|
822
|
-
return getTags(tag)[1][0];
|
|
823
|
-
case OpenNodeTag:
|
|
824
|
-
case GapTag:
|
|
825
|
-
case NullTag:
|
|
826
|
-
return tag;
|
|
827
|
-
}
|
|
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;
|
|
828
611
|
};
|
|
829
612
|
|
|
830
613
|
const parents = new WeakMap();
|
|
831
614
|
|
|
832
615
|
export const Path = class AgastPath {
|
|
833
616
|
static from(node) {
|
|
834
|
-
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
|
+
);
|
|
835
626
|
}
|
|
836
627
|
|
|
837
628
|
static wrap(frames) {
|
|
@@ -842,17 +633,17 @@ export const Path = class AgastPath {
|
|
|
842
633
|
return Path.from(buildNode(openTag));
|
|
843
634
|
}
|
|
844
635
|
|
|
845
|
-
static set(
|
|
636
|
+
static set(path, value, node) {
|
|
846
637
|
return Path.from(node).replaceAt(path, value).node;
|
|
847
638
|
}
|
|
848
639
|
|
|
849
|
-
static get(
|
|
640
|
+
static get(path, node) {
|
|
850
641
|
return Path.from(node).get(path).node;
|
|
851
642
|
}
|
|
852
643
|
|
|
853
644
|
constructor(parent, frame) {
|
|
854
645
|
if (!frame) throw new Error();
|
|
855
|
-
let frame_ = isArray(frame) ?
|
|
646
|
+
let frame_ = isArray(frame) ? BList.getAt(-1, frame) : frame;
|
|
856
647
|
let { property, parentIndex, isGap } = frame_;
|
|
857
648
|
let { node } = property.value;
|
|
858
649
|
|
|
@@ -869,13 +660,13 @@ export const Path = class AgastPath {
|
|
|
869
660
|
parents.set(this, parent);
|
|
870
661
|
}
|
|
871
662
|
|
|
872
|
-
this.depth = parent ? parent.depth + 1 : isArray(frame) ?
|
|
663
|
+
this.depth = parent ? parent.depth + 1 : isArray(frame) ? BList.getSize(frame) - 1 : 0;
|
|
873
664
|
this.frame = frame_;
|
|
874
665
|
this.frames = !parent
|
|
875
666
|
? isArray(frame)
|
|
876
667
|
? frame
|
|
877
|
-
:
|
|
878
|
-
:
|
|
668
|
+
: BList.fromValues([frame])
|
|
669
|
+
: BList.push(frame, parent.frames);
|
|
879
670
|
|
|
880
671
|
buildSkips(this);
|
|
881
672
|
|
|
@@ -889,18 +680,10 @@ export const Path = class AgastPath {
|
|
|
889
680
|
throw new Error();
|
|
890
681
|
}
|
|
891
682
|
|
|
892
|
-
if (
|
|
893
|
-
parentIndex != null &&
|
|
894
|
-
!parent?.node.value.flags.token &&
|
|
895
|
-
(!this.referenceTag || ![ReferenceTag, ShiftTag].includes(this.referenceTag.type))
|
|
896
|
-
) {
|
|
897
|
-
throw new Error();
|
|
898
|
-
}
|
|
899
|
-
|
|
900
683
|
if (
|
|
901
684
|
parent_ &&
|
|
902
685
|
(isGap
|
|
903
|
-
?
|
|
686
|
+
? BList.getAt(0, parent_.node.value.bounds.leading).property
|
|
904
687
|
: parent_.tagPathAt(parentIndex).tag) !== property
|
|
905
688
|
) {
|
|
906
689
|
throw new Error('Path not reachable');
|
|
@@ -915,12 +698,12 @@ export const Path = class AgastPath {
|
|
|
915
698
|
|
|
916
699
|
push(tagsIndex, isGap) {
|
|
917
700
|
let tag = isGap
|
|
918
|
-
?
|
|
701
|
+
? BList.getAt(0, this.node.value.bounds.leading).property
|
|
919
702
|
: tagsIndex != null
|
|
920
703
|
? Tags.getAt(tagsIndex, this.tags)
|
|
921
704
|
: null;
|
|
922
705
|
|
|
923
|
-
if (!tag || tag
|
|
706
|
+
if (!tag || parseTagType(tag) !== Property) {
|
|
924
707
|
return null;
|
|
925
708
|
}
|
|
926
709
|
|
|
@@ -941,7 +724,7 @@ export const Path = class AgastPath {
|
|
|
941
724
|
return parent;
|
|
942
725
|
}
|
|
943
726
|
|
|
944
|
-
parent = new Path(null,
|
|
727
|
+
parent = new Path(null, BList.pop(frames));
|
|
945
728
|
|
|
946
729
|
parents.set(this, parent);
|
|
947
730
|
|
|
@@ -960,6 +743,10 @@ export const Path = class AgastPath {
|
|
|
960
743
|
return this.frame.property.value.node;
|
|
961
744
|
}
|
|
962
745
|
|
|
746
|
+
get value() {
|
|
747
|
+
return this.node.value;
|
|
748
|
+
}
|
|
749
|
+
|
|
963
750
|
get name() {
|
|
964
751
|
let { node } = this;
|
|
965
752
|
return node.type === TreeNode ? node.value.name : null;
|
|
@@ -987,6 +774,7 @@ export const Path = class AgastPath {
|
|
|
987
774
|
getChild(childrenIndex) {
|
|
988
775
|
let { node } = this;
|
|
989
776
|
if (isStubNode(node)) return null;
|
|
777
|
+
|
|
990
778
|
return Tags.getAt(childrenIndex, getChildren(node)) || null;
|
|
991
779
|
}
|
|
992
780
|
|
|
@@ -1000,7 +788,7 @@ export const Path = class AgastPath {
|
|
|
1000
788
|
|
|
1001
789
|
getPropertyTagPath(childrenIndex) {
|
|
1002
790
|
let tagPath = this.tagPathAt(childrenIndex + 1);
|
|
1003
|
-
return tagPath && tagPath.
|
|
791
|
+
return tagPath && tagPath.type === Property ? tagPath : null;
|
|
1004
792
|
}
|
|
1005
793
|
|
|
1006
794
|
getReferenceTagPath(childrenIndex) {
|
|
@@ -1026,12 +814,12 @@ export const Path = class AgastPath {
|
|
|
1026
814
|
|
|
1027
815
|
get openTagPath() {
|
|
1028
816
|
let tagPath = TagPath.from(this, 0);
|
|
1029
|
-
return tagPath.
|
|
817
|
+
return tagPath.type === OpenNodeTag ? tagPath : null;
|
|
1030
818
|
}
|
|
1031
819
|
|
|
1032
820
|
get closeTagPath() {
|
|
1033
821
|
let tagPath = TagPath.from(this, -1);
|
|
1034
|
-
return tagPath.
|
|
822
|
+
return tagPath.type === CloseNodeTag ? tagPath : null;
|
|
1035
823
|
}
|
|
1036
824
|
|
|
1037
825
|
get openTag() {
|
|
@@ -1039,7 +827,7 @@ export const Path = class AgastPath {
|
|
|
1039
827
|
}
|
|
1040
828
|
|
|
1041
829
|
get open() {
|
|
1042
|
-
return this.openTag.value;
|
|
830
|
+
return parseOpenNodeTag(this.openTag).value;
|
|
1043
831
|
}
|
|
1044
832
|
|
|
1045
833
|
get closeTag() {
|
|
@@ -1051,11 +839,12 @@ export const Path = class AgastPath {
|
|
|
1051
839
|
}
|
|
1052
840
|
|
|
1053
841
|
get bindingTags() {
|
|
1054
|
-
return this.parentPropertyPath?.tag.value.tags[1];
|
|
842
|
+
return this.parentPropertyPath?.tag.value.tags[1][1];
|
|
1055
843
|
}
|
|
1056
844
|
|
|
1057
845
|
get reference() {
|
|
1058
|
-
|
|
846
|
+
let { referenceTag } = this;
|
|
847
|
+
return referenceTag && parseTag(referenceTag)?.value;
|
|
1059
848
|
}
|
|
1060
849
|
|
|
1061
850
|
get referenceTag() {
|
|
@@ -1081,8 +870,8 @@ export const Path = class AgastPath {
|
|
|
1081
870
|
return null;
|
|
1082
871
|
}
|
|
1083
872
|
let path = TagPath.from(this.parent, this.parentIndex);
|
|
1084
|
-
if (path.
|
|
1085
|
-
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);
|
|
1086
875
|
}
|
|
1087
876
|
return path;
|
|
1088
877
|
}
|
|
@@ -1097,7 +886,7 @@ export const Path = class AgastPath {
|
|
|
1097
886
|
|
|
1098
887
|
get firstPropertyTagPath() {
|
|
1099
888
|
let tagPath = this.tagPathAt(0);
|
|
1100
|
-
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.
|
|
889
|
+
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.value.node))) {
|
|
1101
890
|
tagPath = tagPath.nextSibling;
|
|
1102
891
|
if (tagPath?.propertyPath) {
|
|
1103
892
|
tagPath = tagPath.propertyPath;
|
|
@@ -1108,7 +897,7 @@ export const Path = class AgastPath {
|
|
|
1108
897
|
|
|
1109
898
|
get lastPropertyTagPath() {
|
|
1110
899
|
let tagPath = this.tagPathAt(-1);
|
|
1111
|
-
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.
|
|
900
|
+
while (tagPath && (!tagPath.propertyPath || isNullNode(tagPath.propertyPath.value.node))) {
|
|
1112
901
|
tagPath = tagPath.previousSibling;
|
|
1113
902
|
if (tagPath?.propertyPath) {
|
|
1114
903
|
tagPath = tagPath.propertyPath;
|
|
@@ -1141,7 +930,9 @@ export const Path = class AgastPath {
|
|
|
1141
930
|
while (!pathInst.node.value.name && pathInst.node.value.type === Symbol.for('_')) {
|
|
1142
931
|
if (pathInst.depth) throw new Error();
|
|
1143
932
|
skippedRootFragment = true;
|
|
1144
|
-
pathInst = pathInst.push(
|
|
933
|
+
pathInst = pathInst.push(
|
|
934
|
+
Tags.getIndex(buildFullPathSegment('_', null, 0), pathInst.node.value.tags),
|
|
935
|
+
);
|
|
1145
936
|
}
|
|
1146
937
|
}
|
|
1147
938
|
|
|
@@ -1161,12 +952,9 @@ export const Path = class AgastPath {
|
|
|
1161
952
|
|
|
1162
953
|
if (i === 0 && seg.type === '_' && skippedRootFragment) continue;
|
|
1163
954
|
|
|
1164
|
-
let tagsIndex =
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
seg.name,
|
|
1168
|
-
seg.index,
|
|
1169
|
-
seg.shiftIndex,
|
|
955
|
+
let tagsIndex = Tags.getIndex(
|
|
956
|
+
buildFullPathSegment(seg.type, seg.name, seg.index, seg.shiftIndex),
|
|
957
|
+
pathInst.node.value.tags,
|
|
1170
958
|
);
|
|
1171
959
|
|
|
1172
960
|
if (tagsIndex == null) return null;
|
|
@@ -1178,9 +966,9 @@ export const Path = class AgastPath {
|
|
|
1178
966
|
}
|
|
1179
967
|
|
|
1180
968
|
replaceWith(node, bindingTags) {
|
|
1181
|
-
let bindings = bindingTags?.map((tag) => tag.value); // TODO improve here
|
|
969
|
+
let bindings = bindingTags?.map((tag) => parseTag(tag).value); // TODO improve here
|
|
1182
970
|
if (bindings != null && !isArray(bindings)) throw new Error();
|
|
1183
|
-
if (!
|
|
971
|
+
if (!isNode(node)) throw new Error();
|
|
1184
972
|
|
|
1185
973
|
if (!node) throw new Error();
|
|
1186
974
|
|
|
@@ -1192,7 +980,7 @@ export const Path = class AgastPath {
|
|
|
1192
980
|
let path = this.parent;
|
|
1193
981
|
let replacementPath = [];
|
|
1194
982
|
|
|
1195
|
-
let targetShift_ = this.parent?.parentProperty?.value.tags[0];
|
|
983
|
+
let targetShift_ = this.parent?.parentProperty?.value.tags[1][0];
|
|
1196
984
|
let targetShift = targetShift_ && (targetShift_.type === ReferenceTag ? null : targetShift_);
|
|
1197
985
|
let targetReference = this.reference;
|
|
1198
986
|
let targetBindings = bindings == null ? this.bindings : bindings;
|
|
@@ -1207,24 +995,29 @@ export const Path = class AgastPath {
|
|
|
1207
995
|
|
|
1208
996
|
let { tags, shift } = Tags.getAt(targetParentIndex, getTags(path.node)).value;
|
|
1209
997
|
|
|
1210
|
-
let firstTag = tags[0];
|
|
998
|
+
let firstTag = tags[1][0];
|
|
1211
999
|
let newFirstTag = firstTag;
|
|
1212
1000
|
if (shift) {
|
|
1213
1001
|
newFirstTag = buildChild(ReferenceTag, targetReference);
|
|
1214
1002
|
}
|
|
1215
1003
|
|
|
1216
|
-
let tags_ =
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
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
|
+
);
|
|
1221
1014
|
|
|
1222
1015
|
if (!held && !shift) {
|
|
1223
1016
|
built = buildNode(
|
|
1224
1017
|
Tags.replaceAt(
|
|
1225
1018
|
targetParentIndex,
|
|
1226
|
-
built.value.tags,
|
|
1227
1019
|
buildChild(Property, buildProperty(tags_)),
|
|
1020
|
+
built.value.tags,
|
|
1228
1021
|
),
|
|
1229
1022
|
);
|
|
1230
1023
|
replacementPath.push(targetParentIndex);
|
|
@@ -1235,16 +1028,18 @@ export const Path = class AgastPath {
|
|
|
1235
1028
|
let nextShift = nextProperty?.type === Property && nextProperty.value.shift;
|
|
1236
1029
|
|
|
1237
1030
|
if (nextShift) {
|
|
1238
|
-
let { reference, bindings } =
|
|
1239
|
-
|
|
1031
|
+
let { reference, bindings } = BList.getAt(
|
|
1032
|
+
-1,
|
|
1033
|
+
nextProperty.value.node.value.bounds.leading,
|
|
1034
|
+
).property.value;
|
|
1240
1035
|
|
|
1241
1036
|
path = path.push(i);
|
|
1242
1037
|
|
|
1243
1038
|
built = buildNode(
|
|
1244
1039
|
Tags.replaceAt(
|
|
1245
1040
|
targetParentIndex - shift.index,
|
|
1246
|
-
built.value.tags,
|
|
1247
1041
|
buildChild(Property, buildProperty(tags_)),
|
|
1042
|
+
built.value.tags,
|
|
1248
1043
|
),
|
|
1249
1044
|
);
|
|
1250
1045
|
|
|
@@ -1253,17 +1048,14 @@ export const Path = class AgastPath {
|
|
|
1253
1048
|
built = buildNode(Tags.removeAt(targetParentIndex + 1, built.value.tags));
|
|
1254
1049
|
}
|
|
1255
1050
|
|
|
1256
|
-
tags_ = [newFirstTag, tags_[1], tags_[2]];
|
|
1051
|
+
tags_ = BList.fromValues([newFirstTag, tags_[1][1], tags_[1][2]], 1);
|
|
1257
1052
|
|
|
1258
1053
|
targetShift = null;
|
|
1259
1054
|
targetReference = reference;
|
|
1260
1055
|
targetBindings = bindings;
|
|
1261
|
-
targetParentIndex =
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
reference.name,
|
|
1265
|
-
0,
|
|
1266
|
-
0,
|
|
1056
|
+
targetParentIndex = Tags.getIndex(
|
|
1057
|
+
buildFullPathSegment(reference.type, reference.name, 0, 0),
|
|
1058
|
+
nextProperty.value.node.value.tags,
|
|
1267
1059
|
);
|
|
1268
1060
|
held = null;
|
|
1269
1061
|
|
|
@@ -1273,8 +1065,8 @@ export const Path = class AgastPath {
|
|
|
1273
1065
|
built = buildNode(
|
|
1274
1066
|
Tags.replaceAt(
|
|
1275
1067
|
targetParentIndex,
|
|
1276
|
-
getTags(built),
|
|
1277
1068
|
buildChild(Property, buildProperty(tags_, shift)),
|
|
1069
|
+
getTags(built),
|
|
1278
1070
|
),
|
|
1279
1071
|
);
|
|
1280
1072
|
replacementPath.push(targetParentIndex);
|
|
@@ -1284,7 +1076,7 @@ export const Path = class AgastPath {
|
|
|
1284
1076
|
held = targetShift ? value : null;
|
|
1285
1077
|
heldCount = held ? heldCount + 1 : 0;
|
|
1286
1078
|
|
|
1287
|
-
targetShift_ = path?.parentProperty?.value.tags[0];
|
|
1079
|
+
targetShift_ = path?.parentProperty?.value.tags[1][0];
|
|
1288
1080
|
targetShift = targetShift_ && (targetShift_.type === ReferenceTag ? null : targetShift_);
|
|
1289
1081
|
targetReference = path.reference;
|
|
1290
1082
|
targetBindings = path.bindings;
|
|
@@ -1296,7 +1088,131 @@ export const Path = class AgastPath {
|
|
|
1296
1088
|
}
|
|
1297
1089
|
|
|
1298
1090
|
replaceAt(path, node, bindings) {
|
|
1299
|
-
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);
|
|
1300
1216
|
}
|
|
1301
1217
|
|
|
1302
1218
|
mapOnto(rootNode) {
|
|
@@ -1322,19 +1238,19 @@ export const Path = class AgastPath {
|
|
|
1322
1238
|
let { parent, node } = this;
|
|
1323
1239
|
let sigilTag = getSigilTag(node);
|
|
1324
1240
|
|
|
1325
|
-
return !parent && sigilTag && !!(isSelfClosingTag(sigilTag) ||
|
|
1241
|
+
return !parent && sigilTag && !!(isSelfClosingTag(sigilTag) || getCloseNodeTag(node));
|
|
1326
1242
|
}
|
|
1327
1243
|
|
|
1328
1244
|
get held() {
|
|
1329
1245
|
let tagPath = this.tagPathAt(-1);
|
|
1330
1246
|
|
|
1331
1247
|
// TODO is this safe
|
|
1332
|
-
if (tagPath.
|
|
1248
|
+
if (tagPath.type !== Property) return null;
|
|
1333
1249
|
|
|
1334
|
-
let { tags } = tagPath.
|
|
1250
|
+
let { tags } = tagPath.value;
|
|
1335
1251
|
|
|
1336
|
-
if (tags[0]?.type === ShiftTag && !tags[2]) {
|
|
1337
|
-
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;
|
|
1338
1254
|
}
|
|
1339
1255
|
|
|
1340
1256
|
// if we're not at the left side, we aren't held
|
|
@@ -1351,8 +1267,8 @@ export const Path = class AgastPath {
|
|
|
1351
1267
|
for (;;) {
|
|
1352
1268
|
let refPath = coverParent.propertyKeyTagPath;
|
|
1353
1269
|
|
|
1354
|
-
if (refPath?.
|
|
1355
|
-
return TagPath.from(refPath.path, refPath.tagsIndex - 1).
|
|
1270
|
+
if (refPath?.type === ShiftTag) {
|
|
1271
|
+
return TagPath.from(refPath.path, refPath.tagsIndex - 1).value;
|
|
1356
1272
|
}
|
|
1357
1273
|
|
|
1358
1274
|
coverParent = coverParent.parent;
|
|
@@ -1365,57 +1281,24 @@ export const Path = class AgastPath {
|
|
|
1365
1281
|
advance(tag) {
|
|
1366
1282
|
if (!tag) throw new Error();
|
|
1367
1283
|
|
|
1368
|
-
let tagPath = this.tagPathAt(-1,
|
|
1284
|
+
let tagPath = this.tagPathAt(-1, -1);
|
|
1369
1285
|
|
|
1370
|
-
if (tagPath?.
|
|
1286
|
+
if (tagPath?.type === Property ? tagPath?.nextSibling : tagPath?.next) throw new Error();
|
|
1371
1287
|
|
|
1372
1288
|
if (this.done) throw new Error();
|
|
1373
1289
|
|
|
1374
1290
|
let resultPath = this;
|
|
1375
1291
|
|
|
1376
|
-
|
|
1377
|
-
case BindingTag: {
|
|
1378
|
-
if (!this.lastPropertyTagPath) {
|
|
1379
|
-
resultPath = this.advanceUnwrapped(buildReferenceTag()).path;
|
|
1380
|
-
}
|
|
1381
|
-
break;
|
|
1382
|
-
}
|
|
1292
|
+
let tag_ = isNode(tag) ? tag : parseTag(tag);
|
|
1383
1293
|
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
case GapNode:
|
|
1387
|
-
case NullTag:
|
|
1388
|
-
case GapTag:
|
|
1389
|
-
case OpenNodeTag: {
|
|
1390
|
-
let sigilTag = getSigilTag_(tag);
|
|
1391
|
-
|
|
1392
|
-
if (sigilTag.type === OpenNodeTag && sigilTag.value.type === Symbol.for('__')) {
|
|
1393
|
-
break;
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
let lastTagPath = this.lastPropertyTagPath;
|
|
1397
|
-
let newProperty = !lastTagPath || propertyIsFull(lastTagPath.tag);
|
|
1398
|
-
let reference = lastTagPath?.referenceTagPath.tag.value;
|
|
1399
|
-
|
|
1400
|
-
// TODO revisit this condition
|
|
1401
|
-
if (!getFlags(this.node)?.token || reference?.type === '@' || tag.type === GapTag) {
|
|
1402
|
-
if (newProperty || !lastTagPath.tag.value.tags.length) {
|
|
1403
|
-
resultPath = this.advanceUnwrapped(buildReferenceTag()).path;
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
break;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
if (tag.type === Property) {
|
|
1412
|
-
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))));
|
|
1413
1296
|
} else {
|
|
1414
|
-
resultPath = resultPath.advanceUnwrapped(tag).path;
|
|
1297
|
+
resultPath = resultPath.advanceUnwrapped(printTag(tag)).path;
|
|
1415
1298
|
}
|
|
1416
1299
|
|
|
1417
1300
|
if (
|
|
1418
|
-
(
|
|
1301
|
+
(tag_.type === CloseNodeTag || (tag_.type === OpenNodeTag && tag_.value.selfClosing)) &&
|
|
1419
1302
|
resultPath.depth
|
|
1420
1303
|
) {
|
|
1421
1304
|
return resultPath.parent;
|
|
@@ -1425,14 +1308,13 @@ export const Path = class AgastPath {
|
|
|
1425
1308
|
}
|
|
1426
1309
|
|
|
1427
1310
|
advanceUnwrapped(tag) {
|
|
1428
|
-
if (!tag) throw new Error();
|
|
1311
|
+
if (!isString(tag) && !isNode(tag)) throw new Error();
|
|
1312
|
+
let tag_ = isString(tag) ? parseTag(tag) : tag;
|
|
1429
1313
|
|
|
1430
1314
|
let tagPath = this.tagPathAt(-1, [-1, -1]);
|
|
1431
1315
|
|
|
1432
1316
|
if (
|
|
1433
|
-
[TreeNode, NullNode, GapNode].includes(tagPath?.
|
|
1434
|
-
? tagPath?.nextSibling
|
|
1435
|
-
: tagPath?.next
|
|
1317
|
+
[TreeNode, NullNode, GapNode].includes(tagPath?.type) ? tagPath?.nextSibling : tagPath?.next
|
|
1436
1318
|
)
|
|
1437
1319
|
throw new Error();
|
|
1438
1320
|
|
|
@@ -1440,11 +1322,11 @@ export const Path = class AgastPath {
|
|
|
1440
1322
|
|
|
1441
1323
|
let targetPath = tagPath && endsNode(tagPath.tag) ? this.parent : this;
|
|
1442
1324
|
|
|
1443
|
-
switch (
|
|
1325
|
+
switch (tag_.type) {
|
|
1444
1326
|
case ReferenceTag: {
|
|
1445
|
-
let { type, name, flags } =
|
|
1327
|
+
let { type, name, flags } = tag_.value;
|
|
1446
1328
|
|
|
1447
|
-
if ([ReferenceTag, ShiftTag, BindingTag].includes(targetPath.tagPathAt(-1, -1)?.
|
|
1329
|
+
if ([ReferenceTag, ShiftTag, BindingTag].includes(targetPath.tagPathAt(-1, -1)?.type))
|
|
1448
1330
|
throw new Error('invalid location for reference');
|
|
1449
1331
|
if (!name && !type) throw new Error();
|
|
1450
1332
|
|
|
@@ -1457,22 +1339,25 @@ export const Path = class AgastPath {
|
|
|
1457
1339
|
if (targetPath.open.type === Symbol.for('_') && !['_', '#'].includes(type))
|
|
1458
1340
|
throw new Error();
|
|
1459
1341
|
|
|
1460
|
-
if (
|
|
1461
|
-
let property = getProperty(
|
|
1342
|
+
if (tag_.value.name) {
|
|
1343
|
+
let property = getProperty(tag_.value.name, targetPath.node);
|
|
1462
1344
|
if (
|
|
1463
|
-
getOr(null,
|
|
1345
|
+
getOr(null, tag_.value.name, targetPath.node) &&
|
|
1464
1346
|
!property.value.shift &&
|
|
1465
|
-
!referencesAreEqual(
|
|
1347
|
+
!Tags.referencesAreEqual(tag_.value, property.value.reference)
|
|
1466
1348
|
) {
|
|
1467
1349
|
throw new Error('mismatched references');
|
|
1468
1350
|
}
|
|
1469
|
-
} else if (
|
|
1470
|
-
let rootIdx =
|
|
1351
|
+
} else if (tag_.value.type === '_') {
|
|
1352
|
+
let rootIdx = Tags.getIndex(
|
|
1353
|
+
buildFullPathSegment('_', null, 0),
|
|
1354
|
+
targetPath.node.value.tags,
|
|
1355
|
+
);
|
|
1471
1356
|
|
|
1472
1357
|
if (
|
|
1473
1358
|
rootIdx != null &&
|
|
1474
|
-
!referencesAreEqual(
|
|
1475
|
-
|
|
1359
|
+
!Tags.referencesAreEqual(
|
|
1360
|
+
tag_.value,
|
|
1476
1361
|
Tags.getAt(rootIdx, getTags(targetPath.node)).value.reference,
|
|
1477
1362
|
)
|
|
1478
1363
|
) {
|
|
@@ -1480,43 +1365,42 @@ export const Path = class AgastPath {
|
|
|
1480
1365
|
}
|
|
1481
1366
|
}
|
|
1482
1367
|
|
|
1483
|
-
let property = buildChild(Property, buildProperty([tag]));
|
|
1368
|
+
let property = buildChild(Property, buildProperty(BList.fromValues([printTag(tag)])));
|
|
1484
1369
|
|
|
1485
1370
|
targetPath = targetPath.replaceWith(
|
|
1486
|
-
buildNode(Tags.push(getTags(targetPath.node)
|
|
1371
|
+
buildNode(Tags.push(property, getTags(targetPath.node))),
|
|
1487
1372
|
);
|
|
1488
1373
|
break;
|
|
1489
1374
|
}
|
|
1490
1375
|
|
|
1491
1376
|
case BindingTag: {
|
|
1492
|
-
if (![ReferenceTag, ShiftTag].includes(this.tagPathAt(-1, -1)
|
|
1377
|
+
if (![ReferenceTag, ShiftTag].includes(parseTagType(this.tagPathAt(-1, -1)))) {
|
|
1493
1378
|
throw new Error('Invalid location for BindingTag');
|
|
1494
1379
|
}
|
|
1495
|
-
if (!tag.value.segments) throw new Error();
|
|
1496
1380
|
|
|
1497
1381
|
let refPath = this.tagPathAt(-1, 0);
|
|
1498
1382
|
let propPath = TagPath.from(refPath.path, refPath.tagsIndex);
|
|
1499
1383
|
|
|
1500
|
-
let { shift } = propPath.
|
|
1384
|
+
let { shift } = propPath.value;
|
|
1501
1385
|
|
|
1502
|
-
if (![ReferenceTag, ShiftTag].includes(refPath.
|
|
1386
|
+
if (![ReferenceTag, ShiftTag].includes(refPath.type)) throw new Error();
|
|
1503
1387
|
|
|
1504
|
-
if (refPath.
|
|
1388
|
+
if (refPath.type === ShiftTag) {
|
|
1505
1389
|
refPath = TagPath.from(refPath.path, refPath.tagsIndex - shift.index, 0);
|
|
1506
1390
|
}
|
|
1507
1391
|
|
|
1508
|
-
let { 0: firstTag, 1: bindingTags = [] } = propPath.
|
|
1509
|
-
let tags = [firstTag,
|
|
1392
|
+
let { 0: firstTag, 1: bindingTags = [] } = propPath.value.tags[1];
|
|
1393
|
+
let tags = BList.fromValues([firstTag, Tags.from(...bindingTags, tag_)], 1);
|
|
1510
1394
|
let property = buildChild(Property, buildProperty(tags, shift));
|
|
1511
1395
|
|
|
1512
1396
|
targetPath = this.replaceWith(
|
|
1513
|
-
buildNode(Tags.replaceAt(propPath.tagsIndex, getTags(this.node)
|
|
1397
|
+
buildNode(Tags.replaceAt(propPath.tagsIndex, property, getTags(this.node))),
|
|
1514
1398
|
);
|
|
1515
1399
|
break;
|
|
1516
1400
|
}
|
|
1517
1401
|
|
|
1518
1402
|
case OpenNodeTag: {
|
|
1519
|
-
let { literalValue, flags, type } =
|
|
1403
|
+
let { literalValue, flags, type, name, attributes } = tag_.value;
|
|
1520
1404
|
|
|
1521
1405
|
if (this.held && flags.token) throw new Error();
|
|
1522
1406
|
|
|
@@ -1525,22 +1409,36 @@ export const Path = class AgastPath {
|
|
|
1525
1409
|
}
|
|
1526
1410
|
|
|
1527
1411
|
let parentProp = this.node && Tags.getAt(-1, getChildren(this.node));
|
|
1528
|
-
|
|
1412
|
+
|
|
1413
|
+
if (parentProp && propertyIsFull(parentProp)) {
|
|
1414
|
+
parentProp = null;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
let ref = parentProp?.value.shift
|
|
1529
1418
|
? this.node &&
|
|
1530
|
-
|
|
1531
|
-
.value
|
|
1532
|
-
|
|
1419
|
+
parseTag(
|
|
1420
|
+
Tags.getAt(-1 - parentProp.value.shift.index, getChildren(this.node)).value
|
|
1421
|
+
.tags[1][0],
|
|
1422
|
+
).value
|
|
1423
|
+
: parentProp?.value.reference;
|
|
1533
1424
|
|
|
1534
|
-
|
|
1425
|
+
let parentFlags = parentProp?.value.shift ? flags : this.node.value.flags;
|
|
1535
1426
|
|
|
1536
|
-
|
|
1427
|
+
if (parentFlags.token && ref?.type !== '@') throw new Error();
|
|
1537
1428
|
|
|
1429
|
+
let node;
|
|
1538
1430
|
if (literalValue && !flags.token) {
|
|
1539
|
-
|
|
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_);
|
|
1540
1439
|
}
|
|
1541
1440
|
|
|
1542
1441
|
targetPath = this.advanceUnwrapped(node).path;
|
|
1543
|
-
|
|
1544
1442
|
targetPath = targetPath.tagPathAt(-1).inner;
|
|
1545
1443
|
|
|
1546
1444
|
break;
|
|
@@ -1549,11 +1447,11 @@ export const Path = class AgastPath {
|
|
|
1549
1447
|
case GapTag:
|
|
1550
1448
|
case NullTag: {
|
|
1551
1449
|
// if (getSigilTag(this.node)) throw new Error();
|
|
1552
|
-
if (this.tagPathAt(-1, 0)
|
|
1450
|
+
if (parseTagType(this.tagPathAt(-1, 0)) !== ReferenceTag) {
|
|
1553
1451
|
throw new Error('Invalid location for NullTag');
|
|
1554
1452
|
}
|
|
1555
1453
|
|
|
1556
|
-
let node = buildNode(
|
|
1454
|
+
let node = buildNode(tag_);
|
|
1557
1455
|
|
|
1558
1456
|
targetPath = this.advanceUnwrapped(node).path;
|
|
1559
1457
|
// targetPath = targetPath.tagPathAt(-1).inner; // ?
|
|
@@ -1566,21 +1464,22 @@ export const Path = class AgastPath {
|
|
|
1566
1464
|
|
|
1567
1465
|
let lastChild = targetPath.getChild(-1);
|
|
1568
1466
|
|
|
1569
|
-
if (lastChild?.type === Property && !propertyIsFull(lastChild))
|
|
1467
|
+
if (isObject(lastChild) && lastChild?.type === Property && !propertyIsFull(lastChild))
|
|
1468
|
+
throw new Error();
|
|
1570
1469
|
|
|
1571
1470
|
let openTag = getOpenTag(node);
|
|
1572
1471
|
|
|
1573
1472
|
if (!openTag) throw new Error();
|
|
1574
|
-
if (openTag.value.selfClosing) throw new Error();
|
|
1473
|
+
if (parseTag(openTag).value.selfClosing) throw new Error();
|
|
1575
1474
|
|
|
1576
|
-
targetPath = targetPath.replaceWith(buildNode(Tags.push(getTags(node)
|
|
1475
|
+
targetPath = targetPath.replaceWith(buildNode(Tags.push(tag_, getTags(node))));
|
|
1577
1476
|
break;
|
|
1578
1477
|
}
|
|
1579
1478
|
|
|
1580
1479
|
case NullNode:
|
|
1581
1480
|
case GapNode:
|
|
1582
1481
|
case TreeNode: {
|
|
1583
|
-
let node =
|
|
1482
|
+
let node = tag_;
|
|
1584
1483
|
let parentPath = targetPath;
|
|
1585
1484
|
let { node: parentNode } = parentPath;
|
|
1586
1485
|
|
|
@@ -1589,12 +1488,12 @@ export const Path = class AgastPath {
|
|
|
1589
1488
|
if (isMultiFragment(node)) {
|
|
1590
1489
|
let existingProperty = tagPath;
|
|
1591
1490
|
|
|
1592
|
-
while (existingProperty?.
|
|
1593
|
-
existingProperty = existingProperty.
|
|
1491
|
+
while (existingProperty?.type === AttributeDefinition) {
|
|
1492
|
+
existingProperty = tagPath.siblingAt(existingProperty.tagsIndex - 1);
|
|
1594
1493
|
}
|
|
1595
1494
|
|
|
1596
1495
|
if (
|
|
1597
|
-
existingProperty.
|
|
1496
|
+
existingProperty.type !== OpenNodeTag &&
|
|
1598
1497
|
existingProperty.tag &&
|
|
1599
1498
|
!propertyIsFull(existingProperty.tag)
|
|
1600
1499
|
) {
|
|
@@ -1604,7 +1503,7 @@ export const Path = class AgastPath {
|
|
|
1604
1503
|
let newPath = Path.from(buildNode(this.node.value.tags));
|
|
1605
1504
|
|
|
1606
1505
|
for (let tag of Tags.traverse(node.value.children)) {
|
|
1607
|
-
if (tag
|
|
1506
|
+
if (parseTagType(tag) === Property) {
|
|
1608
1507
|
newPath = newPath.advance(tag);
|
|
1609
1508
|
} else {
|
|
1610
1509
|
newPath = newPath.advanceUnwrapped(tag).path.atDepth(0);
|
|
@@ -1615,11 +1514,11 @@ export const Path = class AgastPath {
|
|
|
1615
1514
|
break;
|
|
1616
1515
|
}
|
|
1617
1516
|
|
|
1618
|
-
let shift = tagPath.
|
|
1517
|
+
let shift = tagPath.type === Property ? tagPath.value.shift : undefined;
|
|
1619
1518
|
let { held } = this;
|
|
1620
1519
|
|
|
1621
1520
|
if (held) {
|
|
1622
|
-
// let heldProperty = this.tagPathAt(-2, 2).
|
|
1521
|
+
// let heldProperty = this.tagPathAt(-2, 2).value;
|
|
1623
1522
|
let matchesHeld = isGapNode(node);
|
|
1624
1523
|
if (getRoot(node) && nodeIsComplete(node)) {
|
|
1625
1524
|
matchesHeld =
|
|
@@ -1627,8 +1526,10 @@ export const Path = class AgastPath {
|
|
|
1627
1526
|
isGapNode(node) ||
|
|
1628
1527
|
held.node === node ||
|
|
1629
1528
|
held.node ===
|
|
1630
|
-
|
|
1631
|
-
.
|
|
1529
|
+
BList.getAt(
|
|
1530
|
+
-BList.getSize(held.node.value.bounds.leading),
|
|
1531
|
+
node.value.bounds.leading,
|
|
1532
|
+
).property.value.node;
|
|
1632
1533
|
if (!matchesHeld) {
|
|
1633
1534
|
// TODO We're passing by the node that shifted if it's a cover!
|
|
1634
1535
|
throw new Error();
|
|
@@ -1637,17 +1538,17 @@ export const Path = class AgastPath {
|
|
|
1637
1538
|
}
|
|
1638
1539
|
|
|
1639
1540
|
if (propertyIsFull(tagPath.tag)) {
|
|
1640
|
-
let tags = [
|
|
1541
|
+
let tags = BList.fromValues([Tags.fromValues([]), Tags.fromValues([]), node], 1);
|
|
1641
1542
|
let property = buildChild(Property, buildProperty(tags, shift));
|
|
1642
1543
|
|
|
1643
|
-
targetPath = this.replaceWith(buildNode(Tags.push(parentNode.value.tags
|
|
1544
|
+
targetPath = this.replaceWith(buildNode(Tags.push(property, parentNode.value.tags)));
|
|
1644
1545
|
} else {
|
|
1645
|
-
let { 0: firstTag, 1: bindingTags = [] } = tagPath.
|
|
1646
|
-
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);
|
|
1647
1548
|
let property = buildChild(Property, buildProperty(tags, shift));
|
|
1648
1549
|
|
|
1649
1550
|
targetPath = this.replaceWith(
|
|
1650
|
-
buildNode(Tags.replaceAt(tagPath.tagsIndex, parentNode.value.tags
|
|
1551
|
+
buildNode(Tags.replaceAt(tagPath.tagsIndex, property, parentNode.value.tags)),
|
|
1651
1552
|
);
|
|
1652
1553
|
}
|
|
1653
1554
|
|
|
@@ -1663,10 +1564,10 @@ export const Path = class AgastPath {
|
|
|
1663
1564
|
|
|
1664
1565
|
// add undefined attributes from value
|
|
1665
1566
|
let { node } = this;
|
|
1666
|
-
if (
|
|
1567
|
+
if (tag_.type !== AttributeDefinition) throw new Error();
|
|
1667
1568
|
|
|
1668
|
-
let { path, value } =
|
|
1669
|
-
let openTag = getOpenTag(node);
|
|
1569
|
+
let { path, value } = tag_.value;
|
|
1570
|
+
let openTag = parseTag(getOpenTag(node));
|
|
1670
1571
|
let { attributes } = node.value;
|
|
1671
1572
|
|
|
1672
1573
|
if (!objHas(attributes, path) && objGet(attributes, path) !== undefined)
|
|
@@ -1676,10 +1577,10 @@ export const Path = class AgastPath {
|
|
|
1676
1577
|
|
|
1677
1578
|
let { flags, name } = openTag.value;
|
|
1678
1579
|
attributes = immSet(attributes, path, value);
|
|
1679
|
-
let newOpenTag = buildOpenNodeTag(flags, name, null, attributes);
|
|
1580
|
+
let newOpenTag = buildOpenNodeTag(flags, name, null, printObject(attributes));
|
|
1680
1581
|
|
|
1681
1582
|
targetPath = this.replaceWith(
|
|
1682
|
-
buildNode(Tags.push(Tags.replaceAt(0, getTags(node)
|
|
1583
|
+
buildNode(Tags.push(tag_, Tags.replaceAt(0, newOpenTag, getTags(node)))),
|
|
1683
1584
|
);
|
|
1684
1585
|
break;
|
|
1685
1586
|
}
|
|
@@ -1692,7 +1593,7 @@ export const Path = class AgastPath {
|
|
|
1692
1593
|
let { reference, shift: heldShift } = lastPropertyTag.value;
|
|
1693
1594
|
|
|
1694
1595
|
if (!reference) {
|
|
1695
|
-
({ reference } = this.tagPathAt(-1 - (heldShift?.index ?? 0)).
|
|
1596
|
+
({ reference } = this.tagPathAt(-1 - (heldShift?.index ?? 0)).value);
|
|
1696
1597
|
}
|
|
1697
1598
|
|
|
1698
1599
|
if (!reference.flags.expression && reference.type !== '_') throw new Error();
|
|
@@ -1701,55 +1602,114 @@ export const Path = class AgastPath {
|
|
|
1701
1602
|
? buildShift(heldShift.index + 1, heldShift.height + 1)
|
|
1702
1603
|
: buildShift(1, 3);
|
|
1703
1604
|
|
|
1704
|
-
let property = buildChild(Property, buildProperty([tag], shift));
|
|
1605
|
+
let property = buildChild(Property, buildProperty(BList.fromValues([tag]), shift));
|
|
1705
1606
|
|
|
1706
|
-
targetPath = this.replaceWith(buildNode(Tags.push(this.node.value.tags
|
|
1607
|
+
targetPath = this.replaceWith(buildNode(Tags.push(property, this.node.value.tags)));
|
|
1707
1608
|
break;
|
|
1708
1609
|
}
|
|
1709
1610
|
|
|
1710
1611
|
case LiteralTag:
|
|
1711
|
-
if (typeof
|
|
1612
|
+
if (typeof tag_.value !== 'string') throw new Error();
|
|
1712
1613
|
|
|
1713
|
-
targetPath = this.replaceWith(buildNode(Tags.push(this.node.value.tags
|
|
1614
|
+
targetPath = this.replaceWith(buildNode(Tags.push(tag_, this.node.value.tags)));
|
|
1714
1615
|
break;
|
|
1715
1616
|
|
|
1716
1617
|
default:
|
|
1717
1618
|
throw new Error();
|
|
1718
1619
|
}
|
|
1719
1620
|
|
|
1720
|
-
return targetPath && TagPath.from(targetPath, -1,
|
|
1621
|
+
return targetPath && TagPath.from(targetPath, -1, offsetForTag(tag_));
|
|
1721
1622
|
}
|
|
1722
1623
|
};
|
|
1723
1624
|
|
|
1724
|
-
|
|
1625
|
+
freezeClass(Path);
|
|
1725
1626
|
|
|
1726
1627
|
export const tagPathsAreEqual = (a, b) => {
|
|
1727
1628
|
if (a == null || b == null) return b == a;
|
|
1728
1629
|
return a.path.node === b.path.node && a.tagsIndex === b.tagsIndex;
|
|
1729
1630
|
};
|
|
1730
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
|
+
|
|
1731
1654
|
export class TagPath {
|
|
1732
1655
|
static from(path, tagsIndex, propertyIndex) {
|
|
1733
1656
|
let tags = getTags(path.node);
|
|
1734
1657
|
let size = Tags.getSize(tags);
|
|
1735
1658
|
let index = Number.isFinite(tagsIndex) && tagsIndex < 0 ? size + tagsIndex : tagsIndex;
|
|
1736
|
-
|
|
1737
|
-
let
|
|
1738
|
-
|
|
1739
|
-
let propTag = Tags.getAt(index, tags);
|
|
1659
|
+
let propertyIndex_ = propertyIndex;
|
|
1660
|
+
let propTag_ = Tags.getAt(index, tags);
|
|
1661
|
+
let propTag = propTag_ && parseTag(propTag_);
|
|
1740
1662
|
|
|
1741
1663
|
if (
|
|
1742
1664
|
[OpenNodeTag, CloseNodeTag, LiteralTag, AttributeDefinition, GapTag, NullTag].includes(
|
|
1743
1665
|
propTag?.type,
|
|
1744
1666
|
)
|
|
1745
1667
|
) {
|
|
1746
|
-
propertyIndex_ =
|
|
1668
|
+
propertyIndex_ = null;
|
|
1747
1669
|
}
|
|
1748
1670
|
|
|
1749
|
-
let
|
|
1750
|
-
|
|
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
|
+
}
|
|
1751
1698
|
|
|
1752
|
-
|
|
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);
|
|
1709
|
+
|
|
1710
|
+
let pathExists = isArray(propertyIndex_) && propertyIndex_?.length ? idx.length : propTag;
|
|
1711
|
+
|
|
1712
|
+
return pathExists ? new TagPath(path, index, idx) : null;
|
|
1753
1713
|
}
|
|
1754
1714
|
|
|
1755
1715
|
static fromNode(node, tagsIndex, propertyIndex) {
|
|
@@ -1774,28 +1734,26 @@ export class TagPath {
|
|
|
1774
1734
|
if (!Number.isFinite(tagsIndex) || tagsIndex < 0) throw new Error();
|
|
1775
1735
|
if (!isArray(propertyIndex)) throw new Error();
|
|
1776
1736
|
|
|
1777
|
-
let
|
|
1737
|
+
for (let index of recordValues(propertyIndex)) {
|
|
1738
|
+
if (!(index >= 0) || !Number.isFinite(index)) throw new Error();
|
|
1739
|
+
}
|
|
1778
1740
|
|
|
1779
1741
|
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
1780
1742
|
|
|
1781
|
-
if (
|
|
1782
|
-
tag = Tags.getAt(
|
|
1743
|
+
if (propertyIndex.length) {
|
|
1744
|
+
tag = Tags.getAt(propertyIndex, tag.value.tags);
|
|
1783
1745
|
}
|
|
1784
1746
|
|
|
1785
1747
|
if (tag == null || isArray(tag)) throw new Error();
|
|
1786
1748
|
|
|
1787
|
-
for (let segment of propertyIndex_) {
|
|
1788
|
-
if (!isPlainObject(segment) || !(segment.index === 0 || segment.index > 0)) throw new Error();
|
|
1789
|
-
}
|
|
1790
|
-
|
|
1791
1749
|
this.path = path;
|
|
1792
1750
|
this.tagsIndex = tagsIndex;
|
|
1793
|
-
this.propertyIndex =
|
|
1751
|
+
this.propertyIndex = propertyIndex;
|
|
1794
1752
|
|
|
1795
1753
|
this.node = path.node;
|
|
1796
1754
|
this.tag = tag;
|
|
1797
1755
|
|
|
1798
|
-
if (tag.type === Property &&
|
|
1756
|
+
if (isObject(tag) && tag.type === Property && propertyIndex.length) throw new Error();
|
|
1799
1757
|
|
|
1800
1758
|
freeze(this);
|
|
1801
1759
|
}
|
|
@@ -1803,13 +1761,21 @@ export class TagPath {
|
|
|
1803
1761
|
asPrimitive() {
|
|
1804
1762
|
let { path, tagsIndex, propertyIndex } = this;
|
|
1805
1763
|
|
|
1806
|
-
return
|
|
1764
|
+
return freeze({ path: path.asPrimitive(), tagsIndex, propertyIndex });
|
|
1807
1765
|
}
|
|
1808
1766
|
|
|
1809
1767
|
get child() {
|
|
1810
1768
|
return this.tag;
|
|
1811
1769
|
}
|
|
1812
1770
|
|
|
1771
|
+
get type() {
|
|
1772
|
+
return parseTagType(this.tag);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
get value() {
|
|
1776
|
+
return parseTag(this.tag).value;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1813
1779
|
get parentNode() {
|
|
1814
1780
|
return this.path.parentNode;
|
|
1815
1781
|
}
|
|
@@ -1831,12 +1797,12 @@ export class TagPath {
|
|
|
1831
1797
|
get referenceTagPath() {
|
|
1832
1798
|
let path = TagPath.from(this.path, this.tagsIndex, 0);
|
|
1833
1799
|
if (path && path.propertyPath) {
|
|
1834
|
-
let { shift } = path.propertyPath.
|
|
1800
|
+
let { shift } = path.propertyPath.value;
|
|
1835
1801
|
if (shift) {
|
|
1836
1802
|
path = TagPath.from(this.path, this.tagsIndex - shift.index, 0);
|
|
1837
1803
|
}
|
|
1838
1804
|
}
|
|
1839
|
-
return path?.
|
|
1805
|
+
return path?.type === ReferenceTag ? path : null;
|
|
1840
1806
|
}
|
|
1841
1807
|
|
|
1842
1808
|
get nextProperty() {
|
|
@@ -1844,33 +1810,33 @@ export class TagPath {
|
|
|
1844
1810
|
|
|
1845
1811
|
let nextChild = TagPath.from(path, tagsIndex + 1);
|
|
1846
1812
|
|
|
1847
|
-
return nextChild?.
|
|
1813
|
+
return nextChild?.type === Property ? nextChild : null;
|
|
1848
1814
|
}
|
|
1849
1815
|
|
|
1850
1816
|
get nextSibling() {
|
|
1851
1817
|
let { path, tagsIndex, propertyIndex } = this;
|
|
1852
1818
|
|
|
1853
|
-
let propertyIndex0 = propertyIndex[0]
|
|
1819
|
+
let propertyIndex0 = propertyIndex[0];
|
|
1854
1820
|
|
|
1855
|
-
let nextChildIndex = tagsIndex
|
|
1821
|
+
let nextChildIndex = tagsIndex;
|
|
1856
1822
|
let nextChild = path.getChild(nextChildIndex);
|
|
1857
1823
|
|
|
1858
1824
|
if (propertyIndex0 == null && !nextChild) {
|
|
1859
|
-
return this.
|
|
1825
|
+
return this.type === CloseNodeTag ? null : path.closeTagPath;
|
|
1860
1826
|
}
|
|
1861
1827
|
|
|
1862
1828
|
switch (propertyIndex0) {
|
|
1863
1829
|
case 0:
|
|
1864
1830
|
case 1: {
|
|
1865
1831
|
let childIndex = tagsIndex - 1;
|
|
1866
|
-
let bindingIndex = propertyIndex[1]
|
|
1832
|
+
let bindingIndex = propertyIndex[1] ?? -1;
|
|
1867
1833
|
let binding = path.getBindingTagPath(childIndex, bindingIndex + 1);
|
|
1868
1834
|
if (binding) return binding;
|
|
1869
1835
|
return path.getNodeTagPath(childIndex);
|
|
1870
1836
|
}
|
|
1871
1837
|
case 2:
|
|
1872
1838
|
default: {
|
|
1873
|
-
if (!nextChild || nextChild.type !== Property) {
|
|
1839
|
+
if (!nextChild || nextChild.type !== Property || !propertyIndex.length) {
|
|
1874
1840
|
return path.tagPathAt(tagsIndex + 1);
|
|
1875
1841
|
} else {
|
|
1876
1842
|
let ref = path.getReferenceTagPath(nextChildIndex);
|
|
@@ -1917,38 +1883,34 @@ export class TagPath {
|
|
|
1917
1883
|
get next() {
|
|
1918
1884
|
let { path, tagsIndex, propertyIndex } = this;
|
|
1919
1885
|
|
|
1920
|
-
propertyIndex = [...propertyIndex];
|
|
1886
|
+
propertyIndex = [...recordValues(propertyIndex)];
|
|
1921
1887
|
|
|
1922
1888
|
let leaving = false;
|
|
1923
1889
|
|
|
1924
1890
|
for (;;) {
|
|
1925
|
-
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
1891
|
+
let tag = parseTag(Tags.getAt(tagsIndex, getTags(path.node)));
|
|
1926
1892
|
let propTag = tag;
|
|
1927
1893
|
let lastRef = null;
|
|
1894
|
+
let wasLeaving = leaving;
|
|
1928
1895
|
leaving = false;
|
|
1929
1896
|
|
|
1930
1897
|
if (!tag) return null;
|
|
1931
1898
|
|
|
1932
|
-
if (tag.type === Property) {
|
|
1933
|
-
if (propertyIndex.length === 0
|
|
1934
|
-
|
|
1935
|
-
}
|
|
1899
|
+
if (isObject(tag) && tag.type === Property && !wasLeaving) {
|
|
1900
|
+
if (propertyIndex.length === 0) {
|
|
1901
|
+
let { 0: open, 1: bindings } = tag.value.tags[1];
|
|
1936
1902
|
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1903
|
+
let index = !isArray(open) ? 0 : !isArray(bindings) ? 1 : 2;
|
|
1904
|
+
|
|
1905
|
+
propertyIndex.push({ index, node: tag.value.tags });
|
|
1940
1906
|
}
|
|
1941
|
-
}
|
|
1942
1907
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
} else {
|
|
1949
|
-
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_);
|
|
1950
1913
|
}
|
|
1951
|
-
continue;
|
|
1952
1914
|
}
|
|
1953
1915
|
|
|
1954
1916
|
let isInitialTag =
|
|
@@ -1957,21 +1919,21 @@ export class TagPath {
|
|
|
1957
1919
|
arraysEqual(propertyIndex, this.propertyIndex);
|
|
1958
1920
|
|
|
1959
1921
|
// done
|
|
1960
|
-
if (!isInitialTag && !isNodeTag(propTag)) {
|
|
1922
|
+
if (!isInitialTag && !isNodeTag(propTag) && propTag.type !== Property) {
|
|
1961
1923
|
return TagPath.from(path, tagsIndex, propertyIndex);
|
|
1962
1924
|
}
|
|
1963
1925
|
|
|
1964
1926
|
// shift
|
|
1965
|
-
if (propTag.type === BindingTag && lastRef
|
|
1927
|
+
if (propTag.type === BindingTag && lastRef?.type === ShiftTag) {
|
|
1966
1928
|
let lastProp = Tags.getAt(tagsIndex, path.tags);
|
|
1967
1929
|
let { shift } = lastProp.value;
|
|
1968
1930
|
let refIndex = tagsIndex - shift.index;
|
|
1969
1931
|
if (refIndex < 0) throw new Error();
|
|
1970
|
-
let refTag = Tags.getAt(refIndex, path.tags, 0);
|
|
1932
|
+
let refTag = parseTag(Tags.getAt(refIndex, path.tags, 0));
|
|
1971
1933
|
|
|
1972
1934
|
if (refTag.type !== ReferenceTag) throw new Error();
|
|
1973
1935
|
|
|
1974
|
-
let { node } = tag.value;
|
|
1936
|
+
let { node } = parseTag(tag).value;
|
|
1975
1937
|
if (!node) return null;
|
|
1976
1938
|
|
|
1977
1939
|
path = new Path(path, tagsIndex);
|
|
@@ -1983,66 +1945,47 @@ export class TagPath {
|
|
|
1983
1945
|
continue;
|
|
1984
1946
|
}
|
|
1985
1947
|
|
|
1986
|
-
|
|
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
|
+
}
|
|
1987
1972
|
|
|
1988
1973
|
// over
|
|
1974
|
+
let { nextSibling } = TagPath.from(path, tagsIndex, freeze([...arrayValues(propertyIndex)]));
|
|
1975
|
+
|
|
1989
1976
|
if (nextSibling) {
|
|
1990
1977
|
({ tagsIndex, propertyIndex } = nextSibling);
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
let shiftPath = path;
|
|
1994
|
-
|
|
1995
|
-
while (
|
|
1996
|
-
shiftPath.parent &&
|
|
1997
|
-
!Tags.getAt(shiftPath.parentIndex - 1, shiftPath.parent.node.value.children).value.shift
|
|
1998
|
-
) {
|
|
1999
|
-
shiftPath = shiftPath.parent;
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
let isGap =
|
|
2003
|
-
path.parent &&
|
|
2004
|
-
tagsIndex === 1 &&
|
|
2005
|
-
shiftPath.parent &&
|
|
2006
|
-
Tags.getAt(shiftPath.parentIndex - 1, shiftPath.parent.node.value.children).value
|
|
2007
|
-
.shift &&
|
|
2008
|
-
tag.value.node ===
|
|
2009
|
-
Tags.getAt(shiftPath.parentIndex - 2, shiftPath.parent.node.value.children).value
|
|
2010
|
-
.node;
|
|
2011
|
-
|
|
2012
|
-
path = path.push(tagsIndex, isGap);
|
|
2013
|
-
tagsIndex = 0;
|
|
2014
|
-
propertyIndex = [];
|
|
2015
|
-
continue;
|
|
2016
|
-
} else {
|
|
2017
|
-
return nextSibling;
|
|
2018
|
-
}
|
|
1978
|
+
propertyIndex = [...arrayValues(propertyIndex)];
|
|
1979
|
+
continue;
|
|
2019
1980
|
}
|
|
2020
1981
|
|
|
2021
1982
|
// out
|
|
2022
1983
|
if (path.parentIndex != null && path.parent) {
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
Tags.getAt(
|
|
2027
|
-
[path.coverBoundary.parentIndex, 0],
|
|
2028
|
-
path.coverBoundary.parent.node.value.tags,
|
|
2029
|
-
)?.type === ShiftTag
|
|
2030
|
-
) {
|
|
2031
|
-
// while
|
|
2032
|
-
tagsIndex =
|
|
2033
|
-
Tags.getSize(path.parent.node.value.tags) > path.parentIndex + 1
|
|
2034
|
-
? path.parentIndex + 1
|
|
2035
|
-
: null;
|
|
2036
|
-
} else {
|
|
2037
|
-
tagsIndex = path.parentIndex + 1;
|
|
2038
|
-
}
|
|
2039
|
-
|
|
2040
|
-
propertyIndex = [];
|
|
2041
|
-
path = path.parent;
|
|
2042
|
-
leaving = true;
|
|
1984
|
+
tagsIndex = path.parentIndex;
|
|
1985
|
+
propertyIndex = [];
|
|
1986
|
+
path = path.parent;
|
|
2043
1987
|
|
|
2044
|
-
|
|
2045
|
-
} while (tagsIndex == null);
|
|
1988
|
+
if (!path) return null;
|
|
2046
1989
|
|
|
2047
1990
|
leaving = true;
|
|
2048
1991
|
continue;
|
|
@@ -2055,21 +1998,23 @@ export class TagPath {
|
|
|
2055
1998
|
get nextUnshifted() {
|
|
2056
1999
|
let { path, tagsIndex, propertyIndex } = this;
|
|
2057
2000
|
|
|
2058
|
-
propertyIndex = [...propertyIndex];
|
|
2001
|
+
propertyIndex = [...arrayValues(propertyIndex)];
|
|
2059
2002
|
|
|
2060
2003
|
let leaving = false;
|
|
2061
2004
|
|
|
2062
2005
|
for (;;) {
|
|
2063
|
-
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
2006
|
+
let tag = parseTag(Tags.getAt(tagsIndex, getTags(path.node)));
|
|
2064
2007
|
let propTag = tag;
|
|
2065
2008
|
let wasLeaving = leaving;
|
|
2066
2009
|
leaving = false;
|
|
2067
2010
|
|
|
2068
2011
|
if (!tag) return null;
|
|
2069
2012
|
|
|
2070
|
-
if (tag.type === Property) {
|
|
2013
|
+
if (isObject(tag) && tag.type === Property) {
|
|
2071
2014
|
if (propertyIndex.length === 0 && !leaving) {
|
|
2072
|
-
|
|
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 });
|
|
2073
2018
|
}
|
|
2074
2019
|
|
|
2075
2020
|
if (propertyIndex != null) {
|
|
@@ -2078,7 +2023,7 @@ export class TagPath {
|
|
|
2078
2023
|
}
|
|
2079
2024
|
|
|
2080
2025
|
if (isArray(propTag)) {
|
|
2081
|
-
if (propTag
|
|
2026
|
+
if (Tags.getSize(propTag)) {
|
|
2082
2027
|
// enter bindings array
|
|
2083
2028
|
propertyIndex.push({ index: 0, node: propTag });
|
|
2084
2029
|
propTag = propTag[propertyIndex[1].index];
|
|
@@ -2098,7 +2043,7 @@ export class TagPath {
|
|
|
2098
2043
|
tagsIndex === this.tagsIndex &&
|
|
2099
2044
|
arraysEqual(propertyIndex, this.propertyIndex);
|
|
2100
2045
|
|
|
2101
|
-
if (!wasLeaving && propTag
|
|
2046
|
+
if (!wasLeaving && parseTagType(propTag) === ReferenceTag) {
|
|
2102
2047
|
// move past shifts
|
|
2103
2048
|
|
|
2104
2049
|
let shifts = 0;
|
|
@@ -2126,6 +2071,7 @@ export class TagPath {
|
|
|
2126
2071
|
// over
|
|
2127
2072
|
if (nextSibling) {
|
|
2128
2073
|
({ tagsIndex, propertyIndex } = nextSibling);
|
|
2074
|
+
propertyIndex = [...arrayValues(propertyIndex)];
|
|
2129
2075
|
continue;
|
|
2130
2076
|
}
|
|
2131
2077
|
|
|
@@ -2160,7 +2106,7 @@ export class TagPath {
|
|
|
2160
2106
|
|
|
2161
2107
|
let tag = Tags.getAt(tagsIndex, getTags(path.node));
|
|
2162
2108
|
|
|
2163
|
-
return tag.type === Property ? path.tagPathAt(tagsIndex) : null;
|
|
2109
|
+
return isObject(tag) && tag.type === Property ? path.tagPathAt(tagsIndex) : null;
|
|
2164
2110
|
}
|
|
2165
2111
|
|
|
2166
2112
|
get innerNode() {
|
|
@@ -2168,22 +2114,22 @@ export class TagPath {
|
|
|
2168
2114
|
}
|
|
2169
2115
|
|
|
2170
2116
|
get inner() {
|
|
2171
|
-
let { tagsIndex,
|
|
2117
|
+
let { tagsIndex, type } = this;
|
|
2172
2118
|
|
|
2173
2119
|
let node;
|
|
2174
|
-
switch (
|
|
2120
|
+
switch (type) {
|
|
2175
2121
|
case Property: {
|
|
2176
|
-
({ node } = tag.value);
|
|
2122
|
+
({ node } = this.tag.value);
|
|
2177
2123
|
break;
|
|
2178
2124
|
}
|
|
2179
2125
|
case GapNode:
|
|
2180
2126
|
case NullNode:
|
|
2181
2127
|
case TreeNode: {
|
|
2182
|
-
node = tag;
|
|
2128
|
+
node = this.tag;
|
|
2183
2129
|
break;
|
|
2184
2130
|
}
|
|
2185
2131
|
default:
|
|
2186
|
-
|
|
2132
|
+
node = null;
|
|
2187
2133
|
}
|
|
2188
2134
|
return node && this.path.push(tagsIndex);
|
|
2189
2135
|
}
|
|
@@ -2197,4 +2143,4 @@ export class TagPath {
|
|
|
2197
2143
|
}
|
|
2198
2144
|
}
|
|
2199
2145
|
|
|
2200
|
-
|
|
2146
|
+
freezeClass(TagPath);
|