@bablr/bablr-vm 0.23.1 → 0.23.3

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,7 @@
1
1
  import { buildDependentLanguages } from '@bablr/helpers/grammar';
2
- import { facades, actuals } from './facades.js';
2
+ import { getGapNode } from './facades.js';
3
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
- };
4
+ let facades = new WeakMap();
22
5
 
23
6
  export const Context = class BABLRContext {
24
7
  static from(language, productionEnhancer) {
@@ -28,11 +11,13 @@ export const Context = class BABLRContext {
28
11
  constructor(languages, productionEnhancer) {
29
12
  this.languages = languages;
30
13
  this.productionEnhancer = productionEnhancer;
14
+ this.getGrammar = (language) => this.grammars.get(language);
15
+
16
+ Object.freeze(productionEnhancer);
31
17
 
32
18
  this.unboxedValues = new WeakMap();
33
19
 
34
20
  this.grammars = new WeakMap();
35
- this.facade = new ContextFacade(this);
36
21
 
37
22
  for (const { 1: language } of this.languages) {
38
23
  if (!language) throw new Error();
@@ -40,4 +25,21 @@ export const Context = class BABLRContext {
40
25
  this.grammars.set(language, new language.grammar());
41
26
  }
42
27
  }
28
+
29
+ getPublic() {
30
+ let value = facades.get(this);
31
+ if (value) return value;
32
+
33
+ let { productionEnhancer, getGrammar } = this;
34
+
35
+ value = Object.freeze({
36
+ getGrammar,
37
+ getGapNode,
38
+ productionEnhancer,
39
+ });
40
+
41
+ facades.set(this, value);
42
+
43
+ return value;
44
+ }
43
45
  };
package/lib/evaluate.js CHANGED
@@ -1,8 +1,12 @@
1
1
  /* global WeakSet */
2
2
  import { Coroutine } from '@bablr/coroutine';
3
- import { buildAttributeDefinition, buildCloseNodeTag } from '@bablr/agast-helpers/builders';
3
+ import {
4
+ buildAttributeDefinition,
5
+ buildCloseNodeTag,
6
+ buildTypedSpan,
7
+ deepFreeze,
8
+ } from '@bablr/agast-helpers/builders';
4
9
  import { getStreamIterator, printType, StreamIterable, wait } from '@bablr/agast-helpers/stream';
5
- import { facades } from './facades.js';
6
10
  import { State } from './state.js';
7
11
  import {
8
12
  OpenNodeTag,
@@ -22,12 +26,7 @@ import { buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
22
26
  import { has } from '@bablr/agast-helpers/object';
23
27
  import { reifyBablrOptions } from '@bablr/agast-vm-helpers';
24
28
  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
- };
29
+ import * as Spans from '@bablr/agast-helpers/spans';
31
30
 
32
31
  const getSourceLength = (tags) => {
33
32
  let i = 0;
@@ -41,11 +40,18 @@ const getSourceLength = (tags) => {
41
40
  return i;
42
41
  };
43
42
 
44
- export const bablr = (ctx, rootSource, strategy, options = {}) => {
45
- return new StreamIterable(__bablr(ctx, rootSource, strategy, options));
43
+ export const bablr = (
44
+ ctx,
45
+ rootSource,
46
+ language,
47
+ strategy,
48
+ options = {},
49
+ registerNode = () => {},
50
+ ) => {
51
+ return new StreamIterable(__bablr(ctx, rootSource, language, strategy, options, registerNode));
46
52
  };
47
53
 
48
- function* __bablr(ctx, rootSource, strategy, options) {
54
+ function* __bablr(ctx, rootSource, rootLanguage, strategy, options, registerNode) {
49
55
  let s = null;
50
56
  let m = null;
51
57
  let finishedMatch = null;
@@ -53,14 +59,22 @@ function* __bablr(ctx, rootSource, strategy, options) {
53
59
 
54
60
  let getState = () => s.getPublic();
55
61
 
56
- for (const language of ctx.languages.values()) {
57
- validNodesByLanguage.set(language, validNodesByLanguage.get(language) || new WeakSet());
62
+ s = State.from(rootSource, ctx, rootLanguage, options.expressions, options.spans);
63
+
64
+ s.source.advance();
65
+
66
+ if (options.holdUndefinedAttributes) {
67
+ throw new Error('holdUndefinedAttributes not implemented');
58
68
  }
59
69
 
60
- let co = new Coroutine(getStreamIterator(strategy(facades.get(ctx), getState)));
70
+ let co = new Coroutine(getStreamIterator(strategy(ctx.getPublic(), rootLanguage, getState)));
61
71
 
62
72
  co.advance();
63
73
 
74
+ if (s.source.head.step instanceof Promise) {
75
+ yield wait(s.source.head.step);
76
+ }
77
+
64
78
  for (;;) {
65
79
  if (co.current instanceof Promise) {
66
80
  co.current = yield wait(co.current);
@@ -71,6 +85,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
71
85
  throw new Error(`parse ate ${s.source.index} characters but the input was not consumed`);
72
86
  }
73
87
 
88
+ if (m) throw new Error();
89
+
74
90
  let { exchange } = s.source;
75
91
 
76
92
  s.source.release();
@@ -79,7 +95,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
79
95
  throw new Error('Source did not close all forks: ' + exchange.sources);
80
96
  }
81
97
 
82
- return co.value;
98
+ return options.tree === undefined || options.tree ? finishedMatch.node : undefined;
83
99
  }
84
100
 
85
101
  const instr = co.value;
@@ -229,8 +245,6 @@ function* __bablr(ctx, rootSource, strategy, options) {
229
245
  s.node = m.node;
230
246
  }
231
247
 
232
- validNodesByLanguage.get(language).add(node);
233
-
234
248
  break;
235
249
  }
236
250
 
@@ -327,14 +341,15 @@ function* __bablr(ctx, rootSource, strategy, options) {
327
341
  }
328
342
 
329
343
  case 'startSpan': {
330
- let { arguments: { 0: name, 1: guard = null } = [] } = instr;
331
- s.spans = s.spans.push({ type: 'Instruction', name, guard });
344
+ let { arguments: { 0: name, 1: guard = null, 2: { value: props } } = [] } = instr;
345
+ deepFreeze(props);
346
+ s.spans = Spans.push(s.spans, buildTypedSpan('Instruction', name, guard, props));
332
347
  break;
333
348
  }
334
349
 
335
350
  case 'endSpan': {
336
- if (s.spans.value.type !== 'Instruction') throw new Error();
337
- s.spans = s.spans.pop();
351
+ if (s.span.type !== 'Instruction') throw new Error();
352
+ s.spans = Spans.pop(s.spans);
338
353
  break;
339
354
  }
340
355
 
@@ -347,7 +362,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
347
362
 
348
363
  yield* m.emit(outerOptions);
349
364
 
350
- returnValue = facades.get(m);
365
+ returnValue = m.getPublic();
351
366
  break;
352
367
  }
353
368
 
@@ -359,6 +374,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
359
374
  m = m.endFrame(outerOptions);
360
375
  s = m ? m.state : s;
361
376
 
377
+ if (finishedMatch.isNode) {
378
+ registerNode(m.language, m.node);
379
+ }
380
+
362
381
  if (m) {
363
382
  m.running = null;
364
383
  if (finishedMatch.shiftMatch) {
@@ -367,7 +386,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
367
386
  yield* m.emit(outerOptions);
368
387
  }
369
388
 
370
- returnValue = m && facades.get(m);
389
+ returnValue = m && m.getPublic();
371
390
  break;
372
391
  }
373
392
 
@@ -377,7 +396,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
377
396
 
378
397
  let parentMatch = m;
379
398
 
380
- if (finishedMatch.type !== '_') throw new Error();
399
+ if (finishedMatch.type === '__') throw new Error();
381
400
 
382
401
  m = Match.startFrame(
383
402
  ctx,
@@ -395,7 +414,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
395
414
 
396
415
  yield* finishedMatch.emit(outerOptions);
397
416
 
398
- returnValue = m && facades.get(m);
417
+ returnValue = m && m.getPublic();
399
418
  break;
400
419
  }
401
420
 
@@ -410,32 +429,12 @@ function* __bablr(ctx, rootSource, strategy, options) {
410
429
  s = m.state;
411
430
  }
412
431
 
413
- returnValue = m && facades.get(m);
432
+ returnValue = m && m.getPublic();
414
433
  break;
415
434
  }
416
435
 
417
436
  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);
437
+ returnValue = s.getPublic();
439
438
  break;
440
439
  }
441
440
 
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
 
@@ -799,4 +678,97 @@ export class Match extends WeakStackFrame {
799
678
  }
800
679
  }
801
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
+ }
802
774
  }
package/lib/spans.js CHANGED
@@ -1,26 +1,13 @@
1
1
  import { ReferenceTag } from '@bablr/agast-helpers/symbols';
2
- import * as BTree from '@bablr/agast-helpers/btree';
2
+ import * as Spans from '@bablr/agast-helpers/spans';
3
+ import { buildTypedSpan } from '@bablr/agast-helpers/builders';
3
4
 
4
5
  const popSpan = (s) => {
5
- s.spans = s.spans.pop();
6
+ s.spans = Spans.pop(s.spans);
6
7
  };
7
8
 
8
9
  const pushSpan = (s, type, name, guard) => {
9
- let isSubspan = name[0] === '.';
10
- let topFrame = s.spans.value;
11
-
12
- // if (isSubspan) {
13
- // let buildGuard = () => {
14
- // return buildPattern();
15
- // };
16
- // let name_ = topFrame.name + name;
17
- // let subframes = BTree.push(topFrame.subframes, topFrame);
18
- // let guard_ = guard;
19
-
20
- // s.spans = s.spans.push({ type, name: name_, guard: guard_, subframes });
21
- // } else {
22
- s.spans = s.spans.push({ type, name, guard, subframes: BTree.fromValues([]) });
23
- // }
10
+ s.spans = Spans.push(s.spans, buildTypedSpan(type, name, guard));
24
11
  };
25
12
 
26
13
  export function updateSpans(m, phase) {
package/lib/state.js CHANGED
@@ -1,32 +1,42 @@
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';
4
+ import * as Spans from '@bablr/agast-helpers/spans';
5
5
  import { reifyExpression } from '@bablr/agast-vm-helpers';
6
- import { Matcher, Node, Regex, ShiftTag } from '@bablr/agast-vm-helpers/symbols';
6
+ import { Matcher, Node, Regex } from '@bablr/agast-vm-helpers/symbols';
7
7
  import { match, guardWithPattern } from './utils/pattern.js';
8
8
  import { getOpenTag } from '@bablr/agast-helpers/path';
9
9
 
10
10
  export const nodeStates = new WeakMap();
11
11
 
12
- export const State = class BABLRState extends WeakStackFrame {
12
+ export const State = class BABLRState {
13
+ static from(source, context, language, expressions = [], spans = Spans.fromValues([])) {
14
+ return new State(
15
+ null,
16
+ source,
17
+ context,
18
+ BTree.fromValues([language]),
19
+ emptyStack.push(...emptyStack.push(...expressions).valuesReverse()),
20
+ spans,
21
+ );
22
+ }
23
+
13
24
  constructor(
14
25
  parent,
15
26
  source,
16
27
  context,
17
28
  languages,
18
29
  expressions = emptyStack,
30
+ spans = Spans.fromValues([]),
19
31
  balanced = emptyStack,
20
- spans = emptyStack,
21
32
  resultPath = null,
22
33
  depths = { path: -1, result: -1, emitted: -1, shift: 0, nodeShift: 0 },
23
34
  held = null,
24
35
  node = null,
25
36
  ) {
26
- super(parent);
27
-
28
37
  if (!source) throw new Error('invalid args to State');
29
38
 
39
+ this.parent = parent;
30
40
  this.source = source;
31
41
  this.context = context;
32
42
  this.languages = languages;
@@ -38,18 +48,10 @@ export const State = class BABLRState extends WeakStackFrame {
38
48
  this.held = held;
39
49
  this.node = node;
40
50
 
51
+ this.depth = !parent ? 0 : parent.depth + 1;
41
52
  this.status = 'active';
42
53
  }
43
54
 
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
55
  get language() {
54
56
  return BTree.getAt(-1, this.languages);
55
57
  }
@@ -62,7 +64,7 @@ export const State = class BABLRState extends WeakStackFrame {
62
64
  }
63
65
 
64
66
  get span() {
65
- return this.spans.value;
67
+ return Spans.getAt(-1, this.spans);
66
68
  }
67
69
 
68
70
  get result() {
@@ -77,12 +79,30 @@ export const State = class BABLRState extends WeakStackFrame {
77
79
  return !!this.parent;
78
80
  }
79
81
 
82
+ push(source, context, languages, expressions, spans, balanced, resultPath, depths, held, node) {
83
+ return new State(
84
+ this,
85
+ source,
86
+ context,
87
+ languages,
88
+ expressions,
89
+ spans,
90
+ balanced,
91
+ resultPath,
92
+ depths,
93
+ held,
94
+ node,
95
+ );
96
+ }
97
+
80
98
  getPublic() {
81
99
  let { languages, spans, depths, held, node, source, result, resultPath, status } = this;
82
- return {
100
+
101
+ return Object.freeze({
83
102
  languages,
84
- span: spans.value?.name,
85
- depths: { ...depths },
103
+ span: Spans.getAt(-1, spans),
104
+ spans: spans,
105
+ depths: Object.freeze({ ...depths }),
86
106
  holding: !!held,
87
107
  held,
88
108
  node,
@@ -90,9 +110,9 @@ export const State = class BABLRState extends WeakStackFrame {
90
110
  done: source.done,
91
111
  sourceIndex: source.index,
92
112
  result,
93
- resultPath,
113
+ resultPath: resultPath?.frames || null,
94
114
  status,
95
- };
115
+ });
96
116
  }
97
117
 
98
118
  guardedMatch(pattern) {
@@ -101,6 +121,7 @@ export const State = class BABLRState extends WeakStackFrame {
101
121
 
102
122
  let branchedSource = false;
103
123
  let pattern_ = pattern;
124
+
104
125
  if (pattern.type === Matcher) {
105
126
  let { nodeMatcher } = reifyExpression(pattern.value);
106
127
 
@@ -143,8 +164,8 @@ export const State = class BABLRState extends WeakStackFrame {
143
164
  let {
144
165
  source,
145
166
  context,
146
- balanced,
147
167
  spans,
168
+ balanced,
148
169
  resultPath,
149
170
  depths,
150
171
  held,
@@ -158,8 +179,8 @@ export const State = class BABLRState extends WeakStackFrame {
158
179
  context,
159
180
  languages,
160
181
  expressions,
161
- balanced,
162
182
  spans,
183
+ balanced,
163
184
  resultPath,
164
185
  { ...depths },
165
186
  held,
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.1",
4
+ "version": "0.23.3",
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.4",
16
+ "@bablr/agast-vm": "0.11.2",
17
+ "@bablr/agast-vm-helpers": "0.10.4",
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.2",
20
+ "@bablr/regex-vm": "0.14.2",
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
  },