@bablr/agast-vm-helpers 0.9.0 → 0.10.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/builders.js +18 -6
- package/lib/deembed.js +1 -7
- package/lib/index.js +216 -156
- package/lib/print.js +24 -5
- package/lib/stream.js +10 -11
- package/lib/symbols.js +0 -3
- package/package.json +2 -2
package/lib/builders.js
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNode } from '@bablr/agast-helpers/path';
|
|
2
|
+
import { Matcher, Regex, Tag, EmbeddedObject, Instruction, Node } from './symbols.js';
|
|
2
3
|
|
|
3
4
|
const isObject = (val) => val !== null && typeof val === 'object';
|
|
4
5
|
|
|
5
6
|
const { freeze } = Object;
|
|
6
7
|
|
|
8
|
+
export const buildOptions = (options) => {
|
|
9
|
+
let { shift, bind, allowEmpty, internal } = options;
|
|
10
|
+
|
|
11
|
+
let s = !shift ? 'S' : ' ';
|
|
12
|
+
let b = bind ? 'b' : ' ';
|
|
13
|
+
let e = allowEmpty ? 'e' : ' ';
|
|
14
|
+
let i = internal ? 'i' : ' ';
|
|
15
|
+
|
|
16
|
+
return `${s}${b}${e}${i}`;
|
|
17
|
+
};
|
|
18
|
+
|
|
7
19
|
export const buildCall = (verb, ...args) => {
|
|
8
20
|
return freeze({ verb, arguments: freeze(args) });
|
|
9
21
|
};
|
|
@@ -13,11 +25,6 @@ export const buildEmbeddedObject = (obj) => {
|
|
|
13
25
|
return freeze({ type: EmbeddedObject, value: freeze(obj) });
|
|
14
26
|
};
|
|
15
27
|
|
|
16
|
-
export const buildEmbeddedNode = (node) => {
|
|
17
|
-
if (!isObject(node)) throw new Error();
|
|
18
|
-
return freeze({ type: Node, value: freeze(node) });
|
|
19
|
-
};
|
|
20
|
-
|
|
21
28
|
export const buildEmbeddedMatcher = (matcher) => {
|
|
22
29
|
if (!isObject(matcher)) throw new Error();
|
|
23
30
|
return freeze({ type: Matcher, value: matcher });
|
|
@@ -38,6 +45,11 @@ export const buildEmbeddedTag = (tag) => {
|
|
|
38
45
|
return freeze({ type: Tag, value: tag });
|
|
39
46
|
};
|
|
40
47
|
|
|
48
|
+
export const buildEmbeddedNode = (node) => {
|
|
49
|
+
if (!isNode(node)) throw new Error();
|
|
50
|
+
return freeze({ type: Node, value: node });
|
|
51
|
+
};
|
|
52
|
+
|
|
41
53
|
export const buildEffect = (value) => {
|
|
42
54
|
return freeze({ type: 'Effect', value });
|
|
43
55
|
};
|
package/lib/deembed.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EmbeddedObject, Tag, Matcher, Regex, Instruction } from './symbols.js';
|
|
2
2
|
|
|
3
3
|
export const getEmbeddedObject = (expr) => {
|
|
4
4
|
if (!expr) return expr;
|
|
@@ -6,12 +6,6 @@ export const getEmbeddedObject = (expr) => {
|
|
|
6
6
|
return expr.value;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
export const getEmbeddedNode = (expr) => {
|
|
10
|
-
if (!expr) return expr;
|
|
11
|
-
if (expr.type !== Node) throw new Error();
|
|
12
|
-
return expr.value;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
9
|
export const getEmbeddedMatcher = (expr) => {
|
|
16
10
|
if (!expr) return expr;
|
|
17
11
|
if (expr.type !== Matcher) throw new Error();
|
package/lib/index.js
CHANGED
|
@@ -3,46 +3,40 @@ import {
|
|
|
3
3
|
getCooked,
|
|
4
4
|
isNull,
|
|
5
5
|
isNullNode,
|
|
6
|
-
|
|
7
|
-
isFragmentNode,
|
|
6
|
+
isCover,
|
|
8
7
|
buildReferenceTag,
|
|
9
8
|
getRoot,
|
|
10
|
-
buildChild,
|
|
11
9
|
get,
|
|
12
10
|
list,
|
|
13
|
-
buildBounds,
|
|
14
11
|
} from '@bablr/agast-helpers/tree';
|
|
15
12
|
import * as Tags from '@bablr/agast-helpers/tags';
|
|
16
13
|
import {
|
|
17
14
|
buildGapTag,
|
|
18
15
|
buildNullTag,
|
|
19
16
|
buildOpenNodeTag,
|
|
20
|
-
buildBindingTag,
|
|
21
|
-
buildInitializerTag,
|
|
22
17
|
buildShiftTag,
|
|
23
18
|
buildCloseNodeTag,
|
|
24
19
|
buildLiteralTag,
|
|
25
20
|
buildDoctypeTag,
|
|
26
|
-
referenceFlags,
|
|
27
|
-
buildProperty,
|
|
28
|
-
fragmentFlags,
|
|
29
|
-
buildBinding,
|
|
30
21
|
buildAttributeDefinition,
|
|
31
|
-
|
|
22
|
+
nodeFlags,
|
|
23
|
+
referenceFlags,
|
|
24
|
+
buildBindingTag,
|
|
25
|
+
buildDocument,
|
|
26
|
+
buildPropertyTag,
|
|
27
|
+
tokenFlags,
|
|
28
|
+
buildFullOpenNodeTag,
|
|
32
29
|
} from '@bablr/agast-helpers/builders';
|
|
33
30
|
import { buildEmbeddedMatcher, buildEmbeddedRegex } from './builders.js';
|
|
34
31
|
import {
|
|
35
32
|
AttributeDefinition,
|
|
36
33
|
CloseNodeTag,
|
|
37
34
|
GapTag,
|
|
38
|
-
InitializerTag,
|
|
39
35
|
LiteralTag,
|
|
40
36
|
NullTag,
|
|
41
37
|
OpenNodeTag,
|
|
42
|
-
Property,
|
|
43
|
-
PropertyWrapper,
|
|
44
38
|
} from './symbols.js';
|
|
45
|
-
import {
|
|
39
|
+
import { buildNode, getFlags, getTags } from '@bablr/agast-helpers/path';
|
|
46
40
|
|
|
47
41
|
const { freeze } = Object;
|
|
48
42
|
|
|
@@ -50,6 +44,7 @@ export const effectsFor = (verb) => {
|
|
|
50
44
|
switch (verb) {
|
|
51
45
|
case 'eat':
|
|
52
46
|
case 'shift':
|
|
47
|
+
case 'eatHeld':
|
|
53
48
|
return { success: 'eat', failure: 'fail' };
|
|
54
49
|
|
|
55
50
|
case 'eatMatch':
|
|
@@ -67,45 +62,57 @@ export const effectsFor = (verb) => {
|
|
|
67
62
|
}
|
|
68
63
|
};
|
|
69
64
|
|
|
65
|
+
export const reifyBablrOptions = (str) => {
|
|
66
|
+
if (str.length !== 4) throw new Error();
|
|
67
|
+
let shift = !str.includes('S');
|
|
68
|
+
let bind = str.includes('b');
|
|
69
|
+
let allowEmpty = str.includes('e');
|
|
70
|
+
let internal = str.includes('i');
|
|
71
|
+
|
|
72
|
+
return freeze({ shift, bind, allowEmpty, internal });
|
|
73
|
+
};
|
|
74
|
+
|
|
70
75
|
export const shouldBranch = (effects) => {
|
|
71
76
|
return effects ? effects.success === 'none' || effects.failure === 'none' : false;
|
|
72
77
|
};
|
|
73
78
|
|
|
74
|
-
export const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
let multiFragmentToken = get('multiFragmentToken', flags);
|
|
79
|
+
export const reifyMatcherReferenceName = (matcher) => {
|
|
80
|
+
if (matcher == null) return null;
|
|
81
|
+
return reifyExpression(get(['refMatcher', 'name'], matcher.value));
|
|
82
|
+
};
|
|
79
83
|
|
|
80
|
-
|
|
81
|
-
let hasGap =
|
|
82
|
-
let fragment = !!(fragmentToken && reifyExpression(fragmentToken));
|
|
83
|
-
let cover = !!(fragment && !(multiFragmentToken && reifyExpression(multiFragmentToken)));
|
|
84
|
+
export const reifyNodeFlags = (flags) => {
|
|
85
|
+
let { token, hasGap } = flags.value.attributes;
|
|
84
86
|
|
|
85
|
-
return {
|
|
87
|
+
return {
|
|
88
|
+
token,
|
|
89
|
+
hasGap,
|
|
90
|
+
};
|
|
86
91
|
};
|
|
87
92
|
|
|
88
93
|
export const reifyReferenceFlags = (flags) => {
|
|
94
|
+
let arrayToken = get('arrayToken', flags);
|
|
89
95
|
let expressionToken = get('expressionToken', flags);
|
|
96
|
+
let intrinsicToken = get('intrinsicToken', flags);
|
|
90
97
|
let hasGapToken = get('hasGapToken', flags);
|
|
91
98
|
|
|
92
|
-
return {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
return freeze({
|
|
100
|
+
array: !!reifyExpression(arrayToken),
|
|
101
|
+
expression: !!reifyExpression(expressionToken),
|
|
102
|
+
intrinsic: !!reifyExpression(intrinsicToken),
|
|
103
|
+
hasGap: !!reifyExpression(hasGapToken),
|
|
104
|
+
});
|
|
96
105
|
};
|
|
97
106
|
|
|
98
107
|
export const buildTags = (node) => {
|
|
99
|
-
let open = get('
|
|
108
|
+
let open = get('openTag', node);
|
|
100
109
|
|
|
101
|
-
let children = buildChildren(list('children', node));
|
|
102
110
|
let openTag = reifyExpression(open);
|
|
111
|
+
let children = buildChildren(list('children', node));
|
|
103
112
|
let closeTag = buildCloseNodeTag();
|
|
104
113
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (literalValue) {
|
|
108
|
-
children = Tags.fromValues([buildLiteralTag(literalValue)]);
|
|
114
|
+
if (openTag.value.selfClosing) {
|
|
115
|
+
return Tags.fromValues([openTag]);
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
return Tags.fromValues([openTag, children, closeTag]);
|
|
@@ -115,51 +122,36 @@ export const buildChildren = (children) => {
|
|
|
115
122
|
let built = Tags.fromValues([]);
|
|
116
123
|
|
|
117
124
|
for (const child of children) {
|
|
118
|
-
if ([AttributeDefinition, LiteralTag].includes(child.
|
|
125
|
+
if ([AttributeDefinition, LiteralTag].includes(child.value.name)) {
|
|
119
126
|
built = Tags.push(built, reifyExpression(child));
|
|
120
127
|
continue;
|
|
121
128
|
}
|
|
122
129
|
|
|
123
|
-
if (child.
|
|
130
|
+
if (child.value.name !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
124
131
|
|
|
125
|
-
let reference = get('
|
|
126
|
-
let
|
|
127
|
-
let
|
|
132
|
+
let reference = get('referenceTag', child);
|
|
133
|
+
let boundNode = reifyExpression(get('value', child));
|
|
134
|
+
let { node, bindingTags } = boundNode;
|
|
128
135
|
|
|
129
|
-
let
|
|
130
|
-
let bindingTag = binding
|
|
131
|
-
? reifyExpression(binding)
|
|
132
|
-
: buildBindingTag(isStubNode(value) ? null : []);
|
|
136
|
+
let bindings = bindingTags.map((tag) => tag.value);
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
let referenceTag =
|
|
139
|
+
reference && !isNullNode(reference) ? reifyExpression(reference) : buildReferenceTag();
|
|
135
140
|
|
|
136
|
-
if (
|
|
137
|
-
for (let child of Tags.traverse(
|
|
138
|
-
if (![OpenNodeTag, CloseNodeTag].includes(child.type))
|
|
141
|
+
if (node.value.type === Symbol.for('__')) {
|
|
142
|
+
for (let child of Tags.traverse(getTags(node))) {
|
|
143
|
+
if (![OpenNodeTag, CloseNodeTag].includes(child.value.type))
|
|
144
|
+
built = Tags.push(built, child);
|
|
139
145
|
}
|
|
140
146
|
continue;
|
|
141
147
|
}
|
|
142
148
|
|
|
143
|
-
if (value.
|
|
144
|
-
|
|
149
|
+
if (node.value.name === NullTag || node.value.name === GapTag) {
|
|
150
|
+
throw new Error('not implemented');
|
|
151
|
+
node = buildNode(node);
|
|
145
152
|
}
|
|
146
153
|
|
|
147
|
-
built = Tags.push(built, referenceTag);
|
|
148
|
-
if (value.type === InitializerTag) {
|
|
149
|
-
built = Tags.push(built, value);
|
|
150
|
-
} else {
|
|
151
|
-
let property = buildProperty(referenceTag.value, bindingTag.value, value);
|
|
152
|
-
built = Tags.push(
|
|
153
|
-
built,
|
|
154
|
-
buildChild(
|
|
155
|
-
PropertyWrapper,
|
|
156
|
-
buildPropertyWrapper(
|
|
157
|
-
[referenceTag, bindingTag, buildChild(Property, property)],
|
|
158
|
-
property,
|
|
159
|
-
),
|
|
160
|
-
),
|
|
161
|
-
);
|
|
162
|
-
}
|
|
154
|
+
built = Tags.push(built, buildPropertyTag([referenceTag, bindingTags, node]));
|
|
163
155
|
}
|
|
164
156
|
|
|
165
157
|
return built;
|
|
@@ -171,43 +163,47 @@ export const reifyExpression = (node) => {
|
|
|
171
163
|
if (node == null) return node;
|
|
172
164
|
if (isNullNode(node)) return null;
|
|
173
165
|
|
|
174
|
-
if (
|
|
166
|
+
if (isCover(node)) {
|
|
175
167
|
node = getRoot(node);
|
|
176
168
|
}
|
|
177
169
|
|
|
178
|
-
|
|
170
|
+
if (getFlags(node)?.token && !node.value.name) {
|
|
171
|
+
return getCooked(node);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
switch (node.value.name?.description) {
|
|
179
175
|
case 'Document': {
|
|
180
|
-
let
|
|
181
|
-
let tree = get('tree', node);
|
|
176
|
+
let tree = get(['tree', 'node'], node);
|
|
182
177
|
|
|
183
|
-
doctype = reifyExpression(doctype);
|
|
184
178
|
tree = reifyExpression(tree);
|
|
185
179
|
|
|
186
|
-
let
|
|
180
|
+
let doctypeTag = null;
|
|
187
181
|
|
|
188
|
-
return
|
|
189
|
-
flags: fragmentFlags,
|
|
190
|
-
type: null,
|
|
191
|
-
bounds: tree.bounds,
|
|
192
|
-
tags: tree.tags,
|
|
193
|
-
attributes,
|
|
194
|
-
});
|
|
182
|
+
return buildDocument(doctypeTag, tree);
|
|
195
183
|
}
|
|
196
184
|
|
|
197
|
-
case '
|
|
198
|
-
let open = get('
|
|
185
|
+
case 'TreeNode': {
|
|
186
|
+
let open = get('openTag', node);
|
|
199
187
|
|
|
200
188
|
let openTag = reifyExpression(open);
|
|
201
189
|
|
|
202
|
-
let { flags,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
190
|
+
let { flags, name, attributes, literalValue } = openTag.value;
|
|
191
|
+
|
|
192
|
+
if (literalValue && !flags.token) {
|
|
193
|
+
let tokenFragment = buildNode(
|
|
194
|
+
Tags.fromValues([buildOpenNodeTag(tokenFlags, null, literalValue, {}, true)]),
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
return buildNode(
|
|
198
|
+
Tags.fromValues([
|
|
199
|
+
buildOpenNodeTag(flags, name, null, attributes),
|
|
200
|
+
Tags.fromValues([buildPropertyTag([buildReferenceTag('_'), [], tokenFragment])]),
|
|
201
|
+
buildCloseNodeTag(),
|
|
202
|
+
]),
|
|
203
|
+
);
|
|
204
|
+
} else {
|
|
205
|
+
return buildNode(buildTags(node));
|
|
206
|
+
}
|
|
211
207
|
}
|
|
212
208
|
|
|
213
209
|
case 'DoctypeTag': {
|
|
@@ -223,17 +219,13 @@ export const reifyExpression = (node) => {
|
|
|
223
219
|
case 'ReferenceTag': {
|
|
224
220
|
let type = get('type', node);
|
|
225
221
|
let name = get('name', node);
|
|
226
|
-
let arrayOperatorToken = get('arrayOperatorToken', node);
|
|
227
222
|
let flags = get('flags', node);
|
|
228
223
|
|
|
229
|
-
name = name && reifyExpression(name);
|
|
224
|
+
name = name && (reifyExpression(name) || null);
|
|
230
225
|
type = type && reifyExpression(type);
|
|
231
|
-
flags =
|
|
232
|
-
expression: !!(flags && get('expressionToken', flags)),
|
|
233
|
-
hasGap: !!(flags && get('hasGapToken', flags)),
|
|
234
|
-
});
|
|
226
|
+
flags = (flags && reifyReferenceFlags(flags)) || undefined;
|
|
235
227
|
|
|
236
|
-
return buildReferenceTag(type, name,
|
|
228
|
+
return buildReferenceTag(type, name, flags);
|
|
237
229
|
}
|
|
238
230
|
|
|
239
231
|
case 'LiteralTag': {
|
|
@@ -245,29 +237,61 @@ export const reifyExpression = (node) => {
|
|
|
245
237
|
}
|
|
246
238
|
|
|
247
239
|
case 'IdentifierPath': {
|
|
248
|
-
return
|
|
240
|
+
return freeze(
|
|
241
|
+
[...list('segments', node)].map((segment) =>
|
|
242
|
+
freeze({ type: null, name: reifyExpression(segment) }),
|
|
243
|
+
),
|
|
244
|
+
);
|
|
249
245
|
}
|
|
250
246
|
|
|
251
247
|
case 'AttributeDefinition': {
|
|
252
|
-
let
|
|
248
|
+
let key = get('key', node);
|
|
253
249
|
let value = get('value', node);
|
|
254
250
|
|
|
255
|
-
|
|
251
|
+
key = key && reifyExpression(key).map((segment) => segment.name);
|
|
256
252
|
value = value && reifyExpression(value);
|
|
257
253
|
|
|
258
|
-
return buildAttributeDefinition(
|
|
254
|
+
return buildAttributeDefinition(key, value);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
case 'NodeFlags': {
|
|
258
|
+
return reifyNodeFlags(node);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
case 'ReferenceFlags': {
|
|
262
|
+
return reifyReferenceFlags(node);
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
case 'OpenNodeTag': {
|
|
262
266
|
let flags = get('flags', node);
|
|
263
267
|
let type = get('type', node);
|
|
268
|
+
let name = get('name', node);
|
|
264
269
|
let attributes = get('attributes', node);
|
|
270
|
+
let literalValue = get('literalValue', node);
|
|
271
|
+
let openToken = get('openToken', node);
|
|
272
|
+
let selfClosing = get('selfClosingToken', node);
|
|
273
|
+
|
|
274
|
+
literalValue = literalValue && reifyExpression(literalValue);
|
|
265
275
|
|
|
266
|
-
|
|
276
|
+
if (!openToken) {
|
|
277
|
+
if (!literalValue) throw new Error();
|
|
278
|
+
|
|
279
|
+
return buildOpenNodeTag(tokenFlags, null, literalValue, {});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let anonymousToken = !openToken;
|
|
283
|
+
|
|
284
|
+
flags = anonymousToken ? tokenFlags : (flags && reifyNodeFlags(flags)) || nodeFlags;
|
|
267
285
|
type = reifyExpression(type);
|
|
268
|
-
|
|
286
|
+
name = reifyExpression(name);
|
|
287
|
+
attributes = reifyExpression(attributes) || {};
|
|
288
|
+
selfClosing = !!reifyExpression(selfClosing);
|
|
289
|
+
|
|
290
|
+
// if (literalValue && !flags.token) {
|
|
291
|
+
// return buildOpenNodeTag(tokenFlags, null, literalValue, {}, true);
|
|
292
|
+
// }
|
|
269
293
|
|
|
270
|
-
return
|
|
294
|
+
return buildFullOpenNodeTag(flags, type, name, literalValue, attributes, selfClosing);
|
|
271
295
|
}
|
|
272
296
|
|
|
273
297
|
case 'CloseNodeTag': {
|
|
@@ -282,24 +306,17 @@ export const reifyExpression = (node) => {
|
|
|
282
306
|
return getCooked(get('sign', node)) === '-' ? -Infinity : Infinity;
|
|
283
307
|
}
|
|
284
308
|
|
|
285
|
-
case 'Punctuator': {
|
|
286
|
-
return getCooked(node);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
309
|
case 'GapTag':
|
|
290
310
|
return buildGapTag();
|
|
291
311
|
|
|
292
|
-
case 'InitializerTag':
|
|
293
|
-
return buildInitializerTag();
|
|
294
|
-
|
|
295
|
-
case 'BindingTag':
|
|
296
|
-
let languagePath = get('languagePath', node);
|
|
297
|
-
|
|
298
|
-
return buildBindingTag(reifyExpression(languagePath));
|
|
299
|
-
|
|
300
312
|
case 'NullTag':
|
|
301
313
|
return buildNullTag();
|
|
302
314
|
|
|
315
|
+
case 'NullNode':
|
|
316
|
+
case 'GapNode':
|
|
317
|
+
let tag = reifyExpression(get('sigilTag', node));
|
|
318
|
+
return buildNode(tag);
|
|
319
|
+
|
|
303
320
|
case 'ShiftTag':
|
|
304
321
|
return buildShiftTag();
|
|
305
322
|
|
|
@@ -314,88 +331,132 @@ export const reifyExpression = (node) => {
|
|
|
314
331
|
return buildEmbeddedRegex(get('content', node));
|
|
315
332
|
}
|
|
316
333
|
|
|
317
|
-
case '
|
|
334
|
+
case 'TreeNodeMatcherOpen': {
|
|
318
335
|
let flags = get('flags', node);
|
|
336
|
+
let name = get('name', node);
|
|
319
337
|
let type = get('type', node);
|
|
320
338
|
let attributes = get('attributes', node);
|
|
321
339
|
let literalValue = get('literalValue', node);
|
|
322
340
|
|
|
323
341
|
flags = (flags && reifyNodeFlags(flags)) || {};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
? getCooked(get('content',
|
|
327
|
-
: reifyExpression(
|
|
342
|
+
name = name
|
|
343
|
+
? name.value.name === Symbol.for('String')
|
|
344
|
+
? getCooked(get('content', name))
|
|
345
|
+
: reifyExpression(name)
|
|
346
|
+
: null;
|
|
347
|
+
type = reifyExpression(type);
|
|
328
348
|
attributes = attributes ? reifyExpression(attributes) : {};
|
|
329
349
|
literalValue = literalValue && reifyExpression(literalValue);
|
|
330
350
|
|
|
331
|
-
return {
|
|
351
|
+
return freeze({
|
|
352
|
+
flags,
|
|
353
|
+
type,
|
|
354
|
+
name,
|
|
355
|
+
literalValue,
|
|
356
|
+
attributes,
|
|
357
|
+
});
|
|
332
358
|
}
|
|
333
359
|
|
|
334
|
-
case '
|
|
335
|
-
let
|
|
360
|
+
case 'TreeNodeMatcher': {
|
|
361
|
+
let open = reifyExpression(get('open', node));
|
|
336
362
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
flags,
|
|
341
|
-
type: Symbol.for('@bablr/fragment'),
|
|
342
|
-
literalValue: null,
|
|
343
|
-
attributes: null,
|
|
344
|
-
};
|
|
345
|
-
}
|
|
363
|
+
if (!open) {
|
|
364
|
+
return [...list('children', node)].map(reifyExpression)[0];
|
|
365
|
+
}
|
|
346
366
|
|
|
347
|
-
|
|
348
|
-
return reifyExpression(get('open', node));
|
|
367
|
+
return open;
|
|
349
368
|
}
|
|
350
369
|
|
|
351
370
|
case 'PropertyMatcher': {
|
|
352
371
|
let refMatcher = get('refMatcher', node);
|
|
353
|
-
let
|
|
354
|
-
|
|
372
|
+
let boundMatcher = get('valueMatcher', node);
|
|
373
|
+
|
|
374
|
+
refMatcher = reifyExpression(refMatcher);
|
|
355
375
|
|
|
356
|
-
|
|
357
|
-
bindingMatcher = bindingMatcher ? reifyExpression(bindingMatcher) : null;
|
|
358
|
-
nodeMatcher = reifyExpression(nodeMatcher);
|
|
376
|
+
if (!boundMatcher) throw new Error();
|
|
359
377
|
|
|
360
|
-
|
|
378
|
+
if (boundMatcher.value.name !== Symbol.for('BoundNodeMatcher')) throw new Error();
|
|
379
|
+
|
|
380
|
+
let { nodeMatcher, bindingMatchers } = reifyExpression(boundMatcher);
|
|
381
|
+
|
|
382
|
+
return freeze({ refMatcher, bindingMatchers, nodeMatcher });
|
|
361
383
|
}
|
|
362
384
|
|
|
363
385
|
case 'ReferenceMatcher': {
|
|
364
386
|
let type = get('type', node);
|
|
365
387
|
let name = get('name', node);
|
|
366
|
-
let isArray = !isNull(get('openIndexToken', node));
|
|
367
388
|
let flags = get('flags', node);
|
|
368
389
|
|
|
369
390
|
type = type && reifyExpression(type);
|
|
370
391
|
name = name && reifyExpression(name);
|
|
371
392
|
flags = (flags && reifyReferenceFlags(flags)) || referenceFlags;
|
|
372
393
|
|
|
373
|
-
return { type, name,
|
|
394
|
+
return freeze({ type, name, flags });
|
|
374
395
|
}
|
|
375
396
|
|
|
376
|
-
case '
|
|
377
|
-
let
|
|
397
|
+
case 'BoundNodeMatcher': {
|
|
398
|
+
let bindingMatchers, nodeMatcher;
|
|
399
|
+
// if (get(['nodeMatcher', 'open'], node)) {
|
|
400
|
+
bindingMatchers = [...list('bindingMatchers', node)].map(reifyExpression);
|
|
401
|
+
nodeMatcher = reifyExpression(get('nodeMatcher', node));
|
|
402
|
+
// } else {
|
|
403
|
+
// ({ bindingMatchers, nodeMatcher } = reifyExpression(get('nodeMatcher', node)));
|
|
404
|
+
// }
|
|
405
|
+
|
|
406
|
+
return freeze({ bindingMatchers, nodeMatcher });
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
case 'BoundNode': {
|
|
410
|
+
let bindingTags = [],
|
|
411
|
+
node_;
|
|
412
|
+
if (get(['node', 'openTag'], node)) {
|
|
413
|
+
bindingTags = [...list('bindingTags', node)].map(reifyExpression);
|
|
414
|
+
node_ = reifyExpression(get('node', node));
|
|
415
|
+
} else {
|
|
416
|
+
({ bindingTags, node: node_ } = reifyExpression(get('node', node)));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return freeze({ bindingTags, node: node_ });
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
case 'BindingTag': {
|
|
423
|
+
let segments = [...list('segments', node)].map((segment) => {
|
|
424
|
+
return reifyExpression(segment);
|
|
425
|
+
});
|
|
426
|
+
return buildBindingTag(segments);
|
|
427
|
+
}
|
|
378
428
|
|
|
379
|
-
|
|
429
|
+
case 'BindingSegment': {
|
|
430
|
+
let path = get('path', node);
|
|
380
431
|
|
|
381
|
-
|
|
432
|
+
switch (path.value.name && path.value.name.description) {
|
|
433
|
+
case 'Identifier':
|
|
434
|
+
return freeze({ type: null, name: reifyExpression(path) });
|
|
435
|
+
case null:
|
|
436
|
+
return freeze({ type: reifyExpression(path), name: null });
|
|
437
|
+
default:
|
|
438
|
+
throw new Error();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
case 'BindingMatcher': {
|
|
443
|
+
let segments = [...list('segments', node)].map((segment) => reifyExpression(segment));
|
|
444
|
+
|
|
445
|
+
return freeze({ segments });
|
|
382
446
|
}
|
|
383
447
|
|
|
384
448
|
case 'GapNodeMatcher':
|
|
385
|
-
return
|
|
449
|
+
return buildNode(buildGapTag());
|
|
386
450
|
|
|
387
451
|
case 'NullNodeMatcher':
|
|
388
|
-
return
|
|
389
|
-
|
|
390
|
-
case 'ArrayNodeMatcher':
|
|
391
|
-
return [];
|
|
452
|
+
return buildNode(buildNullTag());
|
|
392
453
|
|
|
393
454
|
case 'Call': {
|
|
394
455
|
const verb = get('verb', node);
|
|
395
456
|
|
|
396
457
|
const args = [...list('arguments', node)].map((el) => reifyExpression(el));
|
|
397
458
|
|
|
398
|
-
return { verb: reifyExpression(verb), arguments: args };
|
|
459
|
+
return freeze({ verb: reifyExpression(verb), arguments: args });
|
|
399
460
|
}
|
|
400
461
|
|
|
401
462
|
case 'Object': {
|
|
@@ -403,16 +464,15 @@ export const reifyExpression = (node) => {
|
|
|
403
464
|
[...list('properties', node)].map((property) => {
|
|
404
465
|
const key = get('key', property);
|
|
405
466
|
const value = get('value', property);
|
|
406
|
-
return [reifyExpression(key), reifyExpression(value)];
|
|
467
|
+
return freeze([reifyExpression(key), reifyExpression(value)]);
|
|
407
468
|
}),
|
|
408
469
|
);
|
|
409
470
|
}
|
|
410
471
|
|
|
411
472
|
case 'Array': {
|
|
412
|
-
return [...list('elements', node)].map((el) => reifyExpression(el));
|
|
473
|
+
return freeze([...list('elements', node)].map((el) => reifyExpression(el)));
|
|
413
474
|
}
|
|
414
475
|
|
|
415
|
-
case 'Punctuator':
|
|
416
476
|
case 'Keyword':
|
|
417
477
|
return getCooked(node);
|
|
418
478
|
|
package/lib/print.js
CHANGED
|
@@ -2,14 +2,28 @@ import {
|
|
|
2
2
|
printSource,
|
|
3
3
|
printTag,
|
|
4
4
|
printExpression as printExpression_,
|
|
5
|
+
printCSTML,
|
|
5
6
|
} from '@bablr/agast-helpers/tree';
|
|
6
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Tag,
|
|
9
|
+
EmbeddedObject,
|
|
10
|
+
Matcher,
|
|
11
|
+
Regex,
|
|
12
|
+
Instruction,
|
|
13
|
+
TreeNode,
|
|
14
|
+
NullNode,
|
|
15
|
+
GapNode,
|
|
16
|
+
Node,
|
|
17
|
+
} from './symbols.js';
|
|
7
18
|
|
|
8
19
|
export const printEmbedded = (value) => {
|
|
9
20
|
switch (value.type) {
|
|
10
21
|
case Tag:
|
|
11
22
|
return `t\`${printTag(value.value)}\``;
|
|
12
23
|
|
|
24
|
+
case Node:
|
|
25
|
+
return `n\`${printCSTML(value.value)}\``;
|
|
26
|
+
|
|
13
27
|
case Matcher:
|
|
14
28
|
return `m\`${printSource(value.value)}\``;
|
|
15
29
|
|
|
@@ -23,12 +37,17 @@ export const printEmbedded = (value) => {
|
|
|
23
37
|
return printObject(value.value);
|
|
24
38
|
}
|
|
25
39
|
|
|
26
|
-
case
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
case NullNode:
|
|
41
|
+
case GapNode:
|
|
42
|
+
case TreeNode:
|
|
43
|
+
throw new Error(
|
|
44
|
+
'Cannot print plain node. Did you mean to wrap this node in buildEmbeddedNode?',
|
|
45
|
+
);
|
|
29
46
|
|
|
30
47
|
default:
|
|
31
|
-
throw new Error(
|
|
48
|
+
throw new Error(
|
|
49
|
+
'Cannot print plain object. Did you mean to wrap this object in buildEmbedded*?',
|
|
50
|
+
);
|
|
32
51
|
}
|
|
33
52
|
};
|
|
34
53
|
|
package/lib/stream.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
2
|
import {
|
|
3
|
-
InitializerTag,
|
|
4
3
|
CloseNodeTag,
|
|
5
4
|
EmbeddedObject,
|
|
6
5
|
GapTag,
|
|
@@ -11,11 +10,12 @@ import {
|
|
|
11
10
|
import {
|
|
12
11
|
getStreamIterator,
|
|
13
12
|
printTag,
|
|
13
|
+
wait,
|
|
14
14
|
StreamIterable,
|
|
15
15
|
prettyGroupTags,
|
|
16
|
+
hoistTrivia,
|
|
16
17
|
} from '@bablr/agast-helpers/stream';
|
|
17
18
|
import { buildWriteEffect } from './builders.js';
|
|
18
|
-
import { getCooked } from '@bablr/agast-helpers/tree';
|
|
19
19
|
|
|
20
20
|
const getEmbeddedObject = (obj) => {
|
|
21
21
|
if (obj.type !== EmbeddedObject) throw new Error();
|
|
@@ -29,7 +29,7 @@ function* __generateStandardOutput(tags) {
|
|
|
29
29
|
co.advance();
|
|
30
30
|
|
|
31
31
|
if (co.current instanceof Promise) {
|
|
32
|
-
co.current = yield co.current;
|
|
32
|
+
co.current = yield wait(co.current);
|
|
33
33
|
}
|
|
34
34
|
if (co.done) break;
|
|
35
35
|
|
|
@@ -58,7 +58,7 @@ function* __generateAllOutput(tags) {
|
|
|
58
58
|
co.advance();
|
|
59
59
|
|
|
60
60
|
if (co.current instanceof Promise) {
|
|
61
|
-
co.current = yield co.current;
|
|
61
|
+
co.current = yield wait(co.current);
|
|
62
62
|
}
|
|
63
63
|
if (co.done) break;
|
|
64
64
|
|
|
@@ -99,7 +99,7 @@ function* __writeCSTMLStrategy(tags) {
|
|
|
99
99
|
co.advance();
|
|
100
100
|
|
|
101
101
|
if (co.current instanceof Promise) {
|
|
102
|
-
co.current = yield co.current;
|
|
102
|
+
co.current = yield wait(co.current);
|
|
103
103
|
}
|
|
104
104
|
if (co.done) break;
|
|
105
105
|
|
|
@@ -134,7 +134,8 @@ function* __writePrettyCSTMLStrategy(tags, options) {
|
|
|
134
134
|
return;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
const co = new Coroutine(getStreamIterator(prettyGroupTags(tags)));
|
|
137
|
+
const co = new Coroutine(getStreamIterator(prettyGroupTags(hoistTrivia(tags))));
|
|
138
|
+
// const co = new Coroutine(getStreamIterator(prettyGroupTags(tags)));
|
|
138
139
|
let indentLevel = 0;
|
|
139
140
|
let first = true;
|
|
140
141
|
let inline = false;
|
|
@@ -143,11 +144,10 @@ function* __writePrettyCSTMLStrategy(tags, options) {
|
|
|
143
144
|
for (;;) {
|
|
144
145
|
co.advance();
|
|
145
146
|
|
|
146
|
-
if (co.done) break;
|
|
147
|
-
|
|
148
147
|
if (co.current instanceof Promise) {
|
|
149
|
-
co.current = yield co.current;
|
|
148
|
+
co.current = yield wait(co.current);
|
|
150
149
|
}
|
|
150
|
+
if (co.done) break;
|
|
151
151
|
|
|
152
152
|
const tag = co.value;
|
|
153
153
|
|
|
@@ -174,7 +174,6 @@ function* __writePrettyCSTMLStrategy(tags, options) {
|
|
|
174
174
|
ref &&
|
|
175
175
|
(tag.type === NullTag ||
|
|
176
176
|
tag.type === GapTag ||
|
|
177
|
-
tag.type === InitializerTag ||
|
|
178
177
|
(tag.type === OpenNodeTag && tag.value.selfClosing));
|
|
179
178
|
|
|
180
179
|
if (!first && !inline) {
|
|
@@ -203,7 +202,7 @@ function* __writePrettyCSTMLStrategy(tags, options) {
|
|
|
203
202
|
ref = tag;
|
|
204
203
|
}
|
|
205
204
|
|
|
206
|
-
if (tag.type === OpenNodeTag && !tag.value.
|
|
205
|
+
if (tag.type === OpenNodeTag && !tag.value.selfClosing) {
|
|
207
206
|
indentLevel++;
|
|
208
207
|
}
|
|
209
208
|
|
package/lib/symbols.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
export * from '@bablr/agast-helpers/symbols';
|
|
2
2
|
|
|
3
|
-
export const node = Symbol.for('@bablr/node');
|
|
4
|
-
export const fragment = Symbol.for('@bablr/fragment');
|
|
5
|
-
|
|
6
3
|
export const Instruction = Symbol.for('Instruction');
|
|
7
4
|
export const Matcher = Symbol.for('Matcher');
|
|
8
5
|
export const Regex = Symbol.for('Regex');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/agast-vm-helpers",
|
|
3
3
|
"description": "Helper functions for working with the BABLR VM",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.1",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"sideEffects": false,
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@bablr/agast-helpers": "0.
|
|
25
|
+
"@bablr/agast-helpers": "0.10.1",
|
|
26
26
|
"@bablr/coroutine": "0.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|