@bablr/bablr-vm 0.22.1 → 0.23.1

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/state.js CHANGED
@@ -1,141 +1,27 @@
1
- import { agast as createAgast, TagPathFacade as TagPath } from '@bablr/agast-vm';
2
1
  import emptyStack from '@iter-tools/imm-stack';
3
2
  import { WeakStackFrame } from '@bablr/weak-stack';
4
3
  import { getCooked, maybeWait } from '@bablr/agast-helpers/stream';
5
- import * as Tags from '@bablr/agast-helpers/tags';
4
+ import * as BTree from '@bablr/agast-helpers/btree';
6
5
  import { reifyExpression } from '@bablr/agast-vm-helpers';
7
- import {
8
- Matcher,
9
- Node,
10
- Regex,
11
- GapTag,
12
- InitializerTag,
13
- OpenNodeTag,
14
- ReferenceTag,
15
- ShiftTag,
16
- Property,
17
- BindingTag,
18
- PropertyWrapper,
19
- } from '@bablr/agast-vm-helpers/symbols';
20
- import {
21
- buildBindingTag,
22
- buildChild,
23
- buildInitializerTag,
24
- buildNullNode,
25
- buildProperty,
26
- buildPropertyWrapper,
27
- buildReferenceTag,
28
- getOr,
29
- multiFragmentFlags,
30
- } from '@bablr/agast-helpers/tree';
6
+ import { Matcher, Node, Regex, ShiftTag } from '@bablr/agast-vm-helpers/symbols';
31
7
  import { match, guardWithPattern } from './utils/pattern.js';
32
- import { facades, actuals } from './facades.js';
33
- import { FragmentFacade } from './node.js';
34
- import { wrapperIsFull } from '@bablr/agast-helpers/path';
35
-
36
- const { freeze } = Object;
8
+ import { getOpenTag } from '@bablr/agast-helpers/path';
37
9
 
38
10
  export const nodeStates = new WeakMap();
39
11
 
40
- export const StateFacade = class BABLRStateFacade {
41
- constructor(state) {
42
- facades.set(state, this);
43
- freeze(this);
44
- }
45
-
46
- static from(source) {
47
- return State.from(actuals.get(source));
48
- }
49
-
50
- get ctx() {
51
- return actuals.get(this).context;
52
- }
53
-
54
- get span() {
55
- return actuals.get(this).span.name;
56
- }
57
-
58
- get resultPath() {
59
- return actuals.get(this).resultPath;
60
- }
61
-
62
- get result() {
63
- return actuals.get(this).result;
64
- }
65
-
66
- get referenceTag() {
67
- return actuals.get(this).referenceTag;
68
- }
69
-
70
- get referenceTagPath() {
71
- return actuals.get(this).referenceTagPath;
72
- }
73
-
74
- get referencePath() {
75
- return actuals.get(this).referencePath;
76
- }
77
-
78
- get holding() {
79
- return actuals.get(this).holding;
80
- }
81
-
82
- get language() {
83
- return actuals.get(this).language;
84
- }
85
-
86
- get depths() {
87
- const { path, result, shift, nodeShift } = actuals.get(this).depths;
88
- return { path, result, shift, nodeShift };
89
- }
90
-
91
- get held() {
92
- const { held } = actuals.get(this);
93
- return held && FragmentFacade.wrapNode(held.node, this.ctx);
94
- }
95
-
96
- get node() {
97
- return FragmentFacade.wrapNode(actuals.get(this).node, this.ctx);
98
- }
99
-
100
- get parentNode() {
101
- return FragmentFacade.wrapNode(actuals.get(this).parentNode, this.ctx);
102
- }
103
-
104
- get source() {
105
- return facades.get(actuals.get(this).source);
106
- }
107
-
108
- get depth() {
109
- return actuals.get(this).depth;
110
- }
111
-
112
- get status() {
113
- return actuals.get(this).status;
114
- }
115
-
116
- get parent() {
117
- return facades.get(actuals.get(this).parent);
118
- }
119
-
120
- nodeForPath(path) {
121
- return actuals.get(this).nodeForPath(path);
122
- }
123
- };
124
-
125
12
  export const State = class BABLRState extends WeakStackFrame {
126
13
  constructor(
127
14
  parent,
128
15
  source,
129
16
  context,
130
- language,
17
+ languages,
131
18
  expressions = emptyStack,
132
19
  balanced = emptyStack,
133
- spans = emptyStack.push({ name: 'Bare' }),
134
- referenceTagPath = null,
20
+ spans = emptyStack,
135
21
  resultPath = null,
136
22
  depths = { path: -1, result: -1, emitted: -1, shift: 0, nodeShift: 0 },
137
23
  held = null,
138
- agast = null,
24
+ node = null,
139
25
  ) {
140
26
  super(parent);
141
27
 
@@ -143,51 +29,29 @@ export const State = class BABLRState extends WeakStackFrame {
143
29
 
144
30
  this.source = source;
145
31
  this.context = context;
146
- this.language = language;
32
+ this.languages = languages;
147
33
  this.expressions = expressions;
148
34
  this.balanced = balanced;
149
35
  this.spans = spans;
150
- this.referenceTagPath = referenceTagPath;
151
36
  this.resultPath = resultPath;
152
37
  this.depths = depths;
153
38
  this.held = held;
154
- this.agast = agast;
39
+ this.node = node;
155
40
 
156
41
  this.status = 'active';
157
-
158
- this.emitted = null;
159
-
160
- new StateFacade(this);
161
42
  }
162
43
 
163
44
  static from(source, context, language, expressions = []) {
164
45
  return State.create(
165
46
  source,
166
47
  context,
167
- language,
48
+ BTree.fromValues([language]),
168
49
  emptyStack.push(...emptyStack.push(...expressions).valuesReverse()),
169
50
  );
170
51
  }
171
52
 
172
- get node() {
173
- return this.agast?.state.node;
174
- }
175
-
176
- get referencePath() {
177
- let refPath = this.referenceTagPath;
178
-
179
- if (!refPath) return null;
180
-
181
- let { previousSibling } = refPath;
182
- let isShift = previousSibling.tag.type === ShiftTag;
183
-
184
- let referenceTagPath = previousSibling;
185
-
186
- if (isShift) {
187
- let refIndex = previousSibling.tagsIndex - 1 - previousSibling.tag.value.index * 3;
188
- referenceTagPath = previousSibling.siblingAt(refIndex);
189
- }
190
- return referenceTagPath;
53
+ get language() {
54
+ return BTree.getAt(-1, this.languages);
191
55
  }
192
56
 
193
57
  get guardedSource() {
@@ -201,67 +65,70 @@ export const State = class BABLRState extends WeakStackFrame {
201
65
  return this.spans.value;
202
66
  }
203
67
 
204
- get path() {
205
- return this.agast?.state.path;
206
- }
207
-
208
68
  get result() {
209
- return this.resultPath.tag;
210
- }
211
-
212
- get parentNode() {
213
- throw new Error('not implemented');
69
+ return this.resultPath?.tag;
214
70
  }
215
71
 
216
72
  get holding() {
217
73
  return !!this.held;
218
74
  }
219
75
 
220
- get referenceTag() {
221
- return this.referenceTagPath?.tag;
222
- }
223
-
224
- get isGap() {
225
- return this.tag.type === GapTag;
226
- }
227
-
228
76
  get speculative() {
229
77
  return !!this.parent;
230
78
  }
231
79
 
232
- guardedMatch(pattern, attributes = {}) {
80
+ getPublic() {
81
+ let { languages, spans, depths, held, node, source, result, resultPath, status } = this;
82
+ return {
83
+ languages,
84
+ span: spans.value?.name,
85
+ depths: { ...depths },
86
+ holding: !!held,
87
+ held,
88
+ node,
89
+ atGap: source.atGap,
90
+ done: source.done,
91
+ sourceIndex: source.index,
92
+ result,
93
+ resultPath,
94
+ status,
95
+ };
96
+ }
97
+
98
+ guardedMatch(pattern) {
233
99
  let { span, source } = this;
234
100
  let { guard } = span;
235
101
 
102
+ let branchedSource = false;
236
103
  let pattern_ = pattern;
237
104
  if (pattern.type === Matcher) {
238
- pattern_ = reifyExpression(pattern.value).nodeMatcher;
239
- } else if (pattern.type === Regex || pattern.type === Node) {
240
- pattern_ = pattern.value;
241
- } else if (typeof pattern !== 'string') {
242
- throw new Error();
243
- }
244
-
245
- if (span.type === 'Lexical' && attributes.balancer) {
246
- // also check that the open node starts a lexical span?
247
- guard = null;
248
- }
249
-
250
- if (pattern_?.literalValue) {
251
- pattern_ = pattern_.literalValue || getCooked(pattern_.tags);
105
+ let { nodeMatcher } = reifyExpression(pattern.value);
252
106
 
253
- if (pattern_.type === Symbol.for('String')) {
254
- pattern_ = reifyExpression(pattern_);
107
+ if (nodeMatcher?.literalValue) {
108
+ pattern_ = nodeMatcher.literalValue; // || getCooked(pattern_.value.tags);
109
+ } else {
110
+ throw new Error();
255
111
  }
112
+ } else if (pattern.type === Node) {
113
+ if (!getOpenTag(pattern.value).value.flags.token) throw new Error();
114
+
115
+ pattern_ = reifyExpression(pattern.value);
116
+ } else if (pattern.type === Regex) {
117
+ pattern_ = pattern.value;
118
+ } else if (pattern.type !== Matcher && typeof pattern !== 'string') {
119
+ throw new Error();
256
120
  }
257
121
 
258
- let guardedSource = guard && guardWithPattern(guard, source);
122
+ let guardedSource = guard ? guardWithPattern(guard, source) : source;
259
123
 
260
- let result = match(pattern_, guardedSource || source);
124
+ let result = match(pattern_, guardedSource);
261
125
 
262
126
  return maybeWait(result, (result) => {
263
- if (guardedSource && !guardedSource.done) {
264
- guardedSource.return();
127
+ if (branchedSource) {
128
+ source.release();
129
+ }
130
+ if (guard && !guardedSource.done) {
131
+ return maybeWait(guardedSource.return(), () => result);
265
132
  }
266
133
  return result;
267
134
  });
@@ -274,63 +141,29 @@ export const State = class BABLRState extends WeakStackFrame {
274
141
  branch() {
275
142
  let baseState = this;
276
143
  let {
277
- agast,
278
144
  source,
279
145
  context,
280
146
  balanced,
281
147
  spans,
282
148
  resultPath,
283
149
  depths,
284
- referenceTagPath,
285
150
  held,
286
151
  node,
287
- language,
152
+ languages,
288
153
  expressions,
289
154
  } = baseState;
290
155
 
291
- let newAgast = createAgast(agast.options);
292
-
293
- let fragRefTag = buildReferenceTag('_', null, false, multiFragmentFlags);
294
-
295
- if (node.tags.openTag) newAgast.vm.next(node.tags.openTag);
296
- if (node.tags.childrenNode) {
297
- let property = buildProperty(fragRefTag.value, null, node.tags.childrenNode);
298
- newAgast.vm.next(
299
- buildChild(
300
- PropertyWrapper,
301
- buildPropertyWrapper(
302
- [fragRefTag, buildBindingTag(), buildChild(Property, property)],
303
- property,
304
- ),
305
- ),
306
- );
307
- }
308
- if (node.tags.closeTag) newAgast.vm.next(node.tags.closeTag);
309
-
310
- let newNode = newAgast.state.node;
311
- let nodeState = nodeStates.get(node);
312
- let newResultPath;
313
-
314
- if (resultPath.path.node === node) {
315
- newResultPath = TagPath.fromNode(newNode, resultPath.tagsIndex);
316
- } else {
317
- newResultPath = resultPath;
318
- }
319
-
320
- nodeStates.set(newNode, { ...nodeState });
321
-
322
156
  let child = this.push(
323
157
  source.branch(),
324
158
  context,
325
- language,
159
+ languages,
326
160
  expressions,
327
161
  balanced,
328
162
  spans,
329
- referenceTagPath,
330
- newResultPath,
163
+ resultPath,
331
164
  { ...depths },
332
165
  held,
333
- newAgast,
166
+ node,
334
167
  );
335
168
 
336
169
  return child;
@@ -347,40 +180,11 @@ export const State = class BABLRState extends WeakStackFrame {
347
180
  throw new Error('accepted the root state');
348
181
  }
349
182
 
350
- if (parent.depths.path === accepted.depths.path) {
351
- let parentChildren = parent.node.tags;
352
-
353
- if (parent.node.type !== accepted.node.type) throw new Error();
354
-
355
- let lastParentProp = parentChildren.at(-1);
356
-
357
- let partialOffset =
358
- lastParentProp.type === PropertyWrapper && !wrapperIsFull(lastParentProp) ? -1 : 0;
359
-
360
- for (let i = parentChildren.size + partialOffset; i < accepted.node.tags.size; i++) {
361
- let acceptedTag = accepted.node.tags.at(i);
362
- let tag = parentChildren.at(i);
363
-
364
- // let wrapperTag =
365
-
366
- for (
367
- let i = tag ? Tags.getSize(tag.value.tags) : 0;
368
- i < Tags.getSize(acceptedTag.value.tags);
369
- i++
370
- ) {
371
- let tag = Tags.getAt(i, acceptedTag.value.tags);
372
-
373
- parent.agast.vm.next(tag);
374
- }
375
- }
376
- }
377
-
378
183
  parent.spans = accepted.spans;
379
184
  parent.balanced = accepted.balanced;
380
- parent.referenceTagPath = accepted.referenceTagPath;
381
185
  parent.held = accepted.held;
382
186
  parent.depths = accepted.depths;
383
- parent.language = accepted.language;
187
+ parent.languages = accepted.languages;
384
188
  parent.expressions = accepted.expressions;
385
189
 
386
190
  if (parent.depths.result + 1 === accepted.depths.result) {
@@ -397,97 +201,15 @@ export const State = class BABLRState extends WeakStackFrame {
397
201
  return parent;
398
202
  }
399
203
 
400
- reject(finishedMatch, options) {
401
- let { bind = false } = options;
204
+ reject(finishedMatch) {
402
205
  let rejectedState = this;
403
206
 
404
- let didBranch = finishedMatch.s !== finishedMatch.parent.state;
405
- let abandon =
406
- (!finishedMatch.isNode && !didBranch) ||
407
- finishedMatch.cover ||
408
- finishedMatch.effects.success === 'none';
409
207
  let shallower =
410
208
  finishedMatch.coveredBoundary.didShift &&
411
209
  finishedMatch.coveredBoundary.shiftMatch.state.depth === this.depth - 2
412
210
  ? finishedMatch.coveredBoundary.shiftMatch.state
413
211
  : this.parent;
414
212
 
415
- if (!abandon && shallower) {
416
- let parentChildren = shallower.node.tags;
417
- let ourChildren = finishedMatch.fragmentNode.tags;
418
- let refTag;
419
-
420
- if (shallower.node.type) {
421
- if (shallower.node.type !== rejectedState.node.type) throw new Error();
422
-
423
- for (let i = parentChildren.size; i < ourChildren.size; i++) {
424
- let tag = ourChildren.at(i);
425
-
426
- if (tag.type === PropertyWrapper) {
427
- for (let wrappedTag of tag.value.tags) {
428
- if (wrappedTag.type === ReferenceTag) {
429
- refTag = wrappedTag;
430
- }
431
-
432
- if ([InitializerTag, GapTag].includes(wrappedTag.type)) {
433
- let previousSibling = ourChildren.at(i, 0);
434
- let isShift = previousSibling.type === ShiftTag;
435
-
436
- let referenceTag = previousSibling;
437
-
438
- if (isShift) {
439
- let refIndex = i - 1 - previousSibling.value.index;
440
- referenceTag = ourChildren.at(refIndex, 0);
441
- }
442
-
443
- if (
444
- !['#', '@'].includes(referenceTag.value.type) &&
445
- !referenceTag.value.isArray &&
446
- getOr(0, referenceTag.value.name, shallower.node) === 0 &&
447
- refTag !== ShiftTag
448
- ) {
449
- if (refTag !== ReferenceTag) {
450
- shallower.agast.vm.next(refTag);
451
- }
452
-
453
- if (bind || wrappedTag.type === GapTag) {
454
- shallower.agast.vm.next(
455
- buildChild(Property, buildProperty(refTag.value, null, buildNullNode())),
456
- );
457
- } else {
458
- shallower.agast.vm.next(wrappedTag);
459
- }
460
- }
461
- refTag = null;
462
- }
463
- }
464
- }
465
- }
466
-
467
- if (refTag?.type === ReferenceTag) {
468
- if (
469
- refTag.value.name &&
470
- !refTag.value.isArray &&
471
- !shallower.node.properties.has(refTag.value.name)
472
- ) {
473
- if (bind) {
474
- shallower.agast.vm.next(refTag);
475
- shallower.agast.vm.next(
476
- buildChild(Property, buildProperty(refTag.value, [], buildNullNode())),
477
- );
478
- } else {
479
- if (!refTag.value.flags.expression) {
480
- shallower.agast.vm.next(refTag);
481
- shallower.agast.vm.next(buildInitializerTag(refTag.value.isArray));
482
- }
483
- }
484
- }
485
- shallower.referenceTagPath = null;
486
- shallower.resultPath = TagPath.fromNode(shallower.node, -1);
487
- }
488
- }
489
- }
490
-
491
213
  if (this.status === 'rejected') {
492
214
  return shallower;
493
215
  }
@@ -4,7 +4,7 @@ import { generateMatches } from '@bablr/regex-vm';
4
4
  import {
5
5
  getStreamIterator,
6
6
  maybeWait,
7
- printType,
7
+ printName,
8
8
  StreamIterable,
9
9
  } from '@bablr/agast-helpers/stream';
10
10
  import * as Tags from '@bablr/agast-helpers/tags';
@@ -24,7 +24,7 @@ import {
24
24
  buildOpenNodeTag,
25
25
  tokenFlags,
26
26
  } from '@bablr/agast-helpers/builders';
27
- import { streamIteratorSymbol } from '@bablr/stream-iterator';
27
+ import { streamIteratorSymbol, wait } from '@bablr/stream-iterator';
28
28
 
29
29
  function* __wrapSource(source) {
30
30
  let source_ = source.source || source;
@@ -36,16 +36,31 @@ function* __wrapSource(source) {
36
36
  yield '';
37
37
  }
38
38
  let iter = getStreamIterator(source);
39
-
40
- let step = iter.next();
41
- while (!step.done) {
42
- yield step.value;
39
+ let step;
40
+ try {
43
41
  step = iter.next();
44
- }
45
42
 
46
- iter.return();
43
+ if (step instanceof Promise) {
44
+ step = yield wait(step);
45
+ }
46
+
47
+ while (!step.done) {
48
+ yield step.value;
49
+ step = iter.next();
50
+
51
+ if (step instanceof Promise) {
52
+ step = yield wait(step);
53
+ }
54
+ }
55
+
56
+ yield Symbol.for('EOS');
57
+ } finally {
58
+ step = iter.return();
47
59
 
48
- yield Symbol.for('EOS');
60
+ if (step instanceof Promise) {
61
+ step = yield wait(step);
62
+ }
63
+ }
49
64
  }
50
65
 
51
66
  export const wrapSource = (source) => {
@@ -73,7 +88,7 @@ const buildFragmentRegex = (frag) => {
73
88
  buildAlternatives([
74
89
  buildAlternative(
75
90
  buildElements(
76
- [...Tags.traverse(frag.tags)].flatMap((tag) => {
91
+ [...Tags.traverse(frag.value.tags)].flatMap((tag) => {
77
92
  if (tag.type === LiteralTag) {
78
93
  let str = tag.value;
79
94
  return [...str].map((chr) => buildToken('Character', chr));
@@ -110,25 +125,34 @@ const promiseCo = (gen) => {
110
125
  function* __stringEqual(str, iterable) {
111
126
  let strIter = str[Symbol.iterator]();
112
127
  let iter = getStreamIterator(iterable);
128
+ let step;
113
129
 
114
- let strStep = strIter.next();
115
- let step = iter.next();
130
+ try {
131
+ let strStep = strIter.next();
132
+ step = iter.next();
116
133
 
117
- while (!strStep.done) {
118
- if (step instanceof Promise) {
119
- step = yield step;
120
- }
134
+ while (!strStep.done) {
135
+ if (step instanceof Promise) {
136
+ step = yield wait(step);
137
+ }
121
138
 
122
- if (step.value !== strStep.value) {
123
- iter.return();
124
- return false;
125
- }
139
+ if (step.value !== strStep.value) {
140
+ step = iter.return();
141
+ if (step instanceof Promise) {
142
+ step = yield wait(step);
143
+ }
144
+ return false;
145
+ }
126
146
 
127
- strStep = strIter.next();
128
- step = iter.next();
147
+ strStep = strIter.next();
148
+ step = iter.next();
149
+ }
150
+ } finally {
151
+ step = iter.return();
152
+ if (step instanceof Promise) {
153
+ step = yield wait(step);
154
+ }
129
155
  }
130
-
131
- iter.return();
132
156
  return true;
133
157
  }
134
158
 
@@ -148,13 +172,13 @@ export const match = (pattern, source) => {
148
172
  }
149
173
 
150
174
  const pattern_ =
151
- pattern.type === null && pattern.flags.token
175
+ pattern.type === null && pattern.value.flags.token
152
176
  ? buildFragmentRegex(pattern)
153
177
  : isString(pattern)
154
178
  ? buildStringRegex(pattern)
155
179
  : pattern;
156
180
 
157
- if (printType(pattern_.type) !== 'Pattern') throw new Error();
181
+ if (printName(pattern_.value.name) !== 'Pattern') throw new Error();
158
182
 
159
183
  assertValidRegex(pattern_);
160
184
 
@@ -163,9 +187,11 @@ export const match = (pattern, source) => {
163
187
  const step = iter.next();
164
188
 
165
189
  return maybeWait(step, (step) => {
190
+ if (!step.done && step.value.length > 1) throw new Error('capturing group');
166
191
  const result = step.done ? null : step.value[0];
167
- iter.return();
168
- return isEmpty(result) ? null : result;
192
+ return maybeWait(iter.return(), () => {
193
+ return isEmpty(result) ? null : result;
194
+ });
169
195
  });
170
196
  };
171
197
 
@@ -201,6 +227,10 @@ class GuardedIterator {
201
227
  this.source.release();
202
228
  }
203
229
 
230
+ release() {
231
+ this.source.release();
232
+ }
233
+
204
234
  [streamIteratorSymbol]() {
205
235
  return this;
206
236
  }
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.22.1",
4
+ "version": "0.23.1",
5
5
  "author": "Conrad Buck<conartist6@gmail.com>",
6
6
  "type": "module",
7
7
  "files": [
@@ -12,13 +12,13 @@
12
12
  },
13
13
  "sideEffects": false,
14
14
  "dependencies": {
15
- "@bablr/agast-helpers": "0.9.0",
16
- "@bablr/agast-vm": "0.10.0",
17
- "@bablr/agast-vm-helpers": "0.9.0",
15
+ "@bablr/agast-helpers": "0.10.0",
16
+ "@bablr/agast-vm": "0.11.0",
17
+ "@bablr/agast-vm-helpers": "0.10.0",
18
18
  "@bablr/coroutine": "0.1.0",
19
- "@bablr/helpers": "0.24.0",
20
- "@bablr/regex-vm": "0.13.1",
21
- "@bablr/stream-iterator": "1.0.0",
19
+ "@bablr/helpers": "0.25.0",
20
+ "@bablr/regex-vm": "0.14.0",
21
+ "@bablr/stream-iterator": "2.0.0",
22
22
  "@bablr/weak-stack": "1.0.1",
23
23
  "@iter-tools/imm-stack": "1.2.0",
24
24
  "iter-tools-es": "7.5.3"
@@ -32,7 +32,10 @@
32
32
  "iter-tools-es": "^7.3.1",
33
33
  "prettier": "^2.6.2"
34
34
  },
35
- "repository": "github:bablr-lang/bablr-vm",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/bablr-lang/bablr-vm.git"
38
+ },
36
39
  "homepage": "https://github.com/bablr-lang/bablr-vm",
37
40
  "license": "MIT"
38
41
  }