@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/evaluate.js
CHANGED
|
@@ -1,35 +1,51 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
buildAttributeDefinition,
|
|
4
|
+
buildBindingTag,
|
|
5
|
+
buildChild,
|
|
6
|
+
buildCloseNodeTag,
|
|
7
|
+
buildFacadeProperty,
|
|
8
|
+
buildProperty,
|
|
9
|
+
} from '@bablr/agast-helpers/builders';
|
|
3
10
|
import { getStreamIterator, printType, StreamIterable } from '@bablr/agast-helpers/stream';
|
|
4
|
-
import { formatType } from './utils/format.js';
|
|
5
11
|
import { facades } from './facades.js';
|
|
6
|
-
import {
|
|
12
|
+
import { State } from './state.js';
|
|
7
13
|
import { updateSpans } from './spans.js';
|
|
8
14
|
import {
|
|
9
15
|
OpenNodeTag,
|
|
10
16
|
CloseNodeTag,
|
|
11
17
|
GapTag,
|
|
18
|
+
BindingTag,
|
|
12
19
|
LiteralTag,
|
|
13
20
|
ReferenceTag,
|
|
14
|
-
DoctypeTag,
|
|
15
21
|
NullTag,
|
|
16
22
|
ShiftTag,
|
|
23
|
+
InitializerTag,
|
|
24
|
+
AttributeDefinition,
|
|
25
|
+
Property,
|
|
17
26
|
} from '@bablr/agast-helpers/symbols';
|
|
18
27
|
import * as sym from '@bablr/agast-vm-helpers/symbols';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import
|
|
28
|
+
import { agast, PathFacade, TagPathFacade as TagPath } from '@bablr/agast-vm';
|
|
29
|
+
import { states } from './node.js';
|
|
30
|
+
import {
|
|
31
|
+
buildOpenNodeTag,
|
|
32
|
+
buildReferenceTag,
|
|
33
|
+
buildStubNode,
|
|
34
|
+
getFlagsWithGap,
|
|
35
|
+
getRoot,
|
|
36
|
+
treeFromStreamSync,
|
|
37
|
+
} from '@bablr/agast-helpers/tree';
|
|
22
38
|
import { getEmbeddedObject, getEmbeddedTag } from '@bablr/agast-vm-helpers/deembed';
|
|
23
39
|
import { Match } from './match.js';
|
|
24
40
|
import { effectsFor, reifyExpression } from '@bablr/agast-vm-helpers';
|
|
25
|
-
import { TagPath } from '@bablr/agast-helpers/path';
|
|
26
41
|
import { getProduction } from '@bablr/helpers/grammar';
|
|
27
|
-
import { buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
import { buildEmbeddedNode, buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
|
|
43
|
+
import { has } from '@bablr/agast-helpers/object';
|
|
44
|
+
import { referencesAreEqual } from '@bablr/agast-helpers/path';
|
|
45
|
+
import { isPlainObject } from '@bablr/helpers/object';
|
|
31
46
|
|
|
32
|
-
|
|
47
|
+
const defineAttribute = (m, path, value) => {
|
|
48
|
+
m.agast.vm.next(buildAttributeDefinition(path, value));
|
|
33
49
|
};
|
|
34
50
|
|
|
35
51
|
const getSourceLength = (tags) => {
|
|
@@ -64,6 +80,18 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
if (co.done) {
|
|
83
|
+
if (!s.source.done) {
|
|
84
|
+
throw new Error(`parse ate ${s.source.index} characters but the input was not consumed`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let { exchange } = s.source;
|
|
88
|
+
|
|
89
|
+
s.source.release();
|
|
90
|
+
|
|
91
|
+
if (exchange && exchange.sources > 0) {
|
|
92
|
+
throw new Error('Source did not close all forks: ' + exchange.sources);
|
|
93
|
+
}
|
|
94
|
+
|
|
67
95
|
return co.value && states.get(co.value).node;
|
|
68
96
|
}
|
|
69
97
|
|
|
@@ -73,24 +101,27 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
73
101
|
const { verb } = instr;
|
|
74
102
|
|
|
75
103
|
switch (verb) {
|
|
76
|
-
case '
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (language !== null) throw new Error();
|
|
104
|
+
case 'write': {
|
|
105
|
+
const { arguments: { 0: text, 1: { value: writeOptions } = {} } = [] } = instr;
|
|
80
106
|
|
|
81
|
-
|
|
107
|
+
if (options.emitEffects) {
|
|
108
|
+
yield buildWriteEffect(text, writeOptions);
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
82
112
|
|
|
83
|
-
|
|
113
|
+
case 'match': {
|
|
114
|
+
let { arguments: { 0: pattern } = [] } = instr;
|
|
84
115
|
|
|
85
|
-
|
|
116
|
+
let result = s.guardedMatch(pattern, pattern.attributes);
|
|
86
117
|
|
|
87
|
-
if (
|
|
88
|
-
yield
|
|
118
|
+
if (result instanceof Promise) {
|
|
119
|
+
result = yield result;
|
|
89
120
|
}
|
|
90
121
|
|
|
91
|
-
|
|
122
|
+
let node = result && treeFromStreamSync(result);
|
|
92
123
|
|
|
93
|
-
returnValue =
|
|
124
|
+
returnValue = node && buildEmbeddedNode(node);
|
|
94
125
|
break;
|
|
95
126
|
}
|
|
96
127
|
|
|
@@ -100,50 +131,141 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
100
131
|
const tag = getEmbeddedTag(embeddedTags);
|
|
101
132
|
|
|
102
133
|
if (tag.type !== ReferenceTag) {
|
|
103
|
-
s.
|
|
134
|
+
s.referenceTagPath = null;
|
|
104
135
|
}
|
|
105
136
|
|
|
106
|
-
if (
|
|
137
|
+
if (
|
|
138
|
+
!m.isNode &&
|
|
139
|
+
m.coveredBoundary !== m &&
|
|
140
|
+
!((s.holding && tag.type === GapTag) || tag.type === OpenNodeTag)
|
|
141
|
+
) {
|
|
107
142
|
throw new Error('cannot advance inside a cover');
|
|
143
|
+
}
|
|
108
144
|
|
|
109
145
|
switch (tag.type) {
|
|
110
|
-
case
|
|
111
|
-
s.node
|
|
112
|
-
s.node.type
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
case ReferenceTag: {
|
|
147
|
+
if (s.node.type && tag.value.type === '.') throw new Error();
|
|
148
|
+
if (s.held && s.node.tags.at(2)?.type === InitializerTag) {
|
|
149
|
+
if (!referencesAreEqual(s.node.tags.at(1).value, tag.value) || s.node.tags.size > 3) {
|
|
150
|
+
throw new Error();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
115
153
|
|
|
116
|
-
m.
|
|
154
|
+
m.advance(tag, s);
|
|
155
|
+
|
|
156
|
+
s.referenceTagPath = TagPath.from(s.path, -1, 0);
|
|
157
|
+
if (s.referenceTagPath.tag.type === BindingTag) throw new Error();
|
|
117
158
|
break;
|
|
118
159
|
}
|
|
119
160
|
|
|
120
|
-
case
|
|
121
|
-
|
|
161
|
+
case ShiftTag: {
|
|
162
|
+
let { index, height } = tag.value;
|
|
163
|
+
let refTag = s.node.tags.at(-1, 0);
|
|
164
|
+
let lastShiftTag = refTag;
|
|
165
|
+
|
|
166
|
+
if (refTag.type === ShiftTag) {
|
|
167
|
+
refTag = s.node.tags.at(-refTag.value.index - 1, 0);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (refTag.type !== ReferenceTag) throw new Error();
|
|
171
|
+
|
|
172
|
+
s.depths.shift = height;
|
|
173
|
+
s.depths.nodeShift = index;
|
|
174
|
+
|
|
175
|
+
if (index !== (lastShiftTag.type === ShiftTag ? lastShiftTag.value.index + 1 : 1)) {
|
|
176
|
+
throw new Error();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
s.source.shift();
|
|
180
|
+
s.held = buildFacadeProperty(
|
|
181
|
+
refTag.value,
|
|
182
|
+
s.resultPath.tag.value,
|
|
183
|
+
s.resultPath.nextSibling.tag.value.node,
|
|
184
|
+
);
|
|
122
185
|
|
|
123
|
-
|
|
124
|
-
|
|
186
|
+
m.advance(tag, s);
|
|
187
|
+
s.referenceTagPath = TagPath.from(s.path, 0);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
case BindingTag: {
|
|
192
|
+
m.advance(tag, s);
|
|
193
|
+
|
|
194
|
+
let propertyChild = buildChild(
|
|
195
|
+
sym.Property,
|
|
196
|
+
buildProperty(s.held.reference, tag.value, s.held.node.node),
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
m.agastFragment.vm.next(propertyChild);
|
|
200
|
+
|
|
201
|
+
s.held = null;
|
|
125
202
|
break;
|
|
126
203
|
}
|
|
127
204
|
|
|
128
205
|
case OpenNodeTag: {
|
|
129
|
-
|
|
206
|
+
let { literalValue, selfClosing } = tag.value;
|
|
130
207
|
|
|
131
|
-
|
|
132
|
-
|
|
208
|
+
s.depths.path++;
|
|
209
|
+
s.depths.nodeShift = 0;
|
|
133
210
|
|
|
134
|
-
|
|
211
|
+
if (!m.coveredBoundary.shiftMatch) {
|
|
212
|
+
s.depths.shift = 0;
|
|
135
213
|
}
|
|
136
214
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
215
|
+
s.agast = m.agast;
|
|
216
|
+
|
|
217
|
+
m.advance(tag, s);
|
|
218
|
+
const refPath = m.referencePath;
|
|
219
|
+
|
|
220
|
+
if (selfClosing) {
|
|
221
|
+
if (literalValue) {
|
|
222
|
+
let result;
|
|
223
|
+
if (
|
|
224
|
+
s.resultPath.tag.type === OpenNodeTag &&
|
|
225
|
+
s.resultPath.tag.value.attributes.balancer &&
|
|
226
|
+
s.balanced.value?.attributes.balanced === literalValue
|
|
227
|
+
) {
|
|
228
|
+
result = s.match(literalValue, tag.value.attributes);
|
|
229
|
+
} else {
|
|
230
|
+
result = s.guardedMatch(literalValue, tag.value.attributes);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (result instanceof Promise) {
|
|
234
|
+
result = yield result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (result) {
|
|
238
|
+
let sourceStep = s.source.advance(getSourceLength(result));
|
|
239
|
+
|
|
240
|
+
if (sourceStep instanceof Promise) {
|
|
241
|
+
sourceStep = yield sourceStep;
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
throw new Error('Failed to advance literal');
|
|
245
|
+
}
|
|
140
246
|
}
|
|
247
|
+
|
|
248
|
+
s.depths.path--;
|
|
249
|
+
s.depths.nodeShift = 0;
|
|
250
|
+
s.depths.shift = 0;
|
|
251
|
+
|
|
252
|
+
s.agast = m.agastFragment;
|
|
253
|
+
s.held = Object.freeze({
|
|
254
|
+
reference: refPath.tag.value,
|
|
255
|
+
binding: null,
|
|
256
|
+
node: s.resultPath.node,
|
|
257
|
+
});
|
|
141
258
|
}
|
|
142
259
|
|
|
143
|
-
s.
|
|
260
|
+
if (s.depths.path === 0) {
|
|
261
|
+
m.setRangePreviousIndex(0);
|
|
262
|
+
}
|
|
144
263
|
|
|
145
264
|
if (tag.value.type) {
|
|
146
|
-
updateSpans(m, s.node, 'open');
|
|
265
|
+
updateSpans(m, s.resultPath.node, 'open');
|
|
266
|
+
}
|
|
267
|
+
if (literalValue) {
|
|
268
|
+
updateSpans(m, s.resultPath.node, 'close');
|
|
147
269
|
}
|
|
148
270
|
|
|
149
271
|
break;
|
|
@@ -153,41 +275,67 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
153
275
|
const { node } = s;
|
|
154
276
|
|
|
155
277
|
s.depths.path--;
|
|
278
|
+
s.depths.nodeShift = 0;
|
|
279
|
+
s.depths.shift = 0;
|
|
156
280
|
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
nodeStates.get(m.node).undefinedAttributes.delete('cooked');
|
|
180
|
-
}
|
|
281
|
+
if (m.rangeInitial?.tag.type === ShiftTag) {
|
|
282
|
+
s.depths.nodeShift = m.rangeInitial.tag.value.index;
|
|
283
|
+
s.depths.shift = m.rangeInitial.tag.value.height;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (node.tags.at(0).value.type) {
|
|
287
|
+
const refPath = m.referencePath;
|
|
288
|
+
|
|
289
|
+
m.advance(tag, s);
|
|
290
|
+
let gaplessNode = null;
|
|
291
|
+
|
|
292
|
+
if (refPath?.tag.value.type === '@') {
|
|
293
|
+
let { vm: escapeVm, state: escapeState } = agast();
|
|
294
|
+
|
|
295
|
+
let tagPath = PathFacade.from(node).tagPathAt(0);
|
|
296
|
+
|
|
297
|
+
while (tagPath) {
|
|
298
|
+
if (tagPath.tag.type === GapTag) {
|
|
299
|
+
throw new Error();
|
|
300
|
+
}
|
|
301
|
+
if (tagPath.tag.type === OpenNodeTag) {
|
|
302
|
+
let { flags, type, attributes, literalValue } = tagPath.tag.value;
|
|
181
303
|
|
|
182
|
-
|
|
304
|
+
escapeVm.next(
|
|
305
|
+
buildOpenNodeTag(
|
|
306
|
+
getFlagsWithGap(flags, false),
|
|
307
|
+
type,
|
|
308
|
+
attributes,
|
|
309
|
+
literalValue,
|
|
310
|
+
),
|
|
311
|
+
);
|
|
312
|
+
} else if (tagPath.tag.type === ReferenceTag && tagPath.tag.value.flags.hasGap) {
|
|
313
|
+
let { flags, name, type, isArray, index } = tagPath.tag.value;
|
|
183
314
|
|
|
184
|
-
|
|
185
|
-
// m.add(m.node);
|
|
186
|
-
// }
|
|
315
|
+
flags = getFlagsWithGap(flags, false);
|
|
187
316
|
|
|
188
|
-
|
|
317
|
+
escapeVm.next(buildReferenceTag(type, name, isArray, flags, index));
|
|
318
|
+
} else {
|
|
319
|
+
escapeVm.next(tagPath.tag);
|
|
320
|
+
}
|
|
189
321
|
|
|
190
|
-
|
|
322
|
+
if (tagPath.tag.type === CloseNodeTag && !tagPath.nextUnshifted) {
|
|
323
|
+
gaplessNode = escapeState.resultPath.node;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
tagPath = tagPath.nextUnshifted;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
s.agast = m.agastFragment;
|
|
331
|
+
|
|
332
|
+
s.held = Object.freeze({
|
|
333
|
+
reference: refPath?.tag.value,
|
|
334
|
+
binding: null,
|
|
335
|
+
node: gaplessNode || m.node,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
updateSpans(m, s.resultPath.node, 'close');
|
|
191
339
|
|
|
192
340
|
if (!m.parent) {
|
|
193
341
|
if (!s.source.done) {
|
|
@@ -199,8 +347,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
199
347
|
}
|
|
200
348
|
}
|
|
201
349
|
} else {
|
|
202
|
-
|
|
203
|
-
s.
|
|
350
|
+
m.advance(tag, s);
|
|
351
|
+
s.agast = m.agastFragment;
|
|
204
352
|
}
|
|
205
353
|
|
|
206
354
|
break;
|
|
@@ -231,7 +379,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
231
379
|
sourceStep = yield sourceStep;
|
|
232
380
|
}
|
|
233
381
|
|
|
234
|
-
|
|
382
|
+
m.advance(tag, s);
|
|
235
383
|
} else {
|
|
236
384
|
throw new Error('Failed to advance literal');
|
|
237
385
|
}
|
|
@@ -251,64 +399,87 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
251
399
|
}
|
|
252
400
|
|
|
253
401
|
if (s.held) {
|
|
254
|
-
|
|
402
|
+
if (!s.agast.state.held) throw new Error();
|
|
403
|
+
s.agast.vm.next(
|
|
404
|
+
buildChild(
|
|
405
|
+
Property,
|
|
406
|
+
buildProperty(m.referencePath.tag.value, null, buildStubNode(tag)),
|
|
407
|
+
),
|
|
408
|
+
);
|
|
255
409
|
|
|
256
|
-
s.resultPath = TagPath.
|
|
410
|
+
s.resultPath = TagPath.from(s.resultPath.path, -1);
|
|
257
411
|
|
|
258
412
|
s.held = null;
|
|
259
413
|
break;
|
|
260
414
|
}
|
|
261
415
|
|
|
262
416
|
if (s.expressions.size) {
|
|
263
|
-
|
|
417
|
+
let expression = s.expressions.value;
|
|
418
|
+
let node = getRoot(isPlainObject(expression) ? expression : expression.node);
|
|
419
|
+
|
|
420
|
+
let mergedBinding = buildBindingTag(m.mergedLanguagePath);
|
|
264
421
|
|
|
265
|
-
|
|
422
|
+
s.agast.vm.next(mergedBinding);
|
|
423
|
+
s.agast.vm.next(
|
|
424
|
+
buildChild(
|
|
425
|
+
Property,
|
|
426
|
+
buildProperty(s.resultPath.tag.value, mergedBinding.value, node),
|
|
427
|
+
),
|
|
428
|
+
);
|
|
266
429
|
|
|
267
430
|
s.expressions = s.expressions.pop();
|
|
268
431
|
break;
|
|
269
432
|
}
|
|
270
433
|
|
|
271
|
-
if (
|
|
272
|
-
|
|
434
|
+
if (s.node.tags.size) {
|
|
435
|
+
m.advance(tag, s);
|
|
273
436
|
} else {
|
|
274
437
|
m.add(m.node);
|
|
275
438
|
|
|
276
|
-
|
|
439
|
+
m.advance(tag, s);
|
|
277
440
|
}
|
|
278
441
|
|
|
279
|
-
s.
|
|
442
|
+
s.referenceTagPath = null;
|
|
280
443
|
|
|
281
|
-
s.
|
|
444
|
+
s.agast = m.agastFragment;
|
|
282
445
|
} else {
|
|
283
446
|
throw new Error('Failed to advance gap');
|
|
284
447
|
}
|
|
285
448
|
break;
|
|
286
449
|
}
|
|
287
450
|
|
|
288
|
-
|
|
289
|
-
s.
|
|
290
|
-
|
|
451
|
+
case InitializerTag: {
|
|
452
|
+
if (s.held && s.node.tags.at(2)?.type === InitializerTag) {
|
|
453
|
+
throw new Error();
|
|
454
|
+
}
|
|
455
|
+
m.advance(tag, s);
|
|
456
|
+
break;
|
|
457
|
+
}
|
|
291
458
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
459
|
+
case AttributeDefinition: {
|
|
460
|
+
const { path, value } = tag.value;
|
|
295
461
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
462
|
+
if (!has(m.node.attributes, path)) {
|
|
463
|
+
throw new Error('undefined attributes must be declared');
|
|
464
|
+
}
|
|
299
465
|
|
|
300
|
-
|
|
301
|
-
let { arguments: { 0: pattern } = [] } = instr;
|
|
466
|
+
if (s.held) throw new Error('invalid place for an attribute binding');
|
|
302
467
|
|
|
303
|
-
|
|
468
|
+
if (value && typeof value === 'object') throw new Error('unimplemented');
|
|
304
469
|
|
|
305
|
-
|
|
306
|
-
|
|
470
|
+
defineAttribute(m, path, value);
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
default:
|
|
475
|
+
m.advance(tag, s);
|
|
307
476
|
}
|
|
308
477
|
|
|
309
|
-
|
|
478
|
+
if (s.depth === 0 && (s.node || s.resultPath?.node)) {
|
|
479
|
+
yield* m.emit(options);
|
|
480
|
+
}
|
|
310
481
|
|
|
311
|
-
returnValue =
|
|
482
|
+
returnValue = tag;
|
|
312
483
|
break;
|
|
313
484
|
}
|
|
314
485
|
|
|
@@ -327,6 +498,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
327
498
|
case 'branch': {
|
|
328
499
|
s = s.branch();
|
|
329
500
|
|
|
501
|
+
// m.node = s.agast.node;
|
|
502
|
+
|
|
330
503
|
returnValue = facades.get(s);
|
|
331
504
|
break;
|
|
332
505
|
}
|
|
@@ -334,6 +507,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
334
507
|
case 'accept': {
|
|
335
508
|
s = s.accept(finishedMatch.fragmentNode);
|
|
336
509
|
|
|
510
|
+
if (s.depth === 0 && (s.node || s.resultPath?.node)) {
|
|
511
|
+
yield* m.emit(options);
|
|
512
|
+
}
|
|
513
|
+
|
|
337
514
|
returnValue = facades.get(s);
|
|
338
515
|
break;
|
|
339
516
|
}
|
|
@@ -351,6 +528,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
351
528
|
|
|
352
529
|
s = finishedState.parent;
|
|
353
530
|
|
|
531
|
+
if (s.depth === 0 && (s.node || s.resultPath?.node)) {
|
|
532
|
+
yield* m.emit(options);
|
|
533
|
+
}
|
|
534
|
+
|
|
354
535
|
returnValue = facades.get(s);
|
|
355
536
|
break;
|
|
356
537
|
}
|
|
@@ -361,9 +542,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
361
542
|
} = instr;
|
|
362
543
|
|
|
363
544
|
let effects = effectsFor(verb.description);
|
|
364
|
-
let didShift = verb.description.startsWith('
|
|
365
|
-
|
|
366
|
-
let { undefinedAttributes } = options;
|
|
545
|
+
let didShift = verb.description.startsWith('shift');
|
|
367
546
|
|
|
368
547
|
let parentMatch = m;
|
|
369
548
|
|
|
@@ -379,8 +558,6 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
379
558
|
|
|
380
559
|
finishedMatch = null;
|
|
381
560
|
|
|
382
|
-
if (m.isNode && m.isCover) throw new Error();
|
|
383
|
-
|
|
384
561
|
if (m.type !== sym.fragment && !getProduction(m.grammar, m.type))
|
|
385
562
|
throw new Error(`Production {type: ${printType(m.type)}} does not exist`);
|
|
386
563
|
|
|
@@ -388,45 +565,42 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
388
565
|
throw new Error('tokens must be nodes');
|
|
389
566
|
}
|
|
390
567
|
|
|
391
|
-
if (parentMatch && parentMatch.cover && !
|
|
568
|
+
if (parentMatch && parentMatch.cover && !parentMatch.isNode) {
|
|
392
569
|
if (matcher_.refMatcher) {
|
|
393
570
|
let m = matcher_.refMatcher;
|
|
394
|
-
if (!
|
|
571
|
+
if (!['.', '#'].includes(m.type) || m.flags.expression || m.flags.hasGap || m.isArray) {
|
|
395
572
|
throw new Error('no references inside covers');
|
|
396
573
|
}
|
|
397
574
|
}
|
|
398
575
|
}
|
|
399
576
|
|
|
400
577
|
if (didShift) {
|
|
401
|
-
s.
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
let refTag = sumtree.getAt(-2, s.node.children);
|
|
405
|
-
|
|
406
|
-
s.advance(buildShiftTag(refTag.type === ShiftTag ? refTag.value.index + 1 : 1));
|
|
407
|
-
s.referencePath = TagPath.fromNode(s.node, -1);
|
|
578
|
+
if (s.node.tags.at(-1, 0)?.type !== ShiftTag) {
|
|
579
|
+
throw new Error('advance shift tag before starting new held frame');
|
|
580
|
+
}
|
|
408
581
|
}
|
|
409
582
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
m.fragmentNode = s.node;
|
|
583
|
+
let broken = !parentMatch || effects.success === 'none' || s.agast.state.node.type === null;
|
|
413
584
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
});
|
|
585
|
+
if (effects.success !== 'none') {
|
|
586
|
+
m.agastFragment = s.agast;
|
|
587
|
+
} else {
|
|
588
|
+
s.agast = m.agastFragment = m.agast;
|
|
589
|
+
s.referenceTagPath = null;
|
|
590
|
+
}
|
|
421
591
|
|
|
422
592
|
({ language } = m);
|
|
423
593
|
|
|
424
|
-
|
|
594
|
+
let offset = [ReferenceTag, ShiftTag].includes(s.resultPath?.tag.type) ? -1 : 0;
|
|
595
|
+
|
|
596
|
+
if (!broken) {
|
|
425
597
|
let previousIndex = [CloseNodeTag, NullTag, GapTag].includes(s.resultPath.tag.type)
|
|
426
|
-
?
|
|
427
|
-
: s.resultPath.
|
|
598
|
+
? m.fragmentNode.tags.size - 1
|
|
599
|
+
: s.resultPath.tagsIndex;
|
|
428
600
|
|
|
429
|
-
m.setRangePreviousIndex(previousIndex);
|
|
601
|
+
m.setRangePreviousIndex(previousIndex + offset);
|
|
602
|
+
} else if (parentMatch) {
|
|
603
|
+
m.setRangePreviousIndex(m.fragmentNode.tags.size - 1 + offset);
|
|
430
604
|
}
|
|
431
605
|
|
|
432
606
|
returnValue = facades.get(m);
|
|
@@ -436,22 +610,23 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
436
610
|
}
|
|
437
611
|
|
|
438
612
|
case 'endFrame': {
|
|
439
|
-
const {
|
|
440
|
-
arguments: { 0: hasContinuation },
|
|
441
|
-
} = instr;
|
|
442
613
|
finishedMatch = m;
|
|
443
614
|
|
|
444
615
|
m = m.endFrame();
|
|
445
616
|
|
|
617
|
+
if (finishedMatch.effects.success !== 'none') {
|
|
618
|
+
s.agast = finishedMatch.agastFragment;
|
|
619
|
+
} else {
|
|
620
|
+
finishedMatch.agastFragment.vm.next(buildCloseNodeTag());
|
|
621
|
+
s.agast = m.agast;
|
|
622
|
+
s.referenceTagPath = m.referencePath;
|
|
623
|
+
}
|
|
624
|
+
|
|
446
625
|
if (!m) {
|
|
447
626
|
returnValue = m;
|
|
448
627
|
break;
|
|
449
628
|
}
|
|
450
629
|
|
|
451
|
-
if (finishedMatch.state.status !== 'rejected') {
|
|
452
|
-
yield* m.emit();
|
|
453
|
-
}
|
|
454
|
-
|
|
455
630
|
returnValue = m && facades.get(m);
|
|
456
631
|
break;
|
|
457
632
|
}
|
|
@@ -461,50 +636,45 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
461
636
|
|
|
462
637
|
m = m.throw_();
|
|
463
638
|
|
|
464
|
-
s.status = 'rejected';
|
|
465
639
|
if (m && finishedMatch.s === s) {
|
|
466
|
-
s.
|
|
640
|
+
s.agast = m.agast;
|
|
467
641
|
}
|
|
468
642
|
|
|
469
643
|
returnValue = m && facades.get(m);
|
|
470
644
|
break;
|
|
471
645
|
}
|
|
472
646
|
|
|
473
|
-
case '
|
|
474
|
-
|
|
647
|
+
case 'getState': {
|
|
648
|
+
returnValue = facades.get(s);
|
|
649
|
+
break;
|
|
650
|
+
}
|
|
475
651
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (value && typeof value === 'object') throw new Error('unimplemented');
|
|
652
|
+
case 'init': {
|
|
653
|
+
let { arguments: { 0: canonicalURL } = [] } = instr;
|
|
479
654
|
|
|
480
|
-
|
|
655
|
+
if (language !== null) throw new Error();
|
|
481
656
|
|
|
482
|
-
|
|
657
|
+
s = State.from(rootSource, ctx, canonicalURL, options.expressions);
|
|
483
658
|
|
|
484
|
-
|
|
485
|
-
}
|
|
659
|
+
s.source.advance();
|
|
486
660
|
|
|
487
|
-
|
|
488
|
-
const { arguments: { 0: text, 1: { value: writeOptions } = {} } = [] } = instr;
|
|
661
|
+
const sourceStep = s.source.head.step;
|
|
489
662
|
|
|
490
|
-
if (
|
|
491
|
-
yield
|
|
663
|
+
if (sourceStep instanceof Promise) {
|
|
664
|
+
yield sourceStep;
|
|
492
665
|
}
|
|
493
|
-
break;
|
|
494
|
-
}
|
|
495
666
|
|
|
496
|
-
|
|
667
|
+
language = ctx.languages.get(canonicalURL);
|
|
668
|
+
|
|
497
669
|
returnValue = facades.get(s);
|
|
498
670
|
break;
|
|
499
671
|
}
|
|
500
672
|
|
|
501
673
|
default: {
|
|
502
|
-
throw new Error(`Unexpected call of {type: ${
|
|
674
|
+
throw new Error(`Unexpected call of {type: ${printType(verb)}}`);
|
|
503
675
|
}
|
|
504
676
|
}
|
|
505
677
|
|
|
506
678
|
co.advance(returnValue);
|
|
507
679
|
}
|
|
508
|
-
|
|
509
|
-
return s.node;
|
|
510
680
|
}
|