@bablr/agast-helpers 0.6.1 → 0.7.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/tree.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Coroutine } from '@bablr/coroutine';
2
- import emptyStack from '@iter-tools/imm-stack';
3
2
  import {
4
3
  nodeFlags,
5
4
  buildReferenceTag,
@@ -20,14 +19,14 @@ import {
20
19
  OpenNodeTag,
21
20
  CloseNodeTag,
22
21
  ReferenceTag,
23
- ShiftTag,
24
22
  GapTag,
25
23
  NullTag,
26
- ArrayInitializerTag,
24
+ InitializerTag,
27
25
  LiteralTag,
28
26
  EmbeddedNode,
29
27
  } from './symbols.js';
30
28
  import * as btree from './btree.js';
29
+ import * as sumtree from './sumtree.js';
31
30
  export * from './builders.js';
32
31
  export * from './print.js';
33
32
  import {
@@ -40,6 +39,7 @@ import {
40
39
  isGapNode,
41
40
  getOpenTag,
42
41
  getCloseTag,
42
+ getShifted,
43
43
  } from './path.js';
44
44
 
45
45
  export { add, get, isFragmentNode, isNullNode, isGapNode, getOpenTag, getCloseTag };
@@ -92,8 +92,9 @@ export const mergeReferences = (outer, inner) => {
92
92
  inner.value.name != null &&
93
93
  inner.value.name !== '.' &&
94
94
  name !== inner.value.name
95
- )
96
- throw new Error();
95
+ ) {
96
+ return inner;
97
+ }
97
98
 
98
99
  isArray = isArray || inner.value.isArray;
99
100
  expression = !!(expression || inner.value.flags.expression);
@@ -108,6 +109,20 @@ export const isEmptyReference = (ref) => {
108
109
  return name === '.' && !isArray && !(flags.expression || flags.hasGap);
109
110
  };
110
111
 
112
+ export const defineAttribute = (node, key, value) => {
113
+ const openTag = getOpenTag(node);
114
+
115
+ if (value != null) {
116
+ const { flags, language, type } = openTag.value;
117
+ const attributes = { ...openTag.value.attributes, [key]: value };
118
+ const newOpenTag = buildOpenNodeTag(flags, language, type, attributes);
119
+
120
+ node.attributes = attributes;
121
+
122
+ node.children = sumtree.replaceAt(0, node.children, newOpenTag);
123
+ }
124
+ };
125
+
111
126
  function* __treeFromStream(tags, options) {
112
127
  let path = null;
113
128
  let rootPath = null;
@@ -155,7 +170,7 @@ function* __treeFromStream(tags, options) {
155
170
  break;
156
171
  }
157
172
 
158
- case ArrayInitializerTag: {
173
+ case InitializerTag: {
159
174
  add(path.node, reference, []);
160
175
  suppressTag = true;
161
176
  reference = null;
@@ -198,7 +213,7 @@ function* __treeFromStream(tags, options) {
198
213
 
199
214
  let reference;
200
215
 
201
- for (const tag of btree.traverse(node.children)) {
216
+ for (const tag of sumtree.traverse(node.children)) {
202
217
  switch (tag.type) {
203
218
  case DoctypeTag: {
204
219
  break;
@@ -218,7 +233,7 @@ function* __treeFromStream(tags, options) {
218
233
  reference = tag;
219
234
  break;
220
235
 
221
- case ArrayInitializerTag: {
236
+ case InitializerTag: {
222
237
  add(parentNode, mergeReferences(outerReference, reference), []);
223
238
  break;
224
239
  }
@@ -229,7 +244,7 @@ function* __treeFromStream(tags, options) {
229
244
  }
230
245
 
231
246
  case GapTag: {
232
- const resolvedNode = get(reference, node);
247
+ const resolvedNode = getShifted(shift, reference, node);
233
248
  add(parentNode, mergeReferences(outerReference, reference), resolvedNode);
234
249
  break;
235
250
  }
@@ -324,7 +339,7 @@ function* __treeFromStream(tags, options) {
324
339
  }
325
340
 
326
341
  if (!suppressTag) {
327
- path.node.children = btree.push(path.node.children, tag);
342
+ path.node.children = sumtree.push(path.node.children, tag);
328
343
  }
329
344
 
330
345
  switch (tag.type) {
@@ -395,7 +410,7 @@ export const isEmpty = (node) => {
395
410
 
396
411
  let ref = null;
397
412
 
398
- for (const tag of btree.traverse(node.children)) {
413
+ for (const tag of sumtree.traverse(node.children)) {
399
414
  switch (tag.type) {
400
415
  case ReferenceTag: {
401
416
  const { name } = tag.value;
@@ -444,9 +459,9 @@ export const buildStubNode = (tag) => {
444
459
 
445
460
  function* __streamFromTree(rootNode, options) {
446
461
  const { unshift = false } = options;
447
- if (!rootNode || !btree.getSum(rootNode.children)) return;
462
+ if (!rootNode || !sumtree.getSize(rootNode.children)) return;
448
463
 
449
- let tagPath = TagPath.from(Path.from(rootNode), 0);
464
+ let tagPath = TagPath.fromNode(rootNode, 0);
450
465
 
451
466
  let count = 0;
452
467
 
@@ -474,7 +489,7 @@ export const getCooked = (cookable) => {
474
489
 
475
490
  let reference = null;
476
491
 
477
- for (const tag of btree.traverse(children)) {
492
+ for (const tag of sumtree.traverse(children)) {
478
493
  switch (tag.type) {
479
494
  case ReferenceTag: {
480
495
  const { name } = tag.value;
@@ -540,7 +555,8 @@ export const sourceTextFor = printSource;
540
555
 
541
556
  export const getRange = (node) => {
542
557
  const { children } = node;
543
- return btree.getSum(children) ? [btree.getAt(0, children), btree.getAt(-1, children)] : null;
558
+ let path = Path.from(node);
559
+ return sumtree.getSize(children) ? [TagPath.from(path, 0), TagPath.from(path, -1)] : null;
544
560
  };
545
561
 
546
562
  export const createNode = (openTag) => {
@@ -560,26 +576,7 @@ export const createNode = (openTag) => {
560
576
  };
561
577
 
562
578
  export const finalizeNode = (node) => {
563
- for (const property of Object.values(node.properties)) {
564
- if (isArray(property)) {
565
- btree.freeze(property);
566
- for (const childProperty of btree.traverse(property)) {
567
- freeze(childProperty);
568
- if (childProperty.reference.value.flags.expression) {
569
- btree.freeze(childProperty.node);
570
- }
571
- }
572
- } else {
573
- freeze(property);
574
-
575
- if (property.reference.value.flags.expression) {
576
- btree.freeze(property.node);
577
- }
578
- }
579
- }
580
-
581
579
  freeze(node);
582
- btree.freeze(node.children);
583
580
  freeze(node.properties);
584
581
  freeze(node.attributes);
585
582
  return node;
@@ -598,7 +595,7 @@ export const branchProperties = (properties) => {
598
595
 
599
596
  for (const { 0: key, 1: value } of Object.entries(copy)) {
600
597
  if (isArray(value)) {
601
- copy[key] = btree.fromValues(value);
598
+ copy[key] = btree.treeFromValues(value);
602
599
  }
603
600
  }
604
601
 
@@ -611,8 +608,7 @@ export const branchNode = (node) => {
611
608
  flags,
612
609
  language,
613
610
  type,
614
- // if we always use immutable trees we won't need to do this
615
- children: btree.fromValues(btree.traverse(children)),
611
+ children,
616
612
  properties: branchProperties(properties),
617
613
  attributes: { ...attributes },
618
614
  };
@@ -645,208 +641,3 @@ export function* traverseProperties(properties) {
645
641
  }
646
642
  }
647
643
  }
648
-
649
- export class Resolver {
650
- constructor(
651
- states = emptyStack.push({ properties: new Map(), idx: 0 }),
652
- reference = null,
653
- popped = false,
654
- held = null,
655
- ) {
656
- this.states = states;
657
- this.reference = reference;
658
- this.popped = popped;
659
- this.held = held;
660
- this.doctype = null;
661
- }
662
-
663
- get idx() {
664
- return this.states.value.idx;
665
- }
666
-
667
- get properties() {
668
- return this.states.value.properties;
669
- }
670
-
671
- advance(tag) {
672
- const { states } = this;
673
-
674
- ++states.value.idx;
675
-
676
- this.popped = false;
677
-
678
- let hadReference = this.reference;
679
-
680
- switch (tag.type) {
681
- case ReferenceTag: {
682
- const { name, isArray } = tag.value;
683
- const { properties } = states.value;
684
-
685
- if (this.reference) throw new Error();
686
-
687
- this.reference = tag;
688
-
689
- if (name && name !== '#' && name !== '@') {
690
- let state = properties.get(name);
691
-
692
- if (isArray) {
693
- if (state && !state.isArray) throw new Error();
694
-
695
- const { count = -1 } = state || {};
696
-
697
- state = { count: count + 1, isArray };
698
- } else if (state) {
699
- throw new Error(`attempted to consume property {name: ${name}} twice`);
700
- } else {
701
- state = { count: 1, isArray: false };
702
- }
703
-
704
- properties.set(name, state);
705
- }
706
-
707
- break;
708
- }
709
-
710
- case EmbeddedNode: {
711
- if (!this.reference || !['#', '@'].includes(this.reference.value.name)) throw new Error();
712
-
713
- // this.states = states.push({ properties: new Map(), idx: 0 });
714
- break;
715
- }
716
-
717
- case OpenNodeTag: {
718
- const { reference } = this;
719
- const { flags } = tag.value;
720
- const isRootNode = states.size === 1;
721
-
722
- if (tag.value.type) {
723
- this.states = states.push({ properties: new Map(), idx: 0 });
724
- }
725
-
726
- if (!tag.value.type && (!isRootNode || this.reference)) throw new Error();
727
-
728
- if (
729
- tag.type === OpenNodeTag &&
730
- ((!reference && !isRootNode) ||
731
- (reference &&
732
- reference.type !== ReferenceTag &&
733
- reference.type !== ShiftTag &&
734
- reference.type !== OpenNodeTag))
735
- ) {
736
- throw new Error('Invalid location for OpenNodeTag');
737
- }
738
-
739
- if (!isRootNode && !reference) {
740
- throw new Error();
741
- }
742
-
743
- this.reference = null;
744
- break;
745
- }
746
-
747
- case ArrayInitializerTag: {
748
- if (!this.reference) throw new Error();
749
-
750
- const { name } = this.reference.value;
751
- const { properties } = states.value;
752
- const state = properties.get(name);
753
-
754
- if (!state || !state.isArray || state.count !== 0) throw new Error();
755
-
756
- properties.set(name, { count: 0, isArray: true });
757
-
758
- this.reference = null;
759
- break;
760
- }
761
-
762
- case ShiftTag: {
763
- this.held = this.states.value;
764
- this.states = this.states.push({ properties: new Map(), idx: 0 });
765
- this.reference = tag;
766
-
767
- break;
768
- }
769
-
770
- case NullTag: {
771
- if (!this.reference) throw new Error();
772
-
773
- this.popped = true;
774
- this.reference = null;
775
- break;
776
- }
777
-
778
- case GapTag: {
779
- // if (!this.reference) throw new Error();
780
-
781
- if (this.held) {
782
- // this.states = this.states.push(this.held);
783
- this.held = null;
784
- }
785
-
786
- this.popped = true;
787
- this.reference = null;
788
- break;
789
- }
790
-
791
- case CloseNodeTag: {
792
- if (this.reference) throw new Error();
793
-
794
- this.states = states.pop();
795
- this.popped = true;
796
- break;
797
- }
798
-
799
- case DoctypeTag:
800
- this.doctype = tag;
801
- break;
802
-
803
- case LiteralTag:
804
- break;
805
-
806
- default:
807
- throw new Error();
808
- }
809
-
810
- if (hadReference && this.reference) throw new Error();
811
-
812
- return this;
813
- }
814
-
815
- resolve(reference) {
816
- let { name, isArray, flags } = reference.value;
817
- const { states } = this;
818
- const state = states.value.properties.get(name);
819
- let index = null;
820
-
821
- if (name === '@' || name === '#') return reference;
822
-
823
- if (isArray && state) {
824
- index = state?.count || 0;
825
- }
826
-
827
- return buildReferenceTag(name, isArray, flags, index);
828
- }
829
-
830
- branch() {
831
- const { states, reference, popped, held } = this;
832
- const { properties, idx } = states.value;
833
-
834
- return new Resolver(
835
- states.replace({ properties: new Map(properties), idx }),
836
- reference,
837
- popped,
838
- held,
839
- );
840
- }
841
-
842
- accept(resolver) {
843
- this.states = resolver.states;
844
- this.reference = resolver.reference;
845
- this.popped = resolver.popped;
846
- this.held = resolver.held;
847
-
848
- return this;
849
- }
850
- }
851
-
852
- freeze(Resolver.prototype);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bablr/agast-helpers",
3
3
  "description": "Helper functions for working with agAST trees",
4
- "version": "0.6.1",
4
+ "version": "0.7.0",
5
5
  "author": "Conrad Buck<conartist6@gmail.com>",
6
6
  "type": "module",
7
7
  "files": [
@@ -14,6 +14,7 @@
14
14
  "./print": "./lib/print.js",
15
15
  "./shorthand": "./lib/shorthand.js",
16
16
  "./stream": "./lib/stream.js",
17
+ "./sumtree": "./lib/sumtree.js",
17
18
  "./symbols": "./lib/symbols.js",
18
19
  "./template": "./lib/template.js",
19
20
  "./tree": "./lib/tree.js"