@bablr/bablr-vm 0.19.2 → 0.20.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 +28 -12
- package/lib/evaluate.js +133 -126
- package/lib/match.js +127 -101
- package/lib/node.js +155 -57
- package/lib/source.js +3 -1
- package/lib/state.js +207 -62
- package/lib/utils/pattern.js +31 -2
- package/package.json +6 -6
- package/lib/strategy.js +0 -327
package/lib/context.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { buildDependentLanguages } from '@bablr/helpers/grammar';
|
|
2
2
|
import { facades, actuals } from './facades.js';
|
|
3
3
|
import { getPrototypeOf } from '@bablr/helpers/object';
|
|
4
|
-
import { reifyExpressionShallow } from '@bablr/agast-vm-helpers';
|
|
5
4
|
import { states as nodeStates } from './node.js';
|
|
6
5
|
|
|
7
|
-
import { sourceTextFor } from '@bablr/agast-helpers/
|
|
6
|
+
import { sourceTextFor } from '@bablr/agast-helpers/stream';
|
|
7
|
+
import { streamFromTree } from '@bablr/agast-helpers/tree';
|
|
8
|
+
import { allTagsFor, buildFullRange, Path, TagPath } from '@bablr/agast-helpers/path';
|
|
8
9
|
|
|
9
10
|
export const ContextFacade = class BABLRContextFacade {
|
|
10
11
|
constructor(actual) {
|
|
@@ -30,7 +31,31 @@ export const ContextFacade = class BABLRContextFacade {
|
|
|
30
31
|
// }
|
|
31
32
|
|
|
32
33
|
sourceTextFor(node) {
|
|
33
|
-
|
|
34
|
+
let fragmentStream;
|
|
35
|
+
if (!node) return null;
|
|
36
|
+
if (getPrototypeOf(node) === Object.prototype) {
|
|
37
|
+
fragmentStream = streamFromTree(node);
|
|
38
|
+
} else if (nodeStates.has(node)) {
|
|
39
|
+
let state = nodeStates.get(node);
|
|
40
|
+
let { childrenIndexRange } = state;
|
|
41
|
+
let path = Path.from(state.fragmentNode);
|
|
42
|
+
|
|
43
|
+
if (!childrenIndexRange) {
|
|
44
|
+
childrenIndexRange = buildFullRange(state.node);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fragmentStream = allTagsFor(
|
|
48
|
+
[
|
|
49
|
+
TagPath.from(path, childrenIndexRange[0]),
|
|
50
|
+
TagPath.from(path, childrenIndexRange[1] ?? undefined),
|
|
51
|
+
],
|
|
52
|
+
{ unshift: true },
|
|
53
|
+
);
|
|
54
|
+
} else {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return fragmentStream && sourceTextFor(fragmentStream);
|
|
34
59
|
}
|
|
35
60
|
};
|
|
36
61
|
|
|
@@ -56,13 +81,4 @@ export const Context = class BABLRContext {
|
|
|
56
81
|
this.grammars.set(language, new language.grammar());
|
|
57
82
|
}
|
|
58
83
|
}
|
|
59
|
-
|
|
60
|
-
unbox(value) {
|
|
61
|
-
const { unboxedValues } = this;
|
|
62
|
-
if (!unboxedValues.has(value)) {
|
|
63
|
-
unboxedValues.set(value, reifyExpressionShallow(value));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return unboxedValues.get(value);
|
|
67
|
-
}
|
|
68
84
|
};
|
package/lib/evaluate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
|
-
import { buildOpenNodeTag, buildShiftTag
|
|
2
|
+
import { buildEmbeddedNode, buildOpenNodeTag, buildShiftTag } from '@bablr/agast-helpers/builders';
|
|
3
3
|
import { getStreamIterator, printType, StreamIterable } from '@bablr/agast-helpers/stream';
|
|
4
4
|
import { formatType } from './utils/format.js';
|
|
5
5
|
import { facades } from './facades.js';
|
|
@@ -15,43 +15,21 @@ import {
|
|
|
15
15
|
NullTag,
|
|
16
16
|
ShiftTag,
|
|
17
17
|
} from '@bablr/agast-helpers/symbols';
|
|
18
|
-
import * as sym from '@bablr/agast-helpers/symbols';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
getOpenTag,
|
|
24
|
-
treeFromStreamSync,
|
|
25
|
-
} from '@bablr/agast-helpers/tree';
|
|
26
|
-
import * as btree from '@bablr/agast-helpers/btree';
|
|
27
|
-
import { getEmbeddedTag } from '@bablr/agast-vm-helpers/deembed';
|
|
18
|
+
import * as sym from '@bablr/agast-vm-helpers/symbols';
|
|
19
|
+
import { FragmentFacade, states } from './node.js';
|
|
20
|
+
import { defineAttribute as defineAttribute_, treeFromStreamSync } from '@bablr/agast-helpers/tree';
|
|
21
|
+
import * as sumtree from '@bablr/agast-helpers/sumtree';
|
|
22
|
+
import { getEmbeddedObject, getEmbeddedTag } from '@bablr/agast-vm-helpers/deembed';
|
|
28
23
|
import { Match } from './match.js';
|
|
29
|
-
import {
|
|
24
|
+
import { effectsFor, reifyExpression } from '@bablr/agast-vm-helpers';
|
|
30
25
|
import { TagPath } from '@bablr/agast-helpers/path';
|
|
31
26
|
import { getProduction } from '@bablr/helpers/grammar';
|
|
27
|
+
import { buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
|
|
32
28
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const bindAttribute = (m, s, key, value) => {
|
|
36
|
-
const openTag = getOpenTag(m.node);
|
|
37
|
-
|
|
38
|
-
if (value != null) {
|
|
39
|
-
const { flags, language, type } = openTag.value;
|
|
40
|
-
const attributes = { ...openTag.value.attributes, [key]: value };
|
|
41
|
-
const newOpenTag = buildOpenNodeTag(flags, language, type, attributes);
|
|
29
|
+
const defineAttribute = (m, s, key, value) => {
|
|
30
|
+
defineAttribute_(m.node, key, value);
|
|
42
31
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// if (openNext) {
|
|
46
|
-
// } else {
|
|
47
|
-
// // could this tag be stored anywhere else?
|
|
48
|
-
// s.resultPath = newOpenTag;
|
|
49
|
-
// }
|
|
50
|
-
|
|
51
|
-
m.node.children = btree.replaceAt(0, m.node.children, newOpenTag);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
nodeStates.get(m.node).unboundAttributes.delete(key);
|
|
32
|
+
nodeStates.get(m.node).undefinedAttributes.delete(key);
|
|
55
33
|
};
|
|
56
34
|
|
|
57
35
|
const getSourceLength = (tags) => {
|
|
@@ -71,30 +49,23 @@ export const bablr = (ctx, rootSource, strategy, options = {}) => {
|
|
|
71
49
|
};
|
|
72
50
|
|
|
73
51
|
function* __bablr(ctx, rootSource, strategy, options) {
|
|
74
|
-
let s =
|
|
52
|
+
let s = null;
|
|
75
53
|
let m = null;
|
|
76
54
|
let language = null;
|
|
55
|
+
let finishedMatch = null;
|
|
77
56
|
|
|
78
|
-
let co = new Coroutine(getStreamIterator(strategy(facades.get(
|
|
57
|
+
let co = new Coroutine(getStreamIterator(strategy(facades.get(ctx))));
|
|
79
58
|
|
|
80
59
|
co.advance();
|
|
81
60
|
|
|
82
|
-
{
|
|
83
|
-
s.source.advance();
|
|
84
|
-
|
|
85
|
-
const sourceStep = s.source.fork.head.step;
|
|
86
|
-
|
|
87
|
-
if (sourceStep instanceof Promise) {
|
|
88
|
-
yield sourceStep;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
61
|
for (;;) {
|
|
93
62
|
if (co.current instanceof Promise) {
|
|
94
63
|
co.current = yield co.current;
|
|
95
64
|
}
|
|
96
65
|
|
|
97
|
-
if (co.done)
|
|
66
|
+
if (co.done) {
|
|
67
|
+
return co.value && states.get(co.value).node;
|
|
68
|
+
}
|
|
98
69
|
|
|
99
70
|
const instr = co.value;
|
|
100
71
|
let returnValue = undefined;
|
|
@@ -107,7 +78,19 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
107
78
|
|
|
108
79
|
if (language !== null) throw new Error();
|
|
109
80
|
|
|
81
|
+
s = State.from(rootSource, ctx, canonicalURL, options.expressions);
|
|
82
|
+
|
|
83
|
+
s.source.advance();
|
|
84
|
+
|
|
85
|
+
const sourceStep = s.source.fork.head.step;
|
|
86
|
+
|
|
87
|
+
if (sourceStep instanceof Promise) {
|
|
88
|
+
yield sourceStep;
|
|
89
|
+
}
|
|
90
|
+
|
|
110
91
|
language = ctx.languages.get(canonicalURL);
|
|
92
|
+
|
|
93
|
+
returnValue = facades.get(s);
|
|
111
94
|
break;
|
|
112
95
|
}
|
|
113
96
|
|
|
@@ -120,6 +103,9 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
120
103
|
s.referencePath = null;
|
|
121
104
|
}
|
|
122
105
|
|
|
106
|
+
if (m.cover && !m.isNode && !(s.holding && tag.type === GapTag))
|
|
107
|
+
throw new Error('cannot advance inside a cover');
|
|
108
|
+
|
|
123
109
|
switch (tag.type) {
|
|
124
110
|
case DoctypeTag: {
|
|
125
111
|
s.node = m.node;
|
|
@@ -134,7 +120,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
134
120
|
case ReferenceTag: {
|
|
135
121
|
s.advance(tag);
|
|
136
122
|
|
|
137
|
-
s.referencePath = TagPath.
|
|
123
|
+
s.referencePath = TagPath.fromNode(s.node, -1);
|
|
124
|
+
if (s.referencePath.tag.type === GapTag) throw new Error();
|
|
138
125
|
break;
|
|
139
126
|
}
|
|
140
127
|
|
|
@@ -142,13 +129,17 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
142
129
|
s.depths.path++;
|
|
143
130
|
|
|
144
131
|
if (tag.value.type) {
|
|
145
|
-
|
|
146
|
-
m.add(m.node);
|
|
147
|
-
}
|
|
132
|
+
m.add(m.node);
|
|
148
133
|
|
|
149
134
|
s.node = m.node;
|
|
150
135
|
}
|
|
151
136
|
|
|
137
|
+
for (const { 0: key, 1: value } of Object.entries(tag.value.attributes)) {
|
|
138
|
+
if (value === undefined) {
|
|
139
|
+
nodeStates.get(m.node).undefinedAttributes.add(key);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
152
143
|
s.advance(tag);
|
|
153
144
|
|
|
154
145
|
if (tag.value.type) {
|
|
@@ -161,10 +152,12 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
161
152
|
case CloseNodeTag: {
|
|
162
153
|
const { node } = s;
|
|
163
154
|
|
|
164
|
-
|
|
165
|
-
const refPath = m.referencePath;
|
|
155
|
+
s.depths.path--;
|
|
166
156
|
|
|
167
|
-
|
|
157
|
+
if (sumtree.getAt(0, node.children).value.type) {
|
|
158
|
+
const refPath = m.unshiftedReferencePath;
|
|
159
|
+
|
|
160
|
+
if (refPath?.tag.type === ReferenceTag && refPath?.tag.value.name === '@') {
|
|
168
161
|
const cooked = node.flags.hasGap
|
|
169
162
|
? null
|
|
170
163
|
: ctx.languages
|
|
@@ -174,29 +167,28 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
174
167
|
node,
|
|
175
168
|
ctx,
|
|
176
169
|
true,
|
|
177
|
-
[refPath.childrenIndex, refPath.childrenIndex],
|
|
170
|
+
[refPath.childrenIndex, refPath.childrenIndex + 1],
|
|
178
171
|
null,
|
|
179
172
|
),
|
|
180
173
|
s.span.name,
|
|
181
174
|
facades.get(ctx),
|
|
182
175
|
) || null;
|
|
183
176
|
|
|
184
|
-
|
|
177
|
+
defineAttribute(m, s, 'cooked', cooked);
|
|
185
178
|
|
|
186
|
-
nodeStates.get(m.node).
|
|
179
|
+
nodeStates.get(m.node).undefinedAttributes.delete('cooked');
|
|
187
180
|
}
|
|
188
181
|
|
|
189
182
|
s.advance(tag);
|
|
190
183
|
|
|
184
|
+
// if (s.depth > 0) {
|
|
185
|
+
// m.add(m.node);
|
|
186
|
+
// }
|
|
187
|
+
|
|
191
188
|
s.node = m.fragmentNode;
|
|
192
|
-
s.depths.path--;
|
|
193
189
|
|
|
194
190
|
updateSpans(m, s.resultPath.path.node, 'close');
|
|
195
191
|
|
|
196
|
-
if (s.depth > 0 || m.mergedReference.value.flags.expression) {
|
|
197
|
-
m.add(m.node);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
192
|
if (!m.parent) {
|
|
201
193
|
if (!s.source.done) {
|
|
202
194
|
throw new Error('Parser failed to consume input');
|
|
@@ -208,7 +200,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
208
200
|
}
|
|
209
201
|
} else {
|
|
210
202
|
s.advance(tag);
|
|
211
|
-
s.node = m.
|
|
203
|
+
s.node = m.fragmentNode;
|
|
212
204
|
}
|
|
213
205
|
|
|
214
206
|
break;
|
|
@@ -221,7 +213,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
221
213
|
if (
|
|
222
214
|
s.resultPath.tag.type === OpenNodeTag &&
|
|
223
215
|
s.resultPath.tag.value.attributes.balancer &&
|
|
224
|
-
s.balanced.value
|
|
216
|
+
s.balanced.value?.attributes.balanced === pattern
|
|
225
217
|
) {
|
|
226
218
|
result = s.match(pattern);
|
|
227
219
|
} else {
|
|
@@ -247,7 +239,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
247
239
|
}
|
|
248
240
|
|
|
249
241
|
case GapTag: {
|
|
250
|
-
if (s.source.value == null && !s.source.done) {
|
|
242
|
+
if (s.source.value == null && (!s.source.done || s.source.holding)) {
|
|
251
243
|
if (s.source.holding) {
|
|
252
244
|
s.source.unshift();
|
|
253
245
|
} else {
|
|
@@ -261,7 +253,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
261
253
|
if (s.held) {
|
|
262
254
|
m.add(s.held);
|
|
263
255
|
|
|
264
|
-
s.resultPath = s.resultPath.
|
|
256
|
+
s.resultPath = TagPath.fromNode(s.resultPath.node, -1);
|
|
257
|
+
|
|
265
258
|
s.held = null;
|
|
266
259
|
break;
|
|
267
260
|
}
|
|
@@ -275,7 +268,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
275
268
|
break;
|
|
276
269
|
}
|
|
277
270
|
|
|
278
|
-
if (
|
|
271
|
+
if (sumtree.getSize(s.node.children)) {
|
|
279
272
|
s.advance(tag);
|
|
280
273
|
} else {
|
|
281
274
|
m.add(m.node);
|
|
@@ -283,6 +276,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
283
276
|
s.advance(tag);
|
|
284
277
|
}
|
|
285
278
|
|
|
279
|
+
s.referencePath = null;
|
|
280
|
+
|
|
286
281
|
s.node = m.fragmentNode;
|
|
287
282
|
} else {
|
|
288
283
|
throw new Error('Failed to advance gap');
|
|
@@ -313,7 +308,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
313
308
|
|
|
314
309
|
let node = result && treeFromStreamSync(result);
|
|
315
310
|
|
|
316
|
-
returnValue =
|
|
311
|
+
returnValue = node && buildEmbeddedNode(node);
|
|
317
312
|
break;
|
|
318
313
|
}
|
|
319
314
|
|
|
@@ -329,18 +324,48 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
329
324
|
break;
|
|
330
325
|
}
|
|
331
326
|
|
|
327
|
+
case 'branch': {
|
|
328
|
+
s = s.branch();
|
|
329
|
+
|
|
330
|
+
returnValue = facades.get(s);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
case 'accept': {
|
|
335
|
+
s = s.accept(finishedMatch.fragmentNode);
|
|
336
|
+
|
|
337
|
+
returnValue = facades.get(s);
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
case 'reject': {
|
|
342
|
+
let finishedState = s;
|
|
343
|
+
const { arguments: { 0: embeddedOptions } = [] } = instr;
|
|
344
|
+
let options = getEmbeddedObject(embeddedOptions);
|
|
345
|
+
|
|
346
|
+
s = finishedState.reject(
|
|
347
|
+
finishedMatch,
|
|
348
|
+
// finishedMatch.effects.success === 'none',
|
|
349
|
+
options,
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
s = finishedState.parent;
|
|
353
|
+
|
|
354
|
+
returnValue = facades.get(s);
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
|
|
332
358
|
case 'startFrame': {
|
|
333
|
-
|
|
334
|
-
arguments: {
|
|
335
|
-
0: { value: matcher } = {},
|
|
336
|
-
1: { value: effects } = {},
|
|
337
|
-
2: { value: options = {} } = {},
|
|
338
|
-
} = [],
|
|
359
|
+
let {
|
|
360
|
+
arguments: { 0: verb, 1: { value: matcher } = {}, 2: { value: options = {} } = {} } = [],
|
|
339
361
|
} = instr;
|
|
340
362
|
|
|
341
|
-
|
|
363
|
+
let effects = effectsFor(verb.description);
|
|
364
|
+
let didShift = verb.description.startsWith('holdFor');
|
|
365
|
+
|
|
366
|
+
let { undefinedAttributes } = options;
|
|
342
367
|
|
|
343
|
-
|
|
368
|
+
let parentMatch = m;
|
|
344
369
|
|
|
345
370
|
if (!language) throw new Error('not initialized');
|
|
346
371
|
|
|
@@ -349,8 +374,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
349
374
|
if (didShift && !parentMatch) throw new Error();
|
|
350
375
|
|
|
351
376
|
m = parentMatch
|
|
352
|
-
? parentMatch.startFrame(s, matcher_, effects, didShift,
|
|
353
|
-
: Match.from(ctx, language, s, matcher_, null,
|
|
377
|
+
? parentMatch.startFrame(s, matcher_, effects, didShift ? finishedMatch : null, options)
|
|
378
|
+
: Match.from(ctx, language, s, matcher_, null, options);
|
|
379
|
+
|
|
380
|
+
finishedMatch = null;
|
|
354
381
|
|
|
355
382
|
if (m.isNode && m.isCover) throw new Error();
|
|
356
383
|
|
|
@@ -365,43 +392,46 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
365
392
|
if (matcher_.refMatcher) {
|
|
366
393
|
let m = matcher_.refMatcher;
|
|
367
394
|
if (!(m.name === '.' && !m.flags.expression && !m.flags.hasGap && !m.isArray)) {
|
|
368
|
-
throw new Error();
|
|
395
|
+
throw new Error('no references inside covers');
|
|
369
396
|
}
|
|
370
397
|
}
|
|
371
398
|
}
|
|
372
399
|
|
|
373
|
-
s = m.state;
|
|
374
|
-
|
|
375
400
|
if (didShift) {
|
|
376
401
|
s.source.shift();
|
|
377
402
|
s.held = s.resultPath.node;
|
|
378
403
|
|
|
379
|
-
let refTag =
|
|
404
|
+
let refTag = sumtree.getAt(-2, s.node.children);
|
|
380
405
|
|
|
381
406
|
s.advance(buildShiftTag(refTag.type === ShiftTag ? refTag.value.index + 1 : 1));
|
|
407
|
+
s.referencePath = TagPath.fromNode(s.node, -1);
|
|
382
408
|
}
|
|
383
409
|
|
|
384
|
-
if (!m.isNode && options.
|
|
410
|
+
if (!m.isNode && options.undefinedAttributes) throw new Error();
|
|
385
411
|
|
|
386
412
|
m.fragmentNode = s.node;
|
|
387
413
|
|
|
388
414
|
nodeStates.set(m.node, {
|
|
389
|
-
|
|
390
|
-
? new Set(
|
|
391
|
-
: new Set(
|
|
415
|
+
undefinedAttributes: m.isNode
|
|
416
|
+
? new Set(undefinedAttributes)
|
|
417
|
+
: new Set(
|
|
418
|
+
parentMatch ? nodeStates.get(parentMatch.node).undefinedAttributes || [] : [],
|
|
419
|
+
),
|
|
392
420
|
});
|
|
393
421
|
|
|
394
422
|
({ language } = m);
|
|
395
423
|
|
|
396
424
|
if (parentMatch) {
|
|
397
425
|
let previousIndex = [CloseNodeTag, NullTag, GapTag].includes(s.resultPath.tag.type)
|
|
398
|
-
?
|
|
426
|
+
? sumtree.getSize(m.fragmentNode.children) - 1
|
|
399
427
|
: s.resultPath.childrenIndex;
|
|
400
428
|
|
|
401
429
|
m.setRangePreviousIndex(previousIndex);
|
|
402
430
|
}
|
|
403
431
|
|
|
404
432
|
returnValue = facades.get(m);
|
|
433
|
+
|
|
434
|
+
m.range;
|
|
405
435
|
break;
|
|
406
436
|
}
|
|
407
437
|
|
|
@@ -409,71 +439,48 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
409
439
|
const {
|
|
410
440
|
arguments: { 0: hasContinuation },
|
|
411
441
|
} = instr;
|
|
412
|
-
|
|
442
|
+
finishedMatch = m;
|
|
413
443
|
|
|
414
444
|
m = m.endFrame();
|
|
415
445
|
|
|
416
|
-
if (m && internalStates.get(m.s.node).path.node !== m.s.node) {
|
|
417
|
-
throw new Error('waaat');
|
|
418
|
-
}
|
|
419
|
-
|
|
420
446
|
if (!m) {
|
|
421
447
|
returnValue = m;
|
|
422
448
|
break;
|
|
423
449
|
}
|
|
424
450
|
|
|
425
|
-
s = m.state;
|
|
426
|
-
|
|
427
451
|
if (finishedMatch.state.status !== 'rejected') {
|
|
428
452
|
yield* m.emit();
|
|
429
453
|
}
|
|
430
454
|
|
|
431
|
-
returnValue = facades.get(m
|
|
455
|
+
returnValue = m && facades.get(m);
|
|
432
456
|
break;
|
|
433
457
|
}
|
|
434
458
|
|
|
435
|
-
case '
|
|
436
|
-
|
|
459
|
+
case 'throw': {
|
|
460
|
+
finishedMatch = m;
|
|
437
461
|
|
|
438
|
-
|
|
462
|
+
m = m.throw_();
|
|
439
463
|
|
|
440
|
-
|
|
464
|
+
s.status = 'rejected';
|
|
465
|
+
if (m && finishedMatch.s === s) {
|
|
466
|
+
s.node = m.node;
|
|
467
|
+
}
|
|
441
468
|
|
|
469
|
+
returnValue = m && facades.get(m);
|
|
442
470
|
break;
|
|
443
471
|
}
|
|
444
472
|
|
|
445
|
-
case '
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
let rejectedMatch = m;
|
|
449
|
-
|
|
450
|
-
m = m.endFrame();
|
|
451
|
-
s = m.state;
|
|
452
|
-
|
|
453
|
-
let ref = null;
|
|
454
|
-
|
|
455
|
-
if (rejectedMatch.isNode) {
|
|
456
|
-
ref = rejectedMatch.mergedReference;
|
|
457
|
-
}
|
|
473
|
+
case 'defineAttribute': {
|
|
474
|
+
const { arguments: { 0: key, 1: value } = [] } = instr;
|
|
458
475
|
|
|
459
|
-
if (
|
|
460
|
-
|
|
461
|
-
|
|
476
|
+
if (!nodeStates.get(m.node).undefinedAttributes.has(key))
|
|
477
|
+
throw new Error('undefined attributes must be declared');
|
|
478
|
+
if (value && typeof value === 'object') throw new Error('unimplemented');
|
|
462
479
|
|
|
463
|
-
|
|
464
|
-
s.advance(buildArrayInitializerTag());
|
|
465
|
-
} else {
|
|
466
|
-
s.advance(buildNullTag());
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
480
|
+
defineAttribute(m, s, key, value);
|
|
470
481
|
|
|
471
|
-
|
|
472
|
-
returnValue = m;
|
|
473
|
-
break;
|
|
474
|
-
}
|
|
482
|
+
yield* m.emit();
|
|
475
483
|
|
|
476
|
-
returnValue = facades.get(m);
|
|
477
484
|
break;
|
|
478
485
|
}
|
|
479
486
|
|