@bablr/agast-helpers 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/builders.js +62 -44
- package/lib/path-facade.js +18 -13
- package/lib/path.js +631 -345
- package/lib/print.js +34 -20
- package/lib/shorthand.js +1 -1
- package/lib/stream.js +37 -165
- package/lib/symbols.js +3 -1
- package/lib/tags.js +236 -0
- package/lib/template.js +11 -7
- package/lib/tree.js +224 -292
- package/package.json +6 -4
- package/lib/children.js +0 -120
package/lib/tree.js
CHANGED
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
buildChild,
|
|
14
14
|
buildShiftTag,
|
|
15
15
|
buildGapTag,
|
|
16
|
+
buildBinding,
|
|
17
|
+
buildReference,
|
|
18
|
+
multiFragmentFlags,
|
|
19
|
+
buildPropertyWrapper,
|
|
16
20
|
} from './builders.js';
|
|
17
21
|
import {
|
|
18
22
|
printPrettyCSTML as printPrettyCSTMLFromStream,
|
|
@@ -33,13 +37,17 @@ import {
|
|
|
33
37
|
BindingTag,
|
|
34
38
|
Property,
|
|
35
39
|
ShiftTag,
|
|
40
|
+
PropertyWrapper,
|
|
36
41
|
} from './symbols.js';
|
|
37
|
-
import * as
|
|
38
|
-
import * as
|
|
42
|
+
import * as BTree from './btree.js';
|
|
43
|
+
import * as Tags from './tags.js';
|
|
39
44
|
export * from './builders.js';
|
|
40
45
|
export * from './print.js';
|
|
41
46
|
import {
|
|
42
47
|
get,
|
|
48
|
+
getOr,
|
|
49
|
+
has,
|
|
50
|
+
list,
|
|
43
51
|
TagPath,
|
|
44
52
|
Path,
|
|
45
53
|
isFragmentNode,
|
|
@@ -49,12 +57,16 @@ import {
|
|
|
49
57
|
getCloseTag,
|
|
50
58
|
getRoot,
|
|
51
59
|
getRootArray,
|
|
52
|
-
|
|
60
|
+
isStubTag,
|
|
61
|
+
wrapperIsFull,
|
|
53
62
|
} from './path.js';
|
|
54
63
|
import { isPlainObject } from './object.js';
|
|
55
64
|
|
|
56
65
|
export {
|
|
57
66
|
get,
|
|
67
|
+
getOr,
|
|
68
|
+
has,
|
|
69
|
+
list,
|
|
58
70
|
isFragmentNode,
|
|
59
71
|
isNullNode,
|
|
60
72
|
isGapNode,
|
|
@@ -82,7 +94,7 @@ export const mergeReferences = (outer, inner) => {
|
|
|
82
94
|
|
|
83
95
|
if (
|
|
84
96
|
(name != null && inner.name != null && name !== inner.name) ||
|
|
85
|
-
(type != null && inner.type != null && type !== inner.type)
|
|
97
|
+
(type != null && inner.type != null && type !== inner.type && inner.type !== '.')
|
|
86
98
|
) {
|
|
87
99
|
return inner;
|
|
88
100
|
}
|
|
@@ -145,7 +157,11 @@ function* __treeFromStream(tags, options) {
|
|
|
145
157
|
|
|
146
158
|
switch (tag.type) {
|
|
147
159
|
case LiteralTag:
|
|
160
|
+
break;
|
|
161
|
+
|
|
148
162
|
case CloseNodeTag: {
|
|
163
|
+
let { node } = path;
|
|
164
|
+
if (!node.tags[1]) throw new Error();
|
|
149
165
|
break;
|
|
150
166
|
}
|
|
151
167
|
|
|
@@ -180,11 +196,12 @@ function* __treeFromStream(tags, options) {
|
|
|
180
196
|
|
|
181
197
|
let node = createNode(tag);
|
|
182
198
|
|
|
199
|
+
suppressTag = true;
|
|
200
|
+
|
|
183
201
|
if (isGap) {
|
|
184
202
|
if (held) {
|
|
185
203
|
node = held;
|
|
186
204
|
add(path.node, referenceTag, node, bindingTag);
|
|
187
|
-
suppressTag = true;
|
|
188
205
|
} else if (!expressionsCo.done) {
|
|
189
206
|
expressionsCo.advance();
|
|
190
207
|
|
|
@@ -197,7 +214,6 @@ function* __treeFromStream(tags, options) {
|
|
|
197
214
|
: expressionsCo.value == null
|
|
198
215
|
? buildStubNode(buildNullTag())
|
|
199
216
|
: expressionsCo.value;
|
|
200
|
-
suppressTag = true;
|
|
201
217
|
|
|
202
218
|
if (isFragmentNode(node)) {
|
|
203
219
|
const parentNode = path.node;
|
|
@@ -205,7 +221,7 @@ function* __treeFromStream(tags, options) {
|
|
|
205
221
|
let referenceTag;
|
|
206
222
|
let bindingTag;
|
|
207
223
|
|
|
208
|
-
for (const tag of
|
|
224
|
+
for (const tag of Tags.traverse(node.tags)) {
|
|
209
225
|
switch (tag.type) {
|
|
210
226
|
case DoctypeTag: {
|
|
211
227
|
break;
|
|
@@ -275,7 +291,7 @@ function* __treeFromStream(tags, options) {
|
|
|
275
291
|
}
|
|
276
292
|
|
|
277
293
|
// case ShiftTag: {
|
|
278
|
-
// const {
|
|
294
|
+
// const { tags, properties } = path.node;
|
|
279
295
|
|
|
280
296
|
// let property = properties[ref.value.name];
|
|
281
297
|
// let node;
|
|
@@ -293,9 +309,8 @@ function* __treeFromStream(tags, options) {
|
|
|
293
309
|
// }
|
|
294
310
|
|
|
295
311
|
case OpenNodeTag: {
|
|
312
|
+
const node = createNode(tag);
|
|
296
313
|
if (path) {
|
|
297
|
-
const node = createNode(tag);
|
|
298
|
-
|
|
299
314
|
if (path) {
|
|
300
315
|
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
301
316
|
referenceTag = null;
|
|
@@ -303,23 +318,12 @@ function* __treeFromStream(tags, options) {
|
|
|
303
318
|
|
|
304
319
|
path = { parent: path, node, depth: (path ? path.depth : -1) + 1, arrays: new Set() };
|
|
305
320
|
} else {
|
|
306
|
-
const { type, flags, attributes } = tag.value;
|
|
307
|
-
|
|
308
|
-
const attributes_ = doctype?.value.attributes ?? attributes;
|
|
309
|
-
|
|
310
|
-
const node = {
|
|
311
|
-
flags,
|
|
312
|
-
type,
|
|
313
|
-
children: [],
|
|
314
|
-
properties: {},
|
|
315
|
-
attributes: attributes_,
|
|
316
|
-
};
|
|
317
|
-
|
|
318
321
|
path = { parent: null, node, depth: 0, arrays: new Set() };
|
|
319
322
|
|
|
320
323
|
rootPath = path;
|
|
321
324
|
}
|
|
322
325
|
|
|
326
|
+
suppressTag = true;
|
|
323
327
|
break;
|
|
324
328
|
}
|
|
325
329
|
|
|
@@ -329,7 +333,7 @@ function* __treeFromStream(tags, options) {
|
|
|
329
333
|
}
|
|
330
334
|
|
|
331
335
|
if (!suppressTag) {
|
|
332
|
-
path.node.
|
|
336
|
+
path.node.tags = Tags.push(path.node.tags, tag);
|
|
333
337
|
}
|
|
334
338
|
|
|
335
339
|
switch (tag.type) {
|
|
@@ -394,34 +398,17 @@ export const evaluateReturnAsync = async (generator) => {
|
|
|
394
398
|
};
|
|
395
399
|
|
|
396
400
|
export const isEmpty = (node) => {
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
let ref = null;
|
|
400
|
-
|
|
401
|
-
for (const tag of Children.traverse(node.children)) {
|
|
401
|
+
for (const tag of Tags.traverseInner(node.tags)) {
|
|
402
402
|
switch (tag.type) {
|
|
403
|
-
case ReferenceTag: {
|
|
404
|
-
const { name } = tag.value;
|
|
405
|
-
|
|
406
|
-
ref = tag;
|
|
407
|
-
|
|
408
|
-
if (properties[name]) {
|
|
409
|
-
const property = properties[name];
|
|
410
|
-
|
|
411
|
-
if (
|
|
412
|
-
property != null ||
|
|
413
|
-
(isArray(property) && property.length) ||
|
|
414
|
-
!isNullNode(property.node)
|
|
415
|
-
) {
|
|
416
|
-
return false;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
break;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
403
|
case Property: {
|
|
423
404
|
if (tag.value.reference.type === '@') {
|
|
424
405
|
return false;
|
|
406
|
+
} else {
|
|
407
|
+
const property = tag.value;
|
|
408
|
+
|
|
409
|
+
if (!isNullNode(property.node)) {
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
425
412
|
}
|
|
426
413
|
break;
|
|
427
414
|
}
|
|
@@ -434,32 +421,47 @@ export const isEmpty = (node) => {
|
|
|
434
421
|
return true;
|
|
435
422
|
};
|
|
436
423
|
|
|
424
|
+
let buildGapProperty = () =>
|
|
425
|
+
buildProperty(buildReference('.'), buildBinding(), buildStubNode(buildGapTag()));
|
|
426
|
+
|
|
427
|
+
export const buildBounds = (
|
|
428
|
+
openBoundary = BTree.fromValues([buildGapProperty()]),
|
|
429
|
+
closeBoundary = openBoundary,
|
|
430
|
+
) => {
|
|
431
|
+
return freeze([openBoundary, closeBoundary]);
|
|
432
|
+
};
|
|
433
|
+
|
|
437
434
|
export const buildStubNode = (tag) => {
|
|
435
|
+
if (!isStubTag(tag)) throw new Error();
|
|
438
436
|
return freeze({
|
|
439
437
|
flags: nodeFlags,
|
|
440
438
|
type: null,
|
|
441
|
-
|
|
442
|
-
|
|
439
|
+
bounds: buildBounds(null, null),
|
|
440
|
+
tags: Tags.from(tag),
|
|
443
441
|
attributes: freeze({}),
|
|
444
442
|
});
|
|
445
443
|
};
|
|
446
444
|
|
|
447
|
-
export const streamFromTree = (
|
|
448
|
-
let
|
|
445
|
+
export const streamFromTree = (tree, options = {}) => {
|
|
446
|
+
let rootNode = isPlainObject(tree) ? tree : tree.node;
|
|
449
447
|
|
|
450
|
-
return __streamFromTree(
|
|
448
|
+
return __streamFromTree(null, rootNode, options);
|
|
451
449
|
};
|
|
452
450
|
|
|
453
|
-
function* __streamFromTree(rootNode, options) {
|
|
451
|
+
function* __streamFromTree(doctypeTag, rootNode, options) {
|
|
454
452
|
const { unshift = false } = options;
|
|
455
|
-
if (!rootNode || !
|
|
453
|
+
if (!rootNode || !Tags.getSize(rootNode.tags)) return;
|
|
456
454
|
|
|
457
455
|
let tagPath = TagPath.fromNode(rootNode, 0);
|
|
458
456
|
|
|
459
457
|
let count = 0;
|
|
460
458
|
|
|
459
|
+
if (doctypeTag) {
|
|
460
|
+
yield doctypeTag;
|
|
461
|
+
}
|
|
462
|
+
|
|
461
463
|
do {
|
|
462
|
-
if (tagPath.tag.type === OpenNodeTag) count++;
|
|
464
|
+
if (tagPath.tag.type === OpenNodeTag && !tagPath.tag.value.literalValue) count++;
|
|
463
465
|
if (tagPath.tag.type === CloseNodeTag) count--;
|
|
464
466
|
|
|
465
467
|
if (
|
|
@@ -475,12 +477,107 @@ function* __streamFromTree(rootNode, options) {
|
|
|
475
477
|
if (count !== 0) throw new Error();
|
|
476
478
|
}
|
|
477
479
|
|
|
480
|
+
export const vcsStreamFromTree = (rootNode) => {
|
|
481
|
+
let rootNode_ = isPlainObject(rootNode) ? rootNode : rootNode.node;
|
|
482
|
+
|
|
483
|
+
return __vcsStreamFromTree(rootNode_);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
function* __vcsStreamFromTree(rootNode) {
|
|
487
|
+
let stack = null;
|
|
488
|
+
let agastNode = rootNode;
|
|
489
|
+
let depth = 0;
|
|
490
|
+
let nodeShifted = false;
|
|
491
|
+
let i = 0;
|
|
492
|
+
let seenFirstProperty = false;
|
|
493
|
+
let node = Tags.getValues(rootNode.tags);
|
|
494
|
+
|
|
495
|
+
outer: while (node) {
|
|
496
|
+
while (i >= node.length) {
|
|
497
|
+
if (stack) {
|
|
498
|
+
let oldAgastNode = agastNode;
|
|
499
|
+
let hadSeenFirst = seenFirstProperty;
|
|
500
|
+
({ stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty } = stack);
|
|
501
|
+
if (oldAgastNode === agastNode) {
|
|
502
|
+
seenFirstProperty = hadSeenFirst;
|
|
503
|
+
yield buildCloseNodeTag();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
i++;
|
|
507
|
+
} else {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
let child = node[i];
|
|
513
|
+
|
|
514
|
+
if (isArray(child)) {
|
|
515
|
+
stack = { stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty };
|
|
516
|
+
|
|
517
|
+
yield buildOpenNodeTag(multiFragmentFlags);
|
|
518
|
+
|
|
519
|
+
node = Tags.getValues(child);
|
|
520
|
+
depth++;
|
|
521
|
+
i = 0;
|
|
522
|
+
} else {
|
|
523
|
+
let wrappedTag = child;
|
|
524
|
+
|
|
525
|
+
if (wrappedTag.type === PropertyWrapper) {
|
|
526
|
+
for (let tag of wrappedTag.value.tags) {
|
|
527
|
+
switch (tag.type) {
|
|
528
|
+
case Property: {
|
|
529
|
+
let replaceWithGap = nodeShifted && !seenFirstProperty;
|
|
530
|
+
|
|
531
|
+
if (replaceWithGap) {
|
|
532
|
+
yield buildGapTag();
|
|
533
|
+
|
|
534
|
+
seenFirstProperty = true;
|
|
535
|
+
|
|
536
|
+
break;
|
|
537
|
+
} else {
|
|
538
|
+
stack = { stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty: true };
|
|
539
|
+
node = Tags.getValues(tag.value.node.tags);
|
|
540
|
+
|
|
541
|
+
depth++;
|
|
542
|
+
i = 0;
|
|
543
|
+
agastNode = tag.value.node;
|
|
544
|
+
nodeShifted = wrappedTag.value.tags[0].type === ShiftTag;
|
|
545
|
+
seenFirstProperty = false;
|
|
546
|
+
continue outer;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
default: {
|
|
551
|
+
yield tag;
|
|
552
|
+
|
|
553
|
+
if (tag.type === OpenNodeTag && tag.value.literalValue) {
|
|
554
|
+
({ stack, agastNode, node, depth, i, nodeShifted } = stack);
|
|
555
|
+
seenFirstProperty = true;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
} else {
|
|
563
|
+
yield wrappedTag;
|
|
564
|
+
|
|
565
|
+
if (wrappedTag.type === OpenNodeTag && wrappedTag.value.literalValue) {
|
|
566
|
+
({ stack, agastNode, node, depth, i, nodeShifted } = stack);
|
|
567
|
+
seenFirstProperty = true;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
i++;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
478
575
|
export const getCooked = (cookable) => {
|
|
479
576
|
if (!cookable || isGapNode(cookable.type)) {
|
|
480
577
|
return '';
|
|
481
578
|
}
|
|
482
579
|
|
|
483
|
-
const
|
|
580
|
+
const tags = cookable.tags || cookable;
|
|
484
581
|
|
|
485
582
|
let cooked = '';
|
|
486
583
|
|
|
@@ -489,7 +586,7 @@ export const getCooked = (cookable) => {
|
|
|
489
586
|
|
|
490
587
|
let referenceTag = null;
|
|
491
588
|
|
|
492
|
-
for (let tag of
|
|
589
|
+
for (let tag of Tags.traverse(tags)) {
|
|
493
590
|
switch (tag.type) {
|
|
494
591
|
case ReferenceTag: {
|
|
495
592
|
let { type } = tag.value;
|
|
@@ -505,8 +602,8 @@ export const getCooked = (cookable) => {
|
|
|
505
602
|
case BindingTag:
|
|
506
603
|
break;
|
|
507
604
|
|
|
508
|
-
case
|
|
509
|
-
let { node, reference } = tag.value;
|
|
605
|
+
case PropertyWrapper: {
|
|
606
|
+
let { node, reference } = tag.value.property;
|
|
510
607
|
let { attributes } = node;
|
|
511
608
|
|
|
512
609
|
if (reference.type === '@') {
|
|
@@ -543,50 +640,44 @@ export const getCooked = (cookable) => {
|
|
|
543
640
|
return cooked;
|
|
544
641
|
};
|
|
545
642
|
|
|
546
|
-
export const printCSTML = (
|
|
547
|
-
return printCSTMLFromStream(streamFromTree(
|
|
643
|
+
export const printCSTML = (tree) => {
|
|
644
|
+
return printCSTMLFromStream(streamFromTree(tree));
|
|
548
645
|
};
|
|
549
646
|
|
|
550
|
-
export const printPrettyCSTML = (
|
|
551
|
-
return printPrettyCSTMLFromStream(streamFromTree(
|
|
647
|
+
export const printPrettyCSTML = (tree, options = {}) => {
|
|
648
|
+
return printPrettyCSTMLFromStream(streamFromTree(tree), options);
|
|
552
649
|
};
|
|
553
650
|
|
|
554
|
-
export const printSource = (
|
|
555
|
-
return printSourceFromStream(streamFromTree(
|
|
651
|
+
export const printSource = (tree) => {
|
|
652
|
+
return printSourceFromStream(streamFromTree(tree, { unshift: true }));
|
|
556
653
|
};
|
|
557
654
|
|
|
558
655
|
export const sourceTextFor = printSource;
|
|
559
656
|
|
|
560
657
|
export const getRange = (node) => {
|
|
561
|
-
const {
|
|
658
|
+
const { tags } = node;
|
|
562
659
|
let path = Path.from(node);
|
|
563
|
-
return
|
|
660
|
+
return Tags.getSize(tags) ? [TagPath.from(path, 0), TagPath.from(path, -1)] : null;
|
|
564
661
|
};
|
|
565
662
|
|
|
566
663
|
export const createNode = (openTag) => {
|
|
664
|
+
let bounds = buildBounds();
|
|
665
|
+
let literalTags = [];
|
|
666
|
+
let tags = openTag ? Tags.fromValues([openTag, ...literalTags]) : Tags.fromValues(literalTags);
|
|
667
|
+
let flags, type, attributes;
|
|
668
|
+
|
|
567
669
|
if (!openTag || openTag.type === GapTag || openTag.type === NullTag) {
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
children: [],
|
|
572
|
-
properties: {},
|
|
573
|
-
attributes: openTag?.attributes || {},
|
|
574
|
-
};
|
|
670
|
+
flags = nodeFlags;
|
|
671
|
+
type = openTag && ([NullTag, GapTag].includes(openTag.type) ? null : openTag.type);
|
|
672
|
+
attributes = openTag?.attributes || {};
|
|
575
673
|
} else {
|
|
576
|
-
|
|
577
|
-
return {
|
|
578
|
-
flags,
|
|
579
|
-
type,
|
|
580
|
-
children: [],
|
|
581
|
-
properties: {},
|
|
582
|
-
attributes,
|
|
583
|
-
};
|
|
674
|
+
({ flags, type, attributes = {} } = openTag.value || {});
|
|
584
675
|
}
|
|
676
|
+
return { flags, type, bounds, tags, attributes };
|
|
585
677
|
};
|
|
586
678
|
|
|
587
679
|
export const finalizeNode = (node) => {
|
|
588
680
|
freeze(node);
|
|
589
|
-
freeze(node.properties);
|
|
590
681
|
freeze(node.attributes);
|
|
591
682
|
return node;
|
|
592
683
|
};
|
|
@@ -599,145 +690,17 @@ export const isNull = (node) => {
|
|
|
599
690
|
return node == null || isNullNode(node);
|
|
600
691
|
};
|
|
601
692
|
|
|
602
|
-
export const branchProperties = (properties) => {
|
|
603
|
-
const copy = { ...properties };
|
|
604
|
-
|
|
605
|
-
for (const { 0: key, 1: value } of Object.entries(copy)) {
|
|
606
|
-
if (isArray(value)) {
|
|
607
|
-
copy[key] = btree.fromValues(value);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
return copy;
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
export const branchNode = (node) => {
|
|
615
|
-
const { flags, type, children, properties, attributes } = node;
|
|
616
|
-
return {
|
|
617
|
-
flags,
|
|
618
|
-
type,
|
|
619
|
-
children,
|
|
620
|
-
properties: branchProperties(properties),
|
|
621
|
-
attributes: { ...attributes },
|
|
622
|
-
};
|
|
623
|
-
};
|
|
624
|
-
|
|
625
|
-
export const acceptNode = (node, accepted) => {
|
|
626
|
-
const { children, properties, attributes } = accepted;
|
|
627
|
-
node.children = children;
|
|
628
|
-
node.properties = properties;
|
|
629
|
-
node.attributes = attributes;
|
|
630
|
-
return node;
|
|
631
|
-
};
|
|
632
|
-
|
|
633
|
-
export function* traverseProperties(properties) {
|
|
634
|
-
for (const value of Object.values(properties)) {
|
|
635
|
-
if (isArray(value)) {
|
|
636
|
-
for (let item of btree.traverse(value)) {
|
|
637
|
-
if (isArray(item.node)) {
|
|
638
|
-
yield btree.getAt(-1, item.node);
|
|
639
|
-
} else {
|
|
640
|
-
yield item.node;
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
} else {
|
|
644
|
-
yield value.node;
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
export const addToProperties = (properties, property) => {
|
|
650
|
-
let { reference, node: value } = property;
|
|
651
|
-
let { flags, name, isArray } = reference;
|
|
652
|
-
|
|
653
|
-
if (!name) throw new Error();
|
|
654
|
-
if (value === null) throw new Error();
|
|
655
|
-
if (!hasOwn(property, 'binding')) throw new Error();
|
|
656
|
-
|
|
657
|
-
if (Object.isFrozen(properties)) {
|
|
658
|
-
throw new Error('not implemented');
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
let isInitializer = value === undefined || Array.isArray(value);
|
|
662
|
-
|
|
663
|
-
let outerProperty = property;
|
|
664
|
-
|
|
665
|
-
if (flags.expression && !isInitializer) {
|
|
666
|
-
let shiftStack =
|
|
667
|
-
getFirstNodeShiftStack(value) ||
|
|
668
|
-
btree.fromValues([buildProperty(reference, null, buildStubNode(buildGapTag()))]);
|
|
669
|
-
|
|
670
|
-
shiftStack = btree.push(shiftStack, property);
|
|
671
|
-
outerProperty = buildProperty(reference, null, shiftStack);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
if (isArray && !isInitializer) {
|
|
675
|
-
properties[name] = buildProperty(
|
|
676
|
-
reference,
|
|
677
|
-
null,
|
|
678
|
-
btree.push(properties[name]?.node || btree.fromValues([]), outerProperty),
|
|
679
|
-
);
|
|
680
|
-
} else {
|
|
681
|
-
properties[name] = outerProperty;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
return properties;
|
|
685
|
-
};
|
|
686
|
-
|
|
687
|
-
export const shiftToProperties = (properties, property) => {
|
|
688
|
-
let { reference, node: value } = property;
|
|
689
|
-
let { flags, name, isArray } = reference;
|
|
690
|
-
|
|
691
|
-
if (!name) throw new Error();
|
|
692
|
-
|
|
693
|
-
if (Object.isFrozen(properties)) {
|
|
694
|
-
throw new Error('not implemented');
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
if (!flags.expression) {
|
|
698
|
-
return addToProperties(properties, property);
|
|
699
|
-
}
|
|
700
|
-
let isInitializer = value === undefined || Array.isArray(value);
|
|
701
|
-
|
|
702
|
-
let outerProperty;
|
|
703
|
-
if (flags.expression && !isInitializer) {
|
|
704
|
-
let shiftStack =
|
|
705
|
-
getFirstNodeShiftStack(value) ||
|
|
706
|
-
btree.fromValues([buildProperty(reference, null, buildStubNode(buildGapTag()))]);
|
|
707
|
-
|
|
708
|
-
shiftStack = btree.push(shiftStack, property);
|
|
709
|
-
outerProperty = buildProperty(reference, null, shiftStack);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (isArray) {
|
|
713
|
-
properties[name] = buildProperty(
|
|
714
|
-
reference,
|
|
715
|
-
null,
|
|
716
|
-
btree.replaceAt(-1, properties[name].node, outerProperty),
|
|
717
|
-
);
|
|
718
|
-
} else {
|
|
719
|
-
properties[name] = outerProperty;
|
|
720
|
-
}
|
|
721
|
-
return properties;
|
|
722
|
-
};
|
|
723
|
-
|
|
724
693
|
export const addProperty = (node, property) => {
|
|
725
694
|
if (!node || !property) throw new Error();
|
|
726
695
|
if (!Object.isFrozen(property)) throw new Error();
|
|
727
696
|
|
|
728
|
-
let back1 = Children.getAt(-1, node.children);
|
|
729
|
-
let back2 = Children.getAt(-2, node.children);
|
|
730
|
-
|
|
731
|
-
let referenceTag;
|
|
732
|
-
let bindingTag = null;
|
|
733
|
-
|
|
734
697
|
if (property.node === null) {
|
|
735
698
|
throw new Error();
|
|
736
699
|
}
|
|
737
700
|
|
|
738
|
-
let { node: value } = property;
|
|
701
|
+
let { node: value, binding, reference } = property;
|
|
739
702
|
|
|
740
|
-
let isArrayInitializer = isArray(value);
|
|
703
|
+
let isArrayInitializer = reference.type !== '_' && isArray(value);
|
|
741
704
|
let isInitializer = value === undefined || isArrayInitializer;
|
|
742
705
|
|
|
743
706
|
if (isArrayInitializer && value.length) throw new Error();
|
|
@@ -746,47 +709,39 @@ export const addProperty = (node, property) => {
|
|
|
746
709
|
throw new Error();
|
|
747
710
|
}
|
|
748
711
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
bindingTag = property.binding && back1;
|
|
753
|
-
referenceTag = back2;
|
|
754
|
-
foundShift = foundBinding = true;
|
|
755
|
-
} else if (back1.type === ReferenceTag) {
|
|
756
|
-
bindingTag = property.binding && buildChild(BindingTag, property.binding);
|
|
757
|
-
referenceTag = back1;
|
|
758
|
-
foundShift = true;
|
|
759
|
-
} else {
|
|
760
|
-
bindingTag = property.binding && buildChild(BindingTag, property.binding);
|
|
761
|
-
referenceTag = buildChild(ReferenceTag, property.reference);
|
|
712
|
+
if (reference.type === '_') {
|
|
713
|
+
node.tags = Tags.push(node.tags, value);
|
|
714
|
+
return node;
|
|
762
715
|
}
|
|
763
716
|
|
|
764
|
-
|
|
717
|
+
let referenceTag = buildChild(ReferenceTag, reference);
|
|
718
|
+
let propertyWrapper;
|
|
765
719
|
|
|
766
720
|
if (isInitializer) {
|
|
767
|
-
|
|
768
|
-
addToProperties(node.properties, property);
|
|
769
|
-
}
|
|
721
|
+
let tags = freeze([referenceTag, buildInitializerTag(isArrayInitializer)]);
|
|
770
722
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
723
|
+
propertyWrapper = buildPropertyWrapper(
|
|
724
|
+
tags,
|
|
725
|
+
buildProperty(reference, null, isArrayInitializer ? [] : null),
|
|
726
|
+
);
|
|
727
|
+
} else {
|
|
728
|
+
let tags = freeze([
|
|
729
|
+
referenceTag,
|
|
730
|
+
buildChild(BindingTag, binding),
|
|
731
|
+
buildChild(Property, property),
|
|
732
|
+
]);
|
|
775
733
|
|
|
776
|
-
|
|
734
|
+
propertyWrapper = buildPropertyWrapper(tags, property);
|
|
777
735
|
}
|
|
778
736
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
}
|
|
737
|
+
let lastTag = Tags.getAt(-1, node.tags);
|
|
738
|
+
let unboundProperty = lastTag.type === PropertyWrapper && lastTag.value.tags.length < 3;
|
|
782
739
|
|
|
783
|
-
if (
|
|
784
|
-
node.
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
node.children = Children.push(node.children, bindingTag);
|
|
740
|
+
if (unboundProperty) {
|
|
741
|
+
node.tags = Tags.replaceAt(-1, node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
742
|
+
} else {
|
|
743
|
+
node.tags = Tags.push(node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
788
744
|
}
|
|
789
|
-
node.children = Children.push(node.children, buildChild(Property, property));
|
|
790
745
|
|
|
791
746
|
return node;
|
|
792
747
|
};
|
|
@@ -796,12 +751,6 @@ export const shiftProperty = (node, property) => {
|
|
|
796
751
|
if (!property.reference) throw new Error();
|
|
797
752
|
if (!Object.isFrozen(property)) throw new Error();
|
|
798
753
|
|
|
799
|
-
let back1 = Children.getAt(-1, node.children);
|
|
800
|
-
let back2 = Children.getAt(-2, node.children);
|
|
801
|
-
|
|
802
|
-
let shiftTag;
|
|
803
|
-
let bindingTag = null;
|
|
804
|
-
|
|
805
754
|
if (property.node === null) {
|
|
806
755
|
property.node = buildNullNode();
|
|
807
756
|
}
|
|
@@ -811,79 +760,62 @@ export const shiftProperty = (node, property) => {
|
|
|
811
760
|
let isArrayInitializer = isArray(value);
|
|
812
761
|
let isInitializer = value === undefined || isArrayInitializer;
|
|
813
762
|
|
|
814
|
-
if (
|
|
763
|
+
if (isInitializer || !property.binding) {
|
|
815
764
|
throw new Error();
|
|
816
765
|
}
|
|
817
766
|
|
|
818
|
-
let
|
|
819
|
-
|
|
820
|
-
if (
|
|
821
|
-
|
|
822
|
-
shiftTag = back2;
|
|
823
|
-
foundShift = foundBinding = true;
|
|
824
|
-
|
|
825
|
-
if (bindingTag.value !== property.binding) throw new Error();
|
|
826
|
-
} else if ([ShiftTag, ReferenceTag].includes(back1.type)) {
|
|
827
|
-
bindingTag = buildChild(BindingTag, property.binding);
|
|
828
|
-
shiftTag = back1;
|
|
829
|
-
foundShift = true;
|
|
830
|
-
} else {
|
|
831
|
-
bindingTag = buildChild(BindingTag, property.binding);
|
|
832
|
-
shiftTag = buildChild(ReferenceTag, property.reference);
|
|
767
|
+
let existingProperty = Tags.getAt(-1, node.tags);
|
|
768
|
+
|
|
769
|
+
if (!wrapperIsFull(existingProperty)) {
|
|
770
|
+
existingProperty = Tags.getAt(-2, node.tags);
|
|
833
771
|
}
|
|
834
772
|
|
|
835
|
-
|
|
773
|
+
let existingRef = existingProperty?.value.tags[0];
|
|
836
774
|
|
|
837
|
-
|
|
838
|
-
shiftToProperties(node.properties, property);
|
|
775
|
+
let bindingTag = buildChild(BindingTag, property.binding);
|
|
839
776
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
}
|
|
843
|
-
node.children = Children.push(node.children, buildInitializerTag(isArrayInitializer));
|
|
777
|
+
let shiftStack = existingProperty?.value.property.node.bounds[0] || BTree.fromValues([]);
|
|
778
|
+
let stackSize = shiftStack && property.reference.flags.expression ? BTree.getSize(shiftStack) : 0;
|
|
844
779
|
|
|
845
|
-
|
|
846
|
-
|
|
780
|
+
let index = existingRef.type === ReferenceTag ? 1 : existingRef.value.index + 1;
|
|
781
|
+
let height = BTree.getSize(shiftStack) + 1;
|
|
847
782
|
|
|
848
|
-
let
|
|
849
|
-
let stackSize = shiftStack && property.reference.flags.expression ? btree.getSize(shiftStack) : 0;
|
|
783
|
+
let shiftTag = stackSize ? buildShiftTag(index, height) : existingRef;
|
|
850
784
|
|
|
851
|
-
|
|
785
|
+
let tags = freeze([shiftTag, bindingTag, buildChild(Property, property)]);
|
|
852
786
|
|
|
853
|
-
let
|
|
854
|
-
let
|
|
787
|
+
let lastTag = Tags.getAt(-1, node.tags);
|
|
788
|
+
let unboundProperty = lastTag.type === PropertyWrapper && lastTag.value.tags.length < 3;
|
|
855
789
|
|
|
856
|
-
let
|
|
790
|
+
let propertyWrapper = buildPropertyWrapper(tags, property);
|
|
857
791
|
|
|
858
|
-
if (
|
|
859
|
-
node.
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
node.children = Children.push(node.children, bindingTag);
|
|
792
|
+
if (unboundProperty) {
|
|
793
|
+
node.tags = Tags.replaceAt(-1, node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
794
|
+
} else {
|
|
795
|
+
node.tags = Tags.push(node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
863
796
|
}
|
|
864
|
-
node.children = Children.push(node.children, buildChild(Property, property));
|
|
865
797
|
|
|
866
798
|
return node;
|
|
867
799
|
};
|
|
868
800
|
|
|
869
801
|
export const add = (node, referenceTag, value, bindingTag) => {
|
|
870
|
-
let lastChild =
|
|
802
|
+
let lastChild = Tags.getAt(-1, node.tags);
|
|
871
803
|
let reference = referenceTag.value;
|
|
872
804
|
let binding = bindingTag
|
|
873
805
|
? bindingTag.value
|
|
874
|
-
: lastChild
|
|
806
|
+
: lastChild?.type === BindingTag
|
|
875
807
|
? lastChild.value
|
|
876
|
-
:
|
|
808
|
+
: buildBinding();
|
|
877
809
|
return addProperty(node, buildProperty(reference, binding, value));
|
|
878
810
|
};
|
|
879
811
|
|
|
880
812
|
export const shift = (node, referenceTag, value, bindingTag) => {
|
|
881
|
-
let lastChild =
|
|
813
|
+
let lastChild = Tags.getAt(-1, node.tags);
|
|
882
814
|
let reference = referenceTag.value;
|
|
883
815
|
let binding = bindingTag
|
|
884
816
|
? bindingTag.value
|
|
885
817
|
: lastChild.type === BindingTag
|
|
886
818
|
? lastChild.value
|
|
887
|
-
:
|
|
819
|
+
: buildBinding();
|
|
888
820
|
return shiftProperty(node, buildProperty(reference, binding, value));
|
|
889
821
|
};
|