@bablr/agast-vm-helpers 0.5.2 → 0.6.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/deembed.js +26 -20
- package/lib/embed.js +4 -2
- package/lib/index.js +210 -134
- package/lib/iterable.js +29 -0
- package/lib/languages.js +1 -1
- package/package.json +6 -3
package/lib/deembed.js
CHANGED
|
@@ -1,31 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
EmbeddedNode,
|
|
3
|
+
EmbeddedObject,
|
|
4
|
+
EmbeddedTag,
|
|
5
|
+
EmbeddedMatcher,
|
|
6
|
+
EmbeddedRegex,
|
|
7
|
+
} from '@bablr/agast-helpers/symbols';
|
|
2
8
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
export const getEmbeddedObject = (expr) => {
|
|
10
|
+
if (!expr) return expr;
|
|
11
|
+
if (expr.type !== EmbeddedObject) throw new Error();
|
|
12
|
+
return expr.value;
|
|
13
|
+
};
|
|
6
14
|
|
|
7
|
-
export const
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return expr.map((value) => deembedExpression(value));
|
|
12
|
-
} else if (typeof expr === 'object') {
|
|
13
|
-
return Object.fromEntries(
|
|
14
|
-
Object.entries(expr.value).map(({ 0: key, 1: value }) => [key, deembedExpression(value)]),
|
|
15
|
-
);
|
|
16
|
-
} else {
|
|
17
|
-
throw new Error();
|
|
18
|
-
}
|
|
15
|
+
export const getEmbeddedNode = (expr) => {
|
|
16
|
+
if (!expr) return expr;
|
|
17
|
+
if (expr.type !== EmbeddedNode) throw new Error();
|
|
18
|
+
return expr.value;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export const
|
|
21
|
+
export const getEmbeddedMatcher = (expr) => {
|
|
22
22
|
if (!expr) return expr;
|
|
23
|
-
if (expr.type !==
|
|
23
|
+
if (expr.type !== EmbeddedMatcher) throw new Error();
|
|
24
24
|
return expr.value;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export const
|
|
27
|
+
export const getEmbeddedRegex = (expr) => {
|
|
28
28
|
if (!expr) return expr;
|
|
29
|
-
if (expr.type !==
|
|
29
|
+
if (expr.type !== EmbeddedRegex) throw new Error();
|
|
30
30
|
return expr.value;
|
|
31
31
|
};
|
|
32
|
+
|
|
33
|
+
export const getEmbeddedTag = (expr) => {
|
|
34
|
+
if (expr.type !== EmbeddedTag) throw new Error();
|
|
35
|
+
const tag = expr.value;
|
|
36
|
+
return tag;
|
|
37
|
+
};
|
package/lib/embed.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildEmbeddedObject } from './internal-builders.js';
|
|
2
2
|
|
|
3
3
|
const { isArray } = Array;
|
|
4
4
|
const isString = (val) => typeof val === 'string';
|
|
@@ -10,7 +10,7 @@ export const embedExpression = (expr) => {
|
|
|
10
10
|
} else if (isArray(expr)) {
|
|
11
11
|
return expr.map((value) => embedExpression(value));
|
|
12
12
|
} else if (typeof expr === 'object') {
|
|
13
|
-
return
|
|
13
|
+
return buildEmbeddedObject(
|
|
14
14
|
Object.fromEntries(
|
|
15
15
|
Object.entries(expr).map(({ 0: key, 1: value }) => [key, embedExpression(value)]),
|
|
16
16
|
),
|
|
@@ -19,3 +19,5 @@ export const embedExpression = (expr) => {
|
|
|
19
19
|
throw new Error();
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
export { buildEmbeddedObject, buildEmbeddedObject as o };
|
package/lib/index.js
CHANGED
|
@@ -1,21 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
sourceTextFor,
|
|
3
|
+
getCooked,
|
|
4
|
+
isNull,
|
|
5
|
+
nodeFlags,
|
|
6
|
+
printType,
|
|
7
|
+
buildGapTag,
|
|
8
|
+
buildEmbeddedMatcher,
|
|
9
|
+
isNullNode,
|
|
10
|
+
buildNullTag,
|
|
11
|
+
buildStubNode,
|
|
12
|
+
isFragmentNode,
|
|
13
|
+
buildReferenceTag,
|
|
14
|
+
} from '@bablr/agast-helpers/tree';
|
|
2
15
|
import * as btree from '@bablr/agast-helpers/btree';
|
|
3
|
-
import
|
|
4
|
-
|
|
16
|
+
import {
|
|
17
|
+
buildCloseNodeTag,
|
|
18
|
+
buildLiteralTag,
|
|
19
|
+
buildDoctypeTag,
|
|
20
|
+
referenceFlags,
|
|
21
|
+
buildEmbeddedRegex,
|
|
22
|
+
} from '@bablr/agast-helpers/builders';
|
|
5
23
|
import {
|
|
6
24
|
DoctypeTag,
|
|
7
25
|
OpenNodeTag,
|
|
8
|
-
OpenFragmentTag,
|
|
9
|
-
CloseFragmentTag,
|
|
10
26
|
CloseNodeTag,
|
|
11
|
-
ReferenceTag,
|
|
12
27
|
ShiftTag,
|
|
13
28
|
GapTag,
|
|
14
29
|
NullTag,
|
|
15
|
-
|
|
30
|
+
ArrayInitializerTag,
|
|
16
31
|
LiteralTag,
|
|
17
32
|
} from '@bablr/agast-helpers/symbols';
|
|
18
33
|
|
|
34
|
+
const { freeze } = Object;
|
|
35
|
+
|
|
19
36
|
export const effectsFor = (verb) => {
|
|
20
37
|
switch (verb) {
|
|
21
38
|
case 'eat':
|
|
@@ -41,15 +58,21 @@ export const shouldBranch = (effects) => {
|
|
|
41
58
|
return effects ? effects.success === 'none' || effects.failure === 'none' : false;
|
|
42
59
|
};
|
|
43
60
|
|
|
44
|
-
const
|
|
45
|
-
let {
|
|
61
|
+
export const reifyNodeFlags = (flags) => {
|
|
62
|
+
let { tokenToken, hasGapToken } = flags.properties;
|
|
46
63
|
|
|
47
64
|
return {
|
|
48
|
-
token: !!reifyExpression(tokenToken),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
token: !!(tokenToken && reifyExpression(tokenToken.node)),
|
|
66
|
+
hasGap: !!(hasGapToken && reifyExpression(hasGapToken.node)),
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const reifyReferenceFlags = (flags) => {
|
|
71
|
+
let { expressionToken, hasGapToken } = flags.properties;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
expression: !!(expressionToken && reifyExpression(expressionToken.node)),
|
|
75
|
+
hasGap: !!(hasGapToken && reifyExpression(hasGapToken.node)),
|
|
53
76
|
};
|
|
54
77
|
};
|
|
55
78
|
|
|
@@ -62,18 +85,18 @@ export const reifyLanguage = (language) => {
|
|
|
62
85
|
export const reifyProperties = (properties = []) => {
|
|
63
86
|
const built = {};
|
|
64
87
|
for (const property of btree.traverse(properties)) {
|
|
65
|
-
switch (property.type) {
|
|
66
|
-
case 'Property': {
|
|
67
|
-
let { reference, value } = property.properties;
|
|
88
|
+
switch (property.node.type) {
|
|
89
|
+
case Symbol.for('Property'): {
|
|
90
|
+
let { reference, value: node } = property.node.properties;
|
|
68
91
|
|
|
69
|
-
reference = reifyExpression(reference);
|
|
70
|
-
|
|
92
|
+
reference = reifyExpression(reference.node);
|
|
93
|
+
node = reifyExpression(node.node);
|
|
71
94
|
|
|
72
95
|
if (reference.value.isArray) {
|
|
73
96
|
built[reference.value.name] ||= [];
|
|
74
|
-
built[reference.value.name].push(
|
|
97
|
+
built[reference.value.name].push({ reference, node });
|
|
75
98
|
} else {
|
|
76
|
-
built[reference.value.name] =
|
|
99
|
+
built[reference.value.name] = { reference, node };
|
|
77
100
|
}
|
|
78
101
|
break;
|
|
79
102
|
}
|
|
@@ -89,19 +112,20 @@ export const buildFragmentChildren = (node) => {
|
|
|
89
112
|
|
|
90
113
|
let built = [];
|
|
91
114
|
|
|
92
|
-
open = reifyExpression(open);
|
|
93
|
-
close = reifyExpression(close);
|
|
115
|
+
open = reifyExpression(open.node);
|
|
116
|
+
close = reifyExpression(close.node);
|
|
94
117
|
|
|
95
118
|
built = btree.push(built, open);
|
|
96
119
|
|
|
97
120
|
for (const child of btree.traverse(children)) {
|
|
98
|
-
if (child.type !== 'Property') throw new Error('umimplemented');
|
|
121
|
+
if (child.node.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
99
122
|
|
|
100
|
-
let { reference } = child.properties;
|
|
123
|
+
let { reference } = child.node.properties;
|
|
101
124
|
|
|
102
|
-
reference = reifyExpression(reference);
|
|
125
|
+
reference = reifyExpression(reference.node);
|
|
103
126
|
|
|
104
127
|
built = btree.push(built, reference);
|
|
128
|
+
built = btree.push(built, buildGapTag());
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
built = btree.push(built, close);
|
|
@@ -112,29 +136,30 @@ export const buildFragmentChildren = (node) => {
|
|
|
112
136
|
export const buildChildren = (node) => {
|
|
113
137
|
let { open, children = [], close } = node.properties;
|
|
114
138
|
|
|
115
|
-
const selfClosing =
|
|
116
|
-
const { intrinsicValue } = open.properties;
|
|
139
|
+
const selfClosing = !isNull(open.node.properties.selfClosingTagToken?.node);
|
|
140
|
+
const { intrinsicValue } = open.node.properties;
|
|
117
141
|
let built = [];
|
|
118
142
|
|
|
119
|
-
open = reifyExpression(open);
|
|
120
|
-
close = reifyExpression(close);
|
|
143
|
+
open = reifyExpression(open.node);
|
|
144
|
+
close = reifyExpression(close?.node);
|
|
121
145
|
|
|
122
146
|
if (selfClosing) {
|
|
123
147
|
built = btree.push(built, open);
|
|
124
|
-
if (intrinsicValue) {
|
|
125
|
-
built = btree.push(built, buildLiteralTag(intrinsicValue));
|
|
148
|
+
if (!isNull(intrinsicValue?.node)) {
|
|
149
|
+
built = btree.push(built, buildLiteralTag(intrinsicValue.node));
|
|
126
150
|
}
|
|
127
|
-
built = btree.push(built,
|
|
151
|
+
built = btree.push(built, buildCloseNodeTag());
|
|
128
152
|
} else {
|
|
129
153
|
built = btree.push(built, open);
|
|
130
154
|
for (const child of btree.traverse(children)) {
|
|
131
|
-
if (child.type !== 'Property') throw new Error('umimplemented');
|
|
155
|
+
if (child.node.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
132
156
|
|
|
133
|
-
let { reference } = child.properties;
|
|
157
|
+
let { reference } = child.node.properties;
|
|
134
158
|
|
|
135
|
-
reference = reifyExpression(reference);
|
|
159
|
+
reference = reifyExpression(reference.node);
|
|
136
160
|
|
|
137
161
|
built = btree.push(built, reference);
|
|
162
|
+
built = btree.push(built, buildGapTag());
|
|
138
163
|
}
|
|
139
164
|
|
|
140
165
|
built = btree.push(built, close);
|
|
@@ -146,10 +171,11 @@ export const buildChildren = (node) => {
|
|
|
146
171
|
export const reifyExpression = (node) => {
|
|
147
172
|
if (node instanceof Promise) throw new Error();
|
|
148
173
|
|
|
149
|
-
if (
|
|
174
|
+
if (node == null) return node;
|
|
175
|
+
if (isNullNode(node)) return null;
|
|
150
176
|
|
|
151
|
-
if (
|
|
152
|
-
node = node.properties['.'];
|
|
177
|
+
if (isFragmentNode(node)) {
|
|
178
|
+
node = node.properties['.'].node;
|
|
153
179
|
}
|
|
154
180
|
|
|
155
181
|
if (node.language === 'https://bablr.org/languages/core/en/cstml') {
|
|
@@ -157,19 +183,19 @@ export const reifyExpression = (node) => {
|
|
|
157
183
|
case 'Document': {
|
|
158
184
|
let { doctype, tree } = node.properties;
|
|
159
185
|
|
|
160
|
-
doctype = reifyExpression(doctype);
|
|
161
|
-
tree = reifyExpression(tree);
|
|
186
|
+
doctype = reifyExpression(doctype.node);
|
|
187
|
+
tree = reifyExpression(tree.node);
|
|
162
188
|
|
|
163
189
|
let { attributes } = doctype.value;
|
|
164
190
|
let { properties } = tree;
|
|
165
191
|
|
|
166
192
|
return {
|
|
167
193
|
flags: nodeFlags,
|
|
168
|
-
language: attributes
|
|
194
|
+
language: attributes.bablrLanguage,
|
|
169
195
|
type: null,
|
|
170
196
|
children: btree.addAt(
|
|
171
197
|
0,
|
|
172
|
-
buildFragmentChildren(node.properties.tree),
|
|
198
|
+
buildFragmentChildren(node.properties.tree.node),
|
|
173
199
|
buildDoctypeTag(attributes),
|
|
174
200
|
),
|
|
175
201
|
properties,
|
|
@@ -180,7 +206,7 @@ export const reifyExpression = (node) => {
|
|
|
180
206
|
case 'Node': {
|
|
181
207
|
let { open, children } = node.properties;
|
|
182
208
|
|
|
183
|
-
open = reifyExpression(open);
|
|
209
|
+
open = reifyExpression(open.node);
|
|
184
210
|
|
|
185
211
|
let { flags, language, type, attributes } = open.value;
|
|
186
212
|
|
|
@@ -199,7 +225,7 @@ export const reifyExpression = (node) => {
|
|
|
199
225
|
case 'Fragment': {
|
|
200
226
|
let { open, children } = node.properties;
|
|
201
227
|
|
|
202
|
-
open = reifyExpression(open);
|
|
228
|
+
open = reifyExpression(open.node);
|
|
203
229
|
|
|
204
230
|
let { flags } = open.value;
|
|
205
231
|
|
|
@@ -216,26 +242,24 @@ export const reifyExpression = (node) => {
|
|
|
216
242
|
}
|
|
217
243
|
|
|
218
244
|
case 'DoctypeTag': {
|
|
219
|
-
let {
|
|
245
|
+
let { doctypeToken, version, attributes } = node.properties;
|
|
220
246
|
return {
|
|
221
247
|
type: DoctypeTag,
|
|
222
248
|
value: {
|
|
223
|
-
|
|
224
|
-
version: parseInt(sourceTextFor(version), 10),
|
|
225
|
-
attributes:
|
|
249
|
+
doctypeToken: getCooked(doctypeToken?.node),
|
|
250
|
+
version: parseInt(sourceTextFor(version.node), 10),
|
|
251
|
+
attributes: reifyExpression(attributes.node),
|
|
226
252
|
},
|
|
227
253
|
};
|
|
228
254
|
}
|
|
229
255
|
|
|
230
256
|
case 'ReferenceTag': {
|
|
231
|
-
let { name, arrayOperatorToken,
|
|
257
|
+
let { name, arrayOperatorToken, flags } = node.properties;
|
|
232
258
|
|
|
233
|
-
name = reifyExpression(name);
|
|
259
|
+
name = reifyExpression(name.node);
|
|
260
|
+
flags = freeze({ expression: !!flags?.expressionToken, hasGap: !!flags?.hasGapToken });
|
|
234
261
|
|
|
235
|
-
return
|
|
236
|
-
type: ReferenceTag,
|
|
237
|
-
value: { name, isArray: !isNull(arrayOperatorToken), hasGap: !isNull(hasGapToken) },
|
|
238
|
-
};
|
|
262
|
+
return buildReferenceTag(name, !isNull(arrayOperatorToken?.node), flags);
|
|
239
263
|
}
|
|
240
264
|
|
|
241
265
|
case 'LiteralTag': {
|
|
@@ -243,20 +267,22 @@ export const reifyExpression = (node) => {
|
|
|
243
267
|
|
|
244
268
|
return { type: LiteralTag, value: getCooked(value.properties.content) };
|
|
245
269
|
}
|
|
270
|
+
|
|
246
271
|
case 'Identifier': {
|
|
247
272
|
return getCooked(node);
|
|
248
273
|
}
|
|
274
|
+
|
|
249
275
|
case 'IdentifierPath': {
|
|
250
|
-
return node.properties.segments.map((segment) => reifyExpression(segment));
|
|
276
|
+
return node.properties.segments.map((segment) => reifyExpression(segment.node));
|
|
251
277
|
}
|
|
252
278
|
|
|
253
279
|
case 'OpenNodeTag': {
|
|
254
280
|
let { flags, language, type, attributes } = node.properties;
|
|
255
281
|
|
|
256
|
-
flags =
|
|
257
|
-
language = reifyLanguage(language);
|
|
258
|
-
type = reifyExpression(type);
|
|
259
|
-
attributes =
|
|
282
|
+
flags = reifyNodeFlags(flags.node);
|
|
283
|
+
language = reifyLanguage(language?.node);
|
|
284
|
+
type = reifyExpression(type?.node);
|
|
285
|
+
attributes = reifyExpression(attributes?.node);
|
|
260
286
|
|
|
261
287
|
return {
|
|
262
288
|
type: OpenNodeTag,
|
|
@@ -265,50 +291,27 @@ export const reifyExpression = (node) => {
|
|
|
265
291
|
}
|
|
266
292
|
|
|
267
293
|
case 'CloseNodeTag': {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
language = reifyLanguage(language);
|
|
271
|
-
type = reifyExpression(type);
|
|
272
|
-
|
|
273
|
-
return { type: CloseNodeTag, value: { language, type } };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
case 'OpenFragmentTag': {
|
|
277
|
-
let { flags } = node.properties;
|
|
278
|
-
|
|
279
|
-
flags = reifyFlags(flags);
|
|
280
|
-
|
|
281
|
-
return {
|
|
282
|
-
type: OpenFragmentTag,
|
|
283
|
-
value: { flags },
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
case 'CloseFragmentTag': {
|
|
288
|
-
return { type: CloseFragmentTag, value: undefined };
|
|
294
|
+
return { type: CloseNodeTag, value: undefined };
|
|
289
295
|
}
|
|
290
296
|
|
|
291
297
|
case 'Integer': {
|
|
292
298
|
let { digits } = node.properties;
|
|
293
|
-
return parseInt(digits.map((digit) => getCooked(digit)).join(''), 10);
|
|
299
|
+
return parseInt(digits.map((digit) => getCooked(digit.node)).join(''), 10);
|
|
294
300
|
}
|
|
295
301
|
|
|
296
302
|
case 'Infinity': {
|
|
297
|
-
return node.properties.sign === '-' ? -Infinity : Infinity;
|
|
303
|
+
return getCooked(node.properties.sign.node) === '-' ? -Infinity : Infinity;
|
|
298
304
|
}
|
|
299
305
|
|
|
300
306
|
case 'Punctuator': {
|
|
301
307
|
return getCooked(node);
|
|
302
308
|
}
|
|
303
309
|
|
|
304
|
-
case 'String':
|
|
305
|
-
return node.properties.content ? getCooked(node.properties.content) : '';
|
|
306
|
-
|
|
307
310
|
case 'GapTag':
|
|
308
311
|
return { type: GapTag, value: undefined };
|
|
309
312
|
|
|
310
|
-
case '
|
|
311
|
-
return { type:
|
|
313
|
+
case 'ArrayInitializerTag':
|
|
314
|
+
return { type: ArrayInitializerTag, value: undefined };
|
|
312
315
|
|
|
313
316
|
case 'NullTag':
|
|
314
317
|
return { type: NullTag, value: undefined };
|
|
@@ -324,6 +327,7 @@ export const reifyExpression = (node) => {
|
|
|
324
327
|
if (
|
|
325
328
|
![
|
|
326
329
|
'https://bablr.org/languages/core/en/bablr-vm-instruction',
|
|
330
|
+
'https://bablr.org/languages/core/en/cstml-json',
|
|
327
331
|
'https://bablr.org/languages/core/en/cstml',
|
|
328
332
|
'https://bablr.org/languages/core/en/spamex',
|
|
329
333
|
].includes(node.language)
|
|
@@ -331,44 +335,112 @@ export const reifyExpression = (node) => {
|
|
|
331
335
|
return node;
|
|
332
336
|
}
|
|
333
337
|
|
|
334
|
-
switch (node.type) {
|
|
335
|
-
case '
|
|
336
|
-
|
|
338
|
+
switch (printType(node.type)) {
|
|
339
|
+
case 'String':
|
|
340
|
+
return node.properties.content.node ? getCooked(node.properties.content.node) : '';
|
|
341
|
+
|
|
342
|
+
case 'SpamexString': {
|
|
343
|
+
return buildEmbeddedMatcher(node.properties.content.node);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
case 'RegexString': {
|
|
347
|
+
return buildEmbeddedRegex(node.properties.content.node);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
case 'OpenNodeMatcher': {
|
|
351
|
+
let { flags, language, type, attributes, intrinsicValue } = node.properties;
|
|
337
352
|
|
|
338
|
-
flags =
|
|
339
|
-
language = reifyLanguage(language);
|
|
340
|
-
type =
|
|
341
|
-
|
|
342
|
-
|
|
353
|
+
flags = (flags && reifyNodeFlags(flags.node)) || {};
|
|
354
|
+
language = language && reifyLanguage(language.node);
|
|
355
|
+
type =
|
|
356
|
+
type.node.type === Symbol.for('String')
|
|
357
|
+
? getCooked(type.node.properties.content.node)
|
|
358
|
+
: getCooked(type.node);
|
|
359
|
+
attributes = attributes ? reifyExpression(attributes.node) : {};
|
|
360
|
+
intrinsicValue = intrinsicValue && reifyExpression(intrinsicValue.node);
|
|
343
361
|
|
|
344
362
|
return { flags, language, type, intrinsicValue, attributes };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
case 'FragmentMatcher': {
|
|
366
|
+
let { flags } = node.properties;
|
|
367
|
+
|
|
368
|
+
flags = (flags && reifyNodeFlags(flags.node)) || {};
|
|
369
|
+
|
|
370
|
+
return {
|
|
371
|
+
flags,
|
|
372
|
+
language: null,
|
|
373
|
+
type: Symbol.for('@bablr/fragment'),
|
|
374
|
+
intrinsicValue: null,
|
|
375
|
+
attributes: null,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
case 'BasicNodeMatcher': {
|
|
380
|
+
let { open } = node.properties;
|
|
381
|
+
|
|
382
|
+
return reifyExpression(open.node);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
case 'PropertyMatcher': {
|
|
386
|
+
let { refMatcher, nodeMatcher } = node.properties;
|
|
387
|
+
|
|
388
|
+
refMatcher = refMatcher ? reifyExpression(refMatcher.node) : null;
|
|
389
|
+
nodeMatcher = reifyExpression(nodeMatcher.node);
|
|
390
|
+
|
|
391
|
+
return { refMatcher, nodeMatcher };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
case 'ReferenceMatcher': {
|
|
395
|
+
let { name, openIndexToken, flags } = node.properties;
|
|
396
|
+
|
|
397
|
+
name =
|
|
398
|
+
name &&
|
|
399
|
+
(name.node.type === Symbol.for('Identifier')
|
|
400
|
+
? reifyExpression(name.node)
|
|
401
|
+
: getCooked(name.node));
|
|
402
|
+
let isArray = !isNull(openIndexToken?.node);
|
|
403
|
+
flags = (flags && reifyReferenceFlags(flags?.node)) || referenceFlags;
|
|
404
|
+
|
|
405
|
+
return { name, isArray, flags };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
case 'GapNodeMatcher':
|
|
409
|
+
return buildStubNode(buildGapTag());
|
|
410
|
+
|
|
411
|
+
case 'NullNodeMatcher':
|
|
412
|
+
return buildStubNode(buildNullTag());
|
|
413
|
+
|
|
414
|
+
case 'ArrayNodeMatcher':
|
|
415
|
+
return [];
|
|
345
416
|
|
|
346
417
|
case 'Call': {
|
|
347
418
|
const { verb, arguments: args } = node.properties;
|
|
348
|
-
|
|
419
|
+
|
|
420
|
+
const args_ = [...btree.traverse(args)].map((el) => reifyExpression(el.node));
|
|
421
|
+
|
|
422
|
+
return { verb: reifyExpression(verb.node), arguments: args_ };
|
|
349
423
|
}
|
|
350
424
|
|
|
351
425
|
case 'Object': {
|
|
352
426
|
const { properties } = node.properties;
|
|
353
427
|
|
|
354
428
|
return Object.fromEntries(
|
|
355
|
-
[...btree.traverse(properties)].map((
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
429
|
+
[...btree.traverse(properties)].map((property) => {
|
|
430
|
+
const {
|
|
431
|
+
node: {
|
|
432
|
+
properties: { key, value },
|
|
433
|
+
},
|
|
434
|
+
} = property;
|
|
435
|
+
return [getCooked(key.node), reifyExpression(value.node)];
|
|
436
|
+
}),
|
|
359
437
|
);
|
|
360
438
|
}
|
|
361
439
|
|
|
362
|
-
case 'Tuple': {
|
|
363
|
-
const { values = [] } = node.properties;
|
|
364
|
-
|
|
365
|
-
return [...btree.traverse(values)].map((el) => reifyExpression(el));
|
|
366
|
-
}
|
|
367
|
-
|
|
368
440
|
case 'Array': {
|
|
369
441
|
const { elements = [] } = node.properties;
|
|
370
442
|
|
|
371
|
-
return [...btree.traverse(elements)].map((el) => reifyExpression(el));
|
|
443
|
+
return [...btree.traverse(elements)].map((el) => reifyExpression(el.node));
|
|
372
444
|
}
|
|
373
445
|
|
|
374
446
|
case 'LiteralTag':
|
|
@@ -377,7 +449,7 @@ export const reifyExpression = (node) => {
|
|
|
377
449
|
|
|
378
450
|
case 'Boolean': {
|
|
379
451
|
// prettier-ignore
|
|
380
|
-
switch (getCooked(node.properties.sigilToken)) {
|
|
452
|
+
switch (getCooked(node.properties.sigilToken.node)) {
|
|
381
453
|
case 'true': return true;
|
|
382
454
|
case 'false': return false;
|
|
383
455
|
default: throw new Error();
|
|
@@ -393,52 +465,56 @@ export const reifyExpression = (node) => {
|
|
|
393
465
|
};
|
|
394
466
|
|
|
395
467
|
export const reifyExpressionShallow = (node) => {
|
|
396
|
-
if (!node || node
|
|
468
|
+
if (!node || isNullNode(node)) return null;
|
|
397
469
|
|
|
398
470
|
if (
|
|
399
471
|
![
|
|
400
472
|
'https://bablr.org/languages/core/en/bablr-vm-instruction',
|
|
401
473
|
'https://bablr.org/languages/core/en/cstml',
|
|
474
|
+
'https://bablr.org/languages/core/en/cstml-json',
|
|
475
|
+
'https://bablr.org/languages/core/en/spamex',
|
|
402
476
|
].includes(node.language)
|
|
403
477
|
) {
|
|
404
478
|
return node;
|
|
405
479
|
}
|
|
406
480
|
|
|
407
|
-
switch (node.type) {
|
|
481
|
+
switch (printType(node.type)) {
|
|
482
|
+
case 'String':
|
|
483
|
+
case 'SpamexString':
|
|
484
|
+
case 'RegexString': {
|
|
485
|
+
return reifyExpression(node);
|
|
486
|
+
}
|
|
487
|
+
|
|
408
488
|
case 'Object': {
|
|
409
489
|
const { properties } = node.properties;
|
|
410
490
|
|
|
411
491
|
return Object.fromEntries(
|
|
412
|
-
[...btree.traverse(properties)].map(
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
492
|
+
[...btree.traverse(properties)].map(
|
|
493
|
+
({
|
|
494
|
+
node: {
|
|
495
|
+
properties: { key, value },
|
|
496
|
+
},
|
|
497
|
+
}) => [getCooked(key.node), value.node],
|
|
498
|
+
),
|
|
416
499
|
);
|
|
417
500
|
}
|
|
418
501
|
|
|
419
502
|
case 'Array':
|
|
420
|
-
return [...btree.traverse(node.properties.elements)];
|
|
503
|
+
return [...btree.traverse(node.properties.elements)].map((prop) => prop.node);
|
|
421
504
|
|
|
422
|
-
case '
|
|
423
|
-
|
|
505
|
+
case 'Boolean': {
|
|
506
|
+
// prettier-ignore
|
|
507
|
+
switch (getCooked(node.properties.sigilToken.node)) {
|
|
508
|
+
case 'true': return true;
|
|
509
|
+
case 'false': return false;
|
|
510
|
+
default: throw new Error();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
case 'Null':
|
|
515
|
+
return null;
|
|
424
516
|
|
|
425
517
|
default:
|
|
426
518
|
return reifyExpression(node);
|
|
427
519
|
}
|
|
428
520
|
};
|
|
429
|
-
|
|
430
|
-
export const reifyAttributes = (attributes) => {
|
|
431
|
-
if (attributes == null) return {};
|
|
432
|
-
|
|
433
|
-
return Object.fromEntries(
|
|
434
|
-
[...btree.traverse(attributes)].map((attr) => {
|
|
435
|
-
if (attr.type === 'MappingAttribute') {
|
|
436
|
-
return [reifyExpression(attr.properties.key), reifyExpression(attr.properties.value)];
|
|
437
|
-
} else if (attr.type === 'BooleanAttribute') {
|
|
438
|
-
return [reifyExpression(attr.properties.key), isNull(attr.properties.negateToken)];
|
|
439
|
-
} else {
|
|
440
|
-
throw new Error();
|
|
441
|
-
}
|
|
442
|
-
}),
|
|
443
|
-
);
|
|
444
|
-
};
|
package/lib/iterable.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function* concat(...iterables) {
|
|
2
|
+
for (const iterable of iterables) yield* iterable;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const reduce = (reducer, values, initial) => {
|
|
6
|
+
let acc = initial;
|
|
7
|
+
|
|
8
|
+
for (const value of values) {
|
|
9
|
+
acc = reducer(acc, value);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return acc;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function* takeWhile(fn, iterable) {
|
|
16
|
+
for (const value of iterable) {
|
|
17
|
+
if (fn(value)) {
|
|
18
|
+
yield value;
|
|
19
|
+
} else {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function* map(fn, iterable) {
|
|
26
|
+
for (const value of iterable) {
|
|
27
|
+
yield fn(value);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/lib/languages.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const Spamex = 'https://bablr.org/languages/core/en/spamex';
|
|
2
2
|
export const CSTML = 'https://bablr.org/languages/core/en/cstml';
|
|
3
|
+
export const JSON = 'https://bablr.org/languages/core/en/cstml-json';
|
|
3
4
|
export const Regex = 'https://bablr.org/languages/core/en/bablr-regex-pattern';
|
|
4
5
|
export const Instruction = 'https://bablr.org/languages/core/en/bablr-vm-instruction';
|
|
5
|
-
export const Comment = 'https://bablr.org/languages/core/en/c-comments';
|
|
6
6
|
export const Space = 'https://bablr.org/languages/core/en/space-tab-newline';
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
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.6.1",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"files": [
|
|
7
|
+
"files": [
|
|
8
|
+
"lib"
|
|
9
|
+
],
|
|
8
10
|
"exports": {
|
|
9
11
|
".": "./lib/index.js",
|
|
10
12
|
"./builders": "./lib/builders.js",
|
|
@@ -12,11 +14,12 @@
|
|
|
12
14
|
"./embed": "./lib/embed.js",
|
|
13
15
|
"./facades": "./lib/facades.js",
|
|
14
16
|
"./internal-builders": "./lib/internal-builders.js",
|
|
17
|
+
"./iterable": "./lib/iterable.js",
|
|
15
18
|
"./languages": "./lib/languages.js"
|
|
16
19
|
},
|
|
17
20
|
"sideEffects": false,
|
|
18
21
|
"dependencies": {
|
|
19
|
-
"@bablr/agast-helpers": "
|
|
22
|
+
"@bablr/agast-helpers": "0.6.1"
|
|
20
23
|
},
|
|
21
24
|
"devDependencies": {
|
|
22
25
|
"@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#49f5952efed27f94ee9b94340eb1563c440bf64e",
|