@bablr/bablr-vm 0.20.1 → 0.22.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/context.js +9 -8
- package/lib/evaluate.js +329 -159
- package/lib/match.js +278 -115
- package/lib/node.js +123 -120
- package/lib/source.js +111 -114
- package/lib/spans.js +1 -4
- package/lib/state.js +184 -223
- package/lib/utils/pattern.js +116 -18
- package/package.json +8 -8
- package/lib/utils/array.js +0 -13
- package/lib/utils/format.js +0 -9
- package/lib/utils/object.js +0 -97
- package/lib/utils/pump.js +0 -20
- package/lib/utils/token.js +0 -30
package/lib/source.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { maybeWait, getStreamIterator, emptyStreamIterator } from '@bablr/agast-helpers/stream';
|
|
1
|
+
import { maybeWait, getStreamIterator } from '@bablr/agast-helpers/stream';
|
|
3
2
|
import { facades, actuals } from './facades.js';
|
|
3
|
+
import { streamIteratorSymbol } from '@bablr/stream-iterator';
|
|
4
4
|
|
|
5
|
-
// Queue item instances are shared between all
|
|
5
|
+
// Queue item instances are shared between all sources.
|
|
6
6
|
class QueueItem {
|
|
7
7
|
constructor(step) {
|
|
8
8
|
this.step = step;
|
|
@@ -17,7 +17,7 @@ class Exchange {
|
|
|
17
17
|
this.iterator = iterator;
|
|
18
18
|
this.tail = new QueueItem(null);
|
|
19
19
|
this.head = this.tail;
|
|
20
|
-
this.
|
|
20
|
+
this.sources = 0;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
static from(iterable) {
|
|
@@ -28,10 +28,19 @@ class Exchange {
|
|
|
28
28
|
return this.head.step instanceof Promise;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
const { head = this.tail, exchange = this,
|
|
33
|
-
++this.
|
|
34
|
-
return new
|
|
31
|
+
allocateSource(source) {
|
|
32
|
+
const { head = this.tail, exchange = this, index, holding, prevValue } = source || {};
|
|
33
|
+
++this.sources;
|
|
34
|
+
return new Source(head, exchange, index, holding, prevValue);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
releaseSource(source) {
|
|
38
|
+
--this.sources;
|
|
39
|
+
if (this.sources === 0) {
|
|
40
|
+
this.iterator.return?.();
|
|
41
|
+
}
|
|
42
|
+
source.exchange = null;
|
|
43
|
+
return { value: undefined, done: true };
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
advance() {
|
|
@@ -44,7 +53,6 @@ class Exchange {
|
|
|
44
53
|
if (step instanceof Promise) {
|
|
45
54
|
step = step.then((step) => {
|
|
46
55
|
newItem.step = step;
|
|
47
|
-
return step;
|
|
48
56
|
});
|
|
49
57
|
}
|
|
50
58
|
|
|
@@ -55,99 +63,47 @@ class Exchange {
|
|
|
55
63
|
|
|
56
64
|
return newItem;
|
|
57
65
|
}
|
|
66
|
+
}
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
return
|
|
68
|
+
let sources = new WeakMap();
|
|
69
|
+
|
|
70
|
+
class SourceIterator {
|
|
71
|
+
static from(source) {
|
|
72
|
+
const { exchange } = source;
|
|
73
|
+
return source.done
|
|
74
|
+
? sources.get(source) ?? new SourceIterator(source)
|
|
75
|
+
: new SourceIterator(exchange.allocateSource(source));
|
|
65
76
|
}
|
|
66
|
-
}
|
|
67
77
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
facades.set(fork.clone(), this);
|
|
78
|
+
constructor(source) {
|
|
79
|
+
sources.set(this, source);
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
next() {
|
|
74
|
-
const
|
|
75
|
-
if (!
|
|
76
|
-
const { head } =
|
|
77
|
-
|
|
78
|
-
return maybeWait(
|
|
83
|
+
const source = sources.get(this);
|
|
84
|
+
if (!source.done) {
|
|
85
|
+
const { holding, head } = source;
|
|
86
|
+
source.advance();
|
|
87
|
+
return maybeWait(source.head.step, () => {
|
|
88
|
+
return holding ? { value: null, done: false } : head.step;
|
|
89
|
+
});
|
|
79
90
|
} else {
|
|
80
91
|
return { value: undefined, done: true };
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
return() {
|
|
85
|
-
|
|
96
|
+
sources.get(this).release();
|
|
97
|
+
|
|
86
98
|
return { value: undefined, done: true };
|
|
87
99
|
}
|
|
88
100
|
|
|
89
|
-
[Symbol.
|
|
101
|
+
[Symbol.iterator]() {
|
|
90
102
|
return this;
|
|
91
103
|
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
class Fork {
|
|
95
|
-
constructor(head, exchange, done = false) {
|
|
96
|
-
this.head = head; // QueueItem
|
|
97
|
-
this.exchange = exchange;
|
|
98
|
-
this._done = done;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
get done() {
|
|
102
|
-
return this._done || this.head.step?.done;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
get value() {
|
|
106
|
-
return this.done ? { value: undefined, done: true } : this.head.step?.value;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
advance() {
|
|
110
|
-
const { exchange } = this;
|
|
111
|
-
|
|
112
|
-
if (this.done) {
|
|
113
|
-
throw new Error('cannot advance a fork that is done');
|
|
114
|
-
} else {
|
|
115
|
-
let { head } = this;
|
|
116
|
-
|
|
117
|
-
let nextItem = this.head.next;
|
|
118
|
-
|
|
119
|
-
if (!head.step?.done) {
|
|
120
|
-
if (!nextItem) {
|
|
121
|
-
nextItem = exchange.fetch();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
this.head = nextItem;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return nextItem;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return() {
|
|
132
|
-
const { done, exchange } = this;
|
|
133
|
-
|
|
134
|
-
if (!done) exchange.releaseFork(this);
|
|
135
104
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this._current = step;
|
|
139
|
-
|
|
140
|
-
return step;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
clone() {
|
|
144
|
-
const { exchange } = this;
|
|
145
|
-
|
|
146
|
-
return exchange.allocateFork(this);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
[Symbol.for('@@streamIterator')]() {
|
|
150
|
-
return new ForkIterator(this);
|
|
105
|
+
[streamIteratorSymbol]() {
|
|
106
|
+
return this;
|
|
151
107
|
}
|
|
152
108
|
}
|
|
153
109
|
|
|
@@ -158,10 +114,12 @@ export const SourceFacade = class BABLRSourceFacade {
|
|
|
158
114
|
|
|
159
115
|
constructor(source) {
|
|
160
116
|
facades.set(source, this);
|
|
117
|
+
|
|
118
|
+
Object.freeze(this);
|
|
161
119
|
}
|
|
162
120
|
|
|
163
|
-
[
|
|
164
|
-
return actuals.get(this)[
|
|
121
|
+
[streamIteratorSymbol]() {
|
|
122
|
+
return actuals.get(this)[streamIteratorSymbol]();
|
|
165
123
|
}
|
|
166
124
|
|
|
167
125
|
get done() {
|
|
@@ -181,47 +139,36 @@ export const SourceFacade = class BABLRSourceFacade {
|
|
|
181
139
|
}
|
|
182
140
|
};
|
|
183
141
|
|
|
184
|
-
export const Source = class BABLRSource
|
|
142
|
+
export const Source = class BABLRSource {
|
|
185
143
|
static from(iterable) {
|
|
186
144
|
const exchange = Exchange.from(iterable);
|
|
187
|
-
return
|
|
145
|
+
return exchange.allocateSource();
|
|
188
146
|
}
|
|
189
147
|
|
|
190
|
-
constructor(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (!fork || !exchange) throw new Error();
|
|
148
|
+
constructor(head, exchange, index = -1, holding = false, prevValue = undefined) {
|
|
149
|
+
if (!head || !exchange) throw new Error();
|
|
194
150
|
|
|
195
|
-
this.
|
|
151
|
+
this.head = head;
|
|
196
152
|
this.exchange = exchange;
|
|
197
153
|
this.index = index;
|
|
198
154
|
this.holding = holding;
|
|
155
|
+
this.prevValue = prevValue;
|
|
199
156
|
|
|
200
157
|
new SourceFacade(this);
|
|
201
158
|
}
|
|
202
159
|
|
|
203
160
|
get value() {
|
|
204
|
-
return this.holding ? null : this.
|
|
161
|
+
return this.holding ? null : this.head.step?.value;
|
|
205
162
|
}
|
|
206
163
|
|
|
207
164
|
get done() {
|
|
208
|
-
return this.
|
|
165
|
+
return !this.exchange || this.head.step?.done;
|
|
209
166
|
}
|
|
210
167
|
|
|
211
168
|
get atGap() {
|
|
212
169
|
return this.holding || (!this.done && this.value == null);
|
|
213
170
|
}
|
|
214
171
|
|
|
215
|
-
advance(n = 1) {
|
|
216
|
-
return new Array(n).fill(null).reduce((acc) => {
|
|
217
|
-
return maybeWait(acc, () => {
|
|
218
|
-
this.fork.advance();
|
|
219
|
-
this.index++;
|
|
220
|
-
return this.fork.step;
|
|
221
|
-
});
|
|
222
|
-
}, this.fork.step);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
172
|
shift() {
|
|
226
173
|
this.holding = true;
|
|
227
174
|
}
|
|
@@ -230,30 +177,80 @@ export const Source = class BABLRSource extends WeakStackFrame {
|
|
|
230
177
|
this.holding = false;
|
|
231
178
|
}
|
|
232
179
|
|
|
180
|
+
advance(n = 1) {
|
|
181
|
+
let { exchange } = this;
|
|
182
|
+
|
|
183
|
+
if (this.holding) {
|
|
184
|
+
this.holding = false;
|
|
185
|
+
n--;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return new Array(n).fill(null).reduce((acc) => {
|
|
189
|
+
return maybeWait(acc, () => {
|
|
190
|
+
if (this.done) {
|
|
191
|
+
throw new Error('cannot advance a source that is done');
|
|
192
|
+
} else {
|
|
193
|
+
let { head, value } = this;
|
|
194
|
+
|
|
195
|
+
let nextItem = head.next;
|
|
196
|
+
|
|
197
|
+
if (!this.done) {
|
|
198
|
+
if (!nextItem) {
|
|
199
|
+
nextItem = exchange.fetch();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
this.head = head = nextItem;
|
|
203
|
+
this.prevValue = value;
|
|
204
|
+
|
|
205
|
+
if (head.step?.done) {
|
|
206
|
+
exchange.releaseSource(this);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
this.index++;
|
|
212
|
+
return this.head.step;
|
|
213
|
+
});
|
|
214
|
+
}, this.head.step);
|
|
215
|
+
}
|
|
216
|
+
|
|
233
217
|
branch() {
|
|
234
|
-
const {
|
|
235
|
-
|
|
218
|
+
const { exchange } = this;
|
|
219
|
+
|
|
220
|
+
return exchange ? exchange.allocateSource(this) : this;
|
|
236
221
|
}
|
|
237
222
|
|
|
238
223
|
release() {
|
|
239
|
-
this
|
|
224
|
+
const { exchange, head } = this;
|
|
225
|
+
|
|
226
|
+
if (exchange) exchange.releaseSource(this);
|
|
227
|
+
|
|
228
|
+
const step = { value: undefined, done: true };
|
|
229
|
+
|
|
230
|
+
this.head = { ...head, step };
|
|
231
|
+
|
|
232
|
+
return step;
|
|
240
233
|
}
|
|
241
234
|
|
|
242
235
|
accept(source) {
|
|
243
|
-
this.
|
|
244
|
-
this.fork = source.fork;
|
|
236
|
+
this.head = source.head;
|
|
245
237
|
this.index = source.index;
|
|
246
238
|
this.holding = source.holding;
|
|
239
|
+
this.prevValue = source.prevValue;
|
|
240
|
+
|
|
241
|
+
source.release();
|
|
247
242
|
}
|
|
248
243
|
|
|
249
244
|
reject() {
|
|
250
245
|
this.release();
|
|
251
246
|
}
|
|
252
247
|
|
|
253
|
-
[Symbol.
|
|
254
|
-
return
|
|
255
|
-
|
|
256
|
-
|
|
248
|
+
[Symbol.iterator]() {
|
|
249
|
+
return SourceIterator.from(this);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
[streamIteratorSymbol]() {
|
|
253
|
+
return SourceIterator.from(this);
|
|
257
254
|
}
|
|
258
255
|
|
|
259
256
|
formatIndex() {
|
package/lib/spans.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { ReferenceTag } from '@bablr/agast-helpers/symbols';
|
|
2
|
-
import { getOpenTag } from '@bablr/agast-helpers/tree';
|
|
3
2
|
|
|
4
3
|
export function updateSpans(m, node, phase) {
|
|
5
4
|
const { state: s } = m;
|
|
6
|
-
const {
|
|
5
|
+
const { attributes } = node;
|
|
7
6
|
const refPath = m.reference;
|
|
8
7
|
|
|
9
8
|
if (refPath && refPath.tag.type !== ReferenceTag) throw new Error();
|
|
10
9
|
|
|
11
|
-
const openTag = getOpenTag(node);
|
|
12
|
-
|
|
13
10
|
const intrinsic = !refPath || (refPath.tag.type === ReferenceTag && !refPath.tag.value.hasGap);
|
|
14
11
|
|
|
15
12
|
switch (phase) {
|