@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 CHANGED
@@ -1,9 +1,21 @@
1
- import { Node, Matcher, Regex, Tag, EmbeddedObject, Instruction } from './symbols.js';
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 { Node, EmbeddedObject, Tag, Matcher, Regex, Instruction } from './symbols.js';
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
- buildStubNode,
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
- buildPropertyWrapper,
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 { isStubNode } from '@bablr/agast-helpers/path';
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 reifyNodeFlags = (flags) => {
75
- let tokenToken = get('tokenToken', flags);
76
- let hasGapToken = get('hasGapToken', flags);
77
- let fragmentToken = get('fragmentToken', flags);
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
- let token = !!(tokenToken && reifyExpression(tokenToken));
81
- let hasGap = !!(hasGapToken && reifyExpression(hasGapToken));
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 { token, hasGap, fragment, cover };
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
- expression: !!(expressionToken && reifyExpression(expressionToken)),
94
- hasGap: !!(hasGapToken && reifyExpression(hasGapToken)),
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('open', node);
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
- let literalValue = reifyExpression(get('literalValue', open));
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.type)) {
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.type !== Symbol.for('Property')) throw new Error('umimplemented');
130
+ if (child.value.name !== Symbol.for('Property')) throw new Error('umimplemented');
124
131
 
125
- let reference = get('reference', child);
126
- let binding = get('binding', child);
127
- let value = get('value', child);
132
+ let reference = get('referenceTag', child);
133
+ let boundNode = reifyExpression(get('value', child));
134
+ let { node, bindingTags } = boundNode;
128
135
 
129
- let referenceTag = reference ? reifyExpression(reference) : buildReferenceTag('.');
130
- let bindingTag = binding
131
- ? reifyExpression(binding)
132
- : buildBindingTag(isStubNode(value) ? null : []);
136
+ let bindings = bindingTags.map((tag) => tag.value);
133
137
 
134
- value = reifyExpression(value);
138
+ let referenceTag =
139
+ reference && !isNullNode(reference) ? reifyExpression(reference) : buildReferenceTag();
135
140
 
136
- if (referenceTag.value.type === '_') {
137
- for (let child of Tags.traverse(value.tags)) {
138
- if (![OpenNodeTag, CloseNodeTag].includes(child.type)) built = Tags.push(built, child);
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.type === NullTag || value.type === GapTag) {
144
- value = buildStubNode(value);
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 (isFragmentNode(node)) {
166
+ if (isCover(node)) {
175
167
  node = getRoot(node);
176
168
  }
177
169
 
178
- switch (node.type?.description || node.type) {
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 doctype = get('doctype', node);
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 { attributes } = doctype.value;
180
+ let doctypeTag = null;
187
181
 
188
- return Object.freeze({
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 'Node': {
198
- let open = get('open', node);
185
+ case 'TreeNode': {
186
+ let open = get('openTag', node);
199
187
 
200
188
  let openTag = reifyExpression(open);
201
189
 
202
- let { flags, type, attributes } = openTag.value;
203
-
204
- return Object.freeze({
205
- flags,
206
- type,
207
- bounds: buildBounds(),
208
- tags: buildTags(node),
209
- attributes,
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 = freeze({
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, !isNull(arrayOperatorToken), flags);
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 [...list('segments', node)].map((segment) => reifyExpression(segment));
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 path = get('path', node);
248
+ let key = get('key', node);
253
249
  let value = get('value', node);
254
250
 
255
- path = path && reifyExpression(path);
251
+ key = key && reifyExpression(key).map((segment) => segment.name);
256
252
  value = value && reifyExpression(value);
257
253
 
258
- return buildAttributeDefinition(path, value);
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
- flags = reifyNodeFlags(flags);
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
- attributes = reifyExpression(attributes);
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 buildOpenNodeTag(flags, type, attributes);
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 'OpenNodeMatcher': {
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
- type =
325
- type.type === Symbol.for('String')
326
- ? getCooked(get('content', type))
327
- : reifyExpression(type);
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 { flags, type, literalValue, attributes };
351
+ return freeze({
352
+ flags,
353
+ type,
354
+ name,
355
+ literalValue,
356
+ attributes,
357
+ });
332
358
  }
333
359
 
334
- case 'FragmentMatcher': {
335
- let flags = get('flags', node);
360
+ case 'TreeNodeMatcher': {
361
+ let open = reifyExpression(get('open', node));
336
362
 
337
- flags = (flags && reifyNodeFlags(flags)) || {};
338
-
339
- return {
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
- case 'BasicNodeMatcher': {
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 bindingMatcher = get('bindingMatcher', node);
354
- let nodeMatcher = get('nodeMatcher', node);
372
+ let boundMatcher = get('valueMatcher', node);
373
+
374
+ refMatcher = reifyExpression(refMatcher);
355
375
 
356
- refMatcher = refMatcher ? reifyExpression(refMatcher) : null;
357
- bindingMatcher = bindingMatcher ? reifyExpression(bindingMatcher) : null;
358
- nodeMatcher = reifyExpression(nodeMatcher);
376
+ if (!boundMatcher) throw new Error();
359
377
 
360
- return { refMatcher, bindingMatcher, nodeMatcher };
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, isArray, flags };
394
+ return freeze({ type, name, flags });
374
395
  }
375
396
 
376
- case 'BindingMatcher': {
377
- let languagePath = get('languagePath', node);
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
- languagePath = languagePath && reifyExpression(languagePath);
429
+ case 'BindingSegment': {
430
+ let path = get('path', node);
380
431
 
381
- return { languagePath };
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 buildStubNode(buildGapTag());
449
+ return buildNode(buildGapTag());
386
450
 
387
451
  case 'NullNodeMatcher':
388
- return buildStubNode(buildNullTag());
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 { Node, Tag, EmbeddedObject, Matcher, Regex, Instruction } from './symbols.js';
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 Node: {
27
- return printSource(value.value);
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.literalValue) {
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.9.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.9.0",
25
+ "@bablr/agast-helpers": "0.10.1",
26
26
  "@bablr/coroutine": "0.1.0"
27
27
  },
28
28
  "devDependencies": {