wesl 0.6.0-pre2

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.
Files changed (110) hide show
  1. package/dist/index.cjs +2617 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.js +2617 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/linker/packages/linker/src/AbstractElems.d.ts +104 -0
  6. package/dist/linker/packages/linker/src/BindIdents.d.ts +16 -0
  7. package/dist/linker/packages/linker/src/CommentsGrammar.d.ts +6 -0
  8. package/dist/linker/packages/linker/src/FlattenTreeImport.d.ts +11 -0
  9. package/dist/linker/packages/linker/src/ImportGrammar.d.ts +13 -0
  10. package/dist/linker/packages/linker/src/ImportTree.d.ts +17 -0
  11. package/dist/linker/packages/linker/src/Linker.d.ts +26 -0
  12. package/dist/linker/packages/linker/src/LowerAndEmit.d.ts +25 -0
  13. package/dist/linker/packages/linker/src/ParseWESL.d.ts +36 -0
  14. package/dist/linker/packages/linker/src/ParsedRegistry.d.ts +26 -0
  15. package/dist/linker/packages/linker/src/PathUtil.d.ts +9 -0
  16. package/dist/linker/packages/linker/src/Scope.d.ts +55 -0
  17. package/dist/linker/packages/linker/src/Slicer.d.ts +26 -0
  18. package/dist/linker/packages/linker/src/StandardTypes.d.ts +6 -0
  19. package/dist/linker/packages/linker/src/Util.d.ts +26 -0
  20. package/dist/linker/packages/linker/src/WESLCollect.d.ts +29 -0
  21. package/dist/linker/packages/linker/src/WESLGrammar.d.ts +23 -0
  22. package/dist/linker/packages/linker/src/WESLTokens.d.ts +42 -0
  23. package/dist/linker/packages/linker/src/WgslBundle.d.ts +13 -0
  24. package/dist/linker/packages/linker/src/debug/ASTtoString.d.ts +3 -0
  25. package/dist/linker/packages/linker/src/debug/ImportToString.d.ts +2 -0
  26. package/dist/linker/packages/linker/src/debug/LineWrapper.d.ts +21 -0
  27. package/dist/linker/packages/linker/src/debug/ScopeToString.d.ts +4 -0
  28. package/dist/linker/packages/linker/src/index.d.ts +7 -0
  29. package/dist/linker/packages/linker/src/test/ErrorLogging.test.d.ts +1 -0
  30. package/dist/linker/packages/linker/src/test/Expression.test.d.ts +1 -0
  31. package/dist/linker/packages/linker/src/test/FlattenTreeImport.test.d.ts +1 -0
  32. package/dist/linker/packages/linker/src/test/ImportCases.test.d.ts +1 -0
  33. package/dist/linker/packages/linker/src/test/ImportSyntaxCases.test.d.ts +1 -0
  34. package/dist/linker/packages/linker/src/test/LinkGlob.test.d.ts +1 -0
  35. package/dist/linker/packages/linker/src/test/LinkPackage.test.d.ts +1 -0
  36. package/dist/linker/packages/linker/src/test/Linker.test.d.ts +1 -0
  37. package/dist/linker/packages/linker/src/test/MatchWgslD.test.d.ts +1 -0
  38. package/dist/linker/packages/linker/src/test/ParseComments.test.d.ts +1 -0
  39. package/dist/linker/packages/linker/src/test/ParseWESL.test.d.ts +1 -0
  40. package/dist/linker/packages/linker/src/test/PathUtil.test.d.ts +1 -0
  41. package/dist/linker/packages/linker/src/test/PrettyGrammar.test.d.ts +1 -0
  42. package/dist/linker/packages/linker/src/test/ScopeWESL.test.d.ts +1 -0
  43. package/dist/linker/packages/linker/src/test/Slicer.test.d.ts +1 -0
  44. package/dist/linker/packages/linker/src/test/TestSetup.d.ts +1 -0
  45. package/dist/linker/packages/linker/src/test/TestUtil.d.ts +15 -0
  46. package/dist/linker/packages/linker/src/test/Util.test.d.ts +1 -0
  47. package/dist/linker/packages/linker/src/test/WgslTests.d.ts +0 -0
  48. package/dist/linker/packages/linker/src/test/shared/StringUtil.d.ts +8 -0
  49. package/dist/linker/packages/linker/src/test/shared/test/StringUtil.test.d.ts +1 -0
  50. package/dist/minified.cjs +2 -0
  51. package/dist/minified.cjs.map +1 -0
  52. package/dist/minified.js +2617 -0
  53. package/dist/minified.js.map +1 -0
  54. package/dist/wesl-testsuite/src/test-cases/BulkTests.d.ts +4 -0
  55. package/dist/wesl-testsuite/src/test-cases/ImportCases.d.ts +3 -0
  56. package/dist/wesl-testsuite/src/test-cases/ImportSyntaxCases.d.ts +3 -0
  57. package/package.json +45 -0
  58. package/src/AbstractElems.ts +148 -0
  59. package/src/BindIdents.ts +277 -0
  60. package/src/CommentsGrammar.ts +44 -0
  61. package/src/FlattenTreeImport.ts +59 -0
  62. package/src/ImportGrammar.ts +142 -0
  63. package/src/ImportTree.ts +19 -0
  64. package/src/Linker.ts +151 -0
  65. package/src/LowerAndEmit.ts +143 -0
  66. package/src/ParseWESL.ts +106 -0
  67. package/src/ParsedRegistry.ts +97 -0
  68. package/src/PathUtil.ts +52 -0
  69. package/src/Scope.ts +100 -0
  70. package/src/Slicer.ts +127 -0
  71. package/src/StandardTypes.ts +66 -0
  72. package/src/Util.ts +112 -0
  73. package/src/WESLCollect.ts +336 -0
  74. package/src/WESLGrammar.ts +538 -0
  75. package/src/WESLTokens.ts +97 -0
  76. package/src/WgslBundle.ts +16 -0
  77. package/src/debug/ASTtoString.ts +149 -0
  78. package/src/debug/ImportToString.ts +21 -0
  79. package/src/debug/LineWrapper.ts +65 -0
  80. package/src/debug/ScopeToString.ts +51 -0
  81. package/src/index.ts +7 -0
  82. package/src/test/ErrorLogging.test.ts +14 -0
  83. package/src/test/Expression.test.ts +22 -0
  84. package/src/test/FlattenTreeImport.test.ts +56 -0
  85. package/src/test/ImportCases.test.ts +440 -0
  86. package/src/test/ImportSyntaxCases.test.ts +22 -0
  87. package/src/test/LinkGlob.test.ts +25 -0
  88. package/src/test/LinkPackage.test.ts +26 -0
  89. package/src/test/Linker.test.ts +120 -0
  90. package/src/test/MatchWgslD.test.ts +16 -0
  91. package/src/test/ParseComments.test.ts +74 -0
  92. package/src/test/ParseWESL.test.ts +902 -0
  93. package/src/test/PathUtil.test.ts +34 -0
  94. package/src/test/PrettyGrammar.test.ts +21 -0
  95. package/src/test/ScopeWESL.test.ts +272 -0
  96. package/src/test/Slicer.test.ts +103 -0
  97. package/src/test/TestSetup.ts +4 -0
  98. package/src/test/TestUtil.ts +52 -0
  99. package/src/test/Util.test.ts +22 -0
  100. package/src/test/WgslTests.ts +0 -0
  101. package/src/test/__snapshots__/ParseDirectives.test.ts.snap +25 -0
  102. package/src/test/__snapshots__/ParseWESL.test.ts.snap +119 -0
  103. package/src/test/__snapshots__/ParseWESL2.test.ts.snap +67 -0
  104. package/src/test/__snapshots__/RustDirective.test.ts.snap +359 -0
  105. package/src/test/shared/StringUtil.ts +59 -0
  106. package/src/test/shared/test/StringUtil.test.ts +32 -0
  107. package/src/test/wgsl_1/main.wgsl +3 -0
  108. package/src/test/wgsl_1/util.wgsl +1 -0
  109. package/src/test/wgsl_2/main2.wgsl +3 -0
  110. package/src/test/wgsl_2/util2.wgsl +1 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,2617 @@
1
+ "use strict";
2
+ var __typeError = (msg) => {
3
+ throw TypeError(msg);
4
+ };
5
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
6
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
7
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
8
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
9
+ var _fragments, _column, _spc, _oneLine, _isHanging, _hangingSpc, _fragments2, _destLength, _entries;
10
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
11
+ class ImportTree {
12
+ /** segments in path order */
13
+ constructor(segments) {
14
+ this.segments = segments;
15
+ }
16
+ }
17
+ class SimpleSegment {
18
+ constructor(name, as, args) {
19
+ this.name = name;
20
+ this.as = as;
21
+ this.args = args;
22
+ }
23
+ }
24
+ class SegmentList {
25
+ constructor(list) {
26
+ this.list = list;
27
+ }
28
+ }
29
+ function importToString(tree) {
30
+ return tree.segments.map((s) => segmentToString(s)).join("/");
31
+ }
32
+ function segmentToString(segment) {
33
+ if (segment instanceof SimpleSegment) {
34
+ const { name, as, args } = segment;
35
+ const asMsg = as ? ` as ${as}` : "";
36
+ const argsMsg = args ? `(${args.join(", ")})` : "";
37
+ return `${name}${argsMsg}${asMsg}`;
38
+ }
39
+ if (segment instanceof SegmentList) {
40
+ return `{${segment.list.map((s) => segmentToString(s)).join(", ")}}`;
41
+ }
42
+ if (segment instanceof ImportTree) {
43
+ return `(${importToString(segment)})`;
44
+ }
45
+ return `|unknown segment type ${segment.constructor.name}|`;
46
+ }
47
+ class LineWrapper {
48
+ constructor(indent = 0, maxWidth = 60, hangingIndent = 2) {
49
+ __privateAdd(this, _fragments, []);
50
+ __privateAdd(this, _column, 0);
51
+ __privateAdd(this, _spc);
52
+ __privateAdd(this, _oneLine, true);
53
+ __privateAdd(this, _isHanging, false);
54
+ __privateAdd(this, _hangingSpc);
55
+ this.indent = indent;
56
+ this.maxWidth = maxWidth;
57
+ this.hangingIndent = hangingIndent;
58
+ __privateSet(this, _spc, " ".repeat(indent));
59
+ __privateSet(this, _hangingSpc, " ".repeat(hangingIndent));
60
+ }
61
+ /** add a new line to the constructed string */
62
+ nl() {
63
+ __privateGet(this, _fragments).push("\n");
64
+ __privateSet(this, _column, 0);
65
+ __privateSet(this, _oneLine, false);
66
+ __privateSet(this, _isHanging, false);
67
+ }
68
+ /** add a string, wrapping to the next line if necessary */
69
+ add(s) {
70
+ if (__privateGet(this, _column) + s.length > this.maxWidth) {
71
+ this.hangingNl();
72
+ }
73
+ if (__privateGet(this, _column) === 0) {
74
+ __privateGet(this, _fragments).push(__privateGet(this, _spc));
75
+ if (__privateGet(this, _isHanging)) {
76
+ __privateGet(this, _fragments).push(__privateGet(this, _hangingSpc));
77
+ }
78
+ __privateSet(this, _column, this.indent);
79
+ }
80
+ __privateGet(this, _fragments).push(s);
81
+ __privateSet(this, _column, __privateGet(this, _column) + s.length);
82
+ }
83
+ /** add a raw block of text with no wrapping */
84
+ addBlock(s, andNewLine = true) {
85
+ __privateGet(this, _fragments).push(s);
86
+ if (andNewLine) this.nl();
87
+ }
88
+ /** @return the constructed string */
89
+ get result() {
90
+ return __privateGet(this, _fragments).join("");
91
+ }
92
+ /** true if the result contains no newlines */
93
+ get oneLine() {
94
+ return __privateGet(this, _oneLine);
95
+ }
96
+ hangingNl() {
97
+ this.nl();
98
+ __privateSet(this, _isHanging, true);
99
+ }
100
+ }
101
+ _fragments = new WeakMap();
102
+ _column = new WeakMap();
103
+ _spc = new WeakMap();
104
+ _oneLine = new WeakMap();
105
+ _isHanging = new WeakMap();
106
+ _hangingSpc = new WeakMap();
107
+ function astToString(elem, indent = 0) {
108
+ const { kind: kind2, contents } = elem;
109
+ const str = new LineWrapper(indent);
110
+ str.add(kind2);
111
+ addElemFields(elem, str);
112
+ let childStrings = [];
113
+ if (contents) {
114
+ childStrings = contents.map((e) => astToString(e, indent + 2));
115
+ }
116
+ if (childStrings.length) {
117
+ str.nl();
118
+ str.addBlock(childStrings.join("\n"), false);
119
+ }
120
+ return str.result;
121
+ }
122
+ function elemToString(elem) {
123
+ const { kind: kind2 } = elem;
124
+ const str = new LineWrapper();
125
+ str.add(kind2);
126
+ addElemFields(elem, str);
127
+ let childStrings = [];
128
+ if (childStrings.length) {
129
+ str.nl();
130
+ str.addBlock(childStrings.join("\n"), false);
131
+ }
132
+ return str.result;
133
+ }
134
+ function addElemFields(elem, str) {
135
+ addTextFields(elem, str) || addVarishFields(elem, str) || addStructFields(elem, str) || addNameFields(elem, str) || addFnFields(elem, str) || addAliasFields(elem, str) || addImport(elem, str) || addRefIdent(elem, str) || addDeclIdent(elem, str);
136
+ }
137
+ function addVarishFields(elem, str) {
138
+ const { kind: kind2 } = elem;
139
+ if (kind2 === "var" || kind2 === "gvar" || kind2 === "const" || kind2 === "override") {
140
+ str.add(" " + elem.name.ident.originalName);
141
+ if (elem.typeRef) {
142
+ str.add(":" + elem.typeRef.ident.originalName);
143
+ }
144
+ return true;
145
+ }
146
+ }
147
+ function addTextFields(elem, str) {
148
+ if (elem.kind === "text") {
149
+ const { srcModule, start, end: end2 } = elem;
150
+ str.add(` '${srcModule.src.slice(start, end2)}'`);
151
+ return true;
152
+ }
153
+ }
154
+ function addRefIdent(elem, str) {
155
+ if (elem.kind === "ref") {
156
+ str.add(" " + elem.ident.originalName);
157
+ return true;
158
+ }
159
+ }
160
+ function addDeclIdent(elem, str) {
161
+ if (elem.kind === "decl") {
162
+ str.add(" %" + elem.ident.originalName);
163
+ return true;
164
+ }
165
+ }
166
+ function addAliasFields(elem, str) {
167
+ if (elem.kind === "alias") {
168
+ const { name, typeRef } = elem;
169
+ const prefix = name.ident.kind === "decl" ? "%" : "";
170
+ str.add(" " + prefix + name.ident.originalName);
171
+ str.add("=" + typeRef.ident.originalName);
172
+ return true;
173
+ }
174
+ }
175
+ function addStructFields(elem, str) {
176
+ if (elem.kind === "struct") {
177
+ str.add(" " + elem.name.ident.originalName);
178
+ return true;
179
+ }
180
+ }
181
+ function addImport(elem, str) {
182
+ if (elem.kind === "import") {
183
+ str.add(" " + importToString(elem.imports));
184
+ return true;
185
+ }
186
+ }
187
+ function addNameFields(elem, str) {
188
+ if (elem.kind === "name") {
189
+ str.add(" " + elem.name);
190
+ return true;
191
+ }
192
+ }
193
+ function addFnFields(elem, str) {
194
+ if (elem.kind === "fn") {
195
+ const { name, params, returnType } = elem;
196
+ str.add(" " + name.ident.originalName);
197
+ str.add("(");
198
+ const paramStrs = params.map((p) => p.name.ident.originalName + ": " + p.typeRef.ident.originalName).join(", ");
199
+ str.add(paramStrs);
200
+ str.add(")");
201
+ if (returnType) {
202
+ str.add(" -> " + returnType.ident.originalName);
203
+ }
204
+ return true;
205
+ }
206
+ }
207
+ function scopeToString(scope, indent = 0) {
208
+ const { children } = scope;
209
+ let childStrings = [];
210
+ if (children.length)
211
+ childStrings = children.map((c) => scopeToString(c, indent + 2));
212
+ const identStrings = scope.idents.map(({ kind: kind2, originalName }) => {
213
+ const prefix = kind2 === "decl" ? "%" : "";
214
+ return `${prefix}${originalName}`;
215
+ });
216
+ const str = new LineWrapper(indent);
217
+ str.add("{ ");
218
+ const last2 = identStrings.length - 1;
219
+ identStrings.forEach((s, i) => {
220
+ const element = i < last2 ? s + ", " : s;
221
+ str.add(element);
222
+ });
223
+ if (childStrings.length) {
224
+ str.nl();
225
+ str.addBlock(childStrings.join("\n"));
226
+ }
227
+ if (str.oneLine) {
228
+ str.add(" }");
229
+ } else {
230
+ if (!childStrings.length) str.nl();
231
+ str.add("}");
232
+ }
233
+ return str.result;
234
+ }
235
+ function identToString(ident2) {
236
+ if (!ident2) return JSON.stringify(ident2);
237
+ const { kind: kind2, originalName } = ident2;
238
+ const idStr = ident2.id ? `#${ident2.id}` : "";
239
+ if (kind2 === "ref") {
240
+ const ref = identToString(ident2.refersTo);
241
+ return `${originalName} ${idStr} -> ${ref}`;
242
+ } else {
243
+ return `%${originalName} ${idStr} (${ident2.mangledName})`;
244
+ }
245
+ }
246
+ function mergeTags(a, b) {
247
+ const aKeys = Reflect.ownKeys(a);
248
+ const sharedKeys = aKeys.filter((k) => b[k]);
249
+ const sharedEntries = sharedKeys.map((k) => [
250
+ k,
251
+ [...a[k] ?? [], ...b[k] ?? []]
252
+ ]);
253
+ const shared = Object.fromEntries(sharedEntries);
254
+ return { ...a, ...b, ...shared };
255
+ }
256
+ class ParseError extends Error {
257
+ constructor(msg) {
258
+ super(msg);
259
+ }
260
+ }
261
+ function kind(kindStr) {
262
+ return simpleParser(
263
+ `kind '${kindStr}'`,
264
+ (state) => {
265
+ const next = state.lexer.next();
266
+ return (next == null ? void 0 : next.kind) === kindStr ? next.text : null;
267
+ }
268
+ );
269
+ }
270
+ function text(value) {
271
+ return simpleParser(
272
+ `${quotedText(value)}`,
273
+ (state) => {
274
+ const next = state.lexer.next();
275
+ return (next == null ? void 0 : next.text) === value ? next.text : null;
276
+ }
277
+ );
278
+ }
279
+ function seq(...args) {
280
+ const parsers = args.map(parserArg);
281
+ const seqParser = parser("seq", (ctx) => {
282
+ const values = [];
283
+ let tagged = {};
284
+ let failed = false;
285
+ for (const p of parsers) {
286
+ const result = p._run(ctx);
287
+ if (result === null) {
288
+ failed = true;
289
+ break;
290
+ }
291
+ tagged = mergeTags(tagged, result.tags);
292
+ values.push(result.value);
293
+ }
294
+ if (failed) return null;
295
+ return { value: values, tags: tagged };
296
+ }).collect({ before: pushOpenArray, after: closeArray });
297
+ trackChildren(seqParser, ...parsers);
298
+ return seqParser;
299
+ }
300
+ function or(...args) {
301
+ const parsers = args.map(parserArg);
302
+ const orParser = parser("or", (state) => {
303
+ for (const p of parsers) {
304
+ const result = p._run(state);
305
+ if (result !== null) {
306
+ return result;
307
+ }
308
+ }
309
+ return null;
310
+ });
311
+ trackChildren(orParser, ...parsers);
312
+ return orParser;
313
+ }
314
+ const undefinedResult = {
315
+ value: void 0,
316
+ tags: {}
317
+ };
318
+ function opt(arg) {
319
+ const p = parserArg(arg);
320
+ const optParser = parser(
321
+ "opt",
322
+ (state) => {
323
+ const result = p._run(state);
324
+ return result || undefinedResult;
325
+ }
326
+ );
327
+ return optParser;
328
+ }
329
+ function not(arg) {
330
+ const p = parserArg(arg);
331
+ const notParser = parser("not", (state) => {
332
+ const pos = state.lexer.position();
333
+ const result = p._run(state);
334
+ if (!result) {
335
+ return { value: true, tags: {} };
336
+ }
337
+ state.lexer.position(pos);
338
+ return null;
339
+ });
340
+ return notParser;
341
+ }
342
+ function any() {
343
+ return simpleParser("any", (state) => {
344
+ const next = state.lexer.next();
345
+ return next || null;
346
+ });
347
+ }
348
+ function anyNot(arg) {
349
+ return seq(not(arg), any()).map((r) => r.value[1]).traceName("anyNot");
350
+ }
351
+ function anyThrough(arg) {
352
+ const p = parserArg(arg);
353
+ const anyParser = seq(repeat(anyNot(p)), p).traceName(
354
+ `anyThrough ${p.debugName}`
355
+ );
356
+ return anyParser;
357
+ }
358
+ function repeat(arg) {
359
+ const p = parserArg(arg);
360
+ const repeatParser = parser("repeat", repeatWhileFilter(p));
361
+ return repeatParser;
362
+ }
363
+ function repeatPlus(arg) {
364
+ const p = parserArg(arg);
365
+ const repeatParser = seq(p, repeat(p)).map((r) => [r.value[0], ...r.value[1]]).traceName("repeatPlus");
366
+ return repeatParser;
367
+ }
368
+ function repeatWhileFilter(p, filterFn = () => true) {
369
+ return (ctx) => {
370
+ const values = [];
371
+ let tags = {};
372
+ for (; ; ) {
373
+ const result = runExtended(ctx, p);
374
+ if (result !== null && filterFn(result)) {
375
+ values.push(result.value);
376
+ tags = mergeTags(tags, result.tags);
377
+ } else {
378
+ const r = { value: values, tags };
379
+ return r;
380
+ }
381
+ }
382
+ };
383
+ }
384
+ function eof() {
385
+ return simpleParser(
386
+ "eof",
387
+ (state) => state.lexer.eof() || null
388
+ );
389
+ }
390
+ function req(arg, msg) {
391
+ const p = parserArg(arg);
392
+ const reqParser = parser("req", (ctx) => {
393
+ const result = p._run(ctx);
394
+ if (result === null) {
395
+ const deepName = ctx._debugNames.join(" > ");
396
+ ctxLog(ctx, msg ?? `expected ${p.debugName} ${deepName}`);
397
+ throw new ParseError();
398
+ }
399
+ return result;
400
+ });
401
+ return reqParser;
402
+ }
403
+ function yes() {
404
+ return simpleParser("yes", () => true);
405
+ }
406
+ function withSep(sep, p, opts = {}) {
407
+ const { trailing = true, requireOne = false } = opts;
408
+ const parser2 = parserArg(p);
409
+ const sepParser = parserArg(sep);
410
+ const pTagged = or(parser2).tag("_sepTag");
411
+ const first = requireOne ? pTagged : opt(pTagged);
412
+ const last2 = trailing ? opt(sepParser) : yes();
413
+ const withSepParser = seq(first, repeat(seq(sepParser, pTagged)), last2).map((r) => {
414
+ const result = r.tags._sepTag;
415
+ delete r.tags._sepTag;
416
+ return result;
417
+ }).traceName("withSep");
418
+ return withSepParser;
419
+ }
420
+ function withSepPlus(sep, p) {
421
+ return withSep(sep, p, { requireOne: true }).traceName("withSepPlus");
422
+ }
423
+ function tokens(matcher, arg) {
424
+ const p = parserArg(arg);
425
+ const tokensParser = parser(
426
+ `tokens ${matcher._debugName}`,
427
+ (state) => {
428
+ return state.lexer.withMatcher(matcher, () => {
429
+ return p._run(state);
430
+ });
431
+ }
432
+ );
433
+ return tokensParser;
434
+ }
435
+ function makeEolf(matcher, ws) {
436
+ return tokens(
437
+ matcher,
438
+ tokenSkipSet(
439
+ null,
440
+ // disable automatic ws skipping so we can match newline
441
+ seq(
442
+ opt(kind(ws)),
443
+ or("\n", eof())
444
+ )
445
+ )
446
+ ).traceName("eolf");
447
+ }
448
+ function parserArg(arg) {
449
+ if (typeof arg === "string") {
450
+ return text(arg);
451
+ } else if (arg instanceof Parser) {
452
+ return arg;
453
+ }
454
+ return fn(arg);
455
+ }
456
+ function fn(fn2) {
457
+ const fp = parser("fn()", (state) => {
458
+ if (!fn2) {
459
+ const deepName = state._debugNames.join(".");
460
+ throw new Error(`fn parser called before definition: ${deepName}`);
461
+ }
462
+ const stage = fn2();
463
+ return stage._run(state);
464
+ });
465
+ return fp;
466
+ }
467
+ function collect(p, collectFn2, ctag2) {
468
+ const origAfter = collectFn2.after ?? collectFn2;
469
+ const beforeFn = collectFn2.before;
470
+ let afterFn = origAfter;
471
+ if (ctag2) {
472
+ afterFn = (cc) => {
473
+ const result = origAfter(cc);
474
+ addTagValue(cc.tags, ctag2, result);
475
+ return result;
476
+ };
477
+ }
478
+ const debugName = ctag2 ? `${p.debugName}-${ctag2}` : `${p.debugName}`;
479
+ const collectParser = parser(
480
+ `collect`,
481
+ (ctx) => {
482
+ const origStart = ctx.lexer.position();
483
+ if (beforeFn) {
484
+ queueCollectFn(ctx, origStart, beforeFn, `${debugName}.before`);
485
+ }
486
+ return runAndCollectAfter(p, ctx, afterFn, debugName);
487
+ }
488
+ );
489
+ collectParser._collection = true;
490
+ return collectParser;
491
+ }
492
+ function tagScope(arg) {
493
+ const p = parserArg(arg);
494
+ const sp = parser(
495
+ `tagScope`,
496
+ (ctx) => {
497
+ const origStart = ctx.lexer.position();
498
+ let origTags;
499
+ queueCollectFn(
500
+ ctx,
501
+ origStart,
502
+ (cc) => {
503
+ origTags = cloneTags(cc.tags);
504
+ cc.tags = {};
505
+ },
506
+ `scope.before ${p.debugName}`
507
+ );
508
+ return runAndCollectAfter(
509
+ p,
510
+ ctx,
511
+ (cc) => {
512
+ cc.tags = origTags;
513
+ },
514
+ `tagScope`
515
+ );
516
+ }
517
+ );
518
+ return sp;
519
+ }
520
+ function cloneTags(tags) {
521
+ const cloned = Object.entries(tags).map(([tag, values]) => {
522
+ return [tag, [...values]];
523
+ });
524
+ return Object.fromEntries(cloned);
525
+ }
526
+ function ctag(p, name) {
527
+ const cp = parser(`ctag`, (ctx) => {
528
+ return runAndCollectAfter(
529
+ p,
530
+ ctx,
531
+ (cc) => {
532
+ const valueEntry = last$1(cc._values);
533
+ addTagValue(cc.tags, name, valueEntry.value);
534
+ },
535
+ `ctag ${name}`
536
+ );
537
+ });
538
+ return cp;
539
+ }
540
+ function runAndCollectAfter(p, ctx, collectFn2, debugName = "") {
541
+ const origStart = ctx.lexer.position();
542
+ const result = p._run(ctx);
543
+ if (result) {
544
+ queueCollectFn(ctx, origStart, collectFn2, debugName);
545
+ }
546
+ return result;
547
+ }
548
+ function queueCollectFn(ctx, origStart, collectFn2, debugName) {
549
+ const srcPosition = refinePosition(ctx.lexer, origStart);
550
+ ctx._collect.push({
551
+ srcPosition,
552
+ collectFn: collectFn2,
553
+ debugName
554
+ });
555
+ }
556
+ function pushOpenArray(cc) {
557
+ cc._values.push({ value: null, openArray: [] });
558
+ }
559
+ function closeArray(cc) {
560
+ const lastValue = last$1(cc._values);
561
+ if (lastValue.openArray === void 0)
562
+ console.log("---closeArray: no open array");
563
+ cc._values.pop();
564
+ saveCollectValue(cc, lastValue.openArray);
565
+ }
566
+ function ptag(p, name) {
567
+ const cp = parser(`ptag`, (ctx) => {
568
+ const origStart = ctx.lexer.position();
569
+ const result = p._run(ctx);
570
+ if (result) {
571
+ const tagFn = (ctx2) => addTagValue(ctx2.tags, name, result.value);
572
+ queueCollectFn(ctx, origStart, tagFn, `ptag ${name}`);
573
+ }
574
+ return result;
575
+ });
576
+ return cp;
577
+ }
578
+ function addTagValue(tags, name, value) {
579
+ if (tags[name] === void 0) {
580
+ tags[name] = [];
581
+ }
582
+ tags[name].push(value);
583
+ }
584
+ function runCollection(_collect, app, lexer) {
585
+ const tags = {};
586
+ const { src } = lexer;
587
+ const _values = [{ value: null, openArray: void 0 }];
588
+ const collectContext = {
589
+ tags,
590
+ src,
591
+ start: -1,
592
+ end: -1,
593
+ app,
594
+ _values
595
+ };
596
+ _collect.forEach((entry) => {
597
+ const { collectFn: collectFn2, srcPosition } = entry;
598
+ collectContext.start = srcPosition.start;
599
+ collectContext.end = srcPosition.end;
600
+ const collectResult = collectFn2(collectContext);
601
+ saveCollectValue(collectContext, collectResult);
602
+ });
603
+ }
604
+ function saveCollectValue(cc, value) {
605
+ if (value !== void 0) {
606
+ const valueEntry = last$1(cc._values);
607
+ if (!valueEntry) console.log("----saveCollectValue: no valueEntry");
608
+ if (valueEntry) valueEntry.value = value;
609
+ if ((valueEntry == null ? void 0 : valueEntry.openArray) !== void 0) {
610
+ valueEntry.openArray.push(value);
611
+ }
612
+ }
613
+ }
614
+ function last$1(elems) {
615
+ return elems[elems.length - 1];
616
+ }
617
+ function refinePosition(lexer, origStart) {
618
+ const end2 = lexer.position();
619
+ lexer.position(origStart);
620
+ const start = lexer.skipIgnored();
621
+ lexer.position(end2);
622
+ return { start, end: end2 };
623
+ }
624
+ class Parser {
625
+ constructor(args) {
626
+ this._traceName = args.traceName;
627
+ this.tagName = args.tag;
628
+ this.traceOptions = args.trace;
629
+ this.terminal = args.terminal;
630
+ this.traceSrc = args.traceSrc;
631
+ this.preDisabled = args.preDisabled;
632
+ this._collection = args._collection;
633
+ this._children = args._children;
634
+ this.fn = args.fn;
635
+ }
636
+ /** copy this parser with slightly different settings */
637
+ _cloneWith(p) {
638
+ return new Parser({
639
+ traceName: this._traceName,
640
+ traceSrc: this.traceSrc,
641
+ tag: this.tagName,
642
+ trace: this.traceOptions,
643
+ terminal: this.terminal,
644
+ preDisabled: this.preDisabled,
645
+ _collection: this._collection,
646
+ _children: this._children,
647
+ fn: this.fn,
648
+ ...p
649
+ });
650
+ }
651
+ /** run the parser given an already created parsing context */
652
+ _run(context) {
653
+ return runParser(this, context);
654
+ }
655
+ /**
656
+ * tag results with a name,
657
+ *
658
+ * tagged results can be retrived with map(r => r.tags.myName)
659
+ * note that tagged results are collected into an array,
660
+ * multiple matches with the same name (even from different nested parsers) accumulate
661
+ */
662
+ tag(name) {
663
+ const p = this._cloneWith({
664
+ tag: name,
665
+ traceSrc: this,
666
+ traceName: void 0
667
+ });
668
+ return p;
669
+ }
670
+ /** tag parse results */
671
+ ptag(name) {
672
+ return ptag(this, name);
673
+ }
674
+ /** tag collect results */
675
+ ctag(name) {
676
+ return ctag(this, name);
677
+ }
678
+ /** record a name for debug tracing */
679
+ traceName(name) {
680
+ return this._cloneWith({ traceName: name });
681
+ }
682
+ /** trigger tracing for this parser (and by default also this parsers descendants) */
683
+ trace(opts = {}) {
684
+ return this._cloneWith({ trace: opts });
685
+ }
686
+ /** map results to a new value, or add to app state as a side effect.
687
+ * Return null to cause the parser to fail.
688
+ */
689
+ map(fn2) {
690
+ return map(this, fn2);
691
+ }
692
+ /** Queue a function that runs later, typically to collect AST elements from the parse.
693
+ * when a commit() is parsed.
694
+ * Collection functions are dropped with parser backtracking, so
695
+ * only succsessful parses are collected. */
696
+ collect(fn2, ctag2) {
697
+ return collect(this, fn2, ctag2);
698
+ }
699
+ /** switch next parser based on results */
700
+ toParser(fn2) {
701
+ return toParser(this, fn2);
702
+ }
703
+ /** start parsing */
704
+ parse(init) {
705
+ try {
706
+ const {
707
+ lexer,
708
+ maxParseCount,
709
+ srcMap,
710
+ appState: app = { context: {}, stable: [] }
711
+ } = init;
712
+ const _collect = [];
713
+ const result = this._run({
714
+ lexer,
715
+ app,
716
+ srcMap,
717
+ _preParse: [],
718
+ _parseCount: 0,
719
+ _preCacheFails: /* @__PURE__ */ new Map(),
720
+ maxParseCount,
721
+ _collect,
722
+ _debugNames: []
723
+ });
724
+ if (result) runCollection(_collect, app, lexer);
725
+ return result;
726
+ } catch (e) {
727
+ if (e instanceof ParseError) {
728
+ return null;
729
+ }
730
+ throw e;
731
+ }
732
+ }
733
+ /** name of this parser for debugging/tracing */
734
+ get debugName() {
735
+ var _a, _b;
736
+ return this._traceName ?? ((_a = this.traceSrc) == null ? void 0 : _a._traceName) ?? ((_b = this.tagName) == null ? void 0 : _b.toString()) ?? "parser";
737
+ }
738
+ }
739
+ function parser(traceName, fn2, terminal) {
740
+ const terminalArg = terminal ? { terminal } : {};
741
+ return new Parser({ fn: fn2, traceName, ...terminalArg });
742
+ }
743
+ function simpleParser(traceName, fn2) {
744
+ const parserFn = (ctx) => {
745
+ const r = fn2(ctx);
746
+ if (r == null || r === void 0) return null;
747
+ return { value: r, tags: {} };
748
+ };
749
+ return parser(traceName, parserFn, true);
750
+ }
751
+ function runParser(p, context) {
752
+ const { lexer, _parseCount = 0, maxParseCount } = context;
753
+ context._parseCount = _parseCount + 1;
754
+ if (maxParseCount && _parseCount > maxParseCount) {
755
+ srcLog(lexer.src, lexer.position(), "infinite loop? ", p.debugName);
756
+ return null;
757
+ }
758
+ const origAppContext = context.app.context;
759
+ const result = withTraceLogging()(
760
+ context,
761
+ p.traceOptions,
762
+ runInContext
763
+ );
764
+ return result;
765
+ function runInContext(ctx) {
766
+ var _a;
767
+ const origPosition = lexer.position();
768
+ const origCollectLength = ctx._collect.length;
769
+ (_a = ctx._trace) == null ? void 0 : _a.successOnly;
770
+ if (!p.terminal && tracing)
771
+ ;
772
+ const savePreParse = ctx._preParse;
773
+ if (!p.preDisabled) {
774
+ execPreParsers(ctx);
775
+ } else {
776
+ ctx._preParse = [];
777
+ }
778
+ let result2 = p.fn(ctx);
779
+ if (result2 === null || result2 === void 0) {
780
+ lexer.position(origPosition);
781
+ context.app.context = origAppContext;
782
+ result2 = null;
783
+ ctx._collect.length = origCollectLength;
784
+ } else {
785
+ const value = result2.value;
786
+ let tags;
787
+ if (p.tagName && result2.value !== void 0) {
788
+ tags = mergeTags(result2.tags, {
789
+ [p.tagName]: [result2.value]
790
+ });
791
+ } else {
792
+ tags = result2.tags;
793
+ }
794
+ result2 = { value, tags };
795
+ }
796
+ ctx._preParse = savePreParse;
797
+ return result2;
798
+ }
799
+ }
800
+ function execPreParsers(ctx) {
801
+ const { _preParse, lexer } = ctx;
802
+ const ctxNoPre = { ...ctx, _preParse: [] };
803
+ _preParse.forEach((pre) => {
804
+ const checkedCache = getPreParserCheckedCache(ctx, pre);
805
+ let position;
806
+ let preResult;
807
+ do {
808
+ position = lexer.position();
809
+ if (checkedCache.has(position)) break;
810
+ preResult = pre._run(ctxNoPre);
811
+ } while (preResult !== null && preResult !== void 0);
812
+ checkedCache.add(position);
813
+ lexer.position(position);
814
+ });
815
+ }
816
+ function getPreParserCheckedCache(ctx, pre) {
817
+ let cache = ctx._preCacheFails.get(pre);
818
+ if (!cache) {
819
+ cache = /* @__PURE__ */ new Set();
820
+ ctx._preCacheFails.set(pre, cache);
821
+ }
822
+ return cache;
823
+ }
824
+ function map(p, fn2) {
825
+ const mapParser = parser(
826
+ `map`,
827
+ (ctx) => {
828
+ const extended = runExtended(ctx, p);
829
+ if (!extended) return null;
830
+ const mappedValue = fn2(extended);
831
+ if (mappedValue === null) return null;
832
+ return { value: mappedValue, tags: extended.tags };
833
+ }
834
+ );
835
+ return mapParser;
836
+ }
837
+ function toParser(p, toParserFn) {
838
+ const newParser = parser(
839
+ "toParser",
840
+ (ctx) => {
841
+ const extended = runExtended(ctx, p);
842
+ if (!extended) return null;
843
+ const newParser2 = toParserFn(extended);
844
+ if (newParser2 === void 0) {
845
+ return extended;
846
+ }
847
+ const nextResult = newParser2._run(ctx);
848
+ return nextResult;
849
+ }
850
+ );
851
+ return newParser;
852
+ }
853
+ const emptySet = /* @__PURE__ */ new Set();
854
+ function tokenSkipSet(ignore, p) {
855
+ const ignoreSet = ignore ?? emptySet;
856
+ const ignoreValues = [...ignoreSet.values()].toString() || "(null)";
857
+ const ignoreParser = parser(
858
+ `tokenSkipSet ${ignoreValues}`,
859
+ (ctx) => ctx.lexer.withIgnore(ignoreSet, () => p._run(ctx))
860
+ );
861
+ return ignoreParser;
862
+ }
863
+ function preParse(pre, p) {
864
+ const newParser = parser(
865
+ "preParse",
866
+ (ctx) => {
867
+ const newCtx = { ...ctx, _preParse: [pre, ...ctx._preParse] };
868
+ return p._run(newCtx);
869
+ }
870
+ );
871
+ return newParser;
872
+ }
873
+ function disablePreParse(arg) {
874
+ const parser2 = parserArg(arg);
875
+ return parser2._cloneWith({ preDisabled: true });
876
+ }
877
+ function runExtended(ctx, p) {
878
+ const origStart = ctx.lexer.position();
879
+ const origResults = p._run(ctx);
880
+ if (origResults === null) {
881
+ ctx.lexer.position(origStart);
882
+ return null;
883
+ }
884
+ const end2 = ctx.lexer.position();
885
+ const src = ctx.lexer.src;
886
+ ctx.lexer.position(origStart);
887
+ const start = ctx.lexer.skipIgnored();
888
+ ctx.lexer.position(end2);
889
+ const { app, srcMap } = ctx;
890
+ return { ...origResults, start, end: end2, app, src, srcMap, ctx };
891
+ }
892
+ function trackChildren(p, ...args) {
893
+ }
894
+ let tracing = false;
895
+ let logger = console.log;
896
+ const withTraceLogging = () => stubTraceLogging;
897
+ function stubTraceLogging(ctx, trace, fn2) {
898
+ return fn2(ctx);
899
+ }
900
+ function srcLog(src, pos, ...msgs) {
901
+ logInternal(logger, src, pos, ...msgs);
902
+ }
903
+ function resultLog(result, ...msgs) {
904
+ const { src, srcMap, start, end: end2 } = result;
905
+ srcLog(srcMap ?? src, [start, end2 - 1], ...msgs);
906
+ }
907
+ function ctxLog(ctx, ...msgs) {
908
+ const src = ctx.srcMap ?? ctx.lexer.src;
909
+ srcLog(src, ctx.lexer.position(), ...msgs);
910
+ }
911
+ function logInternal(log, srcOrSrcMap, destPos, ...msgs) {
912
+ if (typeof srcOrSrcMap === "string") {
913
+ logInternalSrc(log, srcOrSrcMap, destPos, ...msgs);
914
+ return;
915
+ }
916
+ const { src, positions } = mapSrcPositions(srcOrSrcMap, destPos);
917
+ logInternalSrc(log, src, positions, ...msgs);
918
+ }
919
+ function mapSrcPositions(srcMap, destPos) {
920
+ var _a;
921
+ const srcPos = srcMap.mapPositions(...[destPos].flat());
922
+ const { src } = srcPos[0];
923
+ let positions;
924
+ if (((_a = srcPos[1]) == null ? void 0 : _a.src) === src) {
925
+ positions = srcPos.map((p) => p.position);
926
+ } else {
927
+ positions = srcPos[0].position;
928
+ }
929
+ return { src, positions };
930
+ }
931
+ function logInternalSrc(log, src, pos, ...msgs) {
932
+ log(...msgs);
933
+ const { line, lineNum, linePos, linePos2 } = srcLine(src, pos);
934
+ {
935
+ log(line, ` Ln ${lineNum}`);
936
+ }
937
+ const caret = carets(linePos, linePos2);
938
+ log(caret);
939
+ }
940
+ function carets(linePos, linePos2) {
941
+ const firstCaret = " ".repeat(linePos) + "^";
942
+ let secondCaret = "";
943
+ if (linePos2 && linePos2 > linePos) {
944
+ secondCaret = " ".repeat(linePos2 - linePos - 1) + "^";
945
+ }
946
+ return firstCaret + secondCaret;
947
+ }
948
+ const startCache = /* @__PURE__ */ new Map();
949
+ function srcLine(src, position) {
950
+ let pos;
951
+ let pos2;
952
+ if (typeof position === "number") {
953
+ pos = position;
954
+ } else {
955
+ [pos, pos2] = position;
956
+ }
957
+ const starts = getStarts(src);
958
+ let start = 0;
959
+ let end2 = starts.length - 1;
960
+ if (pos >= starts[end2]) {
961
+ start = end2;
962
+ }
963
+ while (start + 1 < end2) {
964
+ const mid = start + end2 >> 1;
965
+ if (pos >= starts[mid]) {
966
+ start = mid;
967
+ } else {
968
+ end2 = mid;
969
+ }
970
+ }
971
+ let linePos2;
972
+ if (pos2 !== void 0 && pos2 >= starts[start] && pos2 < starts[end2]) {
973
+ linePos2 = pos2 - starts[start];
974
+ }
975
+ const lineNl = src.slice(starts[start], starts[start + 1] || src.length);
976
+ const line = lineNl.slice(-1) === "\n" ? lineNl.slice(0, -1) : lineNl;
977
+ return { line, linePos: pos - starts[start], linePos2, lineNum: start + 1 };
978
+ }
979
+ function getStarts(src) {
980
+ const found = startCache.get(src);
981
+ if (found) return found;
982
+ const starts = [...src.matchAll(/\n/g)].map((m) => m.index + 1);
983
+ starts.unshift(0);
984
+ startCache.set(src, starts);
985
+ return starts;
986
+ }
987
+ function matchingLexer(src, rootMatcher, ignore = /* @__PURE__ */ new Set(["ws"]), srcMap) {
988
+ let matcher = rootMatcher;
989
+ const matcherStack = [];
990
+ matcher.start(src);
991
+ function next() {
992
+ matcher.position();
993
+ const { token } = toNextToken();
994
+ return token;
995
+ }
996
+ function skipIgnored() {
997
+ const { p } = toNextToken();
998
+ matcher.position(p);
999
+ return p;
1000
+ }
1001
+ function toNextToken() {
1002
+ let p = matcher.position();
1003
+ if (eof2()) return { p };
1004
+ let token = matcher.next();
1005
+ while (token && ignore.has(token.kind)) {
1006
+ p = matcher.position();
1007
+ if (eof2()) return { p };
1008
+ token = matcher.next();
1009
+ }
1010
+ return { p, token };
1011
+ }
1012
+ function pushMatcher(newMatcher, newIgnore) {
1013
+ const position2 = matcher.position();
1014
+ matcherStack.push({ matcher, ignore });
1015
+ newMatcher.start(src, position2);
1016
+ matcher = newMatcher;
1017
+ ignore = newIgnore;
1018
+ }
1019
+ function popMatcher() {
1020
+ const position2 = matcher.position();
1021
+ const elem = matcherStack.pop();
1022
+ if (!elem) {
1023
+ console.error("too many pops");
1024
+ return;
1025
+ }
1026
+ matcher = elem.matcher;
1027
+ ignore = elem.ignore;
1028
+ matcher.position(position2);
1029
+ }
1030
+ function position(pos) {
1031
+ if (pos !== void 0) {
1032
+ matcher.start(src, pos);
1033
+ }
1034
+ return matcher.position();
1035
+ }
1036
+ function withMatcher(newMatcher, fn2) {
1037
+ return withMatcherIgnore(newMatcher, ignore, fn2);
1038
+ }
1039
+ function withIgnore(newIgnore, fn2) {
1040
+ return withMatcherIgnore(matcher, newIgnore, fn2);
1041
+ }
1042
+ function withMatcherIgnore(tokenMatcher2, ignore2, fn2) {
1043
+ pushMatcher(tokenMatcher2, ignore2);
1044
+ const result = fn2();
1045
+ popMatcher();
1046
+ return result;
1047
+ }
1048
+ function eof2() {
1049
+ return matcher.position() === src.length;
1050
+ }
1051
+ return {
1052
+ next,
1053
+ position,
1054
+ withMatcher,
1055
+ withIgnore,
1056
+ eof: eof2,
1057
+ skipIgnored,
1058
+ src
1059
+ };
1060
+ }
1061
+ function quotedText(text2) {
1062
+ return text2 ? `'${text2.replace(/\n/g, "\\n")}'` : "";
1063
+ }
1064
+ class SrcMap {
1065
+ constructor(dest, entries = []) {
1066
+ this.dest = dest;
1067
+ this.entries = entries;
1068
+ }
1069
+ /** add a new mapping from src to dest ranges.
1070
+ * entries must be non-overlapping in the destination
1071
+ */
1072
+ addEntries(newEntries) {
1073
+ this.entries.push(...newEntries);
1074
+ }
1075
+ /** given positions in the dest string,
1076
+ * @return corresponding positions in the src strings */
1077
+ mapPositions(...positions) {
1078
+ return positions.map((p) => this.destToSrc(p));
1079
+ }
1080
+ /** internally compress adjacent entries where possible */
1081
+ compact() {
1082
+ if (!this.entries.length) return;
1083
+ let prev = this.entries[0];
1084
+ const newEntries = [prev];
1085
+ for (let i = 1; i < this.entries.length; i++) {
1086
+ const e = this.entries[i];
1087
+ if (e.src === prev.src && prev.destEnd === e.destStart && prev.srcEnd === e.srcStart) {
1088
+ prev.destEnd = e.destEnd;
1089
+ prev.srcEnd = e.srcEnd;
1090
+ } else {
1091
+ newEntries.push(e);
1092
+ prev = e;
1093
+ }
1094
+ }
1095
+ this.entries = newEntries;
1096
+ }
1097
+ /** sort in destination order */
1098
+ sort() {
1099
+ this.entries.sort((a, b) => a.destStart - b.destStart);
1100
+ }
1101
+ /** This SrcMap's destination is a src for the other srcmap,
1102
+ * so combine the two and return the result.
1103
+ */
1104
+ merge(other) {
1105
+ if (other === this) return this;
1106
+ const mappedEntries = other.entries.filter((e) => e.src === this.dest);
1107
+ if (mappedEntries.length === 0) {
1108
+ console.log("other source map does not link to this one");
1109
+ return other;
1110
+ }
1111
+ sortSrc(mappedEntries);
1112
+ const newEntries = mappedEntries.map((e) => {
1113
+ const { src, position: srcStart } = this.destToSrc(e.srcStart);
1114
+ const { src: endSrc, position: srcEnd } = this.destToSrc(e.srcEnd);
1115
+ if (endSrc !== src) throw new Error("NYI, need to split");
1116
+ const newEntry = {
1117
+ src,
1118
+ srcStart,
1119
+ srcEnd,
1120
+ destStart: e.destStart,
1121
+ destEnd: e.destEnd
1122
+ };
1123
+ return newEntry;
1124
+ });
1125
+ const otherSources = other.entries.filter((e) => e.src !== this.dest);
1126
+ const newMap = new SrcMap(other.dest, [...otherSources, ...newEntries]);
1127
+ newMap.sort();
1128
+ return newMap;
1129
+ }
1130
+ /**
1131
+ * @param entries should be sorted in destStart order
1132
+ * @return the source position corresponding to a provided destination position
1133
+ *
1134
+ */
1135
+ destToSrc(destPos) {
1136
+ const entry = this.entries.find(
1137
+ (e) => e.destStart <= destPos && e.destEnd >= destPos
1138
+ );
1139
+ if (!entry) {
1140
+ return {
1141
+ src: this.dest,
1142
+ position: destPos
1143
+ };
1144
+ }
1145
+ return {
1146
+ src: entry.src,
1147
+ position: entry.srcStart + destPos - entry.destStart
1148
+ };
1149
+ }
1150
+ }
1151
+ function sortSrc(entries) {
1152
+ entries.sort((a, b) => a.srcStart - b.srcStart);
1153
+ }
1154
+ class SrcMapBuilder {
1155
+ constructor() {
1156
+ __privateAdd(this, _fragments2, []);
1157
+ __privateAdd(this, _destLength, 0);
1158
+ __privateAdd(this, _entries, []);
1159
+ }
1160
+ /** append a string fragment to the destination string */
1161
+ // TODO allow for src file name not just string (e.g. SrcModule)
1162
+ add(fragment, src, srcStart, srcEnd) {
1163
+ const destStart = __privateGet(this, _destLength);
1164
+ __privateSet(this, _destLength, __privateGet(this, _destLength) + fragment.length);
1165
+ const destEnd = __privateGet(this, _destLength);
1166
+ __privateGet(this, _fragments2).push(fragment);
1167
+ __privateGet(this, _entries).push({ src, srcStart, srcEnd, destStart, destEnd });
1168
+ }
1169
+ /** append a synthetic newline, mapped to previous source location */
1170
+ addNl() {
1171
+ const lastEntry = __privateGet(this, _entries).slice(-1)[0] ?? {};
1172
+ const { src = "?", srcStart = 0, srcEnd = 0 } = lastEntry;
1173
+ this.add("\n", src, srcStart, srcEnd);
1174
+ }
1175
+ /** copy a string fragment from the src to the destination string */
1176
+ addCopy(src, srcStart, srcEnd) {
1177
+ const fragment = src.slice(srcStart, srcEnd);
1178
+ this.add(fragment, src, srcStart, srcEnd);
1179
+ }
1180
+ /** return a SrcMap */
1181
+ build() {
1182
+ const map2 = new SrcMap(__privateGet(this, _fragments2).join(""), __privateGet(this, _entries));
1183
+ map2.compact();
1184
+ return map2;
1185
+ }
1186
+ }
1187
+ _fragments2 = new WeakMap();
1188
+ _destLength = new WeakMap();
1189
+ _entries = new WeakMap();
1190
+ class Cache extends Map {
1191
+ constructor(max) {
1192
+ super();
1193
+ this.max = max;
1194
+ }
1195
+ set(k, v) {
1196
+ if (this.size > this.max) {
1197
+ const first = this.keys().next().value;
1198
+ if (first) this.delete(first);
1199
+ }
1200
+ return super.set(k, v);
1201
+ }
1202
+ }
1203
+ function tokenMatcher(matchers, debugName = "matcher") {
1204
+ const groups = Object.keys(matchers);
1205
+ let src;
1206
+ const cache = new Cache(5);
1207
+ const expParts = Object.entries(matchers).map(toRegexSource).join("|");
1208
+ const exp = new RegExp(expParts, "midgu");
1209
+ function start(text2, position2 = 0) {
1210
+ if (src !== text2) {
1211
+ cache.clear();
1212
+ }
1213
+ src = text2;
1214
+ exp.lastIndex = position2;
1215
+ }
1216
+ function next() {
1217
+ if (src === void 0) {
1218
+ throw new Error("start() first");
1219
+ }
1220
+ const startPos = exp.lastIndex;
1221
+ const found = cache.get(startPos);
1222
+ if (found) {
1223
+ exp.lastIndex += found.text.length;
1224
+ return found;
1225
+ }
1226
+ const matches = exp.exec(src);
1227
+ const matchedIndex = findGroupDex(matches == null ? void 0 : matches.indices);
1228
+ if (matchedIndex) {
1229
+ const { startEnd, groupDex } = matchedIndex;
1230
+ const kind2 = groups[groupDex];
1231
+ const text2 = src.slice(startEnd[0], startEnd[1]);
1232
+ const token = { kind: kind2, text: text2 };
1233
+ if (startPos != startEnd[0]) {
1234
+ srcLog(
1235
+ src,
1236
+ startPos,
1237
+ `tokens ${debugName} skipped: '${src.slice(startPos, startEnd[0])}' to get to: '${text2}'`
1238
+ );
1239
+ throw new Error("token matcher should match all input");
1240
+ }
1241
+ cache.set(startPos, token);
1242
+ return token;
1243
+ }
1244
+ }
1245
+ function position(pos) {
1246
+ if (pos !== void 0) {
1247
+ exp.lastIndex = pos;
1248
+ }
1249
+ return exp.lastIndex;
1250
+ }
1251
+ const keyEntries = groups.map((k) => [k, k]);
1252
+ const keys = Object.fromEntries(keyEntries);
1253
+ return {
1254
+ ...keys,
1255
+ start,
1256
+ next,
1257
+ position,
1258
+ _debugName: debugName
1259
+ };
1260
+ }
1261
+ function findGroupDex(indices) {
1262
+ if (indices) {
1263
+ for (let i = 1; i < indices.length; i++) {
1264
+ const startEnd = indices[i];
1265
+ if (startEnd) {
1266
+ return { startEnd, groupDex: i - 1 };
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+ function toRegexSource(nameExp) {
1272
+ const [name, e] = nameExp;
1273
+ if (typeof e === "string") {
1274
+ const expSrc = `(${escapeRegex(e)})`;
1275
+ verifyNonCapturing(name, new RegExp(expSrc));
1276
+ return expSrc;
1277
+ } else {
1278
+ verifyNonCapturing(name, e);
1279
+ return `(${e.source})`;
1280
+ }
1281
+ }
1282
+ function verifyNonCapturing(name, exp) {
1283
+ const willMatch = new RegExp("|" + exp.source);
1284
+ const result = willMatch.exec("");
1285
+ if (result.length > 1) {
1286
+ throw new Error(
1287
+ `match expression groups must be non-capturing: ${name}: /${exp.source}/. Use (?:...) instead.`
1288
+ );
1289
+ }
1290
+ }
1291
+ const regexSpecials = /[$+*.?|(){}[\]\\/^]/g;
1292
+ function escapeRegex(s) {
1293
+ return s.replace(regexSpecials, "\\$&");
1294
+ }
1295
+ function matchOneOf(syms) {
1296
+ const symbolList = syms.split(" ").sort((a, b) => b.length - a.length);
1297
+ const escaped = symbolList.filter((s) => s).map(escapeRegex);
1298
+ return new RegExp(escaped.join("|"));
1299
+ }
1300
+ const eol = /[\n\v\f\u{0085}\u{2028}\u{2029}]|\r\n?/u;
1301
+ const blankspaces = /[ \t\n\v\f\r\u{0085}\u{200E}\u{200F}\u{2028}\u{2029}]+/u;
1302
+ const directive = /#[a-zA-Z_]\w*/;
1303
+ const symbolSet = "& && -> @ / ! [ ] { } :: : , == = != >>= >> >= > <<= << <= < % - -- . + ++ | || ( ) ; * ~ ^ // /* */ += -= *= /= %= &= |= ^= _";
1304
+ const symbol = matchOneOf(symbolSet);
1305
+ const quote = /["']/;
1306
+ const ident = /(?:(?:[_\p{XID_Start}][\p{XID_Continue}]+)|(?:[\p{XID_Start}]))/u;
1307
+ const digits = new RegExp(
1308
+ // decimal_float_literal
1309
+ /(?:0[fh])|(?:[1-9][0-9]*[fh])/.source + /|(?:[0-9]*\.[0-9]+(?:[eE][+-]?[0-9]+)?[fh]?)/.source + /|(?:[0-9]+\.[0-9]*(?:[eE][+-]?[0-9]+)?[fh]?)/.source + /|(?:[0-9]+[eE][+-]?[0-9]+[fh]?)/.source + // hex_float_literal
1310
+ /|(?:0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+(?:[pP][+-]?[0-9]+[fh]?)?)/.source + /|(?:0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*(?:[pP][+-]?[0-9]+[fh]?)?)/.source + /|(?:0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?)/.source + // hex_int_literal
1311
+ /|(?:0[xX][0-9a-fA-F]+[iu]?)/.source + // decimal_int_literal
1312
+ /|(?:0[iu]?)|(?:[1-9][0-9]*[iu]?)/.source
1313
+ );
1314
+ const textureStorage = matchOneOf(
1315
+ "texture_strorage_1d texture_storage_2d texture_storage_2d_array texture_storage_3d"
1316
+ );
1317
+ const mainTokens = tokenMatcher(
1318
+ {
1319
+ directive,
1320
+ textureStorage,
1321
+ ident,
1322
+ digits,
1323
+ symbol,
1324
+ quote,
1325
+ ws: blankspaces
1326
+ },
1327
+ "main"
1328
+ );
1329
+ const bracketTokens = tokenMatcher(
1330
+ {
1331
+ bracket: /<|>/,
1332
+ ws: blankspaces,
1333
+ other: /[^<>]+/
1334
+ },
1335
+ "bracket"
1336
+ );
1337
+ const lineCommentTokens = tokenMatcher(
1338
+ {
1339
+ ws: /[ \t]+/,
1340
+ // note ws must be before notEol
1341
+ notEol: /[^\n]+/,
1342
+ eol
1343
+ },
1344
+ "lineComment"
1345
+ );
1346
+ const argsTokens = tokenMatcher(
1347
+ {
1348
+ directive,
1349
+ quote,
1350
+ relPath: /[.][/\w._-]+/,
1351
+ arg: /[\w._-]+/,
1352
+ symbol,
1353
+ ws: /[ \t]+/,
1354
+ // don't include \n, so we can find eol separately
1355
+ eol
1356
+ },
1357
+ "argsTokens"
1358
+ );
1359
+ tokenMatcher(
1360
+ {
1361
+ blanks: /\s+/,
1362
+ other: /[^\s]+/
1363
+ },
1364
+ "rootWs"
1365
+ );
1366
+ function resetScopeIds() {
1367
+ scopeId = 0;
1368
+ }
1369
+ let scopeId = 0;
1370
+ function makeScope(s) {
1371
+ return { ...s, id: scopeId++ };
1372
+ }
1373
+ function emptyScope(kind2) {
1374
+ return makeScope({ idents: [], parent: null, children: [], kind: kind2 });
1375
+ }
1376
+ function emptyBodyScope(parent) {
1377
+ return makeScope({ kind: "body-scope", idents: [], parent, children: [] });
1378
+ }
1379
+ function exportDecl(scope, name) {
1380
+ for (const ident2 of scope.idents) {
1381
+ if (ident2.originalName === name && ident2.kind === "decl") {
1382
+ return ident2;
1383
+ }
1384
+ }
1385
+ }
1386
+ function addToOpenElem(cc, elem) {
1387
+ const weslContext = cc.app.context;
1388
+ const { openElems } = weslContext;
1389
+ if (openElems && openElems.length) {
1390
+ const open = openElems[openElems.length - 1];
1391
+ open.contents.push(elem);
1392
+ }
1393
+ }
1394
+ function refIdent(cc) {
1395
+ const { src, start, end: end2 } = cc;
1396
+ const app = cc.app;
1397
+ const { scope } = app.context;
1398
+ const { srcModule } = app.stable;
1399
+ const originalName = src.slice(start, end2);
1400
+ const kind2 = "ref";
1401
+ const ident2 = { kind: kind2, originalName, ast: cc.app.stable, scope };
1402
+ const identElem = { kind: kind2, start, end: end2, srcModule, ident: ident2 };
1403
+ ident2.refIdentElem = identElem;
1404
+ saveIdent(cc, identElem);
1405
+ return identElem;
1406
+ }
1407
+ function declIdentElem(cc) {
1408
+ const { src, start, end: end2 } = cc;
1409
+ const app = cc.app;
1410
+ const { srcModule } = app.stable;
1411
+ const originalName = src.slice(start, end2);
1412
+ const kind2 = "decl";
1413
+ const declElem = null;
1414
+ const ident2 = { kind: kind2, originalName, scope: null, declElem };
1415
+ const identElem = { kind: kind2, start, end: end2, srcModule, ident: ident2 };
1416
+ saveIdent(cc, identElem);
1417
+ return identElem;
1418
+ }
1419
+ let identId = 0;
1420
+ function saveIdent(cc, identElem) {
1421
+ const { ident: ident2 } = identElem;
1422
+ ident2.id = identId++;
1423
+ const weslContext = cc.app.context;
1424
+ weslContext.scope.idents.push(ident2);
1425
+ addToOpenElem(cc, identElem);
1426
+ }
1427
+ function startScope(cc) {
1428
+ const { scope } = cc.app.context;
1429
+ const newScope = emptyBodyScope(scope);
1430
+ scope.children.push(newScope);
1431
+ cc.app.context.scope = newScope;
1432
+ }
1433
+ function completeScope(cc) {
1434
+ const weslContext = cc.app.context;
1435
+ const completedScope = weslContext.scope;
1436
+ const { parent } = completedScope;
1437
+ if (parent) {
1438
+ weslContext.scope = parent;
1439
+ }
1440
+ return completedScope;
1441
+ }
1442
+ function collectVarLike(kind2) {
1443
+ return collectElem(kind2, (cc, openElem) => {
1444
+ var _a, _b, _c;
1445
+ const name = (_a = cc.tags.declIdent) == null ? void 0 : _a[0];
1446
+ const typeRef = (_b = cc.tags.typeRef) == null ? void 0 : _b[0];
1447
+ const decl_scope = (_c = cc.tags.decl_scope) == null ? void 0 : _c[0];
1448
+ const partElem = { ...openElem, name, typeRef };
1449
+ const varElem = withTextCover(partElem, cc);
1450
+ name.ident.declElem = varElem;
1451
+ name.ident.scope = decl_scope;
1452
+ return varElem;
1453
+ });
1454
+ }
1455
+ function collectFn() {
1456
+ return collectElem("fn", (cc, openElem) => {
1457
+ var _a, _b, _c, _d;
1458
+ const name = (_a = cc.tags.fnName) == null ? void 0 : _a[0];
1459
+ const body_scope = (_b = cc.tags.body_scope) == null ? void 0 : _b[0];
1460
+ const params = ((_c = cc.tags.fnParam) == null ? void 0 : _c.flat(3)) ?? [];
1461
+ const returnType = (_d = cc.tags.returnType) == null ? void 0 : _d.flat(3)[0];
1462
+ const partElem = { ...openElem, name, params, returnType };
1463
+ const fnElem = withTextCover(partElem, cc);
1464
+ name.ident.declElem = fnElem;
1465
+ name.ident.scope = body_scope;
1466
+ return fnElem;
1467
+ });
1468
+ }
1469
+ function collectFnParam() {
1470
+ return collectElem(
1471
+ "param",
1472
+ (cc, openElem) => {
1473
+ var _a, _b;
1474
+ const name = (_a = cc.tags.paramName) == null ? void 0 : _a[0];
1475
+ const typeRef = (_b = cc.tags.typeRef) == null ? void 0 : _b[0];
1476
+ const elem = { ...openElem, name, typeRef };
1477
+ const paramElem = withTextCover(elem, cc);
1478
+ name.ident.declElem = paramElem;
1479
+ return paramElem;
1480
+ }
1481
+ );
1482
+ }
1483
+ function collectStruct() {
1484
+ return collectElem(
1485
+ "struct",
1486
+ (cc, openElem) => {
1487
+ var _a, _b;
1488
+ const name = (_a = cc.tags.typeName) == null ? void 0 : _a[0];
1489
+ const members = cc.tags.members;
1490
+ const structElem = { ...openElem, name, members };
1491
+ const elem = withTextCover(structElem, cc);
1492
+ name.ident.declElem = elem;
1493
+ name.ident.scope = (_b = cc.tags.struct_scope) == null ? void 0 : _b[0];
1494
+ return elem;
1495
+ }
1496
+ );
1497
+ }
1498
+ function collectStructMember() {
1499
+ return collectElem(
1500
+ "member",
1501
+ (cc, openElem) => {
1502
+ var _a, _b;
1503
+ const name = (_a = cc.tags.nameElem) == null ? void 0 : _a[0];
1504
+ const typeRef = (_b = cc.tags.typeRef) == null ? void 0 : _b[0];
1505
+ const partElem = { ...openElem, name, typeRef };
1506
+ return withTextCover(partElem, cc);
1507
+ }
1508
+ );
1509
+ }
1510
+ function collectNameElem(cc) {
1511
+ const { start, end: end2, src, app } = cc;
1512
+ const { srcModule } = app.stable;
1513
+ const name = src.slice(start, end2);
1514
+ const elem = { kind: "name", srcModule, start, end: end2, name };
1515
+ addToOpenElem(cc, elem);
1516
+ return elem;
1517
+ }
1518
+ function collectModule() {
1519
+ return collectElem(
1520
+ "module",
1521
+ (cc, openElem) => {
1522
+ const ccComplete = { ...cc, start: 0, end: cc.src.length };
1523
+ const moduleElem = withTextCover(openElem, ccComplete);
1524
+ const weslState = cc.app.stable;
1525
+ weslState.moduleElem = moduleElem;
1526
+ return moduleElem;
1527
+ }
1528
+ );
1529
+ }
1530
+ function importList(cc) {
1531
+ const list = cc.tags.list;
1532
+ return new SegmentList(list);
1533
+ }
1534
+ function importSegment(cc) {
1535
+ var _a, _b;
1536
+ const segOrig = (_a = cc.tags.segment) == null ? void 0 : _a[0];
1537
+ const seg = segOrig === "." ? "package" : segOrig;
1538
+ return new SimpleSegment(seg, (_b = cc.tags.as) == null ? void 0 : _b[0]);
1539
+ }
1540
+ function importTree(cc) {
1541
+ var _a;
1542
+ const path = (_a = cc.tags.p) == null ? void 0 : _a.flat();
1543
+ return new ImportTree(path);
1544
+ }
1545
+ function importElem() {
1546
+ return collectElem(
1547
+ "import",
1548
+ (cc, openElem) => {
1549
+ const path = cc.tags.p;
1550
+ const imports = new ImportTree(path);
1551
+ const partialElem = { ...openElem, imports };
1552
+ const importElem2 = withTextCover(partialElem, cc);
1553
+ cc.app.stable.imports.push(imports);
1554
+ return importElem2;
1555
+ }
1556
+ );
1557
+ }
1558
+ function scopeCollect() {
1559
+ return {
1560
+ before: startScope,
1561
+ after: completeScope
1562
+ };
1563
+ }
1564
+ function collectSimpleElem(kind2) {
1565
+ return collectElem(kind2, (cc, part) => withTextCover(part, cc));
1566
+ }
1567
+ function collectElem(kind2, fn2) {
1568
+ return {
1569
+ before: (cc) => {
1570
+ const partialElem = { kind: kind2, contents: [] };
1571
+ const weslContext = cc.app.context;
1572
+ weslContext.openElems.push(partialElem);
1573
+ },
1574
+ after: (cc) => {
1575
+ const weslContext = cc.app.context;
1576
+ const partialElem = weslContext.openElems.pop();
1577
+ console.assert(partialElem && partialElem.kind === kind2);
1578
+ const elem = fn2(cc, { ...partialElem, start: cc.start, end: cc.end });
1579
+ addToOpenElem(cc, elem);
1580
+ return elem;
1581
+ }
1582
+ };
1583
+ }
1584
+ function withTextCover(elem, cc) {
1585
+ const contents = coverWithText(cc, elem.contents);
1586
+ return { ...elem, contents };
1587
+ }
1588
+ function coverWithText(cc, existing) {
1589
+ let { start: pos } = cc;
1590
+ const { end: end2, app } = cc;
1591
+ const ast = app.stable;
1592
+ const sorted = existing.sort((a, b) => a.start - b.start);
1593
+ const elems = sorted.flatMap((elem) => {
1594
+ const result = pos < elem.start ? [makeTextElem(elem.start), elem] : [elem];
1595
+ pos = elem.end;
1596
+ return result;
1597
+ });
1598
+ if (pos < end2) {
1599
+ elems.push(makeTextElem(end2));
1600
+ }
1601
+ return elems;
1602
+ function makeTextElem(end22) {
1603
+ return { kind: "text", start: pos, end: end22, srcModule: ast.srcModule };
1604
+ }
1605
+ }
1606
+ const skipWsSet = /* @__PURE__ */ new Set(["ws"]);
1607
+ function skipWs(p) {
1608
+ return tokenSkipSet(skipWsSet, p);
1609
+ }
1610
+ function noSkipWs(p) {
1611
+ return tokenSkipSet(null, p);
1612
+ }
1613
+ const importSymbolSet = "/ { } , ( ) .. . * ; @ #";
1614
+ const importSymbol = matchOneOf(importSymbolSet);
1615
+ const importTokens = tokenMatcher({
1616
+ ws: /\s+/,
1617
+ importSymbol,
1618
+ ident,
1619
+ // TODO allow '-' in pkg names?
1620
+ digits
1621
+ });
1622
+ const eolTokens = tokenMatcher({
1623
+ ws: /[ \t]+/,
1624
+ // don't include \n, for eolf
1625
+ eol
1626
+ });
1627
+ const eolf$1 = disablePreParse(makeEolf(eolTokens, importTokens.ws));
1628
+ const wordToken = kind(importTokens.ident);
1629
+ let packagePath = null;
1630
+ const simpleSegment = tagScope(
1631
+ wordToken.ptag("segment").collect(importSegment)
1632
+ );
1633
+ const lastSimpleSegment = tagScope(
1634
+ seq(
1635
+ wordToken.ptag("segment"),
1636
+ skipWs(opt(seq("as", wordToken.ptag("as"))))
1637
+ ).collect(importSegment)
1638
+ );
1639
+ const collectionItem = or(
1640
+ tagScope(or(() => packagePath).collect(importTree)),
1641
+ lastSimpleSegment
1642
+ );
1643
+ const importCollection = tagScope(
1644
+ seq(
1645
+ "{",
1646
+ skipWs(
1647
+ seq(
1648
+ withSepPlus(",", () => collectionItem.ctag("list")),
1649
+ "}"
1650
+ )
1651
+ )
1652
+ ).collect(importList)
1653
+ );
1654
+ const relativeSegment = tagScope(
1655
+ seq(or(".", "..").ptag("segment"), "/").collect(importSegment)
1656
+ ).ctag("p");
1657
+ const lastSegment = or(lastSimpleSegment, importCollection);
1658
+ const packageTail = seq(
1659
+ repeat(seq(simpleSegment.ctag("p"), "/")),
1660
+ lastSegment.ctag("p")
1661
+ );
1662
+ const relativePath$1 = seq(repeatPlus(relativeSegment), packageTail);
1663
+ const packagePrefix = tagScope(
1664
+ seq(wordToken.ptag("segment"), "/").collect(importSegment)
1665
+ ).ctag("p");
1666
+ packagePath = seq(packagePrefix, packageTail);
1667
+ const fullPath = noSkipWs(
1668
+ seq(kind(importTokens.ws), or(relativePath$1, packagePath))
1669
+ );
1670
+ const weslImport = tagScope(
1671
+ tokens(
1672
+ importTokens,
1673
+ seq("import", fullPath, opt(";"), eolf$1).collect(importElem())
1674
+ )
1675
+ );
1676
+ any().map((r) => {
1677
+ const { kind: kind2, text: text2 } = r.value;
1678
+ const deepName = r.ctx._debugNames.join(" > ");
1679
+ resultLog(r, `??? ${kind2}: '${text2}' ${deepName}`);
1680
+ });
1681
+ const eolf = disablePreParse(
1682
+ makeEolf(argsTokens, argsTokens.ws)
1683
+ );
1684
+ const skipToEol = tokens(lineCommentTokens, anyThrough(eolf));
1685
+ const blockComment = seq(
1686
+ "/*",
1687
+ repeat(or(() => blockComment, anyNot("*/"))),
1688
+ req("*/")
1689
+ );
1690
+ const lineComment = seq(tokens(mainTokens, "//"), skipToEol);
1691
+ const comment = or(() => lineComment, blockComment).trace({
1692
+ hide: true
1693
+ });
1694
+ const word = or(
1695
+ kind(mainTokens.ident),
1696
+ kind(mainTokens.textureStorage)
1697
+ );
1698
+ withSepPlus("::", word);
1699
+ const diagnostic_rule_name = withSep(".", word, { requireOne: true });
1700
+ const diagnostic_control = seq(
1701
+ "(",
1702
+ word,
1703
+ ",",
1704
+ diagnostic_rule_name,
1705
+ opt(","),
1706
+ ")"
1707
+ );
1708
+ const word_list = seq("(", withSep(",", word, { requireOne: true }), ")");
1709
+ const attribute = seq(
1710
+ "@",
1711
+ req(
1712
+ or(
1713
+ // These attributes have no arguments
1714
+ or("compute", "const", "fragment", "invariant", "must_use", "vertex"),
1715
+ // These attributes have arguments, but the argument doesn't have any identifiers
1716
+ seq(
1717
+ or("interpolate", "builtin"),
1718
+ req(() => word_list)
1719
+ ),
1720
+ seq("diagnostic", diagnostic_control),
1721
+ // These are normal attributes
1722
+ seq(
1723
+ or(
1724
+ "workgroup_size",
1725
+ "align",
1726
+ "binding",
1727
+ "blend_src",
1728
+ "group",
1729
+ "id",
1730
+ "location",
1731
+ "size"
1732
+ ),
1733
+ req(() => argument_expression_list)
1734
+ ),
1735
+ // Everything else is also a normal attribute, it might have an expression list
1736
+ seq(
1737
+ word,
1738
+ opt(() => argument_expression_list)
1739
+ )
1740
+ )
1741
+ )
1742
+ );
1743
+ const argument_expression_list = seq(
1744
+ "(",
1745
+ withSep(",", () => expression),
1746
+ req(")")
1747
+ );
1748
+ const opt_attributes = repeat(attribute);
1749
+ const typeNameDecl = req(word.collect(declIdentElem, "typeName"));
1750
+ const fnNameDecl = req(
1751
+ word.collect(declIdentElem, "fnName"),
1752
+ "missing fn name"
1753
+ );
1754
+ const std_type_specifier = seq(
1755
+ word.collect(refIdent, "typeRef"),
1756
+ () => opt_template_list
1757
+ );
1758
+ const texture_storage_type = seq(
1759
+ kind(mainTokens.textureStorage),
1760
+ () => opt_template_words
1761
+ );
1762
+ const ptr_type = seq(
1763
+ "ptr",
1764
+ req("<"),
1765
+ word,
1766
+ req(","),
1767
+ () => template_arg_expression,
1768
+ opt(seq(",", word)),
1769
+ req(">")
1770
+ );
1771
+ const type_specifier = or(
1772
+ texture_storage_type,
1773
+ ptr_type,
1774
+ std_type_specifier
1775
+ );
1776
+ const optionally_typed_ident = seq(
1777
+ word.collect(declIdentElem, "declIdent"),
1778
+ opt(seq(":", type_specifier))
1779
+ );
1780
+ const req_optionally_typed_ident = req(optionally_typed_ident);
1781
+ const struct_member = seq(
1782
+ opt_attributes,
1783
+ word.collect(collectNameElem, "nameElem"),
1784
+ ":",
1785
+ req(type_specifier)
1786
+ ).collect(collectStructMember());
1787
+ const struct_decl = seq(
1788
+ "struct",
1789
+ req(typeNameDecl),
1790
+ seq(
1791
+ req("{"),
1792
+ withSepPlus(",", struct_member).ptag("members"),
1793
+ req("}")
1794
+ ).collect(scopeCollect(), "struct_scope")
1795
+ ).collect(collectStruct());
1796
+ const fn_call = seq(
1797
+ word.collect(refIdent, "fn_call.refIdent"),
1798
+ // we collect this in fnDecl, to attach to FnElem
1799
+ () => opt_template_list,
1800
+ argument_expression_list
1801
+ );
1802
+ const fnParam = tagScope(
1803
+ seq(
1804
+ opt_attributes,
1805
+ word.collect(declIdentElem, "paramName"),
1806
+ opt(seq(":", req(type_specifier)))
1807
+ ).collect(collectFnParam())
1808
+ ).ctag("fnParam");
1809
+ const fnParamList = seq("(", withSep(",", fnParam), ")");
1810
+ const local_variable_decl = seq(
1811
+ "var",
1812
+ () => opt_template_list,
1813
+ req_optionally_typed_ident,
1814
+ opt(seq("=", () => expression))
1815
+ ).collect(collectVarLike("var"), "variable_decl");
1816
+ const global_variable_decl = seq(
1817
+ "var",
1818
+ () => opt_template_words,
1819
+ req_optionally_typed_ident,
1820
+ opt(seq("=", () => expression.collect(scopeCollect(), "decl_scope")))
1821
+ );
1822
+ const opt_template_list = opt(
1823
+ seq(
1824
+ tokens(bracketTokens, "<"),
1825
+ withSepPlus(",", () => template_arg_expression),
1826
+ tokens(bracketTokens, ">")
1827
+ )
1828
+ );
1829
+ const opt_template_words = opt(
1830
+ seq(
1831
+ tokens(bracketTokens, "<"),
1832
+ withSepPlus(",", () => word),
1833
+ tokens(bracketTokens, ">")
1834
+ )
1835
+ );
1836
+ const template_elaborated_ident = seq(
1837
+ word.collect(refIdent),
1838
+ opt_template_list
1839
+ );
1840
+ const literal = or("true", "false", kind(mainTokens.digits));
1841
+ const paren_expression = seq("(", () => expression, req(")"));
1842
+ const call_expression = seq(
1843
+ template_elaborated_ident,
1844
+ argument_expression_list
1845
+ );
1846
+ const primary_expression = or(
1847
+ literal,
1848
+ paren_expression,
1849
+ call_expression,
1850
+ template_elaborated_ident
1851
+ );
1852
+ const component_or_swizzle = repeatPlus(
1853
+ or(
1854
+ seq(".", word),
1855
+ seq("[", () => expression, req("]"))
1856
+ )
1857
+ );
1858
+ const makeExpressionOperator = (isTemplate) => {
1859
+ const allowedOps = ("& | ^ << <= < != == % * / + -" + (isTemplate ? "" : " && || >> >= >")).split(" ");
1860
+ return or(...allowedOps);
1861
+ };
1862
+ const unary_expression = or(
1863
+ seq(or(..."! & * - ~".split(" ")), () => unary_expression),
1864
+ seq(primary_expression, opt(component_or_swizzle))
1865
+ );
1866
+ const makeExpression = (isTemplate) => {
1867
+ return seq(
1868
+ unary_expression,
1869
+ repeat(seq(makeExpressionOperator(isTemplate), unary_expression))
1870
+ );
1871
+ };
1872
+ const expression = makeExpression(false);
1873
+ const template_arg_expression = makeExpression(true);
1874
+ const unscoped_compound_statement = seq(
1875
+ opt_attributes,
1876
+ text("{"),
1877
+ repeat(() => statement),
1878
+ req("}")
1879
+ );
1880
+ const compound_statement = seq(
1881
+ opt_attributes,
1882
+ seq(
1883
+ text("{"),
1884
+ repeat(() => statement),
1885
+ req("}")
1886
+ ).collect(scopeCollect())
1887
+ );
1888
+ const for_init = or(
1889
+ fn_call,
1890
+ () => variable_or_value_statement,
1891
+ () => variable_updating_statement
1892
+ );
1893
+ const for_update = or(fn_call, () => variable_updating_statement);
1894
+ const for_statement = seq(
1895
+ opt_attributes,
1896
+ "for",
1897
+ seq(
1898
+ req("("),
1899
+ opt(for_init),
1900
+ req(";"),
1901
+ opt(expression),
1902
+ req(";"),
1903
+ opt(for_update),
1904
+ req(")"),
1905
+ unscoped_compound_statement
1906
+ ).collect(scopeCollect())
1907
+ );
1908
+ const if_statement = seq(
1909
+ opt_attributes,
1910
+ "if",
1911
+ req(seq(expression, compound_statement)),
1912
+ repeat(seq("else", "if", req(seq(expression, compound_statement)))),
1913
+ opt(seq("else", req(compound_statement)))
1914
+ );
1915
+ const loop_statement = seq(
1916
+ opt_attributes,
1917
+ "loop",
1918
+ opt_attributes,
1919
+ req(
1920
+ seq(
1921
+ "{",
1922
+ repeat(() => statement),
1923
+ opt(
1924
+ seq(
1925
+ "continuing",
1926
+ opt_attributes,
1927
+ "{",
1928
+ repeat(() => statement),
1929
+ opt(seq("break", "if", expression, ";")),
1930
+ "}"
1931
+ )
1932
+ ),
1933
+ "}"
1934
+ )
1935
+ )
1936
+ );
1937
+ const case_selector = or("default", expression);
1938
+ const switch_clause = or(
1939
+ seq(
1940
+ "case",
1941
+ withSep(",", case_selector, { requireOne: true }),
1942
+ opt(":"),
1943
+ compound_statement
1944
+ ),
1945
+ seq("default", opt(":"), compound_statement)
1946
+ );
1947
+ const switch_body = seq(opt_attributes, "{", repeatPlus(switch_clause), "}");
1948
+ const switch_statement = seq(opt_attributes, "switch", expression, switch_body);
1949
+ const while_statement = seq(
1950
+ opt_attributes,
1951
+ "while",
1952
+ expression,
1953
+ compound_statement
1954
+ );
1955
+ const statement = or(
1956
+ for_statement,
1957
+ if_statement,
1958
+ loop_statement,
1959
+ switch_statement,
1960
+ while_statement,
1961
+ compound_statement,
1962
+ seq("break", ";"),
1963
+ seq("continue", ";"),
1964
+ seq(";"),
1965
+ () => const_assert,
1966
+ seq("discard", ";"),
1967
+ seq("return", opt(expression), ";"),
1968
+ seq(fn_call, ";"),
1969
+ seq(() => variable_or_value_statement, ";"),
1970
+ seq(() => variable_updating_statement, ";")
1971
+ );
1972
+ const lhs_expression = or(
1973
+ seq(word.collect(refIdent), opt(component_or_swizzle)),
1974
+ seq("(", () => lhs_expression, ")", opt(component_or_swizzle)),
1975
+ seq("&", () => lhs_expression),
1976
+ seq("*", () => lhs_expression)
1977
+ );
1978
+ const variable_or_value_statement = or(
1979
+ // Also covers the = expression case
1980
+ local_variable_decl,
1981
+ seq("const", req_optionally_typed_ident, req("="), expression),
1982
+ seq("let", req_optionally_typed_ident, req("="), expression)
1983
+ );
1984
+ const variable_updating_statement = or(
1985
+ seq(
1986
+ lhs_expression,
1987
+ or("=", "<<=", ">>=", "%=", "&=", "*=", "+=", "-=", "/=", "^=", "|="),
1988
+ // TODO: try making this a lexer rule instead of a parser rule
1989
+ expression
1990
+ ),
1991
+ seq(lhs_expression, or("++", "--")),
1992
+ seq("_", "=", expression)
1993
+ );
1994
+ const fn_decl = seq(
1995
+ opt_attributes,
1996
+ text("fn"),
1997
+ req(fnNameDecl),
1998
+ seq(
1999
+ req(fnParamList),
2000
+ opt(seq("->", opt_attributes, type_specifier.ctag("returnType"))),
2001
+ req(unscoped_compound_statement)
2002
+ ).collect(scopeCollect(), "body_scope")
2003
+ ).collect(collectFn());
2004
+ const global_value_decl = or(
2005
+ seq(
2006
+ opt_attributes,
2007
+ "override",
2008
+ optionally_typed_ident,
2009
+ seq(opt(seq("=", expression.collect(scopeCollect(), "decl_scope")))),
2010
+ ";"
2011
+ ).collect(collectVarLike("override")),
2012
+ seq(
2013
+ "const",
2014
+ optionally_typed_ident,
2015
+ "=",
2016
+ seq(expression).collect(scopeCollect(), "decl_scope"),
2017
+ ";"
2018
+ ).collect(collectVarLike("const"))
2019
+ );
2020
+ const global_alias = seq(
2021
+ "alias",
2022
+ req(word).collect(declIdentElem, "declIdent"),
2023
+ req("="),
2024
+ req(type_specifier).collect(scopeCollect(), "decl_scope"),
2025
+ req(";")
2026
+ ).collect(collectVarLike("alias"), "global_alias");
2027
+ const const_assert = seq("const_assert", req(expression), ";").collect(
2028
+ collectSimpleElem("assert")
2029
+ );
2030
+ const global_directive = seq(
2031
+ or(
2032
+ seq("diagnostic", diagnostic_control),
2033
+ seq("enable", withSep(",", word, { requireOne: true })),
2034
+ seq("requires", withSep(",", word, { requireOne: true }))
2035
+ ),
2036
+ ";"
2037
+ );
2038
+ const global_decl = tagScope(
2039
+ or(
2040
+ fn_decl,
2041
+ seq(opt_attributes, global_variable_decl, ";").collect(
2042
+ collectVarLike("gvar"),
2043
+ "g_variable_decl"
2044
+ ),
2045
+ global_value_decl,
2046
+ ";",
2047
+ global_alias,
2048
+ const_assert,
2049
+ struct_decl
2050
+ )
2051
+ );
2052
+ const end = tokenSkipSet(null, seq(repeat(kind(mainTokens.ws)), eof()));
2053
+ const weslRoot = preParse(
2054
+ comment,
2055
+ seq(
2056
+ repeat(weslImport),
2057
+ repeat(or(global_directive, weslImport)),
2058
+ repeat(or(global_decl, weslImport)),
2059
+ req(end)
2060
+ ).collect(collectModule(), "collectModule")
2061
+ );
2062
+ function flattenTreeImport(imp) {
2063
+ return recursiveResolve([], [], imp.segments);
2064
+ function recursiveResolve(resolvedImportPath, resolvedExportPath, remainingPath) {
2065
+ const [segment, ...rest] = remainingPath;
2066
+ if (segment === void 0) {
2067
+ throw new Error(`undefined segment ${imp.segments}`);
2068
+ }
2069
+ if (segment instanceof SimpleSegment) {
2070
+ const importPath = [...resolvedImportPath, segment.as || segment.name];
2071
+ const modulePath = [...resolvedExportPath, segment.name];
2072
+ if (rest.length) {
2073
+ return recursiveResolve(importPath, modulePath, rest);
2074
+ } else {
2075
+ return [{ importPath, modulePath }];
2076
+ }
2077
+ }
2078
+ if (segment instanceof SegmentList) {
2079
+ return segment.list.flatMap((elem) => {
2080
+ const rPath = [elem, ...rest];
2081
+ return recursiveResolve(resolvedImportPath, resolvedExportPath, rPath);
2082
+ });
2083
+ } else if (segment instanceof ImportTree) {
2084
+ return recursiveResolve(
2085
+ resolvedImportPath,
2086
+ resolvedExportPath,
2087
+ segment.segments
2088
+ );
2089
+ }
2090
+ return [];
2091
+ }
2092
+ }
2093
+ function parseSrcModule(srcModule, srcMap, maxParseCount = void 0) {
2094
+ resetScopeIds();
2095
+ const lexer = matchingLexer(srcModule.src, mainTokens);
2096
+ const appState = blankWeslParseState(srcModule);
2097
+ const init = { lexer, appState, srcMap, maxParseCount };
2098
+ const parseResult = weslRoot.parse(init);
2099
+ if (parseResult === null) {
2100
+ throw new Error("parseWESL failed");
2101
+ }
2102
+ return appState.stable;
2103
+ }
2104
+ function parseWESL(src, srcMap, maxParseCount = void 0) {
2105
+ const srcModule = {
2106
+ modulePath: "package::test",
2107
+ filePath: "./test.wesl",
2108
+ src
2109
+ };
2110
+ return parseSrcModule(srcModule, srcMap, maxParseCount);
2111
+ }
2112
+ function blankWeslParseState(srcModule) {
2113
+ const rootScope = emptyScope("module-scope");
2114
+ const moduleElem = null;
2115
+ return {
2116
+ context: { scope: rootScope, openElems: [] },
2117
+ stable: { srcModule, imports: [], rootScope, moduleElem }
2118
+ };
2119
+ }
2120
+ function syntheticWeslParseState() {
2121
+ const srcModule = {
2122
+ modulePath: "package::test",
2123
+ filePath: "./test.wesl",
2124
+ src: ""
2125
+ };
2126
+ return blankWeslParseState(srcModule);
2127
+ }
2128
+ function flatImports(ast) {
2129
+ if (ast._flatImports) return ast._flatImports;
2130
+ const flat = ast.imports.flatMap(flattenTreeImport);
2131
+ ast._flatImports = flat;
2132
+ return flat;
2133
+ }
2134
+ const stdFns = `bitcast all any select arrayLength
2135
+ abs acos acosh asin asinh atan atanh atan2 ceil clamp cos cosh
2136
+ countLeadingZeros countOneBits countTrailingZeros cross
2137
+ degrees determinant distance dot dot4UI8Packed dot4I8Packed
2138
+ exp exp2 extractBits faceForward firstLeadingBit firstTrailingBit
2139
+ floor fma fract frexp inserBits inverseSqrt ldexp length log log2
2140
+ max min mix modf normalize pow quantizeToF16 radians reflect refract
2141
+ reverseBits round saturate sign sin sinh smoothstep sqrt step tan tanh
2142
+ transpose trunc
2143
+ dpdx dpdxCoarse dpdxFine dpdy dpdyCoarse dpdyFine fwidth
2144
+ fwdithCoarse fwidthFine
2145
+ textureDimensions textureGather textureGatherCompare textureLoad
2146
+ textureNumLayers textureNumLevels textureNumSamples
2147
+ textureSample textureSampleBias textureSampleCompare textureSampleCompareLevel
2148
+ textureSampleGrad textureSampleLevel textureSampleBaseClampToEdge
2149
+ textureStore
2150
+ atomicLoad atomicStore atomicAdd atomicSub atomicMax atomicMin
2151
+ atomicOr atomicXor atomicExchange atomicCompareExchangeWeak
2152
+ pack4x8snorm pack4x8unorm pack4xI8 pack4xU8 pack4xI8Clamp pack4xU8Clamp
2153
+ pack2x16snorm pack2x16unorm pack2x16float
2154
+ unpack4x8snorm unpack4x8unorm unpack4xI8 unpack4xU8
2155
+ unpack2x16snorm unpack2x16unorm unpack2x16float
2156
+ storageBarrier textureBarrier workgroupBarrier workgroupUniformLoad
2157
+ `.split(/\s+/);
2158
+ const stdTypes = `array atomic bool f16 f32 i32
2159
+ mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4
2160
+ mat2x2f mat2x3f mat2x4f mat3x2f mat3x3f mat3x4f
2161
+ mat4x2f mat4x3f mat4x4f
2162
+ mat2x2h mat2x3h mat2x4h mat3x2h mat3x3h mat3x4h
2163
+ mat4x2h mat4x3h mat4x4h
2164
+ u32 vec2 vec3 vec4 ptr
2165
+ vec2i vec3i vec4i vec2u vec3u vec4u
2166
+ vec2f vec3f vec4f vec2h vec3h vec4h
2167
+ texture_1d texture_2d texture_2d_array texture_3d
2168
+ texture_cube texture_cube_array
2169
+ texture_multisampled_2d texture_depth_multisampled_2d
2170
+ texture_external
2171
+ texture_storage_1d texture_storage_2d texture_storage_2d_array
2172
+ texture_storage_3d
2173
+ texture_depth_2d texture_depth_2d_array texture_depth_cube
2174
+ texture_depth_cube_array
2175
+ sampler sampler_comparison
2176
+ rgba8unorm rgba8snorm rgba8uint rgba8sint
2177
+ rgba16uint rgba16sint rgba16float
2178
+ r32uint r32sint r32float rg32uint rg32sint rg32float
2179
+ rgba32uint rgba32sint rgba32float
2180
+ bgra8unorm
2181
+ function uniform
2182
+ `.split(/\s+/);
2183
+ function stdType(name) {
2184
+ return stdTypes.includes(name);
2185
+ }
2186
+ function stdFn(name) {
2187
+ return stdFns.includes(name) || stdType(name);
2188
+ }
2189
+ function multiKeySet(m, a, b, v) {
2190
+ const bMap = m.get(a) || /* @__PURE__ */ new Map();
2191
+ m.set(a, bMap);
2192
+ bMap.set(b, v);
2193
+ }
2194
+ const tokenRegex = /\b(\w+)\b/gi;
2195
+ function replaceWords(text2, replace) {
2196
+ return text2.replaceAll(tokenRegex, (s) => s in replace ? replace[s] : s);
2197
+ }
2198
+ function grouped(a, size, stride = size) {
2199
+ const groups = [];
2200
+ for (let i = 0; i < a.length; i += stride) {
2201
+ groups.push(a.slice(i, i + size));
2202
+ }
2203
+ return groups;
2204
+ }
2205
+ function groupBy(a, key) {
2206
+ const groups = /* @__PURE__ */ new Map();
2207
+ for (const t of a) {
2208
+ const k = key(t);
2209
+ const group = groups.get(k) || [];
2210
+ group.push(t);
2211
+ groups.set(k, group);
2212
+ }
2213
+ return groups;
2214
+ }
2215
+ function partition(a, partFn) {
2216
+ const yesPart = [];
2217
+ const noPart = [];
2218
+ for (const t of a) {
2219
+ if (partFn(t)) yesPart.push(t);
2220
+ else noPart.push(t);
2221
+ }
2222
+ return [yesPart, noPart];
2223
+ }
2224
+ function scan(array, fn2, zero) {
2225
+ const result = [zero];
2226
+ let current = zero;
2227
+ for (let i = 0; i < array.length; i++) {
2228
+ current = fn2(array[i], current);
2229
+ result.push(current);
2230
+ }
2231
+ return result;
2232
+ }
2233
+ function mapForward(a, b) {
2234
+ const combined = Object.entries(a).map(([key, value]) => {
2235
+ const mappedValue = value in b ? b[value] : value;
2236
+ return [key, mappedValue];
2237
+ });
2238
+ return Object.fromEntries(combined);
2239
+ }
2240
+ function last(a) {
2241
+ return a[a.length - 1];
2242
+ }
2243
+ function overlapTail(a, b) {
2244
+ let overlapSize = Math.min(a.length, b.length);
2245
+ while (overlapSize > 0) {
2246
+ const suffix = a.slice(-overlapSize);
2247
+ const prefix = b.slice(0, overlapSize);
2248
+ if (arrayEquals(suffix, prefix)) {
2249
+ break;
2250
+ } else {
2251
+ overlapSize--;
2252
+ }
2253
+ }
2254
+ if (overlapSize) {
2255
+ return b.slice(overlapSize);
2256
+ }
2257
+ }
2258
+ function arrayEquals(a, b) {
2259
+ return a.length === b.length && a.every((val, index) => val === b[index]);
2260
+ }
2261
+ function bindIdents(ast, parsed, conditions) {
2262
+ const { rootScope } = ast;
2263
+ const globalNames = /* @__PURE__ */ new Set();
2264
+ const knownDecls = /* @__PURE__ */ new Set();
2265
+ rootScope.idents.forEach((ident2) => {
2266
+ if (ident2.kind === "decl") {
2267
+ ident2.mangledName = ident2.originalName;
2268
+ globalNames.add(ident2.originalName);
2269
+ knownDecls.add(ident2);
2270
+ }
2271
+ });
2272
+ const bindContext = {
2273
+ parsed,
2274
+ conditions,
2275
+ knownDecls,
2276
+ foundScopes: /* @__PURE__ */ new Set(),
2277
+ globalNames
2278
+ };
2279
+ const decls = bindIdentsRecursive(rootScope, bindContext);
2280
+ return decls.flatMap(
2281
+ (d) => d.declElem && isGlobal(d.declElem) ? [d.declElem] : []
2282
+ );
2283
+ }
2284
+ function bindIdentsRecursive(scope, bindContext) {
2285
+ const { foundScopes } = bindContext;
2286
+ if (foundScopes.has(scope)) return [];
2287
+ foundScopes.add(scope);
2288
+ const { parsed, conditions } = bindContext;
2289
+ const { globalNames, knownDecls } = bindContext;
2290
+ const newDecls = [];
2291
+ scope.idents.forEach((ident2) => {
2292
+ if (ident2.kind === "ref") {
2293
+ if (!ident2.refersTo && !ident2.std) {
2294
+ if (stdWgsl(ident2.originalName)) {
2295
+ ident2.std = true;
2296
+ } else {
2297
+ let foundDecl = findDeclInModule(ident2.scope, ident2) ?? findDeclImport(ident2, parsed);
2298
+ if (foundDecl) {
2299
+ ident2.refersTo = foundDecl;
2300
+ if (!knownDecls.has(foundDecl)) {
2301
+ knownDecls.add(foundDecl);
2302
+ setDisplayName(ident2.originalName, foundDecl, globalNames);
2303
+ if (foundDecl.declElem && isGlobal(foundDecl.declElem)) {
2304
+ newDecls.push(foundDecl);
2305
+ }
2306
+ }
2307
+ } else {
2308
+ const { refIdentElem } = ident2;
2309
+ if (refIdentElem) {
2310
+ const { srcModule, start, end: end2 } = refIdentElem;
2311
+ const { filePath } = srcModule;
2312
+ const msg = `unresolved identifier in file: ${filePath}`;
2313
+ srcLog(srcModule.src, [start, end2], msg);
2314
+ }
2315
+ }
2316
+ }
2317
+ }
2318
+ }
2319
+ });
2320
+ const newFromChildren = scope.children.flatMap((child) => {
2321
+ return bindIdentsRecursive(child, bindContext);
2322
+ });
2323
+ const newFromRefs = newDecls.flatMap((decl) => {
2324
+ return bindIdentsRecursive(decl.scope, bindContext);
2325
+ });
2326
+ return [newDecls, newFromChildren, newFromRefs].flat();
2327
+ }
2328
+ function setDisplayName(proposedName, decl, globalNames) {
2329
+ if (!decl.mangledName) {
2330
+ if (decl.declElem && isGlobal(decl.declElem)) {
2331
+ decl.mangledName = declUniqueName(proposedName, globalNames);
2332
+ } else {
2333
+ decl.mangledName = decl.originalName;
2334
+ }
2335
+ }
2336
+ }
2337
+ function stdWgsl(name) {
2338
+ return stdType(name) || stdFn(name);
2339
+ }
2340
+ function findDeclInModule(scope, ident2) {
2341
+ const { parent } = scope;
2342
+ const { originalName } = ident2;
2343
+ const found = scope.idents.find(
2344
+ (i) => i.kind === "decl" && i.originalName === originalName
2345
+ );
2346
+ if (found) return found;
2347
+ if (parent) {
2348
+ return findDeclInModule(parent, ident2);
2349
+ }
2350
+ }
2351
+ function findDeclImport(refIdent2, parsed) {
2352
+ const flatImps = flatImports(refIdent2.ast);
2353
+ const modulePathParts = matchingImport(refIdent2, flatImps);
2354
+ if (modulePathParts) {
2355
+ return findExport(modulePathParts, parsed);
2356
+ }
2357
+ }
2358
+ function matchingImport(ident2, flatImports2) {
2359
+ const identParts = ident2.originalName.split("::");
2360
+ for (const flat of flatImports2) {
2361
+ const impTail = overlapTail(flat.importPath, identParts);
2362
+ if (impTail) {
2363
+ return [...flat.modulePath, ...impTail];
2364
+ }
2365
+ }
2366
+ }
2367
+ function findExport(modulePathParts, parsed) {
2368
+ const legacyConvert = modulePathParts.map((p) => p === "." ? "package" : p);
2369
+ const modulePath = legacyConvert.slice(0, -1).join("::");
2370
+ const module2 = parsed.modules[modulePath];
2371
+ if (!module2) {
2372
+ console.log(
2373
+ `ident ${modulePathParts.join("::")} in import statement, but module not found`
2374
+ );
2375
+ }
2376
+ return exportDecl(module2.rootScope, last(modulePathParts));
2377
+ }
2378
+ function declUniqueName(proposedName, rootNames) {
2379
+ const displayName2 = uniquifyName(proposedName, rootNames);
2380
+ rootNames.add(displayName2);
2381
+ return displayName2;
2382
+ }
2383
+ function uniquifyName(proposedName, rootNames) {
2384
+ let renamed = proposedName;
2385
+ let conflicts = 0;
2386
+ while (rootNames.has(renamed)) {
2387
+ renamed = proposedName + conflicts++;
2388
+ }
2389
+ return renamed;
2390
+ }
2391
+ function isGlobal(elem) {
2392
+ return ["alias", "const", "override", "fn", "struct", "gvar"].includes(
2393
+ elem.kind
2394
+ );
2395
+ }
2396
+ function lowerAndEmit(srcBuilder, rootElems, conditions, extracting = true) {
2397
+ const emitContext = { conditions, srcBuilder, extracting };
2398
+ lowerAndEmitRecursive(rootElems, emitContext);
2399
+ }
2400
+ function lowerAndEmitRecursive(elems, emitContext) {
2401
+ const validElems = elems.filter(
2402
+ (e) => conditionsValid()
2403
+ );
2404
+ validElems.forEach((e) => lowerAndEmitElem(e, emitContext));
2405
+ }
2406
+ function lowerAndEmitElem(e, ctx) {
2407
+ switch (e.kind) {
2408
+ case "import":
2409
+ return;
2410
+ // drop imports statements from emitted text
2411
+ case "fn":
2412
+ case "struct":
2413
+ case "override":
2414
+ case "const":
2415
+ case "assert":
2416
+ case "alias":
2417
+ case "gvar":
2418
+ if (ctx.extracting) {
2419
+ ctx.srcBuilder.addNl();
2420
+ ctx.srcBuilder.addNl();
2421
+ }
2422
+ return emitContents(e, ctx);
2423
+ case "text":
2424
+ return emitText(e, ctx);
2425
+ case "ref":
2426
+ case "decl":
2427
+ return emitIdent(e, ctx);
2428
+ case "param":
2429
+ case "var":
2430
+ case "module":
2431
+ case "member":
2432
+ return emitContents(e, ctx);
2433
+ case "name":
2434
+ return emitName(e, ctx);
2435
+ default:
2436
+ const kind2 = e.kind;
2437
+ console.log("NYI for emit, elem kind:", kind2);
2438
+ throw new Error(`NYI emit elem kind: ${kind2}`);
2439
+ }
2440
+ }
2441
+ function emitText(e, ctx) {
2442
+ ctx.srcBuilder.addCopy(e.srcModule.src, e.start, e.end);
2443
+ }
2444
+ function emitName(e, ctx) {
2445
+ ctx.srcBuilder.add(e.name, e.srcModule.src, e.start, e.end);
2446
+ }
2447
+ function emitContents(elem, ctx) {
2448
+ elem.contents.forEach((e) => lowerAndEmitElem(e, ctx));
2449
+ }
2450
+ function emitIdent(e, ctx) {
2451
+ if (e.ident.std) {
2452
+ ctx.srcBuilder.add(e.ident.originalName, e.srcModule.src, e.start, e.end);
2453
+ } else {
2454
+ const declIdent = findDecl(e.ident);
2455
+ const mangledName = displayName(declIdent);
2456
+ ctx.srcBuilder.add(mangledName, e.srcModule.src, e.start, e.end);
2457
+ }
2458
+ }
2459
+ function displayName(declIdent) {
2460
+ if (declIdent.declElem && isGlobal(declIdent.declElem)) {
2461
+ const mangledName = declIdent.mangledName;
2462
+ return mangledName;
2463
+ }
2464
+ return declIdent.mangledName || declIdent.originalName;
2465
+ }
2466
+ function findDecl(ident2) {
2467
+ let i = ident2;
2468
+ do {
2469
+ if (i.kind === "decl") {
2470
+ return i;
2471
+ }
2472
+ i = i.refersTo;
2473
+ } while (i);
2474
+ throw new Error(
2475
+ `unresolved ident: ${ident2.originalName} (bug in bindIdents?)`
2476
+ );
2477
+ }
2478
+ function conditionsValid(elem, conditions) {
2479
+ return true;
2480
+ }
2481
+ function relativePath(srcPath, reqPath) {
2482
+ if (!srcPath) return reqPath;
2483
+ const srcDir = dirname(srcPath);
2484
+ const relative = join(srcDir, reqPath);
2485
+ return relative;
2486
+ }
2487
+ function dirname(path) {
2488
+ const lastSlash = path.lastIndexOf("/");
2489
+ if (lastSlash === -1) return ".";
2490
+ return path.slice(0, lastSlash);
2491
+ }
2492
+ function join(a, b) {
2493
+ const joined = b.startsWith("/") ? a + b : a + "/" + b;
2494
+ return normalize(joined);
2495
+ }
2496
+ function normalize(path) {
2497
+ const segments = path.split("/");
2498
+ const noDots = segments.filter((s) => s !== ".");
2499
+ const noDbl = [];
2500
+ noDots.forEach((s) => {
2501
+ if (s !== "") {
2502
+ if (s === ".." && noDbl.length && noDbl[noDbl.length - 1] !== "..") {
2503
+ noDbl.pop();
2504
+ } else {
2505
+ noDbl.push(s);
2506
+ }
2507
+ }
2508
+ });
2509
+ return noDbl.join("/");
2510
+ }
2511
+ function noSuffix(path) {
2512
+ const lastSlash = path.lastIndexOf("/");
2513
+ const lastStart = lastSlash === -1 ? 0 : lastSlash + 1;
2514
+ const suffix = path.indexOf(".", lastStart);
2515
+ const suffixStart = suffix === -1 ? path.length : suffix;
2516
+ return path.slice(0, suffixStart);
2517
+ }
2518
+ function parsedRegistry() {
2519
+ return { modules: {} };
2520
+ }
2521
+ function parseWeslSrc(src) {
2522
+ const parsedEntries = Object.entries(src).map(([path, src2]) => {
2523
+ const weslAST = parseWESL(src2);
2524
+ return [path, weslAST];
2525
+ });
2526
+ return { modules: Object.fromEntries(parsedEntries) };
2527
+ }
2528
+ function selectModule(parsed, selectPath, packageName = "package") {
2529
+ let modulePath;
2530
+ if (selectPath.includes("::")) {
2531
+ modulePath = selectPath;
2532
+ } else if (selectPath.includes("/")) {
2533
+ modulePath = fileToModulePath(selectPath, packageName);
2534
+ } else {
2535
+ modulePath = packageName + "::" + selectPath;
2536
+ }
2537
+ return parsed.modules[modulePath];
2538
+ }
2539
+ function parseIntoRegistry(srcFiles, registry, packageName = "package", maxParseCount) {
2540
+ const srcModules = Object.entries(srcFiles).map(
2541
+ ([filePath, src]) => {
2542
+ const modulePath = fileToModulePath(filePath, packageName);
2543
+ return { modulePath, filePath, src };
2544
+ }
2545
+ );
2546
+ srcModules.forEach((mod) => {
2547
+ const parsed = parseSrcModule(mod, void 0, maxParseCount);
2548
+ if (registry.modules[mod.modulePath]) {
2549
+ throw new Error(`duplicate module path: '${mod.modulePath}'`);
2550
+ }
2551
+ registry.modules[mod.modulePath] = parsed;
2552
+ });
2553
+ }
2554
+ function parseLibsIntoRegistry(libs, registry) {
2555
+ libs.forEach(
2556
+ ({ modules, name }) => parseIntoRegistry(modules, registry, name)
2557
+ );
2558
+ }
2559
+ const libExp = /^lib\.w[eg]sl$/i;
2560
+ function fileToModulePath(filePath, packageName) {
2561
+ if (packageName !== "package" && libExp.test(filePath)) {
2562
+ return packageName;
2563
+ }
2564
+ const strippedPath = noSuffix(normalize(filePath));
2565
+ const moduleSuffix = strippedPath.replaceAll("/", "::");
2566
+ const modulePath = packageName + "::" + moduleSuffix;
2567
+ return modulePath;
2568
+ }
2569
+ function linkWesl(weslSrc, rootModuleName = "main", conditions = {}) {
2570
+ const parsed = parseWeslSrc(weslSrc);
2571
+ return linkRegistry(parsed, rootModuleName, conditions);
2572
+ }
2573
+ function linkWeslFiles(weslSrc, rootModuleName = "main", conditions = {}, libs = [], maxParseCount) {
2574
+ const registry = parsedRegistry();
2575
+ parseIntoRegistry(weslSrc, registry, "package", maxParseCount);
2576
+ parseLibsIntoRegistry(libs, registry);
2577
+ return linkRegistry(registry, rootModuleName, conditions);
2578
+ }
2579
+ function linkRegistry(parsed, rootModuleName = "main", conditions = {}) {
2580
+ const found = selectModule(parsed, rootModuleName);
2581
+ if (!found) {
2582
+ throw new Error(`Root module not found: ${rootModuleName}`);
2583
+ }
2584
+ const { moduleElem: rootModule } = found;
2585
+ const newDecls = bindIdents(found, parsed, conditions);
2586
+ const srcBuilder = new SrcMapBuilder();
2587
+ lowerAndEmit(srcBuilder, [rootModule], conditions, false);
2588
+ lowerAndEmit(srcBuilder, newDecls, conditions);
2589
+ return srcBuilder.build();
2590
+ }
2591
+ exports.astToString = astToString;
2592
+ exports.blankWeslParseState = blankWeslParseState;
2593
+ exports.dirname = dirname;
2594
+ exports.elemToString = elemToString;
2595
+ exports.flatImports = flatImports;
2596
+ exports.groupBy = groupBy;
2597
+ exports.grouped = grouped;
2598
+ exports.identToString = identToString;
2599
+ exports.join = join;
2600
+ exports.last = last;
2601
+ exports.linkRegistry = linkRegistry;
2602
+ exports.linkWesl = linkWesl;
2603
+ exports.linkWeslFiles = linkWeslFiles;
2604
+ exports.mapForward = mapForward;
2605
+ exports.multiKeySet = multiKeySet;
2606
+ exports.noSuffix = noSuffix;
2607
+ exports.normalize = normalize;
2608
+ exports.overlapTail = overlapTail;
2609
+ exports.parseSrcModule = parseSrcModule;
2610
+ exports.parseWESL = parseWESL;
2611
+ exports.partition = partition;
2612
+ exports.relativePath = relativePath;
2613
+ exports.replaceWords = replaceWords;
2614
+ exports.scan = scan;
2615
+ exports.scopeToString = scopeToString;
2616
+ exports.syntheticWeslParseState = syntheticWeslParseState;
2617
+ //# sourceMappingURL=index.cjs.map