@bablr/bablr-vm 0.18.0 → 0.19.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 +29 -36
- package/lib/evaluate.js +503 -0
- package/lib/facades.js +3 -0
- package/lib/index.js +1 -1
- package/lib/match.js +470 -0
- package/lib/node.js +172 -43
- package/lib/source.js +3 -3
- package/lib/spans.js +31 -23
- package/lib/state.js +265 -50
- package/lib/strategy.js +1 -1
- package/lib/utils/pattern.js +16 -13
- package/lib/utils/pump.js +20 -0
- package/package.json +7 -6
package/lib/context.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { buildDependentLanguages } from '@bablr/helpers/grammar';
|
|
2
|
-
import { facades, actuals } from '
|
|
2
|
+
import { facades, actuals } from './facades.js';
|
|
3
3
|
import { getPrototypeOf } from '@bablr/helpers/object';
|
|
4
|
-
import {
|
|
4
|
+
import { reifyExpressionShallow } from '@bablr/agast-vm-helpers';
|
|
5
|
+
import { states as nodeStates } from './node.js';
|
|
6
|
+
|
|
7
|
+
import { sourceTextFor } from '@bablr/agast-helpers/tree';
|
|
5
8
|
|
|
6
9
|
export const ContextFacade = class BABLRContextFacade {
|
|
10
|
+
constructor(actual) {
|
|
11
|
+
facades.set(actual, this);
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
get languages() {
|
|
8
15
|
return actuals.get(this).languages;
|
|
9
16
|
}
|
|
@@ -16,51 +23,30 @@ export const ContextFacade = class BABLRContextFacade {
|
|
|
16
23
|
return actuals.get(this).productionEnhancer;
|
|
17
24
|
}
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return actuals.get(this).agast.getPreviousTag(token);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
allTagsFor(range) {
|
|
28
|
-
return actuals.get(this).agast.allTagsFor(range);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
ownTagsFor(range) {
|
|
32
|
-
return actuals.get(this).agast.ownTagsFor(range);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getCooked(node) {
|
|
36
|
-
return actuals.get(this).agast.getCooked(actuals.get(node));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
reifyExpression(value) {
|
|
40
|
-
return actuals.get(this).agast.reifyExpression(value);
|
|
41
|
-
}
|
|
26
|
+
// getCooked(nodeOrRange) {
|
|
27
|
+
// return isArray(nodeOrRange)
|
|
28
|
+
// ? getCookedFromStream(this.allTagsFor(nodeOrRange))
|
|
29
|
+
// : getCookedFromTree(nodeOrRange);
|
|
30
|
+
// }
|
|
42
31
|
|
|
43
32
|
sourceTextFor(node) {
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
unbox(value) {
|
|
48
|
-
return actuals.get(this).agast.unbox(value);
|
|
33
|
+
return node && sourceTextFor(nodeStates.get(node).node);
|
|
49
34
|
}
|
|
50
35
|
};
|
|
51
36
|
|
|
52
37
|
export const Context = class BABLRContext {
|
|
53
|
-
static from(
|
|
54
|
-
return new Context(
|
|
38
|
+
static from(language, productionEnhancer) {
|
|
39
|
+
return new Context(buildDependentLanguages(language), productionEnhancer);
|
|
55
40
|
}
|
|
56
41
|
|
|
57
|
-
constructor(
|
|
58
|
-
this.agast = agastContext;
|
|
42
|
+
constructor(languages, productionEnhancer) {
|
|
59
43
|
this.languages = languages;
|
|
60
44
|
this.productionEnhancer = productionEnhancer;
|
|
61
45
|
|
|
46
|
+
this.unboxedValues = new WeakMap();
|
|
47
|
+
|
|
62
48
|
this.grammars = new WeakMap();
|
|
63
|
-
this.facade = new ContextFacade();
|
|
49
|
+
this.facade = new ContextFacade(this);
|
|
64
50
|
|
|
65
51
|
for (const { 1: language } of this.languages) {
|
|
66
52
|
let { prototype } = language.grammar;
|
|
@@ -69,7 +55,14 @@ export const Context = class BABLRContext {
|
|
|
69
55
|
}
|
|
70
56
|
this.grammars.set(language, new language.grammar());
|
|
71
57
|
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
unbox(value) {
|
|
61
|
+
const { unboxedValues } = this;
|
|
62
|
+
if (!unboxedValues.has(value)) {
|
|
63
|
+
unboxedValues.set(value, reifyExpressionShallow(value));
|
|
64
|
+
}
|
|
72
65
|
|
|
73
|
-
|
|
66
|
+
return unboxedValues.get(value);
|
|
74
67
|
}
|
|
75
68
|
};
|
package/lib/evaluate.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import { Coroutine } from '@bablr/coroutine';
|
|
2
|
+
import { buildOpenNodeTag, buildShiftTag, buildWriteEffect } from '@bablr/agast-helpers/builders';
|
|
3
|
+
import { getStreamIterator, printType, StreamIterable } from '@bablr/agast-helpers/stream';
|
|
4
|
+
import { formatType } from './utils/format.js';
|
|
5
|
+
import { facades } from './facades.js';
|
|
6
|
+
import { nodeStates, State } from './state.js';
|
|
7
|
+
import { updateSpans } from './spans.js';
|
|
8
|
+
import {
|
|
9
|
+
OpenNodeTag,
|
|
10
|
+
CloseNodeTag,
|
|
11
|
+
GapTag,
|
|
12
|
+
LiteralTag,
|
|
13
|
+
ReferenceTag,
|
|
14
|
+
DoctypeTag,
|
|
15
|
+
NullTag,
|
|
16
|
+
ShiftTag,
|
|
17
|
+
} from '@bablr/agast-helpers/symbols';
|
|
18
|
+
import * as sym from '@bablr/agast-helpers/symbols';
|
|
19
|
+
import { internalStates, FragmentFacade } from './node.js';
|
|
20
|
+
import {
|
|
21
|
+
buildArrayInitializerTag,
|
|
22
|
+
buildNullTag,
|
|
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';
|
|
28
|
+
import { Match } from './match.js';
|
|
29
|
+
import { reifyExpression, shouldBranch } from '@bablr/agast-vm-helpers';
|
|
30
|
+
import { TagPath } from '@bablr/agast-helpers/path';
|
|
31
|
+
import { getProduction } from '@bablr/helpers/grammar';
|
|
32
|
+
|
|
33
|
+
const { hasOwn } = Object;
|
|
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);
|
|
42
|
+
|
|
43
|
+
m.node.attributes = attributes;
|
|
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);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const getSourceLength = (tags) => {
|
|
58
|
+
let i = 0;
|
|
59
|
+
for (const tag of tags) {
|
|
60
|
+
if (tag.type === LiteralTag) {
|
|
61
|
+
i += tag.value.length;
|
|
62
|
+
} else if (tag.type === GapTag) {
|
|
63
|
+
i += 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return i;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const bablr = (ctx, rootSource, strategy, options = {}) => {
|
|
70
|
+
return new StreamIterable(__bablr(ctx, rootSource, strategy, options));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
function* __bablr(ctx, rootSource, strategy, options) {
|
|
74
|
+
let s = State.from(rootSource, ctx, options.expressions);
|
|
75
|
+
let m = null;
|
|
76
|
+
let language = null;
|
|
77
|
+
|
|
78
|
+
let co = new Coroutine(getStreamIterator(strategy(facades.get(s), facades.get(ctx))));
|
|
79
|
+
|
|
80
|
+
co.advance();
|
|
81
|
+
|
|
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
|
+
for (;;) {
|
|
93
|
+
if (co.current instanceof Promise) {
|
|
94
|
+
co.current = yield co.current;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (co.done) break;
|
|
98
|
+
|
|
99
|
+
const instr = co.value;
|
|
100
|
+
let returnValue = undefined;
|
|
101
|
+
|
|
102
|
+
const { verb } = instr;
|
|
103
|
+
|
|
104
|
+
switch (verb) {
|
|
105
|
+
case 'init': {
|
|
106
|
+
let { arguments: { 0: canonicalURL } = [] } = instr;
|
|
107
|
+
|
|
108
|
+
if (language !== null) throw new Error();
|
|
109
|
+
|
|
110
|
+
language = ctx.languages.get(canonicalURL);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case 'advance': {
|
|
115
|
+
const { arguments: { 0: embeddedTags } = [] } = instr;
|
|
116
|
+
|
|
117
|
+
const tag = getEmbeddedTag(embeddedTags);
|
|
118
|
+
|
|
119
|
+
if (tag.type !== ReferenceTag) {
|
|
120
|
+
s.referencePath = null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
switch (tag.type) {
|
|
124
|
+
case DoctypeTag: {
|
|
125
|
+
s.node = m.node;
|
|
126
|
+
s.node.type = null;
|
|
127
|
+
s.node.language = tag.value.attributes.bablrLanguage;
|
|
128
|
+
s.advance(tag);
|
|
129
|
+
|
|
130
|
+
m.setRangePreviousIndex(0);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
case ReferenceTag: {
|
|
135
|
+
s.advance(tag);
|
|
136
|
+
|
|
137
|
+
s.referencePath = TagPath.from(m.path, -1);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
case OpenNodeTag: {
|
|
142
|
+
s.depths.path++;
|
|
143
|
+
|
|
144
|
+
if (tag.value.type) {
|
|
145
|
+
if (s.depth === 0 && !m.mergedReference.value.flags.expression) {
|
|
146
|
+
m.add(m.node);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
s.node = m.node;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
s.advance(tag);
|
|
153
|
+
|
|
154
|
+
if (tag.value.type) {
|
|
155
|
+
updateSpans(m, s.node, 'open');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
case CloseNodeTag: {
|
|
162
|
+
const { node } = s;
|
|
163
|
+
|
|
164
|
+
if (btree.getAt(0, node.children).value.type) {
|
|
165
|
+
const refPath = m.referencePath;
|
|
166
|
+
|
|
167
|
+
if (refPath.tag.type === ReferenceTag && refPath?.tag.value.name === '@') {
|
|
168
|
+
const cooked = node.flags.hasGap
|
|
169
|
+
? null
|
|
170
|
+
: ctx.languages
|
|
171
|
+
.get(node.language)
|
|
172
|
+
.getCooked?.(
|
|
173
|
+
FragmentFacade.wrap(
|
|
174
|
+
node,
|
|
175
|
+
ctx,
|
|
176
|
+
true,
|
|
177
|
+
[refPath.childrenIndex, refPath.childrenIndex],
|
|
178
|
+
null,
|
|
179
|
+
),
|
|
180
|
+
s.span.name,
|
|
181
|
+
facades.get(ctx),
|
|
182
|
+
) || null;
|
|
183
|
+
|
|
184
|
+
bindAttribute(m, s, 'cooked', cooked);
|
|
185
|
+
|
|
186
|
+
nodeStates.get(m.node).unboundAttributes.delete('cooked');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
s.advance(tag);
|
|
190
|
+
|
|
191
|
+
s.node = m.fragmentNode;
|
|
192
|
+
s.depths.path--;
|
|
193
|
+
|
|
194
|
+
updateSpans(m, s.resultPath.path.node, 'close');
|
|
195
|
+
|
|
196
|
+
if (s.depth > 0 || m.mergedReference.value.flags.expression) {
|
|
197
|
+
m.add(m.node);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!m.parent) {
|
|
201
|
+
if (!s.source.done) {
|
|
202
|
+
throw new Error('Parser failed to consume input');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (s.balanced.size) {
|
|
206
|
+
throw new Error('Parser did not match all balanced nodes');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
s.advance(tag);
|
|
211
|
+
s.node = m.node;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
case LiteralTag: {
|
|
218
|
+
const { value: pattern } = tag;
|
|
219
|
+
|
|
220
|
+
let result;
|
|
221
|
+
if (
|
|
222
|
+
s.resultPath.tag.type === OpenNodeTag &&
|
|
223
|
+
s.resultPath.tag.value.attributes.balancer &&
|
|
224
|
+
s.balanced.value.attributes.balanced === pattern
|
|
225
|
+
) {
|
|
226
|
+
result = s.match(pattern);
|
|
227
|
+
} else {
|
|
228
|
+
result = s.guardedMatch(pattern);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (result instanceof Promise) {
|
|
232
|
+
result = yield result;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (result) {
|
|
236
|
+
let sourceStep = s.source.advance(getSourceLength(result));
|
|
237
|
+
|
|
238
|
+
if (sourceStep instanceof Promise) {
|
|
239
|
+
sourceStep = yield sourceStep;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
s.advance(tag);
|
|
243
|
+
} else {
|
|
244
|
+
throw new Error('Failed to advance literal');
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
case GapTag: {
|
|
250
|
+
if (s.source.value == null && !s.source.done) {
|
|
251
|
+
if (s.source.holding) {
|
|
252
|
+
s.source.unshift();
|
|
253
|
+
} else {
|
|
254
|
+
const sourceStep = s.source.advance(1);
|
|
255
|
+
|
|
256
|
+
if (sourceStep instanceof Promise) {
|
|
257
|
+
yield sourceStep;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (s.held) {
|
|
262
|
+
m.add(s.held);
|
|
263
|
+
|
|
264
|
+
s.resultPath = s.resultPath.nextSibling;
|
|
265
|
+
s.held = null;
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (s.expressions.size) {
|
|
270
|
+
const expression = s.expressions.value;
|
|
271
|
+
|
|
272
|
+
m.add(expression);
|
|
273
|
+
|
|
274
|
+
s.expressions = s.expressions.pop();
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (btree.getSum(s.node.children)) {
|
|
279
|
+
s.advance(tag);
|
|
280
|
+
} else {
|
|
281
|
+
m.add(m.node);
|
|
282
|
+
|
|
283
|
+
s.advance(tag);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
s.node = m.fragmentNode;
|
|
287
|
+
} else {
|
|
288
|
+
throw new Error('Failed to advance gap');
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
default:
|
|
294
|
+
s.advance(tag);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (s.depth === 0) {
|
|
298
|
+
yield* m.emit();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
returnValue = tag;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
case 'match': {
|
|
306
|
+
let { arguments: { 0: pattern } = [] } = instr;
|
|
307
|
+
|
|
308
|
+
let result = s.guardedMatch(pattern);
|
|
309
|
+
|
|
310
|
+
if (result instanceof Promise) {
|
|
311
|
+
result = yield result;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
let node = result && treeFromStreamSync(result);
|
|
315
|
+
|
|
316
|
+
returnValue = result && FragmentFacade.wrap(node, ctx, true);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
case 'openSpan': {
|
|
321
|
+
let { arguments: { 0: name } = [] } = instr;
|
|
322
|
+
s.spans = s.spans.push({ guard: null, name, path: s.path, type: 'Instruction' });
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
case 'closeSpan': {
|
|
327
|
+
if (s.spans.value.type !== 'Instruction') throw new Error();
|
|
328
|
+
s.spans = s.spans.pop();
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
case 'startFrame': {
|
|
333
|
+
const {
|
|
334
|
+
arguments: {
|
|
335
|
+
0: { value: matcher } = {},
|
|
336
|
+
1: { value: effects } = {},
|
|
337
|
+
2: { value: options = {} } = {},
|
|
338
|
+
} = [],
|
|
339
|
+
} = instr;
|
|
340
|
+
|
|
341
|
+
const { unboundAttributes, didShift, suppressNode } = options;
|
|
342
|
+
|
|
343
|
+
const parentMatch = m;
|
|
344
|
+
|
|
345
|
+
if (!language) throw new Error('not initialized');
|
|
346
|
+
|
|
347
|
+
let matcher_ = reifyExpression(matcher);
|
|
348
|
+
|
|
349
|
+
if (didShift && !parentMatch) throw new Error();
|
|
350
|
+
|
|
351
|
+
m = parentMatch
|
|
352
|
+
? parentMatch.startFrame(s, matcher_, effects, didShift, suppressNode)
|
|
353
|
+
: Match.from(ctx, language, s, matcher_, null, suppressNode);
|
|
354
|
+
|
|
355
|
+
if (m.isNode && m.isCover) throw new Error();
|
|
356
|
+
|
|
357
|
+
if (m.type !== sym.fragment && !getProduction(m.grammar, m.type))
|
|
358
|
+
throw new Error(`Production {type: ${printType(m.type)}} does not exist`);
|
|
359
|
+
|
|
360
|
+
if (m.flags.token && !m.isNode) {
|
|
361
|
+
throw new Error('tokens must be nodes');
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (parentMatch && parentMatch.cover && !m.isNode) {
|
|
365
|
+
if (matcher_.refMatcher) {
|
|
366
|
+
let m = matcher_.refMatcher;
|
|
367
|
+
if (!(m.name === '.' && !m.flags.expression && !m.flags.hasGap && !m.isArray)) {
|
|
368
|
+
throw new Error();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
s = m.state;
|
|
374
|
+
|
|
375
|
+
if (didShift) {
|
|
376
|
+
s.source.shift();
|
|
377
|
+
s.held = s.resultPath.node;
|
|
378
|
+
|
|
379
|
+
let refTag = btree.getAt(-2, parentMatch.node.children);
|
|
380
|
+
|
|
381
|
+
s.advance(buildShiftTag(refTag.type === ShiftTag ? refTag.value.index + 1 : 1));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!m.isNode && options.unboundAttributes) throw new Error();
|
|
385
|
+
|
|
386
|
+
m.fragmentNode = s.node;
|
|
387
|
+
|
|
388
|
+
nodeStates.set(m.node, {
|
|
389
|
+
unboundAttributes: m.isNode
|
|
390
|
+
? new Set(unboundAttributes)
|
|
391
|
+
: new Set(parentMatch ? nodeStates.get(parentMatch.node).unboundAttributes || [] : []),
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
({ language } = m);
|
|
395
|
+
|
|
396
|
+
if (parentMatch) {
|
|
397
|
+
let previousIndex = [CloseNodeTag, NullTag, GapTag].includes(s.resultPath.tag.type)
|
|
398
|
+
? btree.getSum(m.fragmentNode.children) - 1
|
|
399
|
+
: s.resultPath.childrenIndex;
|
|
400
|
+
|
|
401
|
+
m.setRangePreviousIndex(previousIndex);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
returnValue = facades.get(m);
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
case 'endFrame': {
|
|
409
|
+
const {
|
|
410
|
+
arguments: { 0: hasContinuation },
|
|
411
|
+
} = instr;
|
|
412
|
+
const finishedMatch = m;
|
|
413
|
+
|
|
414
|
+
m = m.endFrame();
|
|
415
|
+
|
|
416
|
+
if (m && internalStates.get(m.s.node).path.node !== m.s.node) {
|
|
417
|
+
throw new Error('waaat');
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (!m) {
|
|
421
|
+
returnValue = m;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
s = m.state;
|
|
426
|
+
|
|
427
|
+
if (finishedMatch.state.status !== 'rejected') {
|
|
428
|
+
yield* m.emit();
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
returnValue = facades.get(m.node);
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
case 'bindAttribute': {
|
|
436
|
+
const { arguments: { 0: key, 1: value } = [] } = instr;
|
|
437
|
+
|
|
438
|
+
bindAttribute(m, s, key, value);
|
|
439
|
+
|
|
440
|
+
yield* m.emit();
|
|
441
|
+
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
case 'throw': {
|
|
446
|
+
s.reject();
|
|
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
|
+
}
|
|
458
|
+
|
|
459
|
+
if (ref && ref.value.name !== '#' && !rejectedMatch.didShift) {
|
|
460
|
+
if (shouldBranch(rejectedMatch.effects) && !hasOwn(s.node.properties, ref.value.name)) {
|
|
461
|
+
s.advance(ref);
|
|
462
|
+
|
|
463
|
+
if (ref.value.isArray) {
|
|
464
|
+
s.advance(buildArrayInitializerTag());
|
|
465
|
+
} else {
|
|
466
|
+
s.advance(buildNullTag());
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (!m) {
|
|
472
|
+
returnValue = m;
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
returnValue = facades.get(m);
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
case 'write': {
|
|
481
|
+
const { arguments: { 0: text, 1: { value: writeOptions } = {} } = [] } = instr;
|
|
482
|
+
|
|
483
|
+
if (options.emitEffects) {
|
|
484
|
+
yield buildWriteEffect(text, writeOptions);
|
|
485
|
+
}
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
case 'getState': {
|
|
490
|
+
returnValue = facades.get(s);
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
default: {
|
|
495
|
+
throw new Error(`Unexpected call of {type: ${formatType(verb)}}`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
co.advance(returnValue);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return s.node;
|
|
503
|
+
}
|
package/lib/facades.js
ADDED
package/lib/index.js
CHANGED