@bablr/agast-helpers 0.8.0 → 0.10.0
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 +159 -88
- package/lib/path.js +1571 -419
- package/lib/print.js +78 -41
- package/lib/shorthand.js +17 -13
- package/lib/stream.js +437 -164
- package/lib/symbols.js +5 -2
- package/lib/tags.js +285 -0
- package/lib/template.js +52 -46
- package/lib/tree.js +165 -687
- package/package.json +6 -4
- package/lib/children.js +0 -120
- package/lib/path-facade.js +0 -39
package/lib/stream.js
CHANGED
|
@@ -1,160 +1,155 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
2
|
import emptyStack from '@iter-tools/imm-stack';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { getStreamIterator, StreamIterable, StreamGenerator, wait } from '@bablr/stream-iterator';
|
|
4
|
+
import * as Tags from './tags.js';
|
|
5
|
+
import { printTag } from './print.js';
|
|
6
|
+
import {
|
|
7
|
+
buildChild,
|
|
8
|
+
buildGapTag,
|
|
9
|
+
buildNullTag,
|
|
10
|
+
buildOpenNodeTag,
|
|
11
|
+
buildProperty,
|
|
12
|
+
buildReference,
|
|
13
|
+
} from './builders.js';
|
|
5
14
|
import {
|
|
6
|
-
DoctypeTag,
|
|
7
15
|
OpenNodeTag,
|
|
8
16
|
CloseNodeTag,
|
|
9
17
|
ReferenceTag,
|
|
10
|
-
ShiftTag,
|
|
11
18
|
GapTag,
|
|
12
19
|
NullTag,
|
|
13
|
-
InitializerTag,
|
|
14
20
|
LiteralTag,
|
|
15
|
-
TokenGroup,
|
|
16
21
|
BindingTag,
|
|
22
|
+
DoctypeTag,
|
|
23
|
+
ShiftTag,
|
|
17
24
|
AttributeDefinition,
|
|
18
25
|
} from './symbols.js';
|
|
26
|
+
import { buildNode, isGapNode, Path } from './path.js';
|
|
27
|
+
import { streamFromTree } from './tree.js';
|
|
19
28
|
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
export const getStreamIterator = (obj) => {
|
|
23
|
-
return obj[Symbol.for('@@streamIterator')]?.() || obj[Symbol.iterator]?.();
|
|
24
|
-
};
|
|
29
|
+
export { getStreamIterator, StreamIterable, StreamGenerator, wait };
|
|
25
30
|
|
|
26
|
-
export
|
|
27
|
-
constructor(embeddedGenerator) {
|
|
28
|
-
if (!embeddedGenerator.next) throw new Error();
|
|
31
|
+
export * from './print.js';
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
export const maybeWait = (maybePromise, callback) => {
|
|
34
|
+
if (maybePromise instanceof Promise) {
|
|
35
|
+
return maybePromise.then(callback);
|
|
36
|
+
} else {
|
|
37
|
+
return callback(maybePromise);
|
|
31
38
|
}
|
|
39
|
+
};
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
function* __flatMap(fn, tags) {
|
|
42
|
+
const co = new Coroutine(getStreamIterator(tags));
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
44
|
+
for (;;) {
|
|
45
|
+
co.advance();
|
|
39
46
|
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
} else if (step.value instanceof Promise) {
|
|
43
|
-
throw new Error('sync generators cannot resolve promises');
|
|
44
|
-
} else {
|
|
45
|
-
return step;
|
|
47
|
+
if (co.current instanceof Promise) {
|
|
48
|
+
co.current = yield wait(co.current);
|
|
46
49
|
}
|
|
47
|
-
|
|
50
|
+
if (co.done) break;
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
const step = this.generator.return(value);
|
|
51
|
-
if (step instanceof Promise) {
|
|
52
|
-
throw new Error('invalid embedded generator');
|
|
53
|
-
}
|
|
52
|
+
let { value } = co;
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
throw new Error('sync generators cannot resolve promises');
|
|
57
|
-
}
|
|
58
|
-
return step;
|
|
54
|
+
yield* fn(value);
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
return this;
|
|
63
|
-
}
|
|
57
|
+
return true;
|
|
64
58
|
}
|
|
65
59
|
|
|
66
|
-
export
|
|
67
|
-
constructor(embeddedGenerator) {
|
|
68
|
-
this.generator = embeddedGenerator;
|
|
69
|
-
}
|
|
60
|
+
export const flatMap = (fn, tags) => new StreamIterable(__flatMap(fn, tags));
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
|
|
62
|
+
export const evaluateReturnSync = (iterable) => {
|
|
63
|
+
const co = new Coroutine(iterable[Symbol.iterator]());
|
|
64
|
+
while (!co.done) co.advance();
|
|
65
|
+
return co.value;
|
|
66
|
+
};
|
|
73
67
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
export const evaluateReturnAsync = async (iterable) => {
|
|
69
|
+
const co = new Coroutine(getStreamIterator(iterable));
|
|
70
|
+
while (!co.done) {
|
|
71
|
+
co.advance();
|
|
77
72
|
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
} else if (step.value instanceof Promise) {
|
|
81
|
-
return step.value.then((value) => {
|
|
82
|
-
return this.next(value);
|
|
83
|
-
});
|
|
84
|
-
} else {
|
|
85
|
-
return Promise.resolve(step);
|
|
73
|
+
if (co.current instanceof Promise) {
|
|
74
|
+
co.current = await co.current;
|
|
86
75
|
}
|
|
87
76
|
}
|
|
77
|
+
return co.value;
|
|
78
|
+
};
|
|
88
79
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
80
|
+
function* __treeFromStream(tags, options) {
|
|
81
|
+
let path = null;
|
|
82
|
+
const co = new Coroutine(getStreamIterator(tags));
|
|
83
|
+
const expressionsCo = new Coroutine(getStreamIterator(options.expressions || []));
|
|
96
84
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
}
|
|
85
|
+
for (;;) {
|
|
86
|
+
co.advance();
|
|
101
87
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
88
|
+
if (co.current instanceof Promise) {
|
|
89
|
+
co.current = yield wait(co.current);
|
|
90
|
+
}
|
|
106
91
|
|
|
107
|
-
|
|
108
|
-
const step = this.generator.next(value);
|
|
92
|
+
if (co.done) break;
|
|
109
93
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return this.next(value);
|
|
115
|
-
});
|
|
116
|
-
} else {
|
|
117
|
-
return step;
|
|
94
|
+
let tag = co.value;
|
|
95
|
+
|
|
96
|
+
if (tag.type === 'Effect' || tag.type === DoctypeTag) {
|
|
97
|
+
continue;
|
|
118
98
|
}
|
|
119
|
-
}
|
|
120
99
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
100
|
+
if (!path) {
|
|
101
|
+
path = Path.from(buildNode(Tags.fromValues([tag])));
|
|
124
102
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
103
|
+
// if (tag.value.selfClosing) {
|
|
104
|
+
// path = null;
|
|
105
|
+
// }
|
|
128
106
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
}
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
133
109
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
110
|
+
if (tag.type === GapTag && !path.held) {
|
|
111
|
+
if (!expressionsCo.current || !expressionsCo.done) {
|
|
112
|
+
expressionsCo.advance();
|
|
113
|
+
}
|
|
138
114
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
115
|
+
if (path.node.value.flags.token) {
|
|
116
|
+
if (expressionsCo.done || expressionsCo.value != null) {
|
|
117
|
+
let node = expressionsCo.value;
|
|
118
|
+
if (isGapNode(node)) {
|
|
119
|
+
throw new Error('not implemented');
|
|
120
|
+
} else {
|
|
121
|
+
path = path.advance(tag);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
let node = expressionsCo.done
|
|
126
|
+
? buildNode(buildGapTag())
|
|
127
|
+
: path == null || expressionsCo.value == null
|
|
128
|
+
? buildNode(buildNullTag())
|
|
129
|
+
: expressionsCo.value;
|
|
142
130
|
|
|
143
|
-
|
|
144
|
-
|
|
131
|
+
path = path.advance(node);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
path = path.advance(tag);
|
|
135
|
+
}
|
|
145
136
|
}
|
|
146
137
|
|
|
147
|
-
|
|
148
|
-
|
|
138
|
+
if (!path.done) {
|
|
139
|
+
throw new Error('imbalanced tag stack');
|
|
149
140
|
}
|
|
141
|
+
|
|
142
|
+
return path?.node;
|
|
150
143
|
}
|
|
151
144
|
|
|
152
|
-
export const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
145
|
+
export const treeFromStream = (tags, options = {}) => __treeFromStream(tags, options);
|
|
146
|
+
|
|
147
|
+
export const treeFromStreamSync = (tokens, options = {}) => {
|
|
148
|
+
return evaluateReturnSync(treeFromStream(tokens, options));
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const treeFromStreamAsync = async (tokens, options = {}) => {
|
|
152
|
+
return evaluateReturnAsync(treeFromStream(tokens, options));
|
|
158
153
|
};
|
|
159
154
|
|
|
160
155
|
function* __isEmpty(tags) {
|
|
@@ -164,7 +159,7 @@ function* __isEmpty(tags) {
|
|
|
164
159
|
co.advance();
|
|
165
160
|
|
|
166
161
|
if (co.current instanceof Promise) {
|
|
167
|
-
co.current = yield co.current;
|
|
162
|
+
co.current = yield wait(co.current);
|
|
168
163
|
}
|
|
169
164
|
if (co.done) break;
|
|
170
165
|
|
|
@@ -181,7 +176,9 @@ function* __isEmpty(tags) {
|
|
|
181
176
|
case OpenNodeTag:
|
|
182
177
|
++depth;
|
|
183
178
|
|
|
184
|
-
if (
|
|
179
|
+
if (tag.value.literalValue) return false;
|
|
180
|
+
|
|
181
|
+
if (depth === 0 && ref.type === '@') {
|
|
185
182
|
return false;
|
|
186
183
|
}
|
|
187
184
|
|
|
@@ -224,9 +221,9 @@ export const asyncStringFromStream = async (stream) => {
|
|
|
224
221
|
|
|
225
222
|
if (co.done) break;
|
|
226
223
|
|
|
227
|
-
const
|
|
224
|
+
const chr = co.value;
|
|
228
225
|
|
|
229
|
-
str +=
|
|
226
|
+
str += chr;
|
|
230
227
|
}
|
|
231
228
|
|
|
232
229
|
return str;
|
|
@@ -263,7 +260,7 @@ function* __generateCSTML(tags, options) {
|
|
|
263
260
|
co.advance();
|
|
264
261
|
|
|
265
262
|
if (co.current instanceof Promise) {
|
|
266
|
-
co.current = yield co.current;
|
|
263
|
+
co.current = yield wait(co.current);
|
|
267
264
|
}
|
|
268
265
|
if (co.done) break;
|
|
269
266
|
|
|
@@ -277,17 +274,10 @@ function* __generateCSTML(tags, options) {
|
|
|
277
274
|
continue;
|
|
278
275
|
}
|
|
279
276
|
|
|
280
|
-
|
|
281
|
-
const intrinsicValue = getCooked(tag.value);
|
|
282
|
-
yield* printSelfClosingNodeTag(tag.value[0], intrinsicValue);
|
|
283
|
-
} else {
|
|
284
|
-
yield* printTag(tag);
|
|
285
|
-
}
|
|
277
|
+
yield* printTag(tag);
|
|
286
278
|
|
|
287
279
|
prevTag = tag;
|
|
288
280
|
}
|
|
289
|
-
|
|
290
|
-
yield* '\n';
|
|
291
281
|
}
|
|
292
282
|
|
|
293
283
|
export const generateCSTML = (tags, options = {}) =>
|
|
@@ -305,24 +295,18 @@ function* __prettyGroupTags(tags) {
|
|
|
305
295
|
|
|
306
296
|
const co = new Coroutine(getStreamIterator(tags));
|
|
307
297
|
|
|
308
|
-
let ref = null;
|
|
309
|
-
|
|
310
298
|
for (;;) {
|
|
311
299
|
co.advance();
|
|
312
300
|
|
|
313
|
-
if (co.done) break;
|
|
314
|
-
|
|
315
301
|
if (co.current instanceof Promise) {
|
|
316
|
-
co.current = yield co.current;
|
|
302
|
+
co.current = yield wait(co.current);
|
|
317
303
|
}
|
|
318
304
|
|
|
305
|
+
if (co.done) break;
|
|
306
|
+
|
|
319
307
|
const tag = co.value;
|
|
320
308
|
const isOpenClose = tag.type === CloseNodeTag || tag.type === OpenNodeTag;
|
|
321
309
|
|
|
322
|
-
if (tag.type === ReferenceTag) {
|
|
323
|
-
ref = tag;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
310
|
if (
|
|
327
311
|
(tag.type === 'Effect' && tag.value.verb === 'write') ||
|
|
328
312
|
[
|
|
@@ -331,11 +315,10 @@ function* __prettyGroupTags(tags) {
|
|
|
331
315
|
BindingTag,
|
|
332
316
|
GapTag,
|
|
333
317
|
NullTag,
|
|
334
|
-
InitializerTag,
|
|
335
318
|
ShiftTag,
|
|
336
319
|
AttributeDefinition,
|
|
337
|
-
|
|
338
|
-
|
|
320
|
+
OpenNodeTag,
|
|
321
|
+
].includes(tag.type)
|
|
339
322
|
) {
|
|
340
323
|
state.broken = true;
|
|
341
324
|
|
|
@@ -353,8 +336,14 @@ function* __prettyGroupTags(tags) {
|
|
|
353
336
|
|
|
354
337
|
if (tag.type === CloseNodeTag) {
|
|
355
338
|
if (!state.broken && (isToken(state.open) || state.holding.length === 1)) {
|
|
356
|
-
state.holding.
|
|
357
|
-
|
|
339
|
+
let { flags, name, attributes } = state.holding[0].value;
|
|
340
|
+
|
|
341
|
+
let literal = state.holding
|
|
342
|
+
.slice(1)
|
|
343
|
+
.map((lit) => lit.value)
|
|
344
|
+
.join('');
|
|
345
|
+
|
|
346
|
+
yield buildOpenNodeTag(flags, name, literal, attributes, true);
|
|
358
347
|
} else {
|
|
359
348
|
if (state.holding.length) {
|
|
360
349
|
yield* state.holding;
|
|
@@ -367,13 +356,304 @@ function* __prettyGroupTags(tags) {
|
|
|
367
356
|
}
|
|
368
357
|
|
|
369
358
|
if (tag.type === OpenNodeTag) {
|
|
370
|
-
|
|
359
|
+
if (tag.value.selfClosing) {
|
|
360
|
+
yield tag;
|
|
361
|
+
} else {
|
|
362
|
+
states = states.push({ holding: [tag], broken: false, open: tag });
|
|
371
363
|
|
|
372
|
-
|
|
364
|
+
state = states.value;
|
|
365
|
+
}
|
|
373
366
|
}
|
|
374
367
|
}
|
|
375
368
|
}
|
|
376
369
|
|
|
370
|
+
let pushFrame = (parent = null) => {
|
|
371
|
+
let heldProperties = parent ? [...parent.heldProperties] : [];
|
|
372
|
+
if (parent) {
|
|
373
|
+
parent.heldProperties = [];
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
parent,
|
|
377
|
+
depth: !parent ? 0 : parent.depth + 1,
|
|
378
|
+
ref: null,
|
|
379
|
+
bindings: [],
|
|
380
|
+
open: null,
|
|
381
|
+
coverDepth: 0,
|
|
382
|
+
heldProperties,
|
|
383
|
+
expanded: false,
|
|
384
|
+
shifting: parent?.shifting || false,
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
let popFrame = (frame) => {
|
|
389
|
+
let { heldProperties } = frame;
|
|
390
|
+
|
|
391
|
+
if (frame.parent) {
|
|
392
|
+
frame.parent.heldProperties = heldProperties;
|
|
393
|
+
frame.parent.shifting = frame.shifting;
|
|
394
|
+
} else if (heldProperties.length) {
|
|
395
|
+
throw new Error();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return frame.parent;
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
function* emitHeld(frame, nextTag) {
|
|
402
|
+
if (frame.ref?.flags.expression && nextTag?.type === ShiftTag) return;
|
|
403
|
+
|
|
404
|
+
for (let property of frame.heldProperties) {
|
|
405
|
+
let { reference, bindings, node } = property;
|
|
406
|
+
yield buildChild(ReferenceTag, reference);
|
|
407
|
+
let isAnonymous = node.value.flags.token && !node.value.name;
|
|
408
|
+
if (!isAnonymous) {
|
|
409
|
+
for (let binding of bindings) {
|
|
410
|
+
yield buildChild(BindingTag, binding);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
yield* streamFromTree(node);
|
|
414
|
+
}
|
|
415
|
+
frame.heldProperties = [];
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export const hoistTrivia = (tags) => {
|
|
419
|
+
const co = new Coroutine(getStreamIterator(tags));
|
|
420
|
+
|
|
421
|
+
return new StreamIterable(__hoistTriviaOuter(co));
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
function* __hoistTriviaOuter(co) {
|
|
425
|
+
co.advance();
|
|
426
|
+
|
|
427
|
+
let firstTag = co.value;
|
|
428
|
+
|
|
429
|
+
co.advance();
|
|
430
|
+
|
|
431
|
+
yield* __hoistTrivia(co, firstTag);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function* __hoistTrivia(co, firstTag) {
|
|
435
|
+
if (co.current instanceof Promise) {
|
|
436
|
+
co.current = yield wait(co.current);
|
|
437
|
+
}
|
|
438
|
+
let frame = null;
|
|
439
|
+
let lastFrame = null;
|
|
440
|
+
let alreadyAdvanced = true;
|
|
441
|
+
let tag;
|
|
442
|
+
let nextTag;
|
|
443
|
+
|
|
444
|
+
tag = firstTag;
|
|
445
|
+
nextTag = co.value;
|
|
446
|
+
|
|
447
|
+
for (;;) {
|
|
448
|
+
if (co.done || !nextTag) break;
|
|
449
|
+
|
|
450
|
+
if (!alreadyAdvanced) {
|
|
451
|
+
co.advance();
|
|
452
|
+
|
|
453
|
+
if (co.current instanceof Promise) {
|
|
454
|
+
co.current = yield wait(co.current);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
alreadyAdvanced = false;
|
|
458
|
+
|
|
459
|
+
nextTag = co.value;
|
|
460
|
+
|
|
461
|
+
if (tag.type === OpenNodeTag) {
|
|
462
|
+
let isCover = tag.value.type === Symbol.for('_');
|
|
463
|
+
let parentFrame = frame?.ref && !frame.open ? frame.parent : frame;
|
|
464
|
+
let done = false;
|
|
465
|
+
|
|
466
|
+
if (frame?.ref.type === '#' && !frame.ref.name) {
|
|
467
|
+
let { heldProperties } = frame;
|
|
468
|
+
if (heldProperties.length) {
|
|
469
|
+
let property = heldProperties[heldProperties.length - 1];
|
|
470
|
+
|
|
471
|
+
if (property.node) {
|
|
472
|
+
throw new Error();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
let node = yield* treeFromStream(new StreamIterable(__hoistTrivia(co, tag)));
|
|
476
|
+
|
|
477
|
+
frame.heldProperties[heldProperties.length - 1] = buildProperty([
|
|
478
|
+
property.tags[0],
|
|
479
|
+
property.tags[1] || [],
|
|
480
|
+
node,
|
|
481
|
+
]);
|
|
482
|
+
|
|
483
|
+
nextTag = co.value;
|
|
484
|
+
|
|
485
|
+
lastFrame = frame;
|
|
486
|
+
|
|
487
|
+
frame = popFrame(frame);
|
|
488
|
+
|
|
489
|
+
if (
|
|
490
|
+
!frame.ref.flags.expression &&
|
|
491
|
+
(frame.expanded || frame.parent?.open.value.type !== Symbol.for('_'))
|
|
492
|
+
) {
|
|
493
|
+
yield* emitHeld(frame, nextTag);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
done = true;
|
|
497
|
+
}
|
|
498
|
+
} else if (frame && !isCover) {
|
|
499
|
+
if (!frame.shifting && frame.ref && frame.ref.type !== '_') {
|
|
500
|
+
yield buildChild(ReferenceTag, frame.ref);
|
|
501
|
+
let isAnonymous = tag.value.flags.token && !tag.value.name;
|
|
502
|
+
if (!isAnonymous) {
|
|
503
|
+
for (let binding of frame.bindings) {
|
|
504
|
+
yield buildChild(BindingTag, binding);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (!done) {
|
|
511
|
+
if (!frame?.ref || frame.open) {
|
|
512
|
+
frame = pushFrame(parentFrame);
|
|
513
|
+
|
|
514
|
+
frame.heldProperties = parentFrame?.heldProperties ? [...parentFrame.heldProperties] : [];
|
|
515
|
+
|
|
516
|
+
if (tag.value.type === Symbol.for('__')) {
|
|
517
|
+
frame.open = tag;
|
|
518
|
+
frame.ref = buildReference();
|
|
519
|
+
} else if (isCover) {
|
|
520
|
+
frame.ref = parentFrame?.ref || buildReference('_');
|
|
521
|
+
frame.bindings =
|
|
522
|
+
parentFrame && tag.value.type === Symbol.for('_') ? [...parentFrame.bindings] : [];
|
|
523
|
+
frame.shifting =
|
|
524
|
+
parentFrame && tag.value.type === Symbol.for('_') ? parentFrame.shifting : false;
|
|
525
|
+
} else {
|
|
526
|
+
frame.ref = buildReference();
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
frame.coverDepth = isCover ? (parentFrame?.coverDepth ?? 0) + 1 : 0;
|
|
531
|
+
|
|
532
|
+
frame.open = tag;
|
|
533
|
+
|
|
534
|
+
if (tag.value.selfClosing) {
|
|
535
|
+
lastFrame = frame;
|
|
536
|
+
|
|
537
|
+
frame = popFrame(frame);
|
|
538
|
+
|
|
539
|
+
if (!frame) {
|
|
540
|
+
yield tag;
|
|
541
|
+
|
|
542
|
+
break;
|
|
543
|
+
} else {
|
|
544
|
+
yield tag;
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
if (!isCover) {
|
|
548
|
+
yield tag;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
} else if (tag.type === ReferenceTag) {
|
|
553
|
+
let parentFrame = frame;
|
|
554
|
+
|
|
555
|
+
frame = pushFrame(parentFrame);
|
|
556
|
+
|
|
557
|
+
if (tag.value.type === '#' && !tag.value.name) {
|
|
558
|
+
if (parentFrame.depth === 0 && parentFrame.coverDepth && !parentFrame.expanded) {
|
|
559
|
+
yield parentFrame.open;
|
|
560
|
+
|
|
561
|
+
parentFrame.expanded = true;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
frame.heldProperties.push(buildProperty([tag]));
|
|
565
|
+
} else {
|
|
566
|
+
if (!parentFrame.shifting) {
|
|
567
|
+
yield* emitHeld(frame, nextTag);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
frame.coverDepth = parentFrame.coverDepth;
|
|
572
|
+
frame.ref = tag.value.type === '_' ? parentFrame.ref : tag.value;
|
|
573
|
+
frame.bindings = parentFrame && tag.value.type === '_' ? [...parentFrame.bindings] : [];
|
|
574
|
+
frame.shifting = parentFrame && tag.value.type === '_' ? parentFrame.shifting : false;
|
|
575
|
+
|
|
576
|
+
if (tag.value.type === '_' && parentFrame.expanded) {
|
|
577
|
+
yield tag;
|
|
578
|
+
}
|
|
579
|
+
} else if (tag.type === ShiftTag) {
|
|
580
|
+
let doneFrame = frame;
|
|
581
|
+
|
|
582
|
+
frame = pushFrame(doneFrame);
|
|
583
|
+
|
|
584
|
+
frame.coverDepth = doneFrame?.coverDepth || 0;
|
|
585
|
+
frame.ref = lastFrame.ref;
|
|
586
|
+
frame.bindings = doneFrame && tag.value.type === '_' ? [...doneFrame.bindings] : [];
|
|
587
|
+
frame.shifting = true;
|
|
588
|
+
// frame.heldProperties = [...doneFrame.heldProperties];
|
|
589
|
+
|
|
590
|
+
yield tag;
|
|
591
|
+
} else if (tag.type === BindingTag) {
|
|
592
|
+
let { heldProperties } = frame;
|
|
593
|
+
if (heldProperties.length) {
|
|
594
|
+
let property = heldProperties[heldProperties.length - 1];
|
|
595
|
+
let { tags, node } = property;
|
|
596
|
+
if (!node) {
|
|
597
|
+
heldProperties[heldProperties.length - 1] = buildProperty([
|
|
598
|
+
tags[0],
|
|
599
|
+
[...(tags[1] || []), tag],
|
|
600
|
+
]);
|
|
601
|
+
frame.bindings.push(tag.value);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (!frame.ref) {
|
|
605
|
+
frame = pushFrame(frame);
|
|
606
|
+
frame.ref = buildReference();
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
frame.bindings.push(tag.value);
|
|
610
|
+
} else if (tag.type === CloseNodeTag) {
|
|
611
|
+
lastFrame = frame;
|
|
612
|
+
|
|
613
|
+
if (!lastFrame.open.value.type || !lastFrame.parent) {
|
|
614
|
+
yield* emitHeld(lastFrame, nextTag);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
frame = popFrame(frame);
|
|
618
|
+
|
|
619
|
+
if (frame) {
|
|
620
|
+
frame.heldProperties = [...lastFrame.heldProperties];
|
|
621
|
+
if (!lastFrame?.coverDepth) {
|
|
622
|
+
yield tag;
|
|
623
|
+
}
|
|
624
|
+
} else {
|
|
625
|
+
if (lastFrame.expanded || lastFrame.open.value.type !== Symbol.for('_')) {
|
|
626
|
+
yield tag;
|
|
627
|
+
}
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
} else if (tag.type === GapTag || tag.type === NullTag) {
|
|
631
|
+
if (frame.ref) {
|
|
632
|
+
yield buildChild(ReferenceTag, frame.ref);
|
|
633
|
+
}
|
|
634
|
+
lastFrame = frame;
|
|
635
|
+
|
|
636
|
+
frame = popFrame(frame);
|
|
637
|
+
|
|
638
|
+
if (tag.type === GapTag && frame.heldProperties.length) {
|
|
639
|
+
yield tag;
|
|
640
|
+
|
|
641
|
+
frame.shifting = false;
|
|
642
|
+
|
|
643
|
+
yield* emitHeld(frame, nextTag);
|
|
644
|
+
} else {
|
|
645
|
+
yield tag;
|
|
646
|
+
}
|
|
647
|
+
} else {
|
|
648
|
+
yield tag;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
tag = nextTag;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (frame) throw new Error();
|
|
655
|
+
}
|
|
656
|
+
|
|
377
657
|
function* __generatePrettyCSTML(tags, options) {
|
|
378
658
|
let { indent = ' ', inline: inlineOption = true } = options;
|
|
379
659
|
|
|
@@ -382,7 +662,8 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
382
662
|
return;
|
|
383
663
|
}
|
|
384
664
|
|
|
385
|
-
const co = new Coroutine(getStreamIterator(prettyGroupTags(tags)));
|
|
665
|
+
const co = new Coroutine(getStreamIterator(prettyGroupTags(hoistTrivia(tags))));
|
|
666
|
+
// const co = new Coroutine(getStreamIterator(prettyGroupTags(tags)));
|
|
386
667
|
let indentLevel = 0;
|
|
387
668
|
let first = true;
|
|
388
669
|
let inline = false;
|
|
@@ -391,19 +672,19 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
391
672
|
for (;;) {
|
|
392
673
|
co.advance();
|
|
393
674
|
|
|
394
|
-
if (co.done) break;
|
|
395
|
-
|
|
396
675
|
if (co.current instanceof Promise) {
|
|
397
|
-
co.current = yield co.current;
|
|
676
|
+
co.current = yield wait(co.current);
|
|
398
677
|
}
|
|
399
678
|
|
|
679
|
+
if (co.done) break;
|
|
680
|
+
|
|
400
681
|
const tag = co.value;
|
|
401
682
|
|
|
402
683
|
if (tag.type === 'Effect') {
|
|
403
684
|
continue;
|
|
404
685
|
}
|
|
405
686
|
|
|
406
|
-
if (tag.type === BindingTag && !tag.value.
|
|
687
|
+
if (tag.type === BindingTag && !tag.value.segments?.length) {
|
|
407
688
|
continue;
|
|
408
689
|
}
|
|
409
690
|
|
|
@@ -414,8 +695,7 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
414
695
|
(tag.type === NullTag ||
|
|
415
696
|
tag.type === GapTag ||
|
|
416
697
|
tag.type === BindingTag ||
|
|
417
|
-
tag.type ===
|
|
418
|
-
tag.type === TokenGroup);
|
|
698
|
+
(tag.type === OpenNodeTag && tag.value.selfClosing));
|
|
419
699
|
|
|
420
700
|
if (!first && !inline) {
|
|
421
701
|
yield* '\n';
|
|
@@ -428,23 +708,12 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
428
708
|
}
|
|
429
709
|
|
|
430
710
|
if (!inline) {
|
|
431
|
-
yield* indent.repeat(indentLevel);
|
|
711
|
+
yield* indent.repeat(Math.max(0, indentLevel));
|
|
432
712
|
} else {
|
|
433
713
|
yield* ' ';
|
|
434
714
|
}
|
|
435
715
|
|
|
436
|
-
|
|
437
|
-
ref = null;
|
|
438
|
-
const intrinsicValue = tag.value[0].value.flags.token ? getCooked(tag.value) : null;
|
|
439
|
-
let openTag = tag.value[0];
|
|
440
|
-
let { flags, type, attributes } = openTag.value;
|
|
441
|
-
yield* printSelfClosingNodeTag(buildOpenNodeTag(flags, type, attributes), intrinsicValue);
|
|
442
|
-
} else if (tag.type === OpenNodeTag) {
|
|
443
|
-
let { flags, type, attributes } = tag.value;
|
|
444
|
-
yield* printTag(buildOpenNodeTag(flags, type, attributes));
|
|
445
|
-
} else {
|
|
446
|
-
yield* printTag(tag);
|
|
447
|
-
}
|
|
716
|
+
yield* printTag(tag);
|
|
448
717
|
|
|
449
718
|
if (tag.type === ReferenceTag) {
|
|
450
719
|
inline = true;
|
|
@@ -452,7 +721,7 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
452
721
|
}
|
|
453
722
|
|
|
454
723
|
if (tag.type === OpenNodeTag) {
|
|
455
|
-
indentLevel
|
|
724
|
+
indentLevel += tag.value.selfClosing ? 0 : 1;
|
|
456
725
|
}
|
|
457
726
|
|
|
458
727
|
first = false;
|
|
@@ -494,9 +763,9 @@ export const getCooked = (tags) => {
|
|
|
494
763
|
}
|
|
495
764
|
|
|
496
765
|
case OpenNodeTag: {
|
|
497
|
-
const { flags, attributes } = tag.value;
|
|
766
|
+
const { flags, attributes, literalValue, selfClosing } = tag.value;
|
|
498
767
|
|
|
499
|
-
depth
|
|
768
|
+
depth += selfClosing ? 0 : 1;
|
|
500
769
|
|
|
501
770
|
if (first) {
|
|
502
771
|
if (flags.token) {
|
|
@@ -506,16 +775,18 @@ export const getCooked = (tags) => {
|
|
|
506
775
|
}
|
|
507
776
|
}
|
|
508
777
|
|
|
509
|
-
if (!(ref.
|
|
778
|
+
if (!(ref.type === '#' || (ref.type === '@' && attributes.cooked))) {
|
|
510
779
|
throw new Error('cookable nodes must not contain other nodes');
|
|
511
780
|
}
|
|
512
781
|
|
|
513
|
-
if (ref.
|
|
782
|
+
if (ref.type === '@') {
|
|
514
783
|
const { cooked: cookedValue } = tag.value.attributes;
|
|
515
784
|
|
|
516
785
|
if (!cookedValue) throw new Error('cannot cook string: it contains uncooked escapes');
|
|
517
786
|
|
|
518
787
|
cooked += cookedValue;
|
|
788
|
+
} else if (literalValue) {
|
|
789
|
+
cooked += literalValue;
|
|
519
790
|
}
|
|
520
791
|
|
|
521
792
|
break;
|
|
@@ -553,7 +824,9 @@ export const printSource = (tags) => {
|
|
|
553
824
|
if (!tags) return printed;
|
|
554
825
|
|
|
555
826
|
for (const tag of tags) {
|
|
556
|
-
if (tag.type ===
|
|
827
|
+
if (tag.type === OpenNodeTag && tag.value.literalValue) {
|
|
828
|
+
printed += tag.value.literalValue;
|
|
829
|
+
} else if (tag.type === LiteralTag) {
|
|
557
830
|
printed += tag.value;
|
|
558
831
|
} else if (tag.type === GapTag) {
|
|
559
832
|
throw new Error('use generateSourceTextFor');
|