wesl 0.6.0-pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/index.cjs +2617 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.js +2617 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/linker/packages/linker/src/AbstractElems.d.ts +104 -0
  6. package/dist/linker/packages/linker/src/BindIdents.d.ts +16 -0
  7. package/dist/linker/packages/linker/src/CommentsGrammar.d.ts +6 -0
  8. package/dist/linker/packages/linker/src/FlattenTreeImport.d.ts +11 -0
  9. package/dist/linker/packages/linker/src/ImportGrammar.d.ts +13 -0
  10. package/dist/linker/packages/linker/src/ImportTree.d.ts +17 -0
  11. package/dist/linker/packages/linker/src/Linker.d.ts +26 -0
  12. package/dist/linker/packages/linker/src/LowerAndEmit.d.ts +25 -0
  13. package/dist/linker/packages/linker/src/ParseWESL.d.ts +36 -0
  14. package/dist/linker/packages/linker/src/ParsedRegistry.d.ts +26 -0
  15. package/dist/linker/packages/linker/src/PathUtil.d.ts +9 -0
  16. package/dist/linker/packages/linker/src/Scope.d.ts +55 -0
  17. package/dist/linker/packages/linker/src/Slicer.d.ts +26 -0
  18. package/dist/linker/packages/linker/src/StandardTypes.d.ts +6 -0
  19. package/dist/linker/packages/linker/src/Util.d.ts +26 -0
  20. package/dist/linker/packages/linker/src/WESLCollect.d.ts +29 -0
  21. package/dist/linker/packages/linker/src/WESLGrammar.d.ts +23 -0
  22. package/dist/linker/packages/linker/src/WESLTokens.d.ts +42 -0
  23. package/dist/linker/packages/linker/src/WgslBundle.d.ts +13 -0
  24. package/dist/linker/packages/linker/src/debug/ASTtoString.d.ts +3 -0
  25. package/dist/linker/packages/linker/src/debug/ImportToString.d.ts +2 -0
  26. package/dist/linker/packages/linker/src/debug/LineWrapper.d.ts +21 -0
  27. package/dist/linker/packages/linker/src/debug/ScopeToString.d.ts +4 -0
  28. package/dist/linker/packages/linker/src/index.d.ts +7 -0
  29. package/dist/linker/packages/linker/src/test/ErrorLogging.test.d.ts +1 -0
  30. package/dist/linker/packages/linker/src/test/Expression.test.d.ts +1 -0
  31. package/dist/linker/packages/linker/src/test/FlattenTreeImport.test.d.ts +1 -0
  32. package/dist/linker/packages/linker/src/test/ImportCases.test.d.ts +1 -0
  33. package/dist/linker/packages/linker/src/test/ImportSyntaxCases.test.d.ts +1 -0
  34. package/dist/linker/packages/linker/src/test/LinkGlob.test.d.ts +1 -0
  35. package/dist/linker/packages/linker/src/test/LinkPackage.test.d.ts +1 -0
  36. package/dist/linker/packages/linker/src/test/Linker.test.d.ts +1 -0
  37. package/dist/linker/packages/linker/src/test/MatchWgslD.test.d.ts +1 -0
  38. package/dist/linker/packages/linker/src/test/ParseComments.test.d.ts +1 -0
  39. package/dist/linker/packages/linker/src/test/ParseWESL.test.d.ts +1 -0
  40. package/dist/linker/packages/linker/src/test/PathUtil.test.d.ts +1 -0
  41. package/dist/linker/packages/linker/src/test/PrettyGrammar.test.d.ts +1 -0
  42. package/dist/linker/packages/linker/src/test/ScopeWESL.test.d.ts +1 -0
  43. package/dist/linker/packages/linker/src/test/Slicer.test.d.ts +1 -0
  44. package/dist/linker/packages/linker/src/test/TestSetup.d.ts +1 -0
  45. package/dist/linker/packages/linker/src/test/TestUtil.d.ts +15 -0
  46. package/dist/linker/packages/linker/src/test/Util.test.d.ts +1 -0
  47. package/dist/linker/packages/linker/src/test/WgslTests.d.ts +0 -0
  48. package/dist/linker/packages/linker/src/test/shared/StringUtil.d.ts +8 -0
  49. package/dist/linker/packages/linker/src/test/shared/test/StringUtil.test.d.ts +1 -0
  50. package/dist/minified.cjs +2 -0
  51. package/dist/minified.cjs.map +1 -0
  52. package/dist/minified.js +2617 -0
  53. package/dist/minified.js.map +1 -0
  54. package/dist/wesl-testsuite/src/test-cases/BulkTests.d.ts +4 -0
  55. package/dist/wesl-testsuite/src/test-cases/ImportCases.d.ts +3 -0
  56. package/dist/wesl-testsuite/src/test-cases/ImportSyntaxCases.d.ts +3 -0
  57. package/package.json +45 -0
  58. package/src/AbstractElems.ts +148 -0
  59. package/src/BindIdents.ts +277 -0
  60. package/src/CommentsGrammar.ts +44 -0
  61. package/src/FlattenTreeImport.ts +59 -0
  62. package/src/ImportGrammar.ts +142 -0
  63. package/src/ImportTree.ts +19 -0
  64. package/src/Linker.ts +151 -0
  65. package/src/LowerAndEmit.ts +143 -0
  66. package/src/ParseWESL.ts +106 -0
  67. package/src/ParsedRegistry.ts +97 -0
  68. package/src/PathUtil.ts +52 -0
  69. package/src/Scope.ts +100 -0
  70. package/src/Slicer.ts +127 -0
  71. package/src/StandardTypes.ts +66 -0
  72. package/src/Util.ts +112 -0
  73. package/src/WESLCollect.ts +336 -0
  74. package/src/WESLGrammar.ts +538 -0
  75. package/src/WESLTokens.ts +97 -0
  76. package/src/WgslBundle.ts +16 -0
  77. package/src/debug/ASTtoString.ts +149 -0
  78. package/src/debug/ImportToString.ts +21 -0
  79. package/src/debug/LineWrapper.ts +65 -0
  80. package/src/debug/ScopeToString.ts +51 -0
  81. package/src/index.ts +7 -0
  82. package/src/test/ErrorLogging.test.ts +14 -0
  83. package/src/test/Expression.test.ts +22 -0
  84. package/src/test/FlattenTreeImport.test.ts +56 -0
  85. package/src/test/ImportCases.test.ts +440 -0
  86. package/src/test/ImportSyntaxCases.test.ts +22 -0
  87. package/src/test/LinkGlob.test.ts +25 -0
  88. package/src/test/LinkPackage.test.ts +26 -0
  89. package/src/test/Linker.test.ts +120 -0
  90. package/src/test/MatchWgslD.test.ts +16 -0
  91. package/src/test/ParseComments.test.ts +74 -0
  92. package/src/test/ParseWESL.test.ts +902 -0
  93. package/src/test/PathUtil.test.ts +34 -0
  94. package/src/test/PrettyGrammar.test.ts +21 -0
  95. package/src/test/ScopeWESL.test.ts +272 -0
  96. package/src/test/Slicer.test.ts +103 -0
  97. package/src/test/TestSetup.ts +4 -0
  98. package/src/test/TestUtil.ts +52 -0
  99. package/src/test/Util.test.ts +22 -0
  100. package/src/test/WgslTests.ts +0 -0
  101. package/src/test/__snapshots__/ParseDirectives.test.ts.snap +25 -0
  102. package/src/test/__snapshots__/ParseWESL.test.ts.snap +119 -0
  103. package/src/test/__snapshots__/ParseWESL2.test.ts.snap +67 -0
  104. package/src/test/__snapshots__/RustDirective.test.ts.snap +359 -0
  105. package/src/test/shared/StringUtil.ts +59 -0
  106. package/src/test/shared/test/StringUtil.test.ts +32 -0
  107. package/src/test/wgsl_1/main.wgsl +3 -0
  108. package/src/test/wgsl_1/util.wgsl +1 -0
  109. package/src/test/wgsl_2/main2.wgsl +3 -0
  110. package/src/test/wgsl_2/util2.wgsl +1 -0
@@ -0,0 +1,902 @@
1
+ import { expect, test } from "vitest";
2
+ import { astToString } from "../debug/ASTtoString.ts";
3
+ import { parse2Test } from "./TestUtil.ts";
4
+ import { importToString } from "../debug/ImportToString.ts";
5
+
6
+ test("parse empty string", () => {
7
+ const ast = parse2Test("");
8
+ expect(astToString(ast.moduleElem)).toMatchInlineSnapshot(`"module"`);
9
+ });
10
+
11
+ test("parse fn foo() { }", () => {
12
+ const src = "fn foo() { }";
13
+ const ast = parse2Test(src);
14
+ expect(astToString(ast.moduleElem)).toMatchInlineSnapshot(`
15
+ "module
16
+ fn foo()
17
+ text 'fn '
18
+ decl %foo
19
+ text '() { }'"
20
+ `);
21
+ });
22
+
23
+ test("parse fn with calls", () => {
24
+ const src = "fn foo() { foo(); bar(); }";
25
+ const ast = parse2Test(src);
26
+ expect(astToString(ast.moduleElem)).toMatchInlineSnapshot(`
27
+ "module
28
+ fn foo()
29
+ text 'fn '
30
+ decl %foo
31
+ text '() { '
32
+ ref foo
33
+ text '(); '
34
+ ref bar
35
+ text '(); }'"
36
+ `);
37
+ });
38
+
39
+ test("parse unicode ident", () => {
40
+ // List taken straight from the examples at https://www.w3.org/TR/WGSL/#identifiers
41
+ const src = `
42
+ fn Δέλτα(){}
43
+ fn réflexion(){}
44
+ fn Кызыл(){}
45
+ fn 𐰓𐰏𐰇(){}
46
+ fn 朝焼け(){}
47
+ fn سلام(){}
48
+ fn 검정(){}
49
+ fn שָׁלוֹם(){}
50
+ fn गुलाबी(){}
51
+ fn փիրուզ(){}
52
+ `;
53
+ const ast = parse2Test(src);
54
+ const astString = astToString(ast.moduleElem);
55
+ expect(astString).toMatchSnapshot();
56
+ });
57
+
58
+ test("parse global var", () => {
59
+ const src = `var x: i32 = 1;`;
60
+ const ast = parse2Test(src);
61
+ const astString = astToString(ast.moduleElem);
62
+ expect(astString).toMatchInlineSnapshot(`
63
+ "module
64
+ gvar x:i32
65
+ text 'var '
66
+ decl %x
67
+ text ': '
68
+ ref i32
69
+ text ' = 1;'"
70
+ `);
71
+ });
72
+
73
+ test("parse alias", () => {
74
+ const src = `alias Num = i32;`;
75
+ const ast = parse2Test(src);
76
+ const astString = astToString(ast.moduleElem);
77
+ expect(astString).toMatchInlineSnapshot(`
78
+ "module
79
+ alias %Num=i32
80
+ text 'alias '
81
+ decl %Num
82
+ text ' = '
83
+ ref i32
84
+ text ';'"
85
+ `);
86
+ });
87
+
88
+ test("parse const", () => {
89
+ const src = `const y = 11u;`;
90
+ const ast = parse2Test(src);
91
+ const astString = astToString(ast.moduleElem);
92
+ expect(astString).toMatchInlineSnapshot(`
93
+ "module
94
+ const y
95
+ text 'const '
96
+ decl %y
97
+ text ' = 11u;'"
98
+ `);
99
+ });
100
+
101
+ test("parse override ", () => {
102
+ const src = `override z: f32;`;
103
+ const ast = parse2Test(src);
104
+ const astString = astToString(ast.moduleElem);
105
+ expect(astString).toMatchInlineSnapshot(`
106
+ "module
107
+ override z:f32
108
+ text 'override '
109
+ decl %z
110
+ text ': '
111
+ ref f32
112
+ text ';'"
113
+ `);
114
+ });
115
+
116
+ test("parse const_assert", () => {
117
+ const src = `const_assert x < y;`;
118
+ const ast = parse2Test(src);
119
+ const astString = astToString(ast.moduleElem);
120
+ expect(astString).toMatchInlineSnapshot(`
121
+ "module
122
+ assert
123
+ text 'const_assert '
124
+ ref x
125
+ text ' < '
126
+ ref y
127
+ text ';'"
128
+ `);
129
+ });
130
+
131
+ test("parse struct", () => {
132
+ const src = `struct foo { bar: i32, zip: u32, } ;`;
133
+ const ast = parse2Test(src);
134
+ const astString = astToString(ast.moduleElem);
135
+ expect(astString).toMatchInlineSnapshot(`
136
+ "module
137
+ struct foo
138
+ text 'struct '
139
+ decl %foo
140
+ text ' { '
141
+ member
142
+ name bar
143
+ text ': '
144
+ ref i32
145
+ text ', '
146
+ member
147
+ name zip
148
+ text ': '
149
+ ref u32
150
+ text ', }'
151
+ text ' ;'"
152
+ `);
153
+ });
154
+
155
+ test("parse global diagnostic", () => {
156
+ const src = `
157
+ diagnostic(off,derivative_uniformity);
158
+
159
+ fn main() {}
160
+ `;
161
+ const ast = parse2Test(src);
162
+ const astString = astToString(ast.moduleElem);
163
+ expect(astString).toMatchInlineSnapshot(`
164
+ "module
165
+ text '
166
+ diagnostic(off,derivative_uniformity);
167
+
168
+ '
169
+ fn main()
170
+ text 'fn '
171
+ decl %main
172
+ text '() {}'
173
+ text '
174
+ '"
175
+ `);
176
+ });
177
+
178
+ test("parse @attribute before fn", () => {
179
+ const src = `@compute fn main() {} `;
180
+ const ast = parse2Test(src);
181
+ const astString = astToString(ast.moduleElem);
182
+ expect(astString).toMatchInlineSnapshot(`
183
+ "module
184
+ fn main()
185
+ text '@compute fn '
186
+ decl %main
187
+ text '() {}'
188
+ text ' '"
189
+ `);
190
+ });
191
+
192
+ test("parse @compute @workgroup_size(a, b, 1) before fn", () => {
193
+ const src = `
194
+ @compute
195
+ @workgroup_size(a, b, 1)
196
+ fn main() {}
197
+ `;
198
+ const ast = parse2Test(src);
199
+ const astString = astToString(ast.moduleElem);
200
+ expect(astString).toMatchInlineSnapshot(`
201
+ "module
202
+ text '
203
+ '
204
+ fn main()
205
+ text '@compute
206
+ @workgroup_size('
207
+ ref a
208
+ text ', '
209
+ ref b
210
+ text ', 1)
211
+ fn '
212
+ decl %main
213
+ text '() {}'
214
+ text '
215
+ '"
216
+ `);
217
+ });
218
+
219
+ test("parse top level var", () => {
220
+ const src = `
221
+ @group(0) @binding(0) var<uniform> u: Uniforms;
222
+
223
+ fn main() {}
224
+ `;
225
+ const ast = parse2Test(src);
226
+ const astString = astToString(ast.moduleElem);
227
+ expect(astString).toMatchInlineSnapshot(`
228
+ "module
229
+ text '
230
+ '
231
+ gvar u:Uniforms
232
+ text '@group(0) @binding(0) var<uniform> '
233
+ decl %u
234
+ text ': '
235
+ ref Uniforms
236
+ text ';'
237
+ text '
238
+
239
+ '
240
+ fn main()
241
+ text 'fn '
242
+ decl %main
243
+ text '() {}'
244
+ text '
245
+ '"
246
+ `);
247
+ });
248
+
249
+ test("parse top level override and const", () => {
250
+ const src = `
251
+ override x = 21;
252
+ const y = 1;
253
+
254
+ fn main() {}
255
+ `;
256
+ const ast = parse2Test(src);
257
+ const astString = astToString(ast.moduleElem);
258
+ expect(astString).toMatchInlineSnapshot(`
259
+ "module
260
+ text '
261
+ '
262
+ override x
263
+ text 'override '
264
+ decl %x
265
+ text ' = 21;'
266
+ text '
267
+ '
268
+ const y
269
+ text 'const '
270
+ decl %y
271
+ text ' = 1;'
272
+ text '
273
+
274
+ '
275
+ fn main()
276
+ text 'fn '
277
+ decl %main
278
+ text '() {}'
279
+ text '
280
+ '"
281
+ `);
282
+ });
283
+
284
+ test("parse root level ;;", () => {
285
+ const src = ";;";
286
+ const ast = parse2Test(src);
287
+ const astString = astToString(ast.moduleElem);
288
+ expect(astString).toMatchInlineSnapshot(`
289
+ "module
290
+ text ';;'"
291
+ `);
292
+ });
293
+
294
+ test("parse simple alias", () => {
295
+ const src = `alias NewType = OldType;`;
296
+ const ast = parse2Test(src);
297
+ const astString = astToString(ast.moduleElem);
298
+ expect(astString).toMatchInlineSnapshot(`
299
+ "module
300
+ alias %NewType=OldType
301
+ text 'alias '
302
+ decl %NewType
303
+ text ' = '
304
+ ref OldType
305
+ text ';'"
306
+ `);
307
+ });
308
+
309
+ test("parse array alias", () => {
310
+ const src = `
311
+ alias Points3 = array<Point, 3>;
312
+ `;
313
+ const ast = parse2Test(src);
314
+ const astString = astToString(ast.moduleElem);
315
+ expect(astString).toMatchInlineSnapshot(`
316
+ "module
317
+ text '
318
+ '
319
+ alias %Points3=array
320
+ text 'alias '
321
+ decl %Points3
322
+ text ' = '
323
+ ref array
324
+ text '<'
325
+ ref Point
326
+ text ', 3>;'
327
+ text '
328
+ '"
329
+ `);
330
+ });
331
+
332
+ test("fnDecl parses fn with return type", () => {
333
+ const src = `fn foo() -> MyType { }`;
334
+ const ast = parse2Test(src);
335
+ const astString = astToString(ast.moduleElem);
336
+ expect(astString).toMatchInlineSnapshot(`
337
+ "module
338
+ fn foo() -> MyType
339
+ text 'fn '
340
+ decl %foo
341
+ text '() -> '
342
+ ref MyType
343
+ text ' { }'"
344
+ `);
345
+ });
346
+
347
+ test("fnDecl parses :type specifier in fn args", () => {
348
+ const src = `
349
+ fn foo(a: MyType) { }
350
+ `;
351
+ const ast = parse2Test(src);
352
+ const astString = astToString(ast.moduleElem);
353
+ expect(astString).toMatchInlineSnapshot(`
354
+ "module
355
+ text '
356
+ '
357
+ fn foo(a: MyType)
358
+ text 'fn '
359
+ decl %foo
360
+ text '('
361
+ param
362
+ decl %a
363
+ text ': '
364
+ ref MyType
365
+ text ') { }'
366
+ text '
367
+ '"
368
+ `);
369
+ });
370
+
371
+ test("fnDecl parses :type specifier in fn block", () => {
372
+ const src = `
373
+ fn foo() {
374
+ var b:MyType;
375
+ }
376
+ `;
377
+ const ast = parse2Test(src);
378
+ const astString = astToString(ast.moduleElem);
379
+ expect(astString).toMatchInlineSnapshot(`
380
+ "module
381
+ text '
382
+ '
383
+ fn foo()
384
+ text 'fn '
385
+ decl %foo
386
+ text '() {
387
+ '
388
+ var b:MyType
389
+ text 'var '
390
+ decl %b
391
+ text ':'
392
+ ref MyType
393
+ text ';
394
+ }'
395
+ text '
396
+ '"
397
+ `);
398
+ });
399
+
400
+ test("parse type in <template> in fn args", () => {
401
+ const src = `
402
+ fn foo(a: vec2<MyStruct>) { };`;
403
+ const ast = parse2Test(src);
404
+ const astString = astToString(ast.moduleElem);
405
+ expect(astString).toMatchInlineSnapshot(`
406
+ "module
407
+ text '
408
+ '
409
+ fn foo(a: vec2)
410
+ text 'fn '
411
+ decl %foo
412
+ text '('
413
+ param
414
+ decl %a
415
+ text ': '
416
+ ref vec2
417
+ text '<'
418
+ ref MyStruct
419
+ text '>'
420
+ text ') { }'
421
+ text ';'"
422
+ `);
423
+ });
424
+
425
+ test("parse simple templated type", () => {
426
+ const src = `fn main(a: array<MyStruct,4>) { }`;
427
+
428
+ const ast = parse2Test(src);
429
+ const astString = astToString(ast.moduleElem);
430
+ expect(astString).toMatchInlineSnapshot(`
431
+ "module
432
+ fn main(a: array)
433
+ text 'fn '
434
+ decl %main
435
+ text '('
436
+ param
437
+ decl %a
438
+ text ': '
439
+ ref array
440
+ text '<'
441
+ ref MyStruct
442
+ text ',4>'
443
+ text ') { }'"
444
+ `);
445
+ });
446
+
447
+ test("parse nested template that ends with >> ", () => {
448
+ const src = `fn main(a: vec2<array <MyStruct,4>>) { }`;
449
+ const ast = parse2Test(src);
450
+ const astString = astToString(ast.moduleElem);
451
+ expect(astString).toMatchInlineSnapshot(`
452
+ "module
453
+ fn main(a: vec2)
454
+ text 'fn '
455
+ decl %main
456
+ text '('
457
+ param
458
+ decl %a
459
+ text ': '
460
+ ref vec2
461
+ text '<'
462
+ ref array
463
+ text ' <'
464
+ ref MyStruct
465
+ text ',4>>'
466
+ text ') { }'"
467
+ `);
468
+ });
469
+
470
+ test("parse type in <template> in global var", () => {
471
+ const src = `var<private> x:array<MyStruct, 8>;`;
472
+
473
+ const ast = parse2Test(src);
474
+ const astString = astToString(ast.moduleElem);
475
+ expect(astString).toMatchInlineSnapshot(`
476
+ "module
477
+ gvar x:array
478
+ text 'var<private> '
479
+ decl %x
480
+ text ':'
481
+ ref array
482
+ text '<'
483
+ ref MyStruct
484
+ text ', 8>;'"
485
+ `);
486
+ });
487
+
488
+ test("parse for(;;) {} not as a fn call", () => {
489
+ const src = `
490
+ fn main() {
491
+ for (var a = 1; a < 10; a++) {}
492
+ }
493
+ `;
494
+ const ast = parse2Test(src);
495
+ const astString = astToString(ast.moduleElem);
496
+ expect(astString).toMatchInlineSnapshot(`
497
+ "module
498
+ text '
499
+ '
500
+ fn main()
501
+ text 'fn '
502
+ decl %main
503
+ text '() {
504
+ for ('
505
+ var a
506
+ text 'var '
507
+ decl %a
508
+ text ' = 1'
509
+ text '; '
510
+ ref a
511
+ text ' < 10; '
512
+ ref a
513
+ text '++) {}
514
+ }'
515
+ text '
516
+ '"
517
+ `);
518
+ });
519
+
520
+ test("eolf followed by blank line", () => {
521
+ const src = `
522
+ fn foo() { }
523
+ `;
524
+ const ast = parse2Test(src);
525
+ const astString = astToString(ast.moduleElem);
526
+ expect(astString).toMatchInlineSnapshot(`
527
+ "module
528
+ text '
529
+ '
530
+ fn foo()
531
+ text 'fn '
532
+ decl %foo
533
+ text '() { }'
534
+ text '
535
+ '"
536
+ `);
537
+ });
538
+
539
+ test("parse fn with attributes and suffix comma", () => {
540
+ const src = `
541
+ @compute
542
+ @workgroup_size(workgroupThreads, 1, 1)
543
+ fn main(
544
+ @builtin(global_invocation_id) grid: vec3<u32>,
545
+ @builtin(local_invocation_index) localIndex: u32,
546
+ ) { }
547
+ `;
548
+ const ast = parse2Test(src);
549
+ const astString = astToString(ast.moduleElem);
550
+ expect(astString).toMatchInlineSnapshot(`
551
+ "module
552
+ text '
553
+ '
554
+ fn main(grid: vec3, localIndex: u32)
555
+ text '@compute
556
+ @workgroup_size('
557
+ ref workgroupThreads
558
+ text ', 1, 1)
559
+ fn '
560
+ decl %main
561
+ text '(
562
+ '
563
+ param
564
+ text '@builtin(global_invocation_id) '
565
+ decl %grid
566
+ text ': '
567
+ ref vec3
568
+ text '<'
569
+ ref u32
570
+ text '>'
571
+ text ',
572
+ '
573
+ param
574
+ text '@builtin(local_invocation_index) '
575
+ decl %localIndex
576
+ text ': '
577
+ ref u32
578
+ text ',
579
+ ) { }'
580
+ text '
581
+ '"
582
+ `);
583
+ });
584
+
585
+ test("parse fn", () => {
586
+ const src = `fn foo(x: i32, y: u32) -> f32 { return 1.0; }`;
587
+ const ast = parse2Test(src);
588
+ const astString = astToString(ast.moduleElem);
589
+ expect(astString).toMatchInlineSnapshot(`
590
+ "module
591
+ fn foo(x: i32, y: u32) -> f32
592
+ text 'fn '
593
+ decl %foo
594
+ text '('
595
+ param
596
+ decl %x
597
+ text ': '
598
+ ref i32
599
+ text ', '
600
+ param
601
+ decl %y
602
+ text ': '
603
+ ref u32
604
+ text ') -> '
605
+ ref f32
606
+ text ' { return 1.0; }'"
607
+ `);
608
+ });
609
+
610
+ test("parse @attribute before fn", () => {
611
+ const src = `@compute fn main() {} `;
612
+ const ast = parse2Test(src);
613
+ const astString = astToString(ast.moduleElem);
614
+ expect(astString).toMatchInlineSnapshot(`
615
+ "module
616
+ fn main()
617
+ text '@compute fn '
618
+ decl %main
619
+ text '() {}'
620
+ text ' '"
621
+ `);
622
+ });
623
+
624
+ test("import ./foo/bar;", ctx => {
625
+ const src = ctx.task.name;
626
+ const ast = parse2Test(src);
627
+ const astString = astToString(ast.moduleElem);
628
+ expect(astString).toMatchInlineSnapshot(`
629
+ "module
630
+ import package/foo/bar
631
+ text 'import ./foo/bar;'"
632
+ `);
633
+ });
634
+
635
+ // TODO
636
+ test.skip("parse foo::bar(); ", () => {
637
+ const src = "fn main() { foo::bar(); }";
638
+ const ast = parse2Test(src);
639
+ const astString = astToString(ast.moduleElem);
640
+ expect(astString).toMatchInlineSnapshot();
641
+ });
642
+
643
+ // TODO
644
+ test.skip("parse let x: foo::bar; ", () => {
645
+ const src = "fn main() { let x: foo::bar = 1; }";
646
+ const ast = parse2Test(src);
647
+ const astString = astToString(ast.moduleElem);
648
+ expect(astString).toMatchInlineSnapshot();
649
+ });
650
+
651
+ // TODO (consdier should this be legal?)
652
+ test.skip("parse var x: foo.bar;", () => {
653
+ const src = `
654
+ import foo::bar;
655
+ var<private> x: foo::bar;
656
+ fn main() { }
657
+ `;
658
+
659
+ const ast = parse2Test(src);
660
+ const astString = astToString(ast.moduleElem);
661
+ expect(astString).toMatchInlineSnapshot();
662
+ });
663
+
664
+ test("parse switch statement", () => {
665
+ const src = `
666
+ fn main(x: i32) {
667
+ switch (x) {
668
+ case 1: { break; }
669
+ default: { break; }
670
+ }
671
+ }
672
+ `;
673
+ const ast = parse2Test(src);
674
+ const astString = astToString(ast.moduleElem);
675
+ expect(astString).toMatchInlineSnapshot(`
676
+ "module
677
+ text '
678
+ '
679
+ fn main(x: i32)
680
+ text 'fn '
681
+ decl %main
682
+ text '('
683
+ param
684
+ decl %x
685
+ text ': '
686
+ ref i32
687
+ text ') {
688
+ switch ('
689
+ ref x
690
+ text
691
+ ') {
692
+ case 1: { break; }
693
+ default: { break; }
694
+ }
695
+ }'
696
+ text '
697
+ '"
698
+ `);
699
+ });
700
+
701
+ test("parse switch statement-2", () => {
702
+ const src = `
703
+
704
+ fn main(x: u32) {
705
+ switch ( code ) {
706
+ case 5u: { if 1 > 0 { } }
707
+ default: { break; }
708
+ }
709
+ }
710
+ `;
711
+ const ast = parse2Test(src);
712
+ const astString = astToString(ast.moduleElem);
713
+ expect(astString).toMatchInlineSnapshot(`
714
+ "module
715
+ text '
716
+
717
+ '
718
+ fn main(x: u32)
719
+ text 'fn '
720
+ decl %main
721
+ text '('
722
+ param
723
+ decl %x
724
+ text ': '
725
+ ref u32
726
+ text ') {
727
+ switch ( '
728
+ ref code
729
+ text
730
+ ' ) {
731
+ case 5u: { if 1 > 0 { } }
732
+ default: { break; }
733
+ }
734
+ }'
735
+ text '
736
+ '"
737
+ `);
738
+ });
739
+
740
+ test("parse struct constructor in assignment", () => {
741
+ const src = `
742
+ fn main() {
743
+ var x = AStruct(1u);
744
+ }
745
+ `;
746
+ const ast = parse2Test(src);
747
+ const astString = astToString(ast.moduleElem);
748
+ expect(astString).toMatchInlineSnapshot(`
749
+ "module
750
+ text '
751
+ '
752
+ fn main()
753
+ text 'fn '
754
+ decl %main
755
+ text '() {
756
+ '
757
+ var x
758
+ text 'var '
759
+ decl %x
760
+ text ' = '
761
+ ref AStruct
762
+ text '(1u)'
763
+ text ';
764
+ }'
765
+ text '
766
+ '"
767
+ `);
768
+ });
769
+
770
+ test("parse struct.member (component_or_swizzle)", () => {
771
+ const src = `
772
+ fn main() {
773
+ let x = u.frame;
774
+ }
775
+ `;
776
+ const ast = parse2Test(src);
777
+ const astString = astToString(ast.moduleElem);
778
+ expect(astString).toMatchInlineSnapshot(`
779
+ "module
780
+ text '
781
+ '
782
+ fn main()
783
+ text 'fn '
784
+ decl %main
785
+ text '() {
786
+ let '
787
+ decl %x
788
+ text ' = '
789
+ ref u
790
+ text '.frame;
791
+ }'
792
+ text '
793
+ '"
794
+ `);
795
+ });
796
+
797
+ test("var <workgroup> work: array<u32, 128>;", ctx => {
798
+ const ast = parse2Test(ctx.task.name);
799
+ const astString = astToString(ast.moduleElem);
800
+ expect(astString).toMatchInlineSnapshot(`
801
+ "module
802
+ gvar work:array
803
+ text 'var <workgroup> '
804
+ decl %work
805
+ text ': '
806
+ ref array
807
+ text '<'
808
+ ref u32
809
+ text ', 128>;'"
810
+ `);
811
+ });
812
+
813
+ test("fn f() { _ = 1; }", ctx => {
814
+ const ast = parse2Test(ctx.task.name);
815
+ const astString = astToString(ast.moduleElem);
816
+ expect(astString).toMatchInlineSnapshot(`
817
+ "module
818
+ fn f()
819
+ text 'fn '
820
+ decl %f
821
+ text '() { _ = 1; }'"
822
+ `);
823
+ });
824
+
825
+ test("var foo: vec2<f32 >= vec2( 0.5, -0.5);", ctx => {
826
+ const ast = parse2Test(ctx.task.name);
827
+ const astString = astToString(ast.moduleElem);
828
+ expect(astString).toMatchInlineSnapshot(`
829
+ "module
830
+ gvar foo:vec2
831
+ text 'var '
832
+ decl %foo
833
+ text ': '
834
+ ref vec2
835
+ text '<'
836
+ ref f32
837
+ text ' >= '
838
+ ref vec2
839
+ text '( 0.5, -0.5);'"
840
+ `);
841
+ });
842
+
843
+ test("import ./a/b/c", ctx => {
844
+ const ast = parse2Test(ctx.task.name);
845
+ const astString = astToString(ast.moduleElem);
846
+ expect(astString).toMatchInlineSnapshot(`
847
+ "module
848
+ import package/a/b/c
849
+ text 'import ./a/b/c'"
850
+ `);
851
+ });
852
+
853
+ test("import ./file1/{foo, bar}", ctx => {
854
+ const src = ctx.task.name;
855
+ const ast = parse2Test(src);
856
+ const astString = astToString(ast.moduleElem);
857
+ expect(astString).toMatchInlineSnapshot(`
858
+ "module
859
+ import package/file1/{foo, bar}
860
+ text 'import ./file1/{foo, bar}'"
861
+ `);
862
+ });
863
+
864
+ test("import ./file1/{foo, bar}", ctx => {
865
+ const src = ctx.task.name;
866
+ const ast = parse2Test(src);
867
+ const imps = ast.imports.map(t => importToString(t)).join("\n");
868
+
869
+ expect(imps).toMatchInlineSnapshot(`"package/file1/{foo, bar}"`);
870
+ });
871
+
872
+ test("import foo_bar/boo;", ctx => {
873
+ const ast = parse2Test(ctx.task.name);
874
+ const astString = astToString(ast.moduleElem);
875
+ expect(astString).toMatchInlineSnapshot(`
876
+ "module
877
+ import foo_bar/boo
878
+ text 'import foo_bar/boo;'"
879
+ `);
880
+ });
881
+
882
+ test(`import a/{ b }`, ctx => {
883
+ const ast = parse2Test(ctx.task.name);
884
+ const astString = astToString(ast.moduleElem);
885
+ expect(astString).toMatchInlineSnapshot(`
886
+ "module
887
+ import a/{b}
888
+ text 'import a/{ b }'"
889
+ `);
890
+ });
891
+
892
+ test(`import a/{ b, c/{d, e}, f }`, ctx => {
893
+ const src = ctx.task.name;
894
+ const ast = parse2Test(src);
895
+ const astString = astToString(ast.moduleElem);
896
+
897
+ expect(astString).toMatchInlineSnapshot(`
898
+ "module
899
+ import a/{b, (c/{d, e}), f}
900
+ text 'import a/{ b, c/{d, e}, f }'"
901
+ `);
902
+ });