@bablr/agast-helpers 0.10.9 → 0.11.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/README.md +1 -1
- package/lib/b-list-keyed.js +1 -0
- package/lib/b-list.js +1 -0
- package/lib/b-map.js +1 -0
- package/lib/b-set.js +1 -0
- package/lib/builders.js +916 -120
- package/lib/debug.js +39 -0
- package/lib/debug.register.js +5 -0
- package/lib/iterable.js +170 -0
- package/lib/object.js +52 -3
- package/lib/parse.js +30 -0
- package/lib/path.js +584 -635
- package/lib/print.js +45 -22
- package/lib/shorthand.js +4 -30
- package/lib/spans.js +0 -163
- package/lib/stream.js +345 -196
- package/lib/symbols.js +1 -0
- package/lib/tags.js +256 -77
- package/lib/template.js +19 -16
- package/lib/tree.js +49 -44
- package/package.json +14 -8
- package/lib/btree.js +0 -1
package/lib/stream.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
2
|
import emptyStack from '@iter-tools/imm-stack';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getStreamIterator,
|
|
5
|
+
StreamIterable,
|
|
6
|
+
StreamGenerator,
|
|
7
|
+
wait,
|
|
8
|
+
createDeferred,
|
|
9
|
+
continue_,
|
|
10
|
+
} from '@bablr/stream-iterator';
|
|
4
11
|
import * as Tags from './tags.js';
|
|
12
|
+
import * as BList from './b-list.js';
|
|
5
13
|
import { printTag } from './print.js';
|
|
6
14
|
import {
|
|
7
15
|
buildChild,
|
|
@@ -10,6 +18,8 @@ import {
|
|
|
10
18
|
buildOpenNodeTag,
|
|
11
19
|
buildProperty,
|
|
12
20
|
buildReference,
|
|
21
|
+
parseTag,
|
|
22
|
+
parseTagType,
|
|
13
23
|
} from './builders.js';
|
|
14
24
|
import {
|
|
15
25
|
OpenNodeTag,
|
|
@@ -22,78 +32,60 @@ import {
|
|
|
22
32
|
DoctypeTag,
|
|
23
33
|
ShiftTag,
|
|
24
34
|
AttributeDefinition,
|
|
35
|
+
StreamTag,
|
|
25
36
|
} from './symbols.js';
|
|
26
|
-
import { buildNode, isGapNode, Path } from './path.js';
|
|
37
|
+
import { buildNode, getRoot, isGapNode, isNode, Path } from './path.js';
|
|
27
38
|
import { streamFromTree } from './tree.js';
|
|
39
|
+
import { freeze, isObject } from './object.js';
|
|
40
|
+
import { maybeWait } from './iterable.js';
|
|
41
|
+
import { arrayValues } from '@bablr/record';
|
|
42
|
+
import { buildParser } from './parse.js';
|
|
28
43
|
|
|
29
|
-
export { getStreamIterator, StreamIterable, StreamGenerator, wait };
|
|
44
|
+
export { getStreamIterator, StreamIterable, StreamGenerator, wait, continue_ };
|
|
30
45
|
|
|
31
46
|
export * from './print.js';
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
} else {
|
|
37
|
-
return callback(maybePromise);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
function* __flatMap(fn, tags) {
|
|
42
|
-
const co = new Coroutine(getStreamIterator(tags));
|
|
48
|
+
function* __evaluateReturn(iterable) {
|
|
49
|
+
let iter = getStreamIterator(iterable);
|
|
50
|
+
let step;
|
|
43
51
|
|
|
44
52
|
for (;;) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
step = iter.next();
|
|
54
|
+
while (step === null || step instanceof Promise) {
|
|
55
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
56
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
49
57
|
}
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
let { value } = co;
|
|
53
|
-
|
|
54
|
-
yield* fn(value);
|
|
58
|
+
if (step.done) break;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
return
|
|
61
|
+
return step.value;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
export const
|
|
61
|
-
|
|
62
|
-
export const evaluateReturnSync = (iterable) => {
|
|
63
|
-
const co = new Coroutine(iterable[Symbol.iterator]());
|
|
64
|
-
while (!co.done) co.advance();
|
|
65
|
-
return co.value;
|
|
66
|
-
};
|
|
64
|
+
export const evaluateReturn = (iterable) => {
|
|
65
|
+
let iter = new StreamGenerator(__evaluateReturn(iterable));
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
const co = new Coroutine(getStreamIterator(iterable));
|
|
70
|
-
while (true) {
|
|
71
|
-
if (co.current instanceof Promise) {
|
|
72
|
-
co.current = await co.current;
|
|
73
|
-
}
|
|
74
|
-
if (co.done) break;
|
|
75
|
-
co.advance();
|
|
76
|
-
}
|
|
77
|
-
return co.value;
|
|
67
|
+
return maybeWait(iter.next(), (step) => step.value);
|
|
78
68
|
};
|
|
79
69
|
|
|
80
70
|
function* __treeFromStream(tags, options) {
|
|
81
71
|
let path = null;
|
|
82
|
-
|
|
83
|
-
|
|
72
|
+
let iter = getStreamIterator(tags);
|
|
73
|
+
let expressionsIter = getStreamIterator(options.expressions || []);
|
|
74
|
+
let step;
|
|
75
|
+
let expressionsStep;
|
|
84
76
|
|
|
85
77
|
for (;;) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
step = iter.next();
|
|
79
|
+
while (step === null || step instanceof Promise) {
|
|
80
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
81
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
90
82
|
}
|
|
83
|
+
if (step.done) break;
|
|
91
84
|
|
|
92
|
-
|
|
85
|
+
let tag = step.value;
|
|
86
|
+
let tagType = parseTagType(tag);
|
|
93
87
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (tag.type === 'Effect' || tag.type === DoctypeTag) {
|
|
88
|
+
if (tagType === 'Effect' || tagType === DoctypeTag) {
|
|
97
89
|
continue;
|
|
98
90
|
}
|
|
99
91
|
|
|
@@ -107,14 +99,18 @@ function* __treeFromStream(tags, options) {
|
|
|
107
99
|
continue;
|
|
108
100
|
}
|
|
109
101
|
|
|
110
|
-
if (
|
|
111
|
-
if (!
|
|
112
|
-
|
|
102
|
+
if (tagType === GapTag && !path.held) {
|
|
103
|
+
if (!expressionsStep || !expressionsStep.done) {
|
|
104
|
+
expressionsStep = expressionsIter.next();
|
|
105
|
+
while (expressionsStep === null || expressionsStep instanceof Promise) {
|
|
106
|
+
if (expressionsStep === null) yield continue_(), (expressionsStep = iter.next());
|
|
107
|
+
if (expressionsStep instanceof Promise) expressionsStep = yield wait(expressionsStep);
|
|
108
|
+
}
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
if (path.node.value.flags.token) {
|
|
116
|
-
if (
|
|
117
|
-
let node =
|
|
112
|
+
if (expressionsStep.done || expressionsStep.value != null) {
|
|
113
|
+
let node = expressionsStep.value;
|
|
118
114
|
if (isGapNode(node)) {
|
|
119
115
|
throw new Error('not implemented');
|
|
120
116
|
} else {
|
|
@@ -122,11 +118,11 @@ function* __treeFromStream(tags, options) {
|
|
|
122
118
|
}
|
|
123
119
|
}
|
|
124
120
|
} else {
|
|
125
|
-
let node =
|
|
121
|
+
let node = expressionsStep.done
|
|
126
122
|
? buildNode(buildGapTag())
|
|
127
|
-
: path == null ||
|
|
123
|
+
: path == null || expressionsStep.value == null
|
|
128
124
|
? buildNode(buildNullTag())
|
|
129
|
-
:
|
|
125
|
+
: expressionsStep.value;
|
|
130
126
|
|
|
131
127
|
path = path.advance(node);
|
|
132
128
|
}
|
|
@@ -142,33 +138,30 @@ function* __treeFromStream(tags, options) {
|
|
|
142
138
|
return path?.node;
|
|
143
139
|
}
|
|
144
140
|
|
|
145
|
-
export const treeFromStream = (tags, options = {}) =>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
return evaluateReturnSync(treeFromStream(tokens, options));
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
export const treeFromStreamAsync = async (tokens, options = {}) => {
|
|
152
|
-
return evaluateReturnAsync(treeFromStream(tokens, options));
|
|
141
|
+
export const treeFromStream = (tags, options = freeze({})) => {
|
|
142
|
+
let iter = new StreamGenerator(__treeFromStream(tags, options));
|
|
143
|
+
return maybeWait(iter.next(), (step) => step.value);
|
|
153
144
|
};
|
|
154
145
|
|
|
155
146
|
function* __isEmpty(tags) {
|
|
156
|
-
|
|
147
|
+
let iter = getStreamIterator(tags);
|
|
148
|
+
let step;
|
|
157
149
|
|
|
158
150
|
for (;;) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
151
|
+
step = iter.next();
|
|
152
|
+
while (step === null || step instanceof Promise) {
|
|
153
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
154
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
163
155
|
}
|
|
164
|
-
if (
|
|
156
|
+
if (step.done) break;
|
|
165
157
|
|
|
166
158
|
let depth = 0;
|
|
167
159
|
let ref = null;
|
|
168
160
|
|
|
169
|
-
const tag =
|
|
161
|
+
const tag = step.value;
|
|
162
|
+
let tagType = parseTagType(tag);
|
|
170
163
|
|
|
171
|
-
switch (
|
|
164
|
+
switch (tagType) {
|
|
172
165
|
case ReferenceTag:
|
|
173
166
|
ref = tag;
|
|
174
167
|
break;
|
|
@@ -176,7 +169,7 @@ function* __isEmpty(tags) {
|
|
|
176
169
|
case OpenNodeTag:
|
|
177
170
|
++depth;
|
|
178
171
|
|
|
179
|
-
if (tag.value.literalValue) return false;
|
|
172
|
+
if (parseTag(tag).value.literalValue) return false;
|
|
180
173
|
|
|
181
174
|
if (depth === 0 && ref.type === '@') {
|
|
182
175
|
return false;
|
|
@@ -204,73 +197,76 @@ export const printCSTML = (tags) => {
|
|
|
204
197
|
return stringFromStream(generateCSTML(tags));
|
|
205
198
|
};
|
|
206
199
|
|
|
200
|
+
export function* streamFromString(input) {
|
|
201
|
+
let p = buildParser(input);
|
|
202
|
+
let { str } = p;
|
|
203
|
+
let chr = str[p.idx];
|
|
204
|
+
|
|
205
|
+
while (' \t\r\n'.includes(chr)) chr = str[++p.idx];
|
|
206
|
+
|
|
207
|
+
while (p.idx < str.length) {
|
|
208
|
+
yield printTag(parseTag(p));
|
|
209
|
+
chr = str[p.idx];
|
|
210
|
+
|
|
211
|
+
while (' \t\r\n'.includes(chr)) chr = str[++p.idx];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
207
215
|
function* __emptyStreamIterator() {}
|
|
208
216
|
|
|
209
217
|
export const emptyStreamIterator = () => new StreamIterable(__emptyStreamIterator());
|
|
210
218
|
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
function* __stringFromStream(stream) {
|
|
220
|
+
let iter = getStreamIterator(stream);
|
|
221
|
+
let step;
|
|
213
222
|
let str = '';
|
|
214
223
|
|
|
215
224
|
for (;;) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
225
|
+
step = iter.next();
|
|
226
|
+
while (step === null || step instanceof Promise) {
|
|
227
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
228
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
220
229
|
}
|
|
230
|
+
if (step.done) break;
|
|
221
231
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const chr = co.value;
|
|
232
|
+
let chr = step.value;
|
|
225
233
|
|
|
226
234
|
str += chr;
|
|
227
235
|
}
|
|
228
236
|
|
|
229
237
|
return str;
|
|
230
|
-
}
|
|
238
|
+
}
|
|
231
239
|
|
|
232
240
|
export const stringFromStream = (stream) => {
|
|
233
|
-
|
|
234
|
-
let str = '';
|
|
235
|
-
|
|
236
|
-
for (;;) {
|
|
237
|
-
co.advance();
|
|
238
|
-
|
|
239
|
-
if (co.done) break;
|
|
240
|
-
|
|
241
|
-
const chr = co.value;
|
|
242
|
-
|
|
243
|
-
str += chr;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return str;
|
|
241
|
+
return evaluateReturn(__stringFromStream(stream));
|
|
247
242
|
};
|
|
248
243
|
|
|
249
244
|
function* __generateCSTML(tags, options) {
|
|
250
245
|
if (!tags) {
|
|
251
|
-
yield* '
|
|
246
|
+
yield* 'null';
|
|
252
247
|
return;
|
|
253
248
|
}
|
|
254
249
|
|
|
255
250
|
let prevTag = null;
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
let iter = getStreamIterator(prettyGroupTags(tags));
|
|
252
|
+
let step;
|
|
258
253
|
|
|
259
254
|
for (;;) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
255
|
+
step = iter.next();
|
|
256
|
+
while (step === null || step instanceof Promise) {
|
|
257
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
258
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
264
259
|
}
|
|
265
|
-
if (
|
|
260
|
+
if (step.done) break;
|
|
266
261
|
|
|
267
|
-
const tag =
|
|
262
|
+
const tag = step.value;
|
|
263
|
+
let tagType = parseTagType(tag);
|
|
268
264
|
|
|
269
|
-
if (
|
|
265
|
+
if (tagType === ReferenceTag && prevTag.type === NullTag) {
|
|
270
266
|
yield* ' ';
|
|
271
267
|
}
|
|
272
268
|
|
|
273
|
-
if (
|
|
269
|
+
if (tagType === 'Effect') {
|
|
274
270
|
continue;
|
|
275
271
|
}
|
|
276
272
|
|
|
@@ -280,11 +276,11 @@ function* __generateCSTML(tags, options) {
|
|
|
280
276
|
}
|
|
281
277
|
}
|
|
282
278
|
|
|
283
|
-
export const generateCSTML = (tags, options = {}) =>
|
|
279
|
+
export const generateCSTML = (tags, options = freeze({})) =>
|
|
284
280
|
new StreamIterable(__generateCSTML(tags, options));
|
|
285
281
|
|
|
286
282
|
const isToken = (tag) => {
|
|
287
|
-
return tag.value.flags.token;
|
|
283
|
+
return parseTag(tag).value.flags.token;
|
|
288
284
|
};
|
|
289
285
|
|
|
290
286
|
export const prettyGroupTags = (tags) => new StreamIterable(__prettyGroupTags(tags));
|
|
@@ -292,19 +288,19 @@ export const prettyGroupTags = (tags) => new StreamIterable(__prettyGroupTags(ta
|
|
|
292
288
|
function* __prettyGroupTags(tags) {
|
|
293
289
|
let states = emptyStack.push({ holding: [], broken: false, open: null });
|
|
294
290
|
let state = states.value;
|
|
295
|
-
|
|
296
|
-
|
|
291
|
+
let iter = getStreamIterator(tags);
|
|
292
|
+
let step;
|
|
297
293
|
|
|
298
294
|
for (;;) {
|
|
299
|
-
|
|
295
|
+
step = iter.next();
|
|
300
296
|
|
|
301
|
-
|
|
302
|
-
|
|
297
|
+
while (step === null || step instanceof Promise) {
|
|
298
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
299
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
303
300
|
}
|
|
301
|
+
if (step.done) break;
|
|
304
302
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
const tag = co.value;
|
|
303
|
+
const tag = parseTag(step.value);
|
|
308
304
|
const isOpenClose = tag.type === CloseNodeTag || tag.type === OpenNodeTag;
|
|
309
305
|
|
|
310
306
|
if (
|
|
@@ -367,6 +363,99 @@ function* __prettyGroupTags(tags) {
|
|
|
367
363
|
}
|
|
368
364
|
}
|
|
369
365
|
|
|
366
|
+
function* __transformStream(tags, stream, strategy) {
|
|
367
|
+
let iter = getStreamIterator(tags);
|
|
368
|
+
let step;
|
|
369
|
+
let str = '';
|
|
370
|
+
let stream_ = 1;
|
|
371
|
+
let transforming = stream === stream_;
|
|
372
|
+
let alreadyAdvanced = false;
|
|
373
|
+
|
|
374
|
+
function* __streamTags() {
|
|
375
|
+
for (;;) {
|
|
376
|
+
while (step === null || step instanceof Promise) {
|
|
377
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
378
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
379
|
+
}
|
|
380
|
+
if (step.done) break;
|
|
381
|
+
|
|
382
|
+
let tag = parseTag(step.value);
|
|
383
|
+
|
|
384
|
+
if (tag.type === StreamTag) {
|
|
385
|
+
if (tag.value.stream !== stream) {
|
|
386
|
+
transforming = false;
|
|
387
|
+
yield continue_();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
stream_ = tag.value.stream;
|
|
391
|
+
} else {
|
|
392
|
+
yield step.value;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
step = iter.next();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
let strategyIter = getStreamIterator(strategy(new StreamGenerator(__streamTags())));
|
|
400
|
+
let strategyStep;
|
|
401
|
+
|
|
402
|
+
for (;;) {
|
|
403
|
+
if (!alreadyAdvanced) {
|
|
404
|
+
step = iter.next();
|
|
405
|
+
}
|
|
406
|
+
alreadyAdvanced = false;
|
|
407
|
+
while (step === null || step instanceof Promise) {
|
|
408
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
409
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
410
|
+
}
|
|
411
|
+
if (step.done) break;
|
|
412
|
+
|
|
413
|
+
let tag = parseTag(step.value);
|
|
414
|
+
|
|
415
|
+
if (transforming) {
|
|
416
|
+
strategyStep = strategyIter.next();
|
|
417
|
+
|
|
418
|
+
while (strategyStep !== null) {
|
|
419
|
+
if (strategyStep instanceof Promise) strategyStep = yield wait(strategyStep);
|
|
420
|
+
if (strategyStep) {
|
|
421
|
+
if (strategyStep.done) break;
|
|
422
|
+
yield strategyStep.value;
|
|
423
|
+
|
|
424
|
+
strategyStep = strategyIter.next();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (step.done) break;
|
|
428
|
+
tag = parseTag(step.value);
|
|
429
|
+
if (tag.type === StreamTag) {
|
|
430
|
+
stream_ = tag.value.stream;
|
|
431
|
+
} else {
|
|
432
|
+
throw new Error();
|
|
433
|
+
}
|
|
434
|
+
yield step.value;
|
|
435
|
+
transforming = stream_ === stream;
|
|
436
|
+
} else {
|
|
437
|
+
if (tag.type === StreamTag) {
|
|
438
|
+
stream_ = tag.value.stream;
|
|
439
|
+
|
|
440
|
+
yield step.value;
|
|
441
|
+
|
|
442
|
+
if (stream_ === stream) {
|
|
443
|
+
transforming = true;
|
|
444
|
+
alreadyAdvanced = true;
|
|
445
|
+
} else {
|
|
446
|
+
transforming = false;
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
yield step.value;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export const transformStream = (tags, stream, strategy) => {
|
|
456
|
+
return new StreamIterable(__transformStream(tags, stream, strategy));
|
|
457
|
+
};
|
|
458
|
+
|
|
370
459
|
let pushFrame = (parent = null) => {
|
|
371
460
|
let heldProperties = parent ? [...parent.heldProperties] : [];
|
|
372
461
|
if (parent) {
|
|
@@ -380,7 +469,7 @@ let pushFrame = (parent = null) => {
|
|
|
380
469
|
open: null,
|
|
381
470
|
coverDepth: 0,
|
|
382
471
|
heldProperties,
|
|
383
|
-
expanded:
|
|
472
|
+
expanded: !parent,
|
|
384
473
|
shifting: parent?.shifting || false,
|
|
385
474
|
};
|
|
386
475
|
};
|
|
@@ -406,7 +495,7 @@ function* emitHeld(frame, nextTag) {
|
|
|
406
495
|
yield buildChild(ReferenceTag, reference);
|
|
407
496
|
let isAnonymous = node.value.flags.token && !node.value.name;
|
|
408
497
|
if (!isAnonymous) {
|
|
409
|
-
for (let binding of bindings) {
|
|
498
|
+
for (let binding of arrayValues(bindings)) {
|
|
410
499
|
yield buildChild(BindingTag, binding);
|
|
411
500
|
}
|
|
412
501
|
}
|
|
@@ -424,16 +513,18 @@ export const hoistTrivia = (tags) => {
|
|
|
424
513
|
function* __hoistTriviaOuter(co) {
|
|
425
514
|
co.advance();
|
|
426
515
|
|
|
427
|
-
|
|
428
|
-
co.current
|
|
516
|
+
while (co.current === null || co.current instanceof Promise) {
|
|
517
|
+
if (co.current === null) yield continue_(), co.advance();
|
|
518
|
+
if (co.current instanceof Promise) co.current = yield wait(co.current);
|
|
429
519
|
}
|
|
430
520
|
|
|
431
|
-
let firstTag = co.value;
|
|
521
|
+
let firstTag = parseTag(co.value);
|
|
432
522
|
|
|
433
523
|
co.advance();
|
|
434
524
|
|
|
435
|
-
|
|
436
|
-
co.current
|
|
525
|
+
while (co.current === null || co.current instanceof Promise) {
|
|
526
|
+
if (co.current === null) yield continue_(), co.advance();
|
|
527
|
+
if (co.current instanceof Promise) co.current = yield wait(co.current);
|
|
437
528
|
}
|
|
438
529
|
|
|
439
530
|
yield* __hoistTrivia(co, firstTag);
|
|
@@ -443,25 +534,25 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
443
534
|
let frame = null;
|
|
444
535
|
let lastFrame = null;
|
|
445
536
|
let alreadyAdvanced = true;
|
|
446
|
-
let tag;
|
|
537
|
+
let tag = firstTag;
|
|
538
|
+
|
|
447
539
|
let nextTag;
|
|
448
540
|
|
|
449
|
-
|
|
450
|
-
nextTag = co.value;
|
|
541
|
+
nextTag = parseTag(co.value);
|
|
451
542
|
|
|
452
543
|
for (;;) {
|
|
453
544
|
if (co.done || !nextTag) break;
|
|
454
|
-
|
|
455
545
|
if (!alreadyAdvanced) {
|
|
456
546
|
co.advance();
|
|
457
547
|
|
|
458
|
-
|
|
459
|
-
co.current
|
|
548
|
+
while (co.current === null || co.current instanceof Promise) {
|
|
549
|
+
if (co.current === null) yield continue_(), co.advance();
|
|
550
|
+
if (co.current instanceof Promise) co.current = yield wait(co.current);
|
|
460
551
|
}
|
|
461
552
|
}
|
|
462
553
|
alreadyAdvanced = false;
|
|
463
554
|
|
|
464
|
-
nextTag = co.value;
|
|
555
|
+
nextTag = co.done ? nextTag : parseTag(co.value);
|
|
465
556
|
|
|
466
557
|
if (tag.type === OpenNodeTag) {
|
|
467
558
|
let isCover = tag.value.type === Symbol.for('_');
|
|
@@ -471,21 +562,53 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
471
562
|
if (frame?.ref.type === '#' && !frame.ref.name) {
|
|
472
563
|
let { heldProperties } = frame;
|
|
473
564
|
if (heldProperties.length) {
|
|
474
|
-
let
|
|
565
|
+
let heldProperty = heldProperties[heldProperties.length - 1];
|
|
475
566
|
|
|
476
|
-
if (
|
|
567
|
+
if (heldProperty.node) {
|
|
477
568
|
throw new Error();
|
|
478
569
|
}
|
|
479
570
|
|
|
480
|
-
let node =
|
|
571
|
+
let node = treeFromStream(new StreamIterable(__hoistTrivia(co, tag)));
|
|
572
|
+
|
|
573
|
+
if (node instanceof Promise) {
|
|
574
|
+
node = yield wait(node);
|
|
575
|
+
}
|
|
481
576
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
property.
|
|
485
|
-
|
|
486
|
-
|
|
577
|
+
if (node.value.type === Symbol.for('_')) {
|
|
578
|
+
let leading = true;
|
|
579
|
+
for (let property of Tags.traverse(node.value.children)) {
|
|
580
|
+
if (property.value.reference.type === '_') {
|
|
581
|
+
leading = false;
|
|
582
|
+
frame.heldProperties[heldProperties.length - 1] = buildProperty(
|
|
583
|
+
BList.fromValues(
|
|
584
|
+
[
|
|
585
|
+
heldProperty.tags[1][0],
|
|
586
|
+
heldProperty.tags[1][1] || Tags.fromValues([]),
|
|
587
|
+
getRoot(node),
|
|
588
|
+
],
|
|
589
|
+
1,
|
|
590
|
+
),
|
|
591
|
+
);
|
|
592
|
+
} else {
|
|
593
|
+
if (leading) {
|
|
594
|
+
let top = frame.heldProperties.pop();
|
|
595
|
+
frame.heldProperties.push(property);
|
|
596
|
+
frame.heldProperties.push(top);
|
|
597
|
+
} else {
|
|
598
|
+
frame.heldProperties.push(property);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
} else {
|
|
603
|
+
frame.heldProperties[heldProperties.length - 1] = buildProperty(
|
|
604
|
+
BList.fromValues(
|
|
605
|
+
[heldProperty.tags[1][0], heldProperty.tags[1][1] || Tags.fromValues([]), node],
|
|
606
|
+
1,
|
|
607
|
+
),
|
|
608
|
+
);
|
|
609
|
+
}
|
|
487
610
|
|
|
488
|
-
nextTag = co.value;
|
|
611
|
+
nextTag = parseTag(co.value);
|
|
489
612
|
|
|
490
613
|
lastFrame = frame;
|
|
491
614
|
|
|
@@ -493,7 +616,7 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
493
616
|
|
|
494
617
|
if (
|
|
495
618
|
!frame.ref.flags.expression &&
|
|
496
|
-
(frame.expanded || frame.parent?.open
|
|
619
|
+
(frame.expanded || frame.parent?.open?.value.type !== Symbol.for('_'))
|
|
497
620
|
) {
|
|
498
621
|
yield* emitHeld(frame, nextTag);
|
|
499
622
|
}
|
|
@@ -501,7 +624,7 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
501
624
|
done = true;
|
|
502
625
|
}
|
|
503
626
|
} else if (frame && !isCover) {
|
|
504
|
-
if (!frame.shifting && frame.ref && frame.ref.type !== '_') {
|
|
627
|
+
if (!frame.shifting && ((frame.ref && frame.ref.type !== '_') || frame.expanded)) {
|
|
505
628
|
yield buildChild(ReferenceTag, frame.ref);
|
|
506
629
|
let isAnonymous = tag.value.flags.token && !tag.value.name;
|
|
507
630
|
if (!isAnonymous) {
|
|
@@ -549,7 +672,7 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
549
672
|
yield tag;
|
|
550
673
|
}
|
|
551
674
|
} else {
|
|
552
|
-
if (!isCover) {
|
|
675
|
+
if (!isCover || !parentFrame) {
|
|
553
676
|
yield tag;
|
|
554
677
|
}
|
|
555
678
|
}
|
|
@@ -560,13 +683,7 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
560
683
|
frame = pushFrame(parentFrame);
|
|
561
684
|
|
|
562
685
|
if (tag.value.type === '#' && !tag.value.name) {
|
|
563
|
-
|
|
564
|
-
yield parentFrame.open;
|
|
565
|
-
|
|
566
|
-
parentFrame.expanded = true;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
frame.heldProperties.push(buildProperty([tag]));
|
|
686
|
+
frame.heldProperties.push(buildProperty(BList.fromValues([printTag(tag)])));
|
|
570
687
|
} else {
|
|
571
688
|
if (!parentFrame.shifting) {
|
|
572
689
|
yield* emitHeld(frame, nextTag);
|
|
@@ -577,8 +694,9 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
577
694
|
frame.ref = tag.value.type === '_' ? parentFrame.ref : tag.value;
|
|
578
695
|
frame.bindings = parentFrame && tag.value.type === '_' ? [...parentFrame.bindings] : [];
|
|
579
696
|
frame.shifting = parentFrame && tag.value.type === '_' ? parentFrame.shifting : false;
|
|
697
|
+
frame.expanded = frame.depth === 1 && frame.coverDepth === 1;
|
|
580
698
|
|
|
581
|
-
if (tag.value.type === '_' && parentFrame.expanded) {
|
|
699
|
+
if (tag.value.type === '_' && parentFrame.expanded && parentFrame.depth) {
|
|
582
700
|
yield tag;
|
|
583
701
|
}
|
|
584
702
|
} else if (tag.type === ShiftTag) {
|
|
@@ -588,7 +706,7 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
588
706
|
|
|
589
707
|
frame.coverDepth = doneFrame?.coverDepth || 0;
|
|
590
708
|
frame.ref = lastFrame.ref;
|
|
591
|
-
frame.bindings = doneFrame && tag.value
|
|
709
|
+
frame.bindings = doneFrame && tag.value?.type === '_' ? [...doneFrame.bindings] : [];
|
|
592
710
|
frame.shifting = true;
|
|
593
711
|
// frame.heldProperties = [...doneFrame.heldProperties];
|
|
594
712
|
|
|
@@ -599,10 +717,15 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
599
717
|
let property = heldProperties[heldProperties.length - 1];
|
|
600
718
|
let { tags, node } = property;
|
|
601
719
|
if (!node) {
|
|
602
|
-
heldProperties[heldProperties.length - 1] = buildProperty(
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
720
|
+
heldProperties[heldProperties.length - 1] = buildProperty(
|
|
721
|
+
BList.fromValues(
|
|
722
|
+
[
|
|
723
|
+
tags[1][0] || Tags.fromValues([]),
|
|
724
|
+
Tags.push(tag, tags[1][1] || Tags.fromValues([])),
|
|
725
|
+
],
|
|
726
|
+
1,
|
|
727
|
+
),
|
|
728
|
+
);
|
|
606
729
|
frame.bindings.push(tag.value);
|
|
607
730
|
}
|
|
608
731
|
}
|
|
@@ -611,11 +734,13 @@ function* __hoistTrivia(co, firstTag) {
|
|
|
611
734
|
frame.ref = buildReference();
|
|
612
735
|
}
|
|
613
736
|
|
|
614
|
-
|
|
737
|
+
if (!heldProperties.length) {
|
|
738
|
+
frame.bindings.push(tag.value);
|
|
739
|
+
}
|
|
615
740
|
} else if (tag.type === CloseNodeTag) {
|
|
616
741
|
lastFrame = frame;
|
|
617
742
|
|
|
618
|
-
if (!lastFrame.open
|
|
743
|
+
if (!lastFrame.open?.value.type || !lastFrame.parent) {
|
|
619
744
|
yield* emitHeld(lastFrame, nextTag);
|
|
620
745
|
}
|
|
621
746
|
|
|
@@ -663,36 +788,30 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
663
788
|
let { indent = ' ', inline: inlineOption = true } = options;
|
|
664
789
|
|
|
665
790
|
if (!tags) {
|
|
666
|
-
yield* '
|
|
791
|
+
yield* 'null';
|
|
667
792
|
return;
|
|
668
793
|
}
|
|
669
794
|
|
|
670
|
-
|
|
671
|
-
|
|
795
|
+
let iter = getStreamIterator(prettyGroupTags(hoistTrivia(tags)));
|
|
796
|
+
let step;
|
|
672
797
|
let indentLevel = 0;
|
|
673
|
-
let first = true;
|
|
674
798
|
let inline = false;
|
|
675
799
|
let ref = null;
|
|
676
800
|
|
|
677
801
|
for (;;) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
802
|
+
step = iter.next();
|
|
803
|
+
while (step === null || step instanceof Promise) {
|
|
804
|
+
if (step === null) yield continue_(), (step = iter.next());
|
|
805
|
+
if (step instanceof Promise) step = yield wait(step);
|
|
682
806
|
}
|
|
807
|
+
if (step.done) break;
|
|
683
808
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
const tag = co.value;
|
|
809
|
+
const tag = parseTag(step.value);
|
|
687
810
|
|
|
688
811
|
if (tag.type === 'Effect') {
|
|
689
812
|
continue;
|
|
690
813
|
}
|
|
691
814
|
|
|
692
|
-
if (tag.type === BindingTag && !tag.value.segments?.length) {
|
|
693
|
-
continue;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
815
|
inline =
|
|
697
816
|
inlineOption &&
|
|
698
817
|
inline &&
|
|
@@ -702,7 +821,7 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
702
821
|
tag.type === BindingTag ||
|
|
703
822
|
(tag.type === OpenNodeTag && tag.value.selfClosing));
|
|
704
823
|
|
|
705
|
-
if (!
|
|
824
|
+
if (!inline) {
|
|
706
825
|
yield* '\n';
|
|
707
826
|
}
|
|
708
827
|
|
|
@@ -728,8 +847,6 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
728
847
|
if (tag.type === OpenNodeTag) {
|
|
729
848
|
indentLevel += tag.value.selfClosing ? 0 : 1;
|
|
730
849
|
}
|
|
731
|
-
|
|
732
|
-
first = false;
|
|
733
850
|
}
|
|
734
851
|
|
|
735
852
|
if (indentLevel !== 0) {
|
|
@@ -739,11 +856,11 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
739
856
|
yield* '\n';
|
|
740
857
|
}
|
|
741
858
|
|
|
742
|
-
export const generatePrettyCSTML = (tags, options = {}) => {
|
|
859
|
+
export const generatePrettyCSTML = (tags, options = freeze({})) => {
|
|
743
860
|
return new StreamIterable(__generatePrettyCSTML(tags, options));
|
|
744
861
|
};
|
|
745
862
|
|
|
746
|
-
export const printPrettyCSTML = (tags, options = {}) => {
|
|
863
|
+
export const printPrettyCSTML = (tags, options = freeze({})) => {
|
|
747
864
|
return stringFromStream(generatePrettyCSTML(tags, options));
|
|
748
865
|
};
|
|
749
866
|
|
|
@@ -756,11 +873,12 @@ export const getCooked = (tags) => {
|
|
|
756
873
|
let ref = null;
|
|
757
874
|
|
|
758
875
|
for (const tag of tags) {
|
|
876
|
+
let tagType = parseTagType(tag);
|
|
759
877
|
if (foundLast) throw new Error();
|
|
760
878
|
|
|
761
|
-
switch (
|
|
879
|
+
switch (tagType) {
|
|
762
880
|
case ReferenceTag: {
|
|
763
|
-
ref = tag;
|
|
881
|
+
ref = parseTag(tag);
|
|
764
882
|
if (depth === 1) {
|
|
765
883
|
throw new Error('cookable nodes must not contain other nodes');
|
|
766
884
|
}
|
|
@@ -768,7 +886,7 @@ export const getCooked = (tags) => {
|
|
|
768
886
|
}
|
|
769
887
|
|
|
770
888
|
case OpenNodeTag: {
|
|
771
|
-
const { flags, attributes, literalValue, selfClosing } = tag.value;
|
|
889
|
+
const { flags, attributes, literalValue, selfClosing } = parseTag(tag).value;
|
|
772
890
|
|
|
773
891
|
depth += selfClosing ? 0 : 1;
|
|
774
892
|
|
|
@@ -776,7 +894,7 @@ export const getCooked = (tags) => {
|
|
|
776
894
|
if (flags.token) {
|
|
777
895
|
break;
|
|
778
896
|
} else {
|
|
779
|
-
throw new Error(
|
|
897
|
+
throw new Error(flags);
|
|
780
898
|
}
|
|
781
899
|
}
|
|
782
900
|
|
|
@@ -785,7 +903,7 @@ export const getCooked = (tags) => {
|
|
|
785
903
|
}
|
|
786
904
|
|
|
787
905
|
if (ref.type === '@') {
|
|
788
|
-
const { cooked: cookedValue } =
|
|
906
|
+
const { cooked: cookedValue } = attributes;
|
|
789
907
|
|
|
790
908
|
if (!cookedValue) throw new Error('cannot cook string: it contains uncooked escapes');
|
|
791
909
|
|
|
@@ -807,7 +925,7 @@ export const getCooked = (tags) => {
|
|
|
807
925
|
|
|
808
926
|
case LiteralTag: {
|
|
809
927
|
if (depth === 1) {
|
|
810
|
-
cooked += tag.value;
|
|
928
|
+
cooked += parseTag(tag).value;
|
|
811
929
|
}
|
|
812
930
|
break;
|
|
813
931
|
}
|
|
@@ -830,13 +948,17 @@ export const printSource = (tags) => {
|
|
|
830
948
|
if (!tags) return printed;
|
|
831
949
|
|
|
832
950
|
for (const tag of tags) {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
951
|
+
let tagType = parseTagType(tag);
|
|
952
|
+
if (tagType === OpenNodeTag) {
|
|
953
|
+
let { literalValue } = parseTag(tag).value;
|
|
954
|
+
if (literalValue) {
|
|
955
|
+
printed += literalValue;
|
|
956
|
+
}
|
|
957
|
+
} else if (tagType === LiteralTag) {
|
|
958
|
+
printed += parseTag(tag).value;
|
|
959
|
+
} else if (tagType === ShiftTag) {
|
|
838
960
|
held = true;
|
|
839
|
-
} else if (
|
|
961
|
+
} else if (tagType === GapTag) {
|
|
840
962
|
if (held) {
|
|
841
963
|
held = false;
|
|
842
964
|
} else {
|
|
@@ -850,12 +972,39 @@ export const printSource = (tags) => {
|
|
|
850
972
|
|
|
851
973
|
export function* generateSourceTextFor(tags) {
|
|
852
974
|
for (const tag of tags) {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
975
|
+
let tagType = parseTagType(tag);
|
|
976
|
+
if (tagType === LiteralTag) {
|
|
977
|
+
yield* parseTag(tag).value;
|
|
978
|
+
} else if (tagType === GapTag) {
|
|
856
979
|
yield null;
|
|
857
980
|
}
|
|
858
981
|
}
|
|
859
982
|
}
|
|
860
983
|
|
|
861
984
|
export const sourceTextFor = printSource;
|
|
985
|
+
|
|
986
|
+
export function* interpolateFragment(tags) {
|
|
987
|
+
let tags_ = isNode(tags) ? Tags.traverseInner(Tags.getTags(tags)) : tags;
|
|
988
|
+
let lastTag = null;
|
|
989
|
+
let first = true;
|
|
990
|
+
let dropFirst = false;
|
|
991
|
+
let depth = 0;
|
|
992
|
+
for (let tag of tags_) {
|
|
993
|
+
let tagType = parseTagType(tag);
|
|
994
|
+
if (lastTag) yield lastTag;
|
|
995
|
+
|
|
996
|
+
if (tagType === OpenNodeTag && !parseTag(tag).value.selfClosing) depth++;
|
|
997
|
+
if (tagType === CloseNodeTag) depth--;
|
|
998
|
+
|
|
999
|
+
dropFirst ||= first && tag === '<__>';
|
|
1000
|
+
lastTag = first && dropFirst ? null : tag;
|
|
1001
|
+
first = false;
|
|
1002
|
+
}
|
|
1003
|
+
if (dropFirst) {
|
|
1004
|
+
if (lastTag !== '</>') throw new Error();
|
|
1005
|
+
} else {
|
|
1006
|
+
yield lastTag;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
if (depth !== 0) throw new Error();
|
|
1010
|
+
}
|