@bablr/boot 0.7.0 → 0.7.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.
@@ -41,6 +41,8 @@ export const covers = new Map([
41
41
 
42
42
  export const escapables = new Map(
43
43
  objectEntries({
44
+ b: '\b',
45
+ f: '\f',
44
46
  n: '\n',
45
47
  r: '\r',
46
48
  t: '\t',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bablr/boot",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Compile-time tools for bootstrapping BABLR VM",
5
5
  "engines": {
6
6
  "node": ">=12.0.0"
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "sideEffects": false,
17
17
  "dependencies": {
18
- "@bablr/agast-helpers": "0.6.0",
18
+ "@bablr/agast-helpers": "0.6.1",
19
19
  "@bablr/agast-vm-helpers": "0.6.0",
20
20
  "@iter-tools/imm-stack": "1.1.0",
21
21
  "escape-string-regexp": "5.0.0",
@@ -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);