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.
- package/dist/index.cjs +2617 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +2617 -0
- package/dist/index.js.map +1 -0
- package/dist/linker/packages/linker/src/AbstractElems.d.ts +104 -0
- package/dist/linker/packages/linker/src/BindIdents.d.ts +16 -0
- package/dist/linker/packages/linker/src/CommentsGrammar.d.ts +6 -0
- package/dist/linker/packages/linker/src/FlattenTreeImport.d.ts +11 -0
- package/dist/linker/packages/linker/src/ImportGrammar.d.ts +13 -0
- package/dist/linker/packages/linker/src/ImportTree.d.ts +17 -0
- package/dist/linker/packages/linker/src/Linker.d.ts +26 -0
- package/dist/linker/packages/linker/src/LowerAndEmit.d.ts +25 -0
- package/dist/linker/packages/linker/src/ParseWESL.d.ts +36 -0
- package/dist/linker/packages/linker/src/ParsedRegistry.d.ts +26 -0
- package/dist/linker/packages/linker/src/PathUtil.d.ts +9 -0
- package/dist/linker/packages/linker/src/Scope.d.ts +55 -0
- package/dist/linker/packages/linker/src/Slicer.d.ts +26 -0
- package/dist/linker/packages/linker/src/StandardTypes.d.ts +6 -0
- package/dist/linker/packages/linker/src/Util.d.ts +26 -0
- package/dist/linker/packages/linker/src/WESLCollect.d.ts +29 -0
- package/dist/linker/packages/linker/src/WESLGrammar.d.ts +23 -0
- package/dist/linker/packages/linker/src/WESLTokens.d.ts +42 -0
- package/dist/linker/packages/linker/src/WgslBundle.d.ts +13 -0
- package/dist/linker/packages/linker/src/debug/ASTtoString.d.ts +3 -0
- package/dist/linker/packages/linker/src/debug/ImportToString.d.ts +2 -0
- package/dist/linker/packages/linker/src/debug/LineWrapper.d.ts +21 -0
- package/dist/linker/packages/linker/src/debug/ScopeToString.d.ts +4 -0
- package/dist/linker/packages/linker/src/index.d.ts +7 -0
- package/dist/linker/packages/linker/src/test/ErrorLogging.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Expression.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/FlattenTreeImport.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ImportCases.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ImportSyntaxCases.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/LinkGlob.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/LinkPackage.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Linker.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/MatchWgslD.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ParseComments.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ParseWESL.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/PathUtil.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/PrettyGrammar.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ScopeWESL.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Slicer.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/TestSetup.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/TestUtil.d.ts +15 -0
- package/dist/linker/packages/linker/src/test/Util.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/WgslTests.d.ts +0 -0
- package/dist/linker/packages/linker/src/test/shared/StringUtil.d.ts +8 -0
- package/dist/linker/packages/linker/src/test/shared/test/StringUtil.test.d.ts +1 -0
- package/dist/minified.cjs +2 -0
- package/dist/minified.cjs.map +1 -0
- package/dist/minified.js +2617 -0
- package/dist/minified.js.map +1 -0
- package/dist/wesl-testsuite/src/test-cases/BulkTests.d.ts +4 -0
- package/dist/wesl-testsuite/src/test-cases/ImportCases.d.ts +3 -0
- package/dist/wesl-testsuite/src/test-cases/ImportSyntaxCases.d.ts +3 -0
- package/package.json +45 -0
- package/src/AbstractElems.ts +148 -0
- package/src/BindIdents.ts +277 -0
- package/src/CommentsGrammar.ts +44 -0
- package/src/FlattenTreeImport.ts +59 -0
- package/src/ImportGrammar.ts +142 -0
- package/src/ImportTree.ts +19 -0
- package/src/Linker.ts +151 -0
- package/src/LowerAndEmit.ts +143 -0
- package/src/ParseWESL.ts +106 -0
- package/src/ParsedRegistry.ts +97 -0
- package/src/PathUtil.ts +52 -0
- package/src/Scope.ts +100 -0
- package/src/Slicer.ts +127 -0
- package/src/StandardTypes.ts +66 -0
- package/src/Util.ts +112 -0
- package/src/WESLCollect.ts +336 -0
- package/src/WESLGrammar.ts +538 -0
- package/src/WESLTokens.ts +97 -0
- package/src/WgslBundle.ts +16 -0
- package/src/debug/ASTtoString.ts +149 -0
- package/src/debug/ImportToString.ts +21 -0
- package/src/debug/LineWrapper.ts +65 -0
- package/src/debug/ScopeToString.ts +51 -0
- package/src/index.ts +7 -0
- package/src/test/ErrorLogging.test.ts +14 -0
- package/src/test/Expression.test.ts +22 -0
- package/src/test/FlattenTreeImport.test.ts +56 -0
- package/src/test/ImportCases.test.ts +440 -0
- package/src/test/ImportSyntaxCases.test.ts +22 -0
- package/src/test/LinkGlob.test.ts +25 -0
- package/src/test/LinkPackage.test.ts +26 -0
- package/src/test/Linker.test.ts +120 -0
- package/src/test/MatchWgslD.test.ts +16 -0
- package/src/test/ParseComments.test.ts +74 -0
- package/src/test/ParseWESL.test.ts +902 -0
- package/src/test/PathUtil.test.ts +34 -0
- package/src/test/PrettyGrammar.test.ts +21 -0
- package/src/test/ScopeWESL.test.ts +272 -0
- package/src/test/Slicer.test.ts +103 -0
- package/src/test/TestSetup.ts +4 -0
- package/src/test/TestUtil.ts +52 -0
- package/src/test/Util.test.ts +22 -0
- package/src/test/WgslTests.ts +0 -0
- package/src/test/__snapshots__/ParseDirectives.test.ts.snap +25 -0
- package/src/test/__snapshots__/ParseWESL.test.ts.snap +119 -0
- package/src/test/__snapshots__/ParseWESL2.test.ts.snap +67 -0
- package/src/test/__snapshots__/RustDirective.test.ts.snap +359 -0
- package/src/test/shared/StringUtil.ts +59 -0
- package/src/test/shared/test/StringUtil.test.ts +32 -0
- package/src/test/wgsl_1/main.wgsl +3 -0
- package/src/test/wgsl_1/util.wgsl +1 -0
- package/src/test/wgsl_2/main2.wgsl +3 -0
- 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
|