@bablr/boot 0.7.0 → 0.7.2
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/languages/json.js +2 -0
- package/package.json +3 -3
- package/shorthand.macro.js +0 -380
package/lib/languages/json.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/boot",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Compile-time tools for bootstrapping BABLR VM",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=12.0.0"
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
],
|
|
16
16
|
"sideEffects": false,
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@bablr/agast-helpers": "0.6.
|
|
19
|
-
"@bablr/agast-vm-helpers": "0.6.
|
|
18
|
+
"@bablr/agast-helpers": "0.6.1",
|
|
19
|
+
"@bablr/agast-vm-helpers": "0.6.1",
|
|
20
20
|
"@iter-tools/imm-stack": "1.1.0",
|
|
21
21
|
"escape-string-regexp": "5.0.0",
|
|
22
22
|
"iter-tools": "^7.5.3"
|
package/shorthand.macro.js
DELETED
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
const { spawnSync } = require('node:child_process');
|
|
2
|
-
const t = require('@babel/types');
|
|
3
|
-
const { expression } = require('@babel/template');
|
|
4
|
-
const { diff } = require('jest-diff');
|
|
5
|
-
const isObject = require('iter-tools-es/methods/is-object');
|
|
6
|
-
const isUndefined = require('iter-tools-es/methods/is-undefined');
|
|
7
|
-
const isNull = require('iter-tools-es/methods/is-null');
|
|
8
|
-
const isString = require('iter-tools-es/methods/is-string');
|
|
9
|
-
const concat = require('iter-tools-es/methods/concat');
|
|
10
|
-
const { createMacro } = require('babel-plugin-macros');
|
|
11
|
-
const { TemplateParser, add, getAgASTValue } = require('./lib/index.js');
|
|
12
|
-
const i = require('./lib/languages/instruction.js');
|
|
13
|
-
const re = require('./lib/languages/regex.js');
|
|
14
|
-
const spam = require('./lib/languages/spamex.js');
|
|
15
|
-
const cstml = require('./lib/languages/cstml.js');
|
|
16
|
-
const { addNamespace, addNamed } = require('@babel/helper-module-imports');
|
|
17
|
-
const { printPrettyCSTML } = require('./lib/print.js');
|
|
18
|
-
const sym = require('@bablr/boot-helpers/symbols');
|
|
19
|
-
const {
|
|
20
|
-
OpenNodeTag,
|
|
21
|
-
CloseNodeTag,
|
|
22
|
-
ReferenceTag,
|
|
23
|
-
GapTag,
|
|
24
|
-
ArrayTag,
|
|
25
|
-
LiteralTag,
|
|
26
|
-
EmbeddedNode,
|
|
27
|
-
} = require('@bablr/boot-helpers/symbols');
|
|
28
|
-
const btree = require('@bablr/boot-helpers/btree');
|
|
29
|
-
|
|
30
|
-
const { isArray } = Array;
|
|
31
|
-
const { hasOwn } = Object;
|
|
32
|
-
const isNumber = (v) => typeof v === 'number';
|
|
33
|
-
const isBoolean = (v) => typeof v === 'boolean';
|
|
34
|
-
const isPlainObject = (v) => isObject(v) && !isArray(v);
|
|
35
|
-
const printRef = (ref) => (ref.isArray ? `${ref.name}[]` : ref.name);
|
|
36
|
-
|
|
37
|
-
const getBtreeASTValue = (tree, exprs, bindings) => {
|
|
38
|
-
if (!isArray(tree)) return tree;
|
|
39
|
-
|
|
40
|
-
if (btree.isLeafNode(tree)) {
|
|
41
|
-
return t.arrayExpression(tree);
|
|
42
|
-
} else {
|
|
43
|
-
return t.arrayExpression([
|
|
44
|
-
t.numericLiteral(tree[0]),
|
|
45
|
-
t.arrayExpression(tree[1].map((v) => getBtreeASTValue(v, exprs, bindings))),
|
|
46
|
-
]);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const getBabelASTValue = (v, exprs, bindings) => {
|
|
51
|
-
return isNull(v)
|
|
52
|
-
? t.nullLiteral()
|
|
53
|
-
: isUndefined(v)
|
|
54
|
-
? t.identifier('undefined')
|
|
55
|
-
: isString(v)
|
|
56
|
-
? t.stringLiteral(v)
|
|
57
|
-
: isNumber(v)
|
|
58
|
-
? t.numericLiteral(v)
|
|
59
|
-
: isBoolean(v)
|
|
60
|
-
? t.booleanLiteral(v)
|
|
61
|
-
: isArray(v)
|
|
62
|
-
? t.arrayExpression(v.map((v) => getBabelASTValue(v, exprs, bindings)))
|
|
63
|
-
: isPlainObject(v) && !v.language
|
|
64
|
-
? t.objectExpression(
|
|
65
|
-
Object.entries(v).map(([k, v]) =>
|
|
66
|
-
t.objectProperty(t.identifier(k), getBabelASTValue(v, exprs, bindings)),
|
|
67
|
-
),
|
|
68
|
-
)
|
|
69
|
-
: generateBabelNode(v, exprs, bindings);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const generateBabelNodeChild = (child, exprs, bindings) => {
|
|
73
|
-
if (child.type === ReferenceTag) {
|
|
74
|
-
return expression(`%%t%%.ref\`${printRef(child.value)}\``)({ t: bindings.t });
|
|
75
|
-
} else if (child.type === LiteralTag) {
|
|
76
|
-
return expression(`%%t%%.lit(%%value%%)`)({
|
|
77
|
-
t: bindings.t,
|
|
78
|
-
value: getBabelASTValue(child.value, exprs, bindings),
|
|
79
|
-
});
|
|
80
|
-
} else if (child.type === EmbeddedNode) {
|
|
81
|
-
return expression(`%%t%%.embedded(%%value%%)`)({
|
|
82
|
-
t: bindings.t,
|
|
83
|
-
value: generateBabelNode(child.value, exprs, bindings),
|
|
84
|
-
});
|
|
85
|
-
} else if (child.type === ArrayTag) {
|
|
86
|
-
return expression(`%%t%%.arr()`)({
|
|
87
|
-
t: bindings.t,
|
|
88
|
-
});
|
|
89
|
-
} else if (child.type === GapTag) {
|
|
90
|
-
return expression(`%%t%%.gap()`)({
|
|
91
|
-
t: bindings.t,
|
|
92
|
-
});
|
|
93
|
-
} else {
|
|
94
|
-
throw new Error(`Unknown child type ${child.type}`);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const getAgastNodeType = (flags) => {
|
|
99
|
-
if (flags.token && flags.trivia) {
|
|
100
|
-
return 's_t_node';
|
|
101
|
-
} else if (flags.token && flags.escape) {
|
|
102
|
-
return 's_e_node';
|
|
103
|
-
} else if (flags.escape) {
|
|
104
|
-
return 'e_node';
|
|
105
|
-
} else if (flags.token) {
|
|
106
|
-
return 's_node';
|
|
107
|
-
} else {
|
|
108
|
-
return 'node';
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const generateBabelNode = (node, exprs, bindings) => {
|
|
113
|
-
const { flags = {}, children, type, language, attributes } = node;
|
|
114
|
-
|
|
115
|
-
const properties_ = {};
|
|
116
|
-
let children_ = [];
|
|
117
|
-
|
|
118
|
-
if (!children) {
|
|
119
|
-
throw new Error();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// resolver.advance({ type: DoctypeTag, value: {} });
|
|
123
|
-
|
|
124
|
-
for (const child of btree.traverse(children)) {
|
|
125
|
-
if (child.type === ReferenceTag) {
|
|
126
|
-
const path = child.value;
|
|
127
|
-
const { isArray: pathIsArray, name } = path;
|
|
128
|
-
if (!pathIsArray || hasOwn(properties_, name)) {
|
|
129
|
-
let resolved = node.properties[name];
|
|
130
|
-
|
|
131
|
-
if (pathIsArray) {
|
|
132
|
-
resolved = btree.getAt(btree.getSum(properties_[name]), resolved);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (resolved.type !== sym.gap) {
|
|
136
|
-
add(properties_, path, generateBabelNode(resolved, exprs, bindings));
|
|
137
|
-
children_ = btree.push(children_, generateBabelNodeChild(child, exprs, bindings));
|
|
138
|
-
} else {
|
|
139
|
-
// gap
|
|
140
|
-
const expr = exprs.pop();
|
|
141
|
-
const { interpolateArray, interpolateFragmentChildren, interpolateString } = bindings;
|
|
142
|
-
|
|
143
|
-
if (pathIsArray) {
|
|
144
|
-
add(
|
|
145
|
-
properties_,
|
|
146
|
-
path,
|
|
147
|
-
expression('[...%%interpolateArray%%(%%expr%%)]')({
|
|
148
|
-
interpolateArray,
|
|
149
|
-
expr,
|
|
150
|
-
}).elements[0],
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
children_ = btree.push(
|
|
154
|
-
children_,
|
|
155
|
-
t.spreadElement(
|
|
156
|
-
expression('%%interpolateFragmentChildren%%(%%expr%%, %%ref%%)')({
|
|
157
|
-
interpolateFragmentChildren,
|
|
158
|
-
expr,
|
|
159
|
-
ref: expression(`%%t%%.ref\`${printRef(child.value)}\``)({ t: bindings.t }),
|
|
160
|
-
}),
|
|
161
|
-
),
|
|
162
|
-
);
|
|
163
|
-
} else if (language === cstml.canonicalURL && type === 'String') {
|
|
164
|
-
add(
|
|
165
|
-
properties_,
|
|
166
|
-
path,
|
|
167
|
-
expression('%%interpolateString%%(%%expr%%)')({
|
|
168
|
-
interpolateString,
|
|
169
|
-
expr,
|
|
170
|
-
}),
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
children_ = btree.push(children_, generateBabelNodeChild(child, exprs, bindings));
|
|
174
|
-
} else {
|
|
175
|
-
add(properties_, path, expr);
|
|
176
|
-
|
|
177
|
-
children_ = btree.push(children_, generateBabelNodeChild(child, exprs, bindings));
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
} else if (pathIsArray) {
|
|
181
|
-
children_ = btree.push(children_, generateBabelNodeChild(child, exprs, bindings));
|
|
182
|
-
properties_[name] = [];
|
|
183
|
-
}
|
|
184
|
-
} else {
|
|
185
|
-
if (child.type !== OpenNodeTag && child.type !== CloseNodeTag) {
|
|
186
|
-
children_ = btree.push(children_, generateBabelNodeChild(child, exprs, bindings));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const nodeType = getAgastNodeType(flags);
|
|
192
|
-
|
|
193
|
-
const propsAtts =
|
|
194
|
-
nodeType === 's_node' || nodeType === 's_i_node' ? '' : ', %%properties%%, %%attributes%%';
|
|
195
|
-
const propsAttsValue =
|
|
196
|
-
nodeType === 's_node' || nodeType === 's_i_node'
|
|
197
|
-
? {}
|
|
198
|
-
: {
|
|
199
|
-
properties: t.objectExpression(
|
|
200
|
-
Object.entries(properties_).map(([key, value]) =>
|
|
201
|
-
t.objectProperty(t.identifier(key), isArray(value) ? getBtreeASTValue(value) : value),
|
|
202
|
-
),
|
|
203
|
-
),
|
|
204
|
-
attributes: t.objectExpression(
|
|
205
|
-
Object.entries(attributes).map(([key, value]) =>
|
|
206
|
-
t.objectProperty(t.identifier(key), getBabelASTValue(value, exprs, bindings)),
|
|
207
|
-
),
|
|
208
|
-
),
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
if (type === sym.gap) {
|
|
212
|
-
return expression(`%%t%%.g_node()`)({ t: bindings.t });
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return expression(`%%t%%.%%nodeType%%(%%l%%.%%language%%, %%type%%, %%children%%${propsAtts})`)({
|
|
216
|
-
t: bindings.t,
|
|
217
|
-
l: bindings.l,
|
|
218
|
-
language: t.identifier(namesFor[language]),
|
|
219
|
-
nodeType: t.identifier(nodeType),
|
|
220
|
-
type: t.stringLiteral(type),
|
|
221
|
-
children:
|
|
222
|
-
nodeType === 's_node' || nodeType === 's_i_node'
|
|
223
|
-
? t.stringLiteral(btree.getAt(1, children).value)
|
|
224
|
-
: getBtreeASTValue(children_),
|
|
225
|
-
...propsAttsValue,
|
|
226
|
-
});
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const getTopScope = (scope) => {
|
|
230
|
-
let top = scope;
|
|
231
|
-
while (top.parent) top = top.parent;
|
|
232
|
-
return top;
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const namesFor = Object.fromEntries([
|
|
236
|
-
...[i, re, spam, cstml].map((l) => [l.canonicalURL, l.name]),
|
|
237
|
-
['https://bablr.org/languages/core/en/space-tab-newline', 'Space'],
|
|
238
|
-
]);
|
|
239
|
-
|
|
240
|
-
const languages = {
|
|
241
|
-
i: '@bablr/language-en-bablr-vm-instruction',
|
|
242
|
-
re: '@bablr/language-en-regex-vm-pattern',
|
|
243
|
-
spam: '@bablr/language-en-spamex',
|
|
244
|
-
str: '@bablr/language-en-cstml',
|
|
245
|
-
num: '@bablr/language-en-cstml',
|
|
246
|
-
cst: '@bablr/language-en-cstml',
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
const topTypes = {
|
|
250
|
-
i: 'Call',
|
|
251
|
-
re: 'Pattern',
|
|
252
|
-
spam: 'Matcher',
|
|
253
|
-
str: 'String',
|
|
254
|
-
num: 'Integer',
|
|
255
|
-
cst: 'Node',
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const miniLanguages = {
|
|
259
|
-
i,
|
|
260
|
-
re,
|
|
261
|
-
spam,
|
|
262
|
-
str: cstml,
|
|
263
|
-
num: cstml,
|
|
264
|
-
cst: cstml,
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
const shorthandMacro = ({ references }) => {
|
|
268
|
-
const bindings = {};
|
|
269
|
-
|
|
270
|
-
// decorator references
|
|
271
|
-
|
|
272
|
-
for (const ref of concat(
|
|
273
|
-
references.i,
|
|
274
|
-
references.spam,
|
|
275
|
-
references.re,
|
|
276
|
-
references.str,
|
|
277
|
-
references.num,
|
|
278
|
-
references.cst,
|
|
279
|
-
)) {
|
|
280
|
-
if (!bindings.t) {
|
|
281
|
-
bindings.t = addNamespace(getTopScope(ref.scope).path, '@bablr/agast-helpers/shorthand', {
|
|
282
|
-
nameHint: 't',
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (!bindings.l) {
|
|
287
|
-
bindings.l = addNamespace(getTopScope(ref.scope).path, '@bablr/agast-vm-helpers/languages', {
|
|
288
|
-
nameHint: 'l',
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (!bindings.interpolateArray) {
|
|
293
|
-
bindings.interpolateArray = addNamed(
|
|
294
|
-
getTopScope(ref.scope).path,
|
|
295
|
-
'interpolateArray',
|
|
296
|
-
'@bablr/agast-helpers/template',
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (!bindings.interpolateFragmentChildren) {
|
|
301
|
-
bindings.interpolateFragmentChildren = addNamed(
|
|
302
|
-
getTopScope(ref.scope).path,
|
|
303
|
-
'interpolateFragmentChildren',
|
|
304
|
-
'@bablr/agast-helpers/template',
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (!bindings.interpolateString) {
|
|
309
|
-
bindings.interpolateString = addNamed(
|
|
310
|
-
getTopScope(ref.scope).path,
|
|
311
|
-
'interpolateString',
|
|
312
|
-
'@bablr/agast-helpers/template',
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
const taggedTemplate =
|
|
317
|
-
ref.parentPath.type === 'MemberExpression' ? ref.parentPath.parentPath : ref.parentPath;
|
|
318
|
-
|
|
319
|
-
const { quasis, expressions } = taggedTemplate.node.quasi;
|
|
320
|
-
|
|
321
|
-
const tagName = ref.node.name;
|
|
322
|
-
const language = languages[tagName];
|
|
323
|
-
const type =
|
|
324
|
-
ref.parentPath.type === 'MemberExpression'
|
|
325
|
-
? ref.parentPath.node.property.name
|
|
326
|
-
: topTypes[tagName];
|
|
327
|
-
|
|
328
|
-
const streamText = quasis
|
|
329
|
-
.map((q) => `"${q.value.raw.replace(/[\\"]/g, '\\$&')}"`)
|
|
330
|
-
.join(' <//> ');
|
|
331
|
-
|
|
332
|
-
// console.log(streamText);
|
|
333
|
-
|
|
334
|
-
const miniLanguage = miniLanguages[tagName];
|
|
335
|
-
|
|
336
|
-
const ast = new TemplateParser(
|
|
337
|
-
miniLanguage,
|
|
338
|
-
quasis.map((q) => q.value.raw),
|
|
339
|
-
expressions.map(() => null),
|
|
340
|
-
).eval({ language: miniLanguage.name, type });
|
|
341
|
-
|
|
342
|
-
const agAST = getAgASTValue(miniLanguage, ast);
|
|
343
|
-
let referenceDocument = null;
|
|
344
|
-
|
|
345
|
-
const document = printPrettyCSTML(agAST);
|
|
346
|
-
|
|
347
|
-
// try {
|
|
348
|
-
// const documentResult = spawnSync(
|
|
349
|
-
// '../bablr-cli/bin/index.js',
|
|
350
|
-
// ['-l', language, '-p', type, '-f'],
|
|
351
|
-
// {
|
|
352
|
-
// input: streamText,
|
|
353
|
-
// encoding: 'utf8',
|
|
354
|
-
// },
|
|
355
|
-
// );
|
|
356
|
-
|
|
357
|
-
// if (documentResult.status > 0) {
|
|
358
|
-
// throw new Error('bablr CLI parse return non-zero exit');
|
|
359
|
-
// }
|
|
360
|
-
|
|
361
|
-
// if (documentResult.error) {
|
|
362
|
-
// throw new Error(documentResult.error);
|
|
363
|
-
// }
|
|
364
|
-
|
|
365
|
-
// referenceDocument = documentResult.stdout.slice(0, -1);
|
|
366
|
-
|
|
367
|
-
// if (!referenceDocument.length) {
|
|
368
|
-
// throw new Error();
|
|
369
|
-
// }
|
|
370
|
-
|
|
371
|
-
// // secondaryAst = parse(cstml, 'Document', document);
|
|
372
|
-
// } catch (e) {
|
|
373
|
-
// console.warn(' parse failure');
|
|
374
|
-
// }
|
|
375
|
-
|
|
376
|
-
taggedTemplate.replaceWith(generateBabelNode(agAST, expressions.reverse(), bindings));
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
module.exports = createMacro(shorthandMacro);
|