@bablr/bablr-vm 0.23.0 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/context.js CHANGED
@@ -1,24 +1,5 @@
1
1
  import { buildDependentLanguages } from '@bablr/helpers/grammar';
2
- import { facades, actuals } from './facades.js';
3
-
4
- export const ContextFacade = class BABLRContextFacade {
5
- constructor(actual) {
6
- facades.set(actual, this);
7
- Object.freeze(this);
8
- }
9
-
10
- get languages() {
11
- return actuals.get(this).languages;
12
- }
13
-
14
- get grammars() {
15
- return actuals.get(this).grammars;
16
- }
17
-
18
- get productionEnhancer() {
19
- return actuals.get(this).productionEnhancer;
20
- }
21
- };
2
+ import { getGapNode } from './facades.js';
22
3
 
23
4
  export const Context = class BABLRContext {
24
5
  static from(language, productionEnhancer) {
@@ -28,11 +9,13 @@ export const Context = class BABLRContext {
28
9
  constructor(languages, productionEnhancer) {
29
10
  this.languages = languages;
30
11
  this.productionEnhancer = productionEnhancer;
12
+ this.getGrammar = (language) => this.grammars.get(language);
13
+
14
+ Object.freeze(productionEnhancer);
31
15
 
32
16
  this.unboxedValues = new WeakMap();
33
17
 
34
18
  this.grammars = new WeakMap();
35
- this.facade = new ContextFacade(this);
36
19
 
37
20
  for (const { 1: language } of this.languages) {
38
21
  if (!language) throw new Error();
@@ -40,4 +23,14 @@ export const Context = class BABLRContext {
40
23
  this.grammars.set(language, new language.grammar());
41
24
  }
42
25
  }
26
+
27
+ getPublic() {
28
+ let { productionEnhancer, getGrammar } = this;
29
+
30
+ return Object.freeze({
31
+ getGrammar,
32
+ getGapNode,
33
+ productionEnhancer,
34
+ });
35
+ }
43
36
  };
package/lib/evaluate.js CHANGED
@@ -2,7 +2,6 @@
2
2
  import { Coroutine } from '@bablr/coroutine';
3
3
  import { buildAttributeDefinition, buildCloseNodeTag } from '@bablr/agast-helpers/builders';
4
4
  import { getStreamIterator, printType, StreamIterable, wait } from '@bablr/agast-helpers/stream';
5
- import { facades } from './facades.js';
6
5
  import { State } from './state.js';
7
6
  import {
8
7
  OpenNodeTag,
@@ -22,12 +21,8 @@ import { buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
22
21
  import { has } from '@bablr/agast-helpers/object';
23
22
  import { reifyBablrOptions } from '@bablr/agast-vm-helpers';
24
23
  import { buildNode, getTags } from '@bablr/agast-helpers/path';
25
-
26
- const validNodesByLanguage = new Map();
27
-
28
- export const isKnownValid = (language, node) => {
29
- return !!validNodesByLanguage.get(language)?.has(node);
30
- };
24
+ import * as BTree from '@bablr/agast-helpers/btree';
25
+ import { resolveLanguage } from '@bablr/helpers/grammar';
31
26
 
32
27
  const getSourceLength = (tags) => {
33
28
  let i = 0;
@@ -41,11 +36,18 @@ const getSourceLength = (tags) => {
41
36
  return i;
42
37
  };
43
38
 
44
- export const bablr = (ctx, rootSource, strategy, options = {}) => {
45
- return new StreamIterable(__bablr(ctx, rootSource, strategy, options));
39
+ export const bablr = (
40
+ ctx,
41
+ rootSource,
42
+ language,
43
+ strategy,
44
+ options = {},
45
+ registerNode = () => {},
46
+ ) => {
47
+ return new StreamIterable(__bablr(ctx, rootSource, language, strategy, options, registerNode));
46
48
  };
47
49
 
48
- function* __bablr(ctx, rootSource, strategy, options) {
50
+ function* __bablr(ctx, rootSource, rootLanguage, strategy, options, registerNode) {
49
51
  let s = null;
50
52
  let m = null;
51
53
  let finishedMatch = null;
@@ -53,14 +55,22 @@ function* __bablr(ctx, rootSource, strategy, options) {
53
55
 
54
56
  let getState = () => s.getPublic();
55
57
 
56
- for (const language of ctx.languages.values()) {
57
- validNodesByLanguage.set(language, validNodesByLanguage.get(language) || new WeakSet());
58
+ s = State.from(rootSource, ctx, rootLanguage, options.expressions);
59
+
60
+ s.source.advance();
61
+
62
+ if (options.holdUndefinedAttributes) {
63
+ throw new Error('holdUndefinedAttributes not implemented');
58
64
  }
59
65
 
60
- let co = new Coroutine(getStreamIterator(strategy(facades.get(ctx), getState)));
66
+ let co = new Coroutine(getStreamIterator(strategy(ctx.getPublic(), rootLanguage, getState)));
61
67
 
62
68
  co.advance();
63
69
 
70
+ if (s.source.head.step instanceof Promise) {
71
+ yield wait(s.source.head.step);
72
+ }
73
+
64
74
  for (;;) {
65
75
  if (co.current instanceof Promise) {
66
76
  co.current = yield wait(co.current);
@@ -71,6 +81,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
71
81
  throw new Error(`parse ate ${s.source.index} characters but the input was not consumed`);
72
82
  }
73
83
 
84
+ if (m) throw new Error();
85
+
74
86
  let { exchange } = s.source;
75
87
 
76
88
  s.source.release();
@@ -79,7 +91,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
79
91
  throw new Error('Source did not close all forks: ' + exchange.sources);
80
92
  }
81
93
 
82
- return co.value;
94
+ return options.tree === undefined || options.tree ? finishedMatch.node : undefined;
83
95
  }
84
96
 
85
97
  const instr = co.value;
@@ -229,8 +241,6 @@ function* __bablr(ctx, rootSource, strategy, options) {
229
241
  s.node = m.node;
230
242
  }
231
243
 
232
- validNodesByLanguage.get(language).add(node);
233
-
234
244
  break;
235
245
  }
236
246
 
@@ -347,7 +357,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
347
357
 
348
358
  yield* m.emit(outerOptions);
349
359
 
350
- returnValue = facades.get(m);
360
+ returnValue = m.getPublic();
351
361
  break;
352
362
  }
353
363
 
@@ -359,6 +369,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
359
369
  m = m.endFrame(outerOptions);
360
370
  s = m ? m.state : s;
361
371
 
372
+ if (finishedMatch.isNode) {
373
+ registerNode(m.language, m.node);
374
+ }
375
+
362
376
  if (m) {
363
377
  m.running = null;
364
378
  if (finishedMatch.shiftMatch) {
@@ -367,7 +381,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
367
381
  yield* m.emit(outerOptions);
368
382
  }
369
383
 
370
- returnValue = m && facades.get(m);
384
+ returnValue = m && m.getPublic();
371
385
  break;
372
386
  }
373
387
 
@@ -377,7 +391,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
377
391
 
378
392
  let parentMatch = m;
379
393
 
380
- if (finishedMatch.type !== '_') throw new Error();
394
+ if (finishedMatch.type === '__') throw new Error();
381
395
 
382
396
  m = Match.startFrame(
383
397
  ctx,
@@ -395,7 +409,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
395
409
 
396
410
  yield* finishedMatch.emit(outerOptions);
397
411
 
398
- returnValue = m && facades.get(m);
412
+ returnValue = m && m.getPublic();
399
413
  break;
400
414
  }
401
415
 
@@ -410,32 +424,12 @@ function* __bablr(ctx, rootSource, strategy, options) {
410
424
  s = m.state;
411
425
  }
412
426
 
413
- returnValue = m && facades.get(m);
427
+ returnValue = m && m.getPublic();
414
428
  break;
415
429
  }
416
430
 
417
431
  case 'getState': {
418
- returnValue = facades.get(s);
419
- break;
420
- }
421
-
422
- case 'init': {
423
- let { arguments: { 0: canonicalURL } = [] } = instr;
424
-
425
- if (s !== null) throw new Error();
426
-
427
- // TODO get rid of ctx.languages
428
- s = State.from(rootSource, ctx, ctx.languages.get(canonicalURL), options.expressions);
429
-
430
- s.source.advance();
431
-
432
- const sourceStep = s.source.head.step;
433
-
434
- if (sourceStep instanceof Promise) {
435
- yield wait(sourceStep);
436
- }
437
-
438
- returnValue = facades.get(s);
432
+ returnValue = s.getPublic();
439
433
  break;
440
434
  }
441
435
 
package/lib/facades.js CHANGED
@@ -1,33 +1,44 @@
1
1
  import * as Tags from '@bablr/agast-helpers/tags';
2
- import { buildGapTag, buildProperty } from '@bablr/agast-helpers/builders';
2
+ import { buildGapTag, buildPropertyTag } from '@bablr/agast-helpers/builders';
3
3
  import { buildFacadeLayer } from '@bablr/agast-vm-helpers/facades';
4
- import { buildNode, getTags } from '@bablr/agast-helpers/path';
4
+ import { buildNode, getTags, isStubNode } from '@bablr/agast-helpers/path';
5
5
  import { Property } from '@bablr/agast-helpers/symbols';
6
6
 
7
7
  export const { facades, actuals } = buildFacadeLayer();
8
8
 
9
+ let gapNodes = new WeakMap();
10
+
11
+ export const getGapNode = (gap) => gapNodes.get(gap);
12
+
9
13
  export const buildFacadeNode = (node) => {
14
+ if (!node) return null;
15
+
10
16
  let facadeTags = Tags.fromValues([]);
11
17
 
18
+ if (isStubNode(node)) {
19
+ return node;
20
+ }
21
+
12
22
  for (let tag of Tags.traverse(getTags(node))) {
13
23
  if (tag.type === Property) {
14
24
  let property = tag;
15
- let { reference, bindings, node, tags } = property;
16
-
17
- let property_ = property;
25
+ let { reference, shift, node, tags } = property.value;
18
26
 
19
- if (!reference.flags.intrinsic) {
27
+ let tags_;
28
+ if (reference?.flags.intrinsic || ['_', '#', '@'].includes(reference?.type)) {
29
+ tags_ = [tags[0], tags[1], buildFacadeNode(node)];
30
+ } else {
20
31
  let gapNode = buildNode(buildGapTag());
21
- if (!reference.flags.hasGap) {
22
- actuals.set(gapNode, node);
32
+ if (!reference?.flags.hasGap) {
33
+ gapNodes.set(gapNode, node);
23
34
  }
24
35
 
25
- let tags_ = Tags.fromValues([tags[0], tags[1], gapNode]);
26
-
27
- property_ = buildProperty(tags_);
36
+ tags_ = [tags[0], tags[1], gapNode];
28
37
  }
29
38
 
30
- facadeTags = Tags.push(facadeTags, property_);
39
+ tags_ = tags_.slice(0, tags.length);
40
+
41
+ facadeTags = Tags.push(facadeTags, buildPropertyTag(tags_, shift));
31
42
  } else {
32
43
  facadeTags = Tags.push(facadeTags, tag);
33
44
  }
package/lib/match.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { getProduction } from '@bablr/helpers/grammar';
2
- import { WeakStackFrame } from '@bablr/weak-stack';
3
2
 
4
3
  import { agast } from '@bablr/agast-vm';
5
4
  import * as Tags from '@bablr/agast-helpers/tags';
@@ -14,11 +13,10 @@ import {
14
13
  buildPropertyTag,
15
14
  buildOpenFragmentTag,
16
15
  nodeFlags,
17
- streamFromTree,
18
16
  } from '@bablr/agast-helpers/tree';
19
17
  import { effectsFor, reifyExpression, shouldBranch } from '@bablr/agast-vm-helpers';
20
18
 
21
- import { facades, actuals } from './facades.js';
19
+ import { buildFacadeNode } from './facades.js';
22
20
  import {
23
21
  CloseNodeTag,
24
22
  OpenNodeTag,
@@ -41,134 +39,13 @@ import {
41
39
  } from '@bablr/agast-helpers/path';
42
40
  import { updateSpans } from './spans.js';
43
41
 
44
- export class MatchFacade {
45
- constructor(match) {
46
- facades.set(match, this);
47
- Object.freeze(this);
48
- }
49
-
50
- get language() {
51
- return actuals.get(this).language;
52
- }
53
-
54
- get matcher() {
55
- return actuals.get(this).matcher;
56
- }
57
-
58
- get options() {
59
- return actuals.get(this).options;
60
- }
61
-
62
- get mergedReference() {
63
- return actuals.get(this).mergedReference;
64
- }
65
-
66
- get propertyMatcher() {
67
- return actuals.get(this).propertyMatcher;
68
- }
69
-
70
- get rawPropertyMatcher() {
71
- return actuals.get(this).rawPropertyMatcher;
72
- }
73
-
74
- get depth() {
75
- return actuals.get(this).depth;
76
- }
77
-
78
- get path() {
79
- return actuals.get(this).path;
80
- }
81
-
82
- get fragment() {
83
- return actuals.get(this).fragment;
84
- }
85
-
86
- get pathDepth() {
87
- return actuals.get(this).depths.path;
88
- }
89
-
90
- get pathName() {
91
- return actuals.get(this).pathName;
92
- }
93
-
94
- get node() {
95
- return actuals.get(this).node;
96
- }
97
-
98
- get props() {
99
- return actuals.get(this).props;
100
- }
101
-
102
- get type() {
103
- return actuals.get(this).type;
104
- }
105
-
106
- get isNode() {
107
- return actuals.get(this).isNode;
108
- }
109
-
110
- get isCover() {
111
- return actuals.get(this).isCover;
112
- }
113
-
114
- get allowEmpty() {
115
- return actuals.get(this).allowEmpty;
116
- }
117
-
118
- get didShift() {
119
- return actuals.get(this).didShift;
120
- }
121
-
122
- get isCoverBoundary() {
123
- return actuals.get(this).isCoverBoundary;
124
- }
125
-
126
- get coveredBoundary() {
127
- return facades.get(actuals.get(this).coveredBoundary);
128
- }
129
-
130
- get nodeMatch() {
131
- return facades.get(actuals.get(this).nodeMatch);
132
- }
133
-
134
- get cover() {
135
- return facades.get(actuals.get(this).cover);
136
- }
137
-
138
- get shiftMatch() {
139
- return facades.get(actuals.get(this).coveredBoundary.shiftMatch);
140
- }
141
-
142
- get effects() {
143
- return actuals.get(this).effects;
144
- }
145
-
146
- get parent() {
147
- return facades.get(actuals.get(this).parent);
148
- }
149
-
150
- get grammar() {
151
- return actuals.get(this).grammar;
152
- }
153
-
154
- get state() {
155
- return actuals.get(this).s.getPublic();
156
- }
157
-
158
- get s() {
159
- return actuals.get(this).s.getPublic();
160
- }
161
-
162
- ancestors(...args) {
163
- return actuals.get(this).ancestors(...args);
164
- }
165
- }
42
+ let facades = new WeakMap();
166
43
 
167
44
  const normalizeBindingPath = (path) => {
168
45
  if (path.length <= 1) return path;
169
46
  };
170
47
 
171
- export class Match extends WeakStackFrame {
48
+ export class Match {
172
49
  static startFrame(ctx, s, m, finishedMatch, verb, matcher, options) {
173
50
  let effects = effectsFor(verb.description);
174
51
  let isShift = verb.description.startsWith('shift'); // should this be didShift?
@@ -230,8 +107,7 @@ export class Match extends WeakStackFrame {
230
107
  }
231
108
  let matcher = reifyExpression(rawMatcher);
232
109
 
233
- super(parent);
234
-
110
+ this.parent = parent;
235
111
  this.context = context;
236
112
  this.state = state;
237
113
  this.rawPropertyMatcher = rawMatcher;
@@ -240,6 +116,7 @@ export class Match extends WeakStackFrame {
240
116
  this.shiftMatch = shiftMatch;
241
117
  this.emittedMatch = parent?.emittedMatch || this;
242
118
 
119
+ this.depth = !parent ? 0 : parent.depth + 1;
243
120
  this.agast = null;
244
121
  this.cover = null;
245
122
  this.running = null;
@@ -290,12 +167,10 @@ export class Match extends WeakStackFrame {
290
167
  this.agast.vm.next(shiftMatch.rootNode);
291
168
  }
292
169
  this.rootNode = this.agast.getState().node;
293
-
294
- new MatchFacade(this);
295
170
  }
296
171
 
297
172
  static from(context, state, matcher, props, options) {
298
- return Match.create(context, state, matcher, effectsFor('eat'), props, options);
173
+ return new Match(null, context, state, matcher, effectsFor('eat'), props, options);
299
174
  }
300
175
 
301
176
  get language() {
@@ -363,7 +238,7 @@ export class Match extends WeakStackFrame {
363
238
  get path() {
364
239
  let { agast } = this;
365
240
 
366
- return agast.getState().path || agast.getState().resultPath?.path;
241
+ return Path.wrap(agast.getState().path || agast.getState().resultPath?.path);
367
242
  }
368
243
 
369
244
  get coveredBoundary() {
@@ -410,6 +285,10 @@ export class Match extends WeakStackFrame {
410
285
  return this.propertyMatcher.nodeMatcher.type === '_';
411
286
  }
412
287
 
288
+ push(context, state, rawMatcher, effects, shiftMatch, options) {
289
+ return new Match(this, context, state, rawMatcher, effects, shiftMatch, options);
290
+ }
291
+
413
292
  advance(tag) {
414
293
  let { vm, getState } = this.agast;
415
294
  let s = this.state;
@@ -426,9 +305,9 @@ export class Match extends WeakStackFrame {
426
305
  s.depths.result--;
427
306
  }
428
307
 
429
- this.rootNode = agastState.path.atDepth(0).node;
308
+ this.rootNode = Path.wrap(agastState.path).atDepth(0).node;
430
309
 
431
- s.resultPath = agastState.resultPath;
310
+ s.resultPath = TagPath.wrap(agastState.resultPath);
432
311
 
433
312
  // if (this.emitted?.depth > 1) throw new Error();
434
313
 
@@ -679,9 +558,18 @@ export class Match extends WeakStackFrame {
679
558
  let finishedMatch = m;
680
559
  m = m.parent;
681
560
 
682
- let parentNextTagPath = Path.from(m.rootNode)
683
- .tagPathAt(getCloseTag(m.rootNode) ? -2 : -1)
684
- .inner?.tagPathAt(finishedMatch.parentPreviousTagPath.tagsIndex + 2);
561
+ let parentRoot = Path.from(m.rootNode);
562
+
563
+ if (m.type !== '__') {
564
+ parentRoot = parentRoot.tagPathAt(getCloseTag(m.rootNode) ? -2 : -1).inner;
565
+ }
566
+
567
+ let finishedChildren =
568
+ finishedMatch.type !== '__' ? 1 : Tags.getSize(finishedMatch.rootNode.value.children);
569
+
570
+ let parentNextTagPath = parentRoot?.tagPathAt(
571
+ finishedMatch.parentPreviousTagPath.tagsIndex + finishedChildren + 1,
572
+ );
685
573
 
686
574
  tagPath = parentNextTagPath;
687
575
 
@@ -750,7 +638,9 @@ export class Match extends WeakStackFrame {
750
638
  do {
751
639
  if (m.running) {
752
640
  m = m.running;
753
- tagPath = TagPath.fromNode(m.rootNode, 0);
641
+ // TODO is -1 ok
642
+ let shiftIndex = m.didShift ? -1 : 0;
643
+ tagPath = TagPath.fromNode(m.rootNode, shiftIndex);
754
644
  } else if (m.parent && (!m.parent.running || m.parent.running !== m)) {
755
645
  tagPath = m.parentPreviousTagPath;
756
646
 
@@ -788,4 +678,97 @@ export class Match extends WeakStackFrame {
788
678
  }
789
679
  }
790
680
  }
681
+
682
+ getPublic() {
683
+ let cached = facades.get(this);
684
+ if (cached) {
685
+ return cached;
686
+ }
687
+
688
+ let {
689
+ parent,
690
+ cover,
691
+ nodeMatch,
692
+ shiftMatch,
693
+ coveredBoundary,
694
+ mergedReference,
695
+ matcher,
696
+ propertyMatcher,
697
+ rawPropertyMatcher,
698
+ language,
699
+ isNode,
700
+ isCover,
701
+ isCoverBoundary,
702
+ effects,
703
+ options,
704
+ allowEmpty,
705
+ depth,
706
+ state,
707
+ } = this;
708
+
709
+ let getParent = () => {
710
+ let value = parent;
711
+ if (parent) facades.set((value = facades.get(parent) || parent.getPublic()));
712
+ return value;
713
+ };
714
+
715
+ let getCover = () => {
716
+ let value = cover;
717
+ if (cover) facades.set((value = facades.get(cover) || cover.getPublic()));
718
+ return value;
719
+ };
720
+
721
+ let getCoveredBoundary = () => {
722
+ let value = coveredBoundary;
723
+ if (coveredBoundary)
724
+ facades.set((value = facades.get(coveredBoundary) || coveredBoundary.getPublic()));
725
+ return value;
726
+ };
727
+
728
+ let getNodeMatch = () => {
729
+ let value = nodeMatch;
730
+ if (nodeMatch) facades.set((value = facades.get(nodeMatch) || nodeMatch.getPublic()));
731
+ return value;
732
+ };
733
+
734
+ let getShiftMatch = () => {
735
+ let value = shiftMatch;
736
+ if (shiftMatch) facades.set((value = facades.get(shiftMatch) || shiftMatch.getPublic()));
737
+ return value;
738
+ };
739
+
740
+ let getState = () => {
741
+ return state.getPublic();
742
+ };
743
+
744
+ let getNode = () => {
745
+ return buildFacadeNode(this.node);
746
+ };
747
+
748
+ cached = {
749
+ getParent,
750
+ getCover,
751
+ getCoveredBoundary,
752
+ getNodeMatch,
753
+ getShiftMatch,
754
+ getState,
755
+ getNode,
756
+ mergedReference,
757
+ matcher,
758
+ propertyMatcher,
759
+ rawPropertyMatcher,
760
+ language,
761
+ isNode,
762
+ isCover,
763
+ isCoverBoundary,
764
+ effects,
765
+ options,
766
+ allowEmpty,
767
+ depth,
768
+ };
769
+
770
+ facades.set(this, cached);
771
+
772
+ return cached;
773
+ }
791
774
  }
package/lib/state.js CHANGED
@@ -1,15 +1,24 @@
1
1
  import emptyStack from '@iter-tools/imm-stack';
2
- import { WeakStackFrame } from '@bablr/weak-stack';
3
- import { getCooked, maybeWait } from '@bablr/agast-helpers/stream';
2
+ import { maybeWait } from '@bablr/agast-helpers/stream';
4
3
  import * as BTree from '@bablr/agast-helpers/btree';
5
4
  import { reifyExpression } from '@bablr/agast-vm-helpers';
6
- import { Matcher, Node, Regex, ShiftTag } from '@bablr/agast-vm-helpers/symbols';
5
+ import { Matcher, Node, Regex } from '@bablr/agast-vm-helpers/symbols';
7
6
  import { match, guardWithPattern } from './utils/pattern.js';
8
7
  import { getOpenTag } from '@bablr/agast-helpers/path';
9
8
 
10
9
  export const nodeStates = new WeakMap();
11
10
 
12
- export const State = class BABLRState extends WeakStackFrame {
11
+ export const State = class BABLRState {
12
+ static from(source, context, language, expressions = []) {
13
+ return new State(
14
+ null,
15
+ source,
16
+ context,
17
+ BTree.fromValues([language]),
18
+ emptyStack.push(...emptyStack.push(...expressions).valuesReverse()),
19
+ );
20
+ }
21
+
13
22
  constructor(
14
23
  parent,
15
24
  source,
@@ -23,10 +32,9 @@ export const State = class BABLRState extends WeakStackFrame {
23
32
  held = null,
24
33
  node = null,
25
34
  ) {
26
- super(parent);
27
-
28
35
  if (!source) throw new Error('invalid args to State');
29
36
 
37
+ this.parent = parent;
30
38
  this.source = source;
31
39
  this.context = context;
32
40
  this.languages = languages;
@@ -38,18 +46,10 @@ export const State = class BABLRState extends WeakStackFrame {
38
46
  this.held = held;
39
47
  this.node = node;
40
48
 
49
+ this.depth = !parent ? 0 : parent.depth + 1;
41
50
  this.status = 'active';
42
51
  }
43
52
 
44
- static from(source, context, language, expressions = []) {
45
- return State.create(
46
- source,
47
- context,
48
- BTree.fromValues([language]),
49
- emptyStack.push(...emptyStack.push(...expressions).valuesReverse()),
50
- );
51
- }
52
-
53
53
  get language() {
54
54
  return BTree.getAt(-1, this.languages);
55
55
  }
@@ -77,12 +77,29 @@ export const State = class BABLRState extends WeakStackFrame {
77
77
  return !!this.parent;
78
78
  }
79
79
 
80
+ push(source, context, languages, expressions, balanced, spans, resultPath, depths, held, node) {
81
+ return new State(
82
+ this,
83
+ source,
84
+ context,
85
+ languages,
86
+ expressions,
87
+ balanced,
88
+ spans,
89
+ resultPath,
90
+ depths,
91
+ held,
92
+ node,
93
+ );
94
+ }
95
+
80
96
  getPublic() {
81
97
  let { languages, spans, depths, held, node, source, result, resultPath, status } = this;
82
- return {
98
+
99
+ return Object.freeze({
83
100
  languages,
84
101
  span: spans.value?.name,
85
- depths: { ...depths },
102
+ depths: Object.freeze({ ...depths }),
86
103
  holding: !!held,
87
104
  held,
88
105
  node,
@@ -90,9 +107,9 @@ export const State = class BABLRState extends WeakStackFrame {
90
107
  done: source.done,
91
108
  sourceIndex: source.index,
92
109
  result,
93
- resultPath,
110
+ resultPath: resultPath?.frames || null,
94
111
  status,
95
- };
112
+ });
96
113
  }
97
114
 
98
115
  guardedMatch(pattern) {
@@ -101,6 +118,7 @@ export const State = class BABLRState extends WeakStackFrame {
101
118
 
102
119
  let branchedSource = false;
103
120
  let pattern_ = pattern;
121
+
104
122
  if (pattern.type === Matcher) {
105
123
  let { nodeMatcher } = reifyExpression(pattern.value);
106
124
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bablr/bablr-vm",
3
3
  "description": "A VM for parsing using BABLR languages",
4
- "version": "0.23.0",
4
+ "version": "0.23.2",
5
5
  "author": "Conrad Buck<conartist6@gmail.com>",
6
6
  "type": "module",
7
7
  "files": [
@@ -12,14 +12,13 @@
12
12
  },
13
13
  "sideEffects": false,
14
14
  "dependencies": {
15
- "@bablr/agast-helpers": "0.10.0",
16
- "@bablr/agast-vm": "0.11.0",
17
- "@bablr/agast-vm-helpers": "0.10.0",
15
+ "@bablr/agast-helpers": "0.10.2",
16
+ "@bablr/agast-vm": "0.11.1",
17
+ "@bablr/agast-vm-helpers": "0.10.2",
18
18
  "@bablr/coroutine": "0.1.0",
19
- "@bablr/helpers": "0.25.0",
20
- "@bablr/regex-vm": "0.14.0",
19
+ "@bablr/helpers": "0.25.1",
20
+ "@bablr/regex-vm": "0.14.1",
21
21
  "@bablr/stream-iterator": "2.0.0",
22
- "@bablr/weak-stack": "1.0.1",
23
22
  "@iter-tools/imm-stack": "1.2.0",
24
23
  "iter-tools-es": "7.5.3"
25
24
  },