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
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { afterAll, expect, test } from "vitest";
|
|
2
|
+
import { importCases } from "wesl-testsuite";
|
|
3
|
+
import { linkWeslFiles } from "../Linker.js";
|
|
4
|
+
import { matchTrimmed, trimSrc } from "./shared/StringUtil.js";
|
|
5
|
+
|
|
6
|
+
/** so vitest triggers when this file changes */
|
|
7
|
+
import("../../../../../wesl-testsuite/src/test-cases/ImportCases.js");
|
|
8
|
+
|
|
9
|
+
interface LinkExpectation {
|
|
10
|
+
includes?: string[];
|
|
11
|
+
excludes?: string[];
|
|
12
|
+
linked?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// wgsl example src, indexed by name
|
|
16
|
+
const examplesByName = new Map(importCases.map(t => [t.name, t.src]));
|
|
17
|
+
|
|
18
|
+
test("import ./bar/foo", ctx => {
|
|
19
|
+
linkTest2(ctx.task.name, {
|
|
20
|
+
linked: `
|
|
21
|
+
fn main() {
|
|
22
|
+
foo();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
fn foo() { }
|
|
26
|
+
`,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("main has other root elements", ctx => {
|
|
31
|
+
linkTest2(ctx.task.name, {
|
|
32
|
+
linked: `
|
|
33
|
+
struct Uniforms {
|
|
34
|
+
a: u32
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
38
|
+
|
|
39
|
+
fn main() { }
|
|
40
|
+
`,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("import foo as bar", ctx => {
|
|
45
|
+
linkTest2(ctx.task.name, {
|
|
46
|
+
linked: `
|
|
47
|
+
fn main() {
|
|
48
|
+
bar();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fn bar() { /* fooImpl */ }
|
|
52
|
+
`,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("import twice doesn't get two copies", ctx => {
|
|
57
|
+
linkTest2(ctx.task.name, {
|
|
58
|
+
linked: `
|
|
59
|
+
fn main() {
|
|
60
|
+
foo();
|
|
61
|
+
bar();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fn foo() { /* fooImpl */ }
|
|
65
|
+
|
|
66
|
+
fn bar() { foo(); }
|
|
67
|
+
`,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("imported fn calls support fn with root conflict", ctx => {
|
|
72
|
+
linkTest2(ctx.task.name, {
|
|
73
|
+
linked: `
|
|
74
|
+
fn main() { foo(); }
|
|
75
|
+
|
|
76
|
+
fn conflicted() { }
|
|
77
|
+
|
|
78
|
+
fn foo() {
|
|
79
|
+
conflicted0(0);
|
|
80
|
+
conflicted0(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fn conflicted0(a:i32) {}
|
|
84
|
+
`,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("import twice with two as names", ctx => {
|
|
89
|
+
linkTest2(ctx.task.name, {
|
|
90
|
+
linked: `
|
|
91
|
+
fn main() { bar(); bar(); }
|
|
92
|
+
|
|
93
|
+
fn bar() { }
|
|
94
|
+
`,
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("import transitive conflicts with main", ctx => {
|
|
99
|
+
linkTest2(ctx.task.name, {
|
|
100
|
+
linked: `
|
|
101
|
+
fn main() {
|
|
102
|
+
mid();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn grand() {
|
|
106
|
+
/* main impl */
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fn mid() { grand0(); }
|
|
110
|
+
|
|
111
|
+
fn grand0() { /* grandImpl */ }
|
|
112
|
+
`,
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("multiple exports from the same module", ctx => {
|
|
117
|
+
linkTest2(ctx.task.name, {
|
|
118
|
+
linked: `
|
|
119
|
+
fn main() {
|
|
120
|
+
foo();
|
|
121
|
+
bar();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fn foo() { }
|
|
125
|
+
|
|
126
|
+
fn bar() { }
|
|
127
|
+
`,
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("import and resolve conflicting support function", ctx => {
|
|
132
|
+
linkTest2(ctx.task.name, {
|
|
133
|
+
linked: `
|
|
134
|
+
fn support() {
|
|
135
|
+
bar();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
fn bar() {
|
|
139
|
+
support0();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
fn support0() { }
|
|
143
|
+
`,
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("import support fn that references another import", ctx => {
|
|
148
|
+
linkTest2(ctx.task.name, {
|
|
149
|
+
linked: `
|
|
150
|
+
fn support() {
|
|
151
|
+
foo();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fn foo() {
|
|
155
|
+
support0();
|
|
156
|
+
bar();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fn support0() { }
|
|
160
|
+
|
|
161
|
+
fn bar() {
|
|
162
|
+
support1();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
fn support1() { }
|
|
166
|
+
`,
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("import support fn from two exports", ctx => {
|
|
171
|
+
linkTest2(ctx.task.name, {
|
|
172
|
+
linked: `
|
|
173
|
+
fn main() {
|
|
174
|
+
foo();
|
|
175
|
+
bar();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fn foo() {
|
|
179
|
+
support();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fn bar() {
|
|
183
|
+
support();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
fn support() { }
|
|
187
|
+
`,
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("import a struct", ctx => {
|
|
192
|
+
linkTest2(ctx.task.name, {
|
|
193
|
+
linked: `
|
|
194
|
+
fn main() {
|
|
195
|
+
let a = AStruct(1u);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
struct AStruct {
|
|
199
|
+
x: u32,
|
|
200
|
+
}
|
|
201
|
+
`,
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test("struct referenced by a fn param", ctx => {
|
|
206
|
+
linkTest2(ctx.task.name, {
|
|
207
|
+
linked: `
|
|
208
|
+
fn main() { foo(); }
|
|
209
|
+
|
|
210
|
+
fn foo(a: AStruct) {
|
|
211
|
+
let b = a.x;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
struct AStruct {
|
|
215
|
+
x: u32
|
|
216
|
+
}
|
|
217
|
+
`,
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("import fn with support struct constructor", ctx => {
|
|
222
|
+
linkTest2(ctx.task.name, {
|
|
223
|
+
linked: `
|
|
224
|
+
fn main() {
|
|
225
|
+
let ze = elemOne();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
fn elemOne() -> Elem {
|
|
229
|
+
return Elem(1u);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
struct Elem {
|
|
233
|
+
sum: u32
|
|
234
|
+
}
|
|
235
|
+
`,
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("import a transitive struct", ctx => {
|
|
240
|
+
linkTest2(ctx.task.name, {
|
|
241
|
+
linked: `
|
|
242
|
+
struct SrcStruct {
|
|
243
|
+
a: AStruct,
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
struct AStruct {
|
|
247
|
+
s: BStruct,
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
struct BStruct {
|
|
251
|
+
x: u32,
|
|
252
|
+
}
|
|
253
|
+
`,
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("'import as' a struct", ctx => {
|
|
258
|
+
linkTest2(ctx.task.name, {
|
|
259
|
+
linked: `
|
|
260
|
+
fn foo (a: AA) { }
|
|
261
|
+
|
|
262
|
+
struct AA { x: u32 }
|
|
263
|
+
`,
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test("import a struct with name conflicting support struct", ctx => {
|
|
268
|
+
linkTest2(ctx.task.name, {
|
|
269
|
+
linked: `
|
|
270
|
+
struct Base {
|
|
271
|
+
b: i32
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
fn foo() -> AStruct {var a:AStruct; return a;}
|
|
275
|
+
|
|
276
|
+
struct AStruct {
|
|
277
|
+
x: Base0
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
struct Base0 {
|
|
281
|
+
x: u32
|
|
282
|
+
}
|
|
283
|
+
`,
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test("copy alias to output", ctx => {
|
|
288
|
+
linkTest2(ctx.task.name, {
|
|
289
|
+
linked: `
|
|
290
|
+
alias MyType = u32;
|
|
291
|
+
`,
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("copy diagnostics to output", ctx => {
|
|
296
|
+
linkTest2(ctx.task.name, {
|
|
297
|
+
linked: `
|
|
298
|
+
diagnostic(off,derivative_uniformity);
|
|
299
|
+
`,
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("const referenced by imported fn", ctx => {
|
|
304
|
+
linkTest2(ctx.task.name, {
|
|
305
|
+
linked: `
|
|
306
|
+
fn main() { foo(); }
|
|
307
|
+
|
|
308
|
+
fn foo() {
|
|
309
|
+
let a = conA;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const conA = 7;
|
|
313
|
+
`,
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
test.skip("fn call with a separator", ctx => {
|
|
318
|
+
linkTest2(ctx.task.name, {
|
|
319
|
+
linked: `
|
|
320
|
+
fn main() { bar(); }
|
|
321
|
+
|
|
322
|
+
fn bar() { }
|
|
323
|
+
`,
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
test("local var to struct", ctx => {
|
|
328
|
+
linkTest2(ctx.task.name, {
|
|
329
|
+
linked: `
|
|
330
|
+
fn main() {
|
|
331
|
+
var a: AStruct;
|
|
332
|
+
}
|
|
333
|
+
struct AStruct { x: u32 }
|
|
334
|
+
`,
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("global var to struct", ctx => {
|
|
339
|
+
linkTest2(ctx.task.name, {
|
|
340
|
+
linked: `
|
|
341
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
342
|
+
struct Uniforms { model: mat4x4<f32> }
|
|
343
|
+
`,
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
test("return type of function", ctx => {
|
|
348
|
+
linkTest2(ctx.task.name, {
|
|
349
|
+
linked: `
|
|
350
|
+
fn b() -> A { }
|
|
351
|
+
struct A { y: i32 }
|
|
352
|
+
`,
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("import a const", ctx => {
|
|
357
|
+
linkTest2(ctx.task.name, {
|
|
358
|
+
linked: `
|
|
359
|
+
fn m() { let a = conA; }
|
|
360
|
+
const conA = 11;
|
|
361
|
+
`,
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
test("import an alias", ctx => {
|
|
366
|
+
linkTest2(ctx.task.name, {
|
|
367
|
+
linked: `
|
|
368
|
+
fn m() { let a: aliasA = 4; }
|
|
369
|
+
alias aliasA = u32;
|
|
370
|
+
`,
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// test(, ctx => {
|
|
375
|
+
// linkTest2(ctx.task.name, {
|
|
376
|
+
// linked: `
|
|
377
|
+
// `,
|
|
378
|
+
// });
|
|
379
|
+
// });
|
|
380
|
+
|
|
381
|
+
// test(, ctx => {
|
|
382
|
+
// linkTest2(ctx.task.name, {
|
|
383
|
+
// linked: `
|
|
384
|
+
// `,
|
|
385
|
+
// });
|
|
386
|
+
// });
|
|
387
|
+
|
|
388
|
+
// test(, ctx => {
|
|
389
|
+
// linkTest2(ctx.task.name, {
|
|
390
|
+
// linked: `
|
|
391
|
+
// `,
|
|
392
|
+
// });
|
|
393
|
+
// });
|
|
394
|
+
|
|
395
|
+
// TODO add case for const_assert in non root module
|
|
396
|
+
// TODO add case for diagnostic in non-root module (should fail?)
|
|
397
|
+
|
|
398
|
+
afterAll(c => {
|
|
399
|
+
const testNameSet = new Set(c.tasks.map(t => t.name));
|
|
400
|
+
const cases = importCases.map(c => c.name);
|
|
401
|
+
const missing = cases.filter(name => !testNameSet.has(name));
|
|
402
|
+
if (missing.length) {
|
|
403
|
+
console.error("Missing tests for cases:", missing);
|
|
404
|
+
expect("missing test: " + missing.toString()).toBe("");
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
function linkTest2(name: string, expectation: LinkExpectation): void {
|
|
409
|
+
/* -- find and trim source texts -- */
|
|
410
|
+
const exampleSrc = examplesByName.get(name);
|
|
411
|
+
if (!exampleSrc) {
|
|
412
|
+
throw new Error(`Skipping test "${name}"\nNo example found.`);
|
|
413
|
+
}
|
|
414
|
+
const srcs = Object.entries(exampleSrc).map(([name, wgsl]) => {
|
|
415
|
+
const trimmedSrc = trimSrc(wgsl);
|
|
416
|
+
return [name, trimmedSrc] as [string, string];
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
const wesl = Object.fromEntries(srcs);
|
|
420
|
+
|
|
421
|
+
/* -- link -- */
|
|
422
|
+
const resultMap = linkWeslFiles(wesl, srcs[0][0]);
|
|
423
|
+
const result = resultMap.dest;
|
|
424
|
+
|
|
425
|
+
/* -- trim and verify results line by line -- */
|
|
426
|
+
const { linked, includes, excludes } = expectation;
|
|
427
|
+
if (linked !== undefined) {
|
|
428
|
+
matchTrimmed(result, linked);
|
|
429
|
+
}
|
|
430
|
+
if (includes !== undefined) {
|
|
431
|
+
includes.forEach(inc => {
|
|
432
|
+
expect(result).toContain(inc);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
if (excludes !== undefined) {
|
|
436
|
+
excludes.forEach(exc => {
|
|
437
|
+
expect(result).not.toContain(exc);
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { importSyntaxCases } from "wesl-testsuite";
|
|
3
|
+
import { weslImport } from "../ImportGrammar.js";
|
|
4
|
+
import { testAppParse } from "./TestUtil.js";
|
|
5
|
+
|
|
6
|
+
function expectParseFail(src: string): void {
|
|
7
|
+
const result = testAppParse(weslImport, src);
|
|
8
|
+
expect(result.stable.imports).toEqual([]); // TODO tighten test, shouldn't parse
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function expectParses(src: string): void {
|
|
12
|
+
const result = testAppParse(weslImport, src);
|
|
13
|
+
expect(result.stable.imports.length).toBeGreaterThan(0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
importSyntaxCases.forEach(c => {
|
|
17
|
+
if (c.fails) {
|
|
18
|
+
test(c.src, () => expectParseFail(c.src));
|
|
19
|
+
} else {
|
|
20
|
+
test(c.src, () => expectParses(c.src));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
import { linkWeslFiles } from "../Linker.js";
|
|
4
|
+
|
|
5
|
+
const wgsl1: Record<string, string> = import.meta.glob("./wgsl_1/*.wgsl", {
|
|
6
|
+
query: "?raw",
|
|
7
|
+
eager: true,
|
|
8
|
+
import: "default",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const wgsl2: Record<string, string> = import.meta.glob("./wgsl_2/*.wgsl", {
|
|
12
|
+
query: "?raw",
|
|
13
|
+
eager: true,
|
|
14
|
+
import: "default",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("basic import glob", async () => {
|
|
18
|
+
const linked = linkWeslFiles(wgsl1, "wgsl_1/main");
|
|
19
|
+
expect(linked.dest).toContain("fn bar()");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("#import from path ./util", async () => {
|
|
23
|
+
const linked = linkWeslFiles(wgsl2, "wgsl_2/main2");
|
|
24
|
+
expect(linked.dest).toContain("fn bar()");
|
|
25
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { expectNoLog } from "mini-parse/test-util";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
import lib from "random_wgsl";
|
|
4
|
+
import { linkWeslFiles } from "../Linker.ts";
|
|
5
|
+
|
|
6
|
+
test("import rand() from a package", () => {
|
|
7
|
+
const src = `
|
|
8
|
+
import random_wgsl/pcg_2u_3f;
|
|
9
|
+
|
|
10
|
+
struct Uniforms { frame: u32 }
|
|
11
|
+
@binding(0) @group(0) var<uniform> u: Uniforms;
|
|
12
|
+
|
|
13
|
+
@fragment
|
|
14
|
+
fn fragmentMain(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
15
|
+
let rand = pcg_2u_3f(vec2u(pos.xy) + u.frame);
|
|
16
|
+
return vec4(rand, 1f);
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const wgsl = { "./main.wesl": src };
|
|
21
|
+
const result = expectNoLog(() =>
|
|
22
|
+
linkWeslFiles(wgsl, "./main.wesl", {}, [lib]),
|
|
23
|
+
);
|
|
24
|
+
expect(result.dest).toContain("fn pcg_2u_3f");
|
|
25
|
+
expect(result.dest).not.toContain("sinRand");
|
|
26
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { link2Test } from "./TestUtil.js";
|
|
3
|
+
import { matchTrimmed } from "./shared/StringUtil.js";
|
|
4
|
+
import { dlog } from "berry-pretty";
|
|
5
|
+
|
|
6
|
+
test("link global var", () => {
|
|
7
|
+
const src = `var x: i32 = 1;`;
|
|
8
|
+
const result = link2Test(src);
|
|
9
|
+
matchTrimmed(result, src);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("link an alias", () => {
|
|
13
|
+
const src = `
|
|
14
|
+
alias Num = f32;
|
|
15
|
+
|
|
16
|
+
fn main() { Num(1.0); }
|
|
17
|
+
`;
|
|
18
|
+
const result = link2Test(src);
|
|
19
|
+
matchTrimmed(result, src);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("link a const_assert", () => {
|
|
23
|
+
const src = `
|
|
24
|
+
var x = 1;
|
|
25
|
+
var y = 2;
|
|
26
|
+
const_assert x < y;
|
|
27
|
+
`;
|
|
28
|
+
const result = link2Test(src);
|
|
29
|
+
matchTrimmed(result, src);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("link a struct", () => {
|
|
33
|
+
const src = `
|
|
34
|
+
struct Point {
|
|
35
|
+
x: i32,
|
|
36
|
+
y: i32,
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
const result = link2Test(src);
|
|
40
|
+
matchTrimmed(result, src);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("link a fn", () => {
|
|
44
|
+
const src = `
|
|
45
|
+
fn foo(x: i32, y: u32) -> f32 {
|
|
46
|
+
return 1.0;
|
|
47
|
+
}`;
|
|
48
|
+
const result = link2Test(src);
|
|
49
|
+
matchTrimmed(result, src);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("handle a ptr type", () => {
|
|
53
|
+
const src = `
|
|
54
|
+
fn uint_bitfieldExtract_u1_i1_i1_(
|
|
55
|
+
value: ptr<function, u32>,
|
|
56
|
+
bits: ptr<function, i32>) -> u32 { }
|
|
57
|
+
`;
|
|
58
|
+
const result = link2Test(src);
|
|
59
|
+
matchTrimmed(result, src);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("struct after var", () => {
|
|
63
|
+
const src = `
|
|
64
|
+
var config: TwoPassConfig;
|
|
65
|
+
|
|
66
|
+
struct TwoPassConfig {
|
|
67
|
+
x: u32,
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const result = link2Test(src);
|
|
71
|
+
matchTrimmed(result, src);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("type inside fn with same name as fn", () => {
|
|
75
|
+
// illegal but shouldn't hang
|
|
76
|
+
const src = `
|
|
77
|
+
fn foo() {
|
|
78
|
+
var a:foo;
|
|
79
|
+
}
|
|
80
|
+
fn bar() {}
|
|
81
|
+
`;
|
|
82
|
+
const result = link2Test(src);
|
|
83
|
+
matchTrimmed(result, src);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("call cross reference", () => {
|
|
87
|
+
const src = `
|
|
88
|
+
fn foo() {
|
|
89
|
+
bar();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fn bar() {
|
|
93
|
+
foo();
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
|
|
97
|
+
const result = link2Test(src);
|
|
98
|
+
matchTrimmed(result, src);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("struct self reference", () => {
|
|
102
|
+
const src = `
|
|
103
|
+
struct A {
|
|
104
|
+
a: A,
|
|
105
|
+
b: B,
|
|
106
|
+
}
|
|
107
|
+
struct B {
|
|
108
|
+
f: f32,
|
|
109
|
+
}
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
const result = link2Test(src);
|
|
113
|
+
matchTrimmed(result, src);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("parse texture_storage_2d with texture format in typical type position", () => {
|
|
117
|
+
const src = `var t: texture_storage_2d<rgba8unorm, write>;`;
|
|
118
|
+
const result = link2Test(src);
|
|
119
|
+
matchTrimmed(result, src);
|
|
120
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { matchingLexer } from "mini-parse";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
import { mainTokens } from "../WESLTokens.js";
|
|
4
|
+
|
|
5
|
+
test("lex #import foo", () => {
|
|
6
|
+
const lexer = matchingLexer(`#import foo`, mainTokens);
|
|
7
|
+
const tokens = [1, 2].map(lexer.next);
|
|
8
|
+
expect(tokens.map(t => t?.kind)).toEqual(["directive", "ident"]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("/* foo */", () => {
|
|
12
|
+
const lexer = matchingLexer(`/* foo */`, mainTokens);
|
|
13
|
+
const tokens = [1, 2, 3].map(lexer.next);
|
|
14
|
+
const tokenKinds = tokens.map(t => t?.kind);
|
|
15
|
+
expect(tokenKinds).toEqual(["symbol", "ident", "symbol"]);
|
|
16
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { expectNoLog } from "mini-parse/test-util";
|
|
2
|
+
|
|
3
|
+
import { expect, test } from "vitest";
|
|
4
|
+
import { blockComment, lineComment } from "../CommentsGrammar.js";
|
|
5
|
+
import { parseWESL } from "../ParseWESL.js";
|
|
6
|
+
import { testAppParse } from "./TestUtil.js";
|
|
7
|
+
import { astToString } from "../debug/ASTtoString.js";
|
|
8
|
+
|
|
9
|
+
test("lineComment parse // foo bar", () => {
|
|
10
|
+
const src = "// foo bar";
|
|
11
|
+
const { position } = testAppParse(lineComment, src);
|
|
12
|
+
expect(position).toBe(src.length);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("lineComment parse // foo bar \\n", () => {
|
|
16
|
+
const src = "// foo bar\n";
|
|
17
|
+
const { position } = testAppParse(lineComment, src);
|
|
18
|
+
expect(position).toBe(src.length);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("blockComment parses /* comment */", () => {
|
|
22
|
+
const src = "/* comment */";
|
|
23
|
+
expectNoLog(() => {
|
|
24
|
+
const { parsed } = testAppParse(blockComment, src);
|
|
25
|
+
expect(parsed?.value).toMatchInlineSnapshot(`
|
|
26
|
+
[
|
|
27
|
+
"/*",
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
"kind": "ident",
|
|
31
|
+
"text": "comment",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
"*/",
|
|
35
|
+
]
|
|
36
|
+
`);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("skipBlockComment parses nested comment", () => {
|
|
41
|
+
const src = "/** comment1 /* comment2 */ */";
|
|
42
|
+
expectNoLog(() => testAppParse(blockComment, src));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("parse fn with line comment", () => {
|
|
46
|
+
const src = `
|
|
47
|
+
fn binaryOp() { // binOpImpl
|
|
48
|
+
}`;
|
|
49
|
+
const parsed = parseWESL(src);
|
|
50
|
+
expect(astToString(parsed.moduleElem)).toMatchInlineSnapshot(`
|
|
51
|
+
"module
|
|
52
|
+
text '
|
|
53
|
+
'
|
|
54
|
+
fn binaryOp()
|
|
55
|
+
text 'fn '
|
|
56
|
+
decl %binaryOp
|
|
57
|
+
text '() { // binOpImpl
|
|
58
|
+
}'"
|
|
59
|
+
`);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("parse empty line comment", () => {
|
|
63
|
+
const src = `
|
|
64
|
+
var workgroupThreads= 4; //
|
|
65
|
+
`;
|
|
66
|
+
expectNoLog(() => parseWESL(src));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("parse line comment with #replace", () => {
|
|
70
|
+
const src = `
|
|
71
|
+
const workgroupThreads= 4; // #replace 4=workgroupThreads
|
|
72
|
+
`;
|
|
73
|
+
expectNoLog(() => parseWESL(src));
|
|
74
|
+
});
|