wesl 0.6.0-pre10

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 (141) hide show
  1. package/README.md +31 -0
  2. package/dist/index.js +4468 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/minified.js +3426 -0
  5. package/dist/minified.js.map +1 -0
  6. package/dist/tools/packages/wesl/src/AbstractElems.d.ts +322 -0
  7. package/dist/tools/packages/wesl/src/Assertions.d.ts +27 -0
  8. package/dist/tools/packages/wesl/src/BindIdents.d.ts +70 -0
  9. package/dist/tools/packages/wesl/src/Conditions.d.ts +6 -0
  10. package/dist/tools/packages/wesl/src/FlattenTreeImport.d.ts +11 -0
  11. package/dist/tools/packages/wesl/src/LinkedWesl.d.ts +50 -0
  12. package/dist/tools/packages/wesl/src/Linker.d.ts +87 -0
  13. package/dist/tools/packages/wesl/src/LinkerUtil.d.ts +3 -0
  14. package/dist/tools/packages/wesl/src/LiveDeclarations.d.ts +12 -0
  15. package/dist/tools/packages/wesl/src/LowerAndEmit.d.ts +31 -0
  16. package/dist/tools/packages/wesl/src/Mangler.d.ts +39 -0
  17. package/dist/tools/packages/wesl/src/ParseWESL.d.ts +60 -0
  18. package/dist/tools/packages/wesl/src/ParsedRegistry.d.ts +29 -0
  19. package/dist/tools/packages/wesl/src/PathUtil.d.ts +6 -0
  20. package/dist/tools/packages/wesl/src/RawEmit.d.ts +6 -0
  21. package/dist/tools/packages/wesl/src/Reflection.d.ts +45 -0
  22. package/dist/tools/packages/wesl/src/Scope.d.ts +81 -0
  23. package/dist/tools/packages/wesl/src/StandardTypes.d.ts +13 -0
  24. package/dist/tools/packages/wesl/src/TransformBindingStructs.d.ts +52 -0
  25. package/dist/tools/packages/wesl/src/Util.d.ts +43 -0
  26. package/dist/tools/packages/wesl/src/WESLCollect.d.ts +94 -0
  27. package/dist/tools/packages/wesl/src/WeslBundle.d.ts +13 -0
  28. package/dist/tools/packages/wesl/src/WeslDevice.d.ts +25 -0
  29. package/dist/tools/packages/wesl/src/debug/ASTtoString.d.ts +5 -0
  30. package/dist/tools/packages/wesl/src/debug/ImportToString.d.ts +2 -0
  31. package/dist/tools/packages/wesl/src/debug/LineWrapper.d.ts +21 -0
  32. package/dist/tools/packages/wesl/src/debug/ScopeToString.d.ts +6 -0
  33. package/dist/tools/packages/wesl/src/index.d.ts +11 -0
  34. package/dist/tools/packages/wesl/src/parse/ImportGrammar.d.ts +5 -0
  35. package/dist/tools/packages/wesl/src/parse/Keywords.d.ts +4 -0
  36. package/dist/tools/packages/wesl/src/parse/WeslBaseGrammar.d.ts +5 -0
  37. package/dist/tools/packages/wesl/src/parse/WeslExpression.d.ts +13 -0
  38. package/dist/tools/packages/wesl/src/parse/WeslGrammar.d.ts +80 -0
  39. package/dist/tools/packages/wesl/src/parse/WeslStream.d.ts +44 -0
  40. package/dist/tools/packages/wesl/src/test/BindWESL.test.d.ts +1 -0
  41. package/dist/tools/packages/wesl/src/test/ConditionLinking.test.d.ts +1 -0
  42. package/dist/tools/packages/wesl/src/test/ConditionalTranslationCases.test.d.ts +1 -0
  43. package/dist/tools/packages/wesl/src/test/ErrorLogging.test.d.ts +1 -0
  44. package/dist/tools/packages/wesl/src/test/Expression.test.d.ts +1 -0
  45. package/dist/tools/packages/wesl/src/test/FlattenTreeImport.test.d.ts +1 -0
  46. package/dist/tools/packages/wesl/src/test/ImportCases.test.d.ts +1 -0
  47. package/dist/tools/packages/wesl/src/test/ImportSyntaxCases.test.d.ts +1 -0
  48. package/dist/tools/packages/wesl/src/test/LinkGlob.test.d.ts +1 -0
  49. package/dist/tools/packages/wesl/src/test/LinkPackage.test.d.ts +1 -0
  50. package/dist/tools/packages/wesl/src/test/Linker.test.d.ts +1 -0
  51. package/dist/tools/packages/wesl/src/test/Mangling.test.d.ts +1 -0
  52. package/dist/tools/packages/wesl/src/test/ParseComments.test.d.ts +1 -0
  53. package/dist/tools/packages/wesl/src/test/ParseConditions.test.d.ts +1 -0
  54. package/dist/tools/packages/wesl/src/test/ParseError.test.d.ts +1 -0
  55. package/dist/tools/packages/wesl/src/test/ParseWESL.test.d.ts +1 -0
  56. package/dist/tools/packages/wesl/src/test/PathUtil.test.d.ts +1 -0
  57. package/dist/tools/packages/wesl/src/test/PrettyGrammar.test.d.ts +1 -0
  58. package/dist/tools/packages/wesl/src/test/Reflection.test.d.ts +1 -0
  59. package/dist/tools/packages/wesl/src/test/ScopeWESL.test.d.ts +1 -0
  60. package/dist/tools/packages/wesl/src/test/TestLink.d.ts +21 -0
  61. package/dist/tools/packages/wesl/src/test/TestSetup.d.ts +1 -0
  62. package/dist/tools/packages/wesl/src/test/TestUtil.d.ts +40 -0
  63. package/dist/tools/packages/wesl/src/test/Tokenizer.test.d.ts +1 -0
  64. package/dist/tools/packages/wesl/src/test/TransformBindingStructs.test.d.ts +1 -0
  65. package/dist/tools/packages/wesl/src/test/Util.test.d.ts +1 -0
  66. package/dist/tools/packages/wesl/src/test/VirtualModules.test.d.ts +1 -0
  67. package/dist/tools/packages/wesl/src/test/WeslDevice.test.d.ts +1 -0
  68. package/dist/tools/packages/wesl/src/test/WgslTests.d.ts +0 -0
  69. package/dist/tools/packages/wesl/src/vlq/vlq.d.ts +11 -0
  70. package/package.json +46 -0
  71. package/src/AbstractElems.ts +446 -0
  72. package/src/Assertions.ts +51 -0
  73. package/src/BindIdents.ts +523 -0
  74. package/src/Conditions.ts +74 -0
  75. package/src/FlattenTreeImport.ts +55 -0
  76. package/src/LinkedWesl.ts +184 -0
  77. package/src/Linker.ts +284 -0
  78. package/src/LinkerUtil.ts +29 -0
  79. package/src/LiveDeclarations.ts +31 -0
  80. package/src/LowerAndEmit.ts +413 -0
  81. package/src/Mangler.ts +94 -0
  82. package/src/ParseWESL.ts +157 -0
  83. package/src/ParsedRegistry.ts +120 -0
  84. package/src/PathUtil.ts +31 -0
  85. package/src/RawEmit.ts +102 -0
  86. package/src/Reflection.ts +334 -0
  87. package/src/Scope.ts +162 -0
  88. package/src/StandardTypes.ts +97 -0
  89. package/src/TransformBindingStructs.ts +319 -0
  90. package/src/Util.ts +194 -0
  91. package/src/WESLCollect.ts +614 -0
  92. package/src/WeslBundle.ts +16 -0
  93. package/src/WeslDevice.ts +209 -0
  94. package/src/debug/ASTtoString.ts +290 -0
  95. package/src/debug/ImportToString.ts +29 -0
  96. package/src/debug/LineWrapper.ts +70 -0
  97. package/src/debug/ScopeToString.ts +79 -0
  98. package/src/index.ts +11 -0
  99. package/src/parse/ImportGrammar.ts +157 -0
  100. package/src/parse/Keywords.ts +26 -0
  101. package/src/parse/WeslBaseGrammar.ts +8 -0
  102. package/src/parse/WeslExpression.ts +207 -0
  103. package/src/parse/WeslGrammar.ts +856 -0
  104. package/src/parse/WeslStream.ts +279 -0
  105. package/src/test/BindWESL.test.ts +57 -0
  106. package/src/test/ConditionLinking.test.ts +91 -0
  107. package/src/test/ConditionalTranslationCases.test.ts +56 -0
  108. package/src/test/ErrorLogging.test.ts +30 -0
  109. package/src/test/Expression.test.ts +22 -0
  110. package/src/test/FlattenTreeImport.test.ts +74 -0
  111. package/src/test/ImportCases.test.ts +56 -0
  112. package/src/test/ImportSyntaxCases.test.ts +24 -0
  113. package/src/test/LinkGlob.test.ts +25 -0
  114. package/src/test/LinkPackage.test.ts +26 -0
  115. package/src/test/Linker.test.ts +125 -0
  116. package/src/test/Mangling.test.ts +45 -0
  117. package/src/test/ParseComments.test.ts +36 -0
  118. package/src/test/ParseConditions.test.ts +183 -0
  119. package/src/test/ParseError.test.ts +36 -0
  120. package/src/test/ParseWESL.test.ts +1572 -0
  121. package/src/test/PathUtil.test.ts +34 -0
  122. package/src/test/PrettyGrammar.test.ts +20 -0
  123. package/src/test/Reflection.test.ts +172 -0
  124. package/src/test/ScopeWESL.test.ts +462 -0
  125. package/src/test/TestLink.ts +82 -0
  126. package/src/test/TestSetup.ts +4 -0
  127. package/src/test/TestUtil.ts +126 -0
  128. package/src/test/Tokenizer.test.ts +135 -0
  129. package/src/test/TransformBindingStructs.test.ts +230 -0
  130. package/src/test/Util.test.ts +22 -0
  131. package/src/test/VirtualModules.test.ts +37 -0
  132. package/src/test/WeslDevice.test.ts +265 -0
  133. package/src/test/WgslTests.ts +0 -0
  134. package/src/test/__snapshots__/ParseDirectives.test.ts.snap +25 -0
  135. package/src/test/__snapshots__/ParseWESL.test.ts.snap +119 -0
  136. package/src/test/__snapshots__/RustDirective.test.ts.snap +359 -0
  137. package/src/test/wgsl_1/main.wgsl +3 -0
  138. package/src/test/wgsl_1/util.wgsl +1 -0
  139. package/src/test/wgsl_2/main2.wgsl +3 -0
  140. package/src/test/wgsl_2/util2.wgsl +1 -0
  141. package/src/vlq/vlq.ts +94 -0
@@ -0,0 +1,1572 @@
1
+ import { expect, test } from "vitest";
2
+ import { astToString } from "../debug/ASTtoString.ts";
3
+ import { importToString } from "../debug/ImportToString.ts";
4
+ import { parseTest, parseTestRaw } from "./TestUtil.ts";
5
+
6
+ test("parse empty string", () => {
7
+ const ast = parseTest("");
8
+ expect(astToString(ast.moduleElem)).toMatchInlineSnapshot(`"module"`);
9
+ });
10
+
11
+ test("parse fn foo() { }", () => {
12
+ const src = "fn foo() { }";
13
+ const ast = parseTest(src);
14
+ expect(astToString(ast.moduleElem)).toMatchInlineSnapshot(`
15
+ "module
16
+ fn foo()
17
+ decl %foo
18
+ statement
19
+ text '{ }'"
20
+ `);
21
+ });
22
+
23
+ test("parse fn with calls", () => {
24
+ const src = "fn foo() { foo(); bar(); }";
25
+ const ast = parseTest(src);
26
+ expect(astToString(ast.moduleElem)).toMatchInlineSnapshot(`
27
+ "module
28
+ fn foo()
29
+ decl %foo
30
+ statement
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 = parseTest(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 = parseTest(src);
61
+ const astString = astToString(ast.moduleElem);
62
+ expect(astString).toMatchInlineSnapshot(`
63
+ "module
64
+ gvar %x : i32
65
+ text 'var '
66
+ typeDecl %x : i32
67
+ decl %x
68
+ text ': '
69
+ type i32
70
+ ref i32
71
+ text ' = 1;'"
72
+ `);
73
+ });
74
+
75
+ test("parse alias", () => {
76
+ const src = `alias Num = i32;`;
77
+ const ast = parseTest(src);
78
+ const astString = astToString(ast.moduleElem);
79
+ expect(astString).toMatchInlineSnapshot(`
80
+ "module
81
+ alias %Num=i32
82
+ text 'alias '
83
+ decl %Num
84
+ text ' = '
85
+ type i32
86
+ ref i32
87
+ text ';'"
88
+ `);
89
+ });
90
+
91
+ test("parse const", () => {
92
+ const src = `const y = 11u;`;
93
+ const ast = parseTest(src);
94
+ const astString = astToString(ast.moduleElem);
95
+ expect(astString).toMatchInlineSnapshot(`
96
+ "module
97
+ const %y
98
+ text 'const '
99
+ typeDecl %y
100
+ decl %y
101
+ text ' = 11u;'"
102
+ `);
103
+ });
104
+
105
+ test("parse override ", () => {
106
+ const src = `override z: f32;`;
107
+ const ast = parseTest(src);
108
+ const astString = astToString(ast.moduleElem);
109
+ expect(astString).toMatchInlineSnapshot(`
110
+ "module
111
+ override %z : f32
112
+ text 'override '
113
+ typeDecl %z : f32
114
+ decl %z
115
+ text ': '
116
+ type f32
117
+ ref f32
118
+ text ';'"
119
+ `);
120
+ });
121
+
122
+ test("parse const_assert", () => {
123
+ const src = `const_assert x < y;`;
124
+ const ast = parseTest(src);
125
+ const astString = astToString(ast.moduleElem);
126
+ expect(astString).toMatchInlineSnapshot(`
127
+ "module
128
+ assert
129
+ text 'const_assert '
130
+ ref x
131
+ text ' < '
132
+ ref y
133
+ text ';'"
134
+ `);
135
+ });
136
+
137
+ test("parse struct", () => {
138
+ const src = `struct foo { bar: i32, zip: u32, } ;`;
139
+ const ast = parseTest(src);
140
+ const astString = astToString(ast.moduleElem);
141
+ expect(astString).toMatchInlineSnapshot(`
142
+ "module
143
+ struct foo
144
+ text 'struct '
145
+ decl %foo
146
+ text ' { '
147
+ member bar: i32
148
+ name bar
149
+ text ': '
150
+ type i32
151
+ ref i32
152
+ text ', '
153
+ member zip: u32
154
+ name zip
155
+ text ': '
156
+ type u32
157
+ ref u32
158
+ text ', }'
159
+ text ' ;'"
160
+ `);
161
+ });
162
+
163
+ test("parse global diagnostic", () => {
164
+ const src = `
165
+ diagnostic(off,derivative_uniformity);
166
+
167
+ fn main() {}
168
+ `;
169
+ const ast = parseTest(src);
170
+ const astString = astToString(ast.moduleElem);
171
+ expect(astString).toMatchInlineSnapshot(`
172
+ "module
173
+ text '
174
+ '
175
+ directive diagnostic(off, derivative_uniformity)
176
+ text '
177
+
178
+ '
179
+ fn main()
180
+ decl %main
181
+ statement
182
+ text '{}'
183
+ text '
184
+ '"
185
+ `);
186
+ });
187
+
188
+ test("parse @attribute before fn", () => {
189
+ const src = `@compute fn main() {} `;
190
+ const ast = parseTest(src);
191
+ const astString = astToString(ast.moduleElem);
192
+ expect(astString).toMatchInlineSnapshot(`
193
+ "module
194
+ fn main() @compute
195
+ attribute @compute
196
+ decl %main
197
+ statement
198
+ text '{}'
199
+ text ' '"
200
+ `);
201
+ });
202
+
203
+ test("parse @compute @workgroup_size(a, b, 1) before fn", () => {
204
+ const src = `
205
+ @compute
206
+ @workgroup_size(a, b, 1)
207
+ fn main() {}
208
+ `;
209
+ const ast = parseTest(src);
210
+ const astString = astToString(ast.moduleElem);
211
+ expect(astString).toMatchInlineSnapshot(`
212
+ "module
213
+ text '
214
+ '
215
+ fn main() @compute @workgroup_size
216
+ attribute @compute
217
+ attribute @workgroup_size(ref a, ref b, '1')
218
+ expression ref a
219
+ ref a
220
+ expression ref b
221
+ ref b
222
+ expression '1'
223
+ text '1'
224
+ decl %main
225
+ statement
226
+ text '{}'
227
+ text '
228
+ '"
229
+ `);
230
+ });
231
+
232
+ test("parse top level var", () => {
233
+ const src = `
234
+ @group(0) @binding(0) var<uniform> u: Uniforms;
235
+
236
+ fn main() {}
237
+ `;
238
+ const ast = parseTest(src);
239
+ const astString = astToString(ast.moduleElem);
240
+ expect(astString).toMatchInlineSnapshot(`
241
+ "module
242
+ text '
243
+ '
244
+ gvar %u : Uniforms @group @binding
245
+ attribute @group('0')
246
+ expression '0'
247
+ text '0'
248
+ text ' '
249
+ attribute @binding('0')
250
+ expression '0'
251
+ text '0'
252
+ text ' var<'
253
+ type uniform
254
+ ref uniform
255
+ text '> '
256
+ typeDecl %u : Uniforms
257
+ decl %u
258
+ text ': '
259
+ type Uniforms
260
+ ref Uniforms
261
+ text ';'
262
+ text '
263
+
264
+ '
265
+ fn main()
266
+ decl %main
267
+ statement
268
+ text '{}'
269
+ text '
270
+ '"
271
+ `);
272
+ });
273
+
274
+ test("parse top level override and const", () => {
275
+ const src = `
276
+ override x = 21;
277
+ const y = 1;
278
+
279
+ fn main() {}
280
+ `;
281
+ const ast = parseTest(src);
282
+ const astString = astToString(ast.moduleElem);
283
+ expect(astString).toMatchInlineSnapshot(`
284
+ "module
285
+ text '
286
+ '
287
+ override %x
288
+ text 'override '
289
+ typeDecl %x
290
+ decl %x
291
+ text ' = 21;'
292
+ text '
293
+ '
294
+ const %y
295
+ text 'const '
296
+ typeDecl %y
297
+ decl %y
298
+ text ' = 1;'
299
+ text '
300
+
301
+ '
302
+ fn main()
303
+ decl %main
304
+ statement
305
+ text '{}'
306
+ text '
307
+ '"
308
+ `);
309
+ });
310
+
311
+ test("parse root level ;;", () => {
312
+ const src = ";;";
313
+ const ast = parseTest(src);
314
+ const astString = astToString(ast.moduleElem);
315
+ expect(astString).toMatchInlineSnapshot(`
316
+ "module
317
+ text ';;'"
318
+ `);
319
+ });
320
+
321
+ test("parse simple alias", () => {
322
+ const src = `alias NewType = OldType;`;
323
+ const ast = parseTest(src);
324
+ const astString = astToString(ast.moduleElem);
325
+ expect(astString).toMatchInlineSnapshot(`
326
+ "module
327
+ alias %NewType=OldType
328
+ text 'alias '
329
+ decl %NewType
330
+ text ' = '
331
+ type OldType
332
+ ref OldType
333
+ text ';'"
334
+ `);
335
+ });
336
+
337
+ test("parse array alias", () => {
338
+ const src = `
339
+ alias Points3 = array<Point, 3>;
340
+ `;
341
+ const ast = parseTest(src);
342
+ const astString = astToString(ast.moduleElem);
343
+ expect(astString).toMatchInlineSnapshot(`
344
+ "module
345
+ text '
346
+ '
347
+ alias %Points3=array<Point, '3'>
348
+ text 'alias '
349
+ decl %Points3
350
+ text ' = '
351
+ type array<Point, '3'>
352
+ ref array
353
+ text '<'
354
+ type Point
355
+ ref Point
356
+ text ', '
357
+ expression '3'
358
+ text '3'
359
+ text '>'
360
+ text ';'
361
+ text '
362
+ '"
363
+ `);
364
+ });
365
+
366
+ test("fnDecl parses fn with return type", () => {
367
+ const src = `fn foo() -> MyType { }`;
368
+ const ast = parseTest(src);
369
+ const astString = astToString(ast.moduleElem);
370
+ expect(astString).toMatchInlineSnapshot(`
371
+ "module
372
+ fn foo() -> MyType
373
+ decl %foo
374
+ type MyType
375
+ ref MyType
376
+ statement
377
+ text '{ }'"
378
+ `);
379
+ });
380
+
381
+ test("fnDecl parses :type specifier in fn args", () => {
382
+ const src = `
383
+ fn foo(a: MyType) { }
384
+ `;
385
+ const ast = parseTest(src);
386
+ const astString = astToString(ast.moduleElem);
387
+ expect(astString).toMatchInlineSnapshot(`
388
+ "module
389
+ text '
390
+ '
391
+ fn foo(a: MyType)
392
+ decl %foo
393
+ param
394
+ decl %a
395
+ typeDecl %a : MyType
396
+ text ': '
397
+ type MyType
398
+ ref MyType
399
+ statement
400
+ text '{ }'
401
+ text '
402
+ '"
403
+ `);
404
+ });
405
+
406
+ test("fnDecl parses :type specifier in fn block", () => {
407
+ const src = `
408
+ fn foo() {
409
+ var b:MyType;
410
+ }
411
+ `;
412
+ const ast = parseTest(src);
413
+ const astString = astToString(ast.moduleElem);
414
+ expect(astString).toMatchInlineSnapshot(`
415
+ "module
416
+ text '
417
+ '
418
+ fn foo()
419
+ decl %foo
420
+ statement
421
+ text '{
422
+ '
423
+ var %b : MyType
424
+ text 'var '
425
+ typeDecl %b : MyType
426
+ decl %b
427
+ text ':'
428
+ type MyType
429
+ ref MyType
430
+ text ';
431
+ }'
432
+ text '
433
+ '"
434
+ `);
435
+ });
436
+
437
+ test("parse type in <template> in fn args", () => {
438
+ const src = `
439
+ fn foo(a: vec2<MyStruct>) { };`;
440
+ const ast = parseTest(src);
441
+ const astString = astToString(ast.moduleElem);
442
+ expect(astString).toMatchInlineSnapshot(`
443
+ "module
444
+ text '
445
+ '
446
+ fn foo(a: vec2<MyStruct>)
447
+ decl %foo
448
+ param
449
+ decl %a
450
+ typeDecl %a : vec2<MyStruct>
451
+ text ': '
452
+ type vec2<MyStruct>
453
+ ref vec2
454
+ text '<'
455
+ type MyStruct
456
+ ref MyStruct
457
+ text '>'
458
+ statement
459
+ text '{ }'
460
+ text ';'"
461
+ `);
462
+ });
463
+
464
+ test("parse simple templated type", () => {
465
+ const src = `fn main(a: array<MyStruct,4>) { }`;
466
+
467
+ const ast = parseTest(src);
468
+ const astString = astToString(ast.moduleElem);
469
+ expect(astString).toMatchInlineSnapshot(`
470
+ "module
471
+ fn main(a: array<MyStruct, '4'>)
472
+ decl %main
473
+ param
474
+ decl %a
475
+ typeDecl %a : array<MyStruct, '4'>
476
+ text ': '
477
+ type array<MyStruct, '4'>
478
+ ref array
479
+ text '<'
480
+ type MyStruct
481
+ ref MyStruct
482
+ text ','
483
+ expression '4'
484
+ text '4'
485
+ text '>'
486
+ statement
487
+ text '{ }'"
488
+ `);
489
+ });
490
+
491
+ test("parse with space before template", () => {
492
+ const src = `fn main(a: array <MyStruct,4>) { }`;
493
+ const ast = parseTest(src);
494
+ const astString = astToString(ast.moduleElem);
495
+ expect(astString).toMatchInlineSnapshot(`
496
+ "module
497
+ fn main(a: array<MyStruct, '4'>)
498
+ decl %main
499
+ param
500
+ decl %a
501
+ typeDecl %a : array<MyStruct, '4'>
502
+ text ': '
503
+ type array<MyStruct, '4'>
504
+ ref array
505
+ text ' <'
506
+ type MyStruct
507
+ ref MyStruct
508
+ text ','
509
+ expression '4'
510
+ text '4'
511
+ text '>'
512
+ statement
513
+ text '{ }'"
514
+ `);
515
+ });
516
+
517
+ test("parse nested template that ends with >> ", () => {
518
+ const src = `fn main(a: vec2<array <MyStruct,4>>) { }`;
519
+ const ast = parseTest(src);
520
+ const astString = astToString(ast.moduleElem);
521
+ expect(astString).toMatchInlineSnapshot(`
522
+ "module
523
+ fn main(a: vec2<array<MyStruct, '4'>>)
524
+ decl %main
525
+ param
526
+ decl %a
527
+ typeDecl %a : vec2<array<MyStruct, '4'>>
528
+ text ': '
529
+ type vec2<array<MyStruct, '4'>>
530
+ ref vec2
531
+ text '<'
532
+ type array<MyStruct, '4'>
533
+ ref array
534
+ text ' <'
535
+ type MyStruct
536
+ ref MyStruct
537
+ text ','
538
+ expression '4'
539
+ text '4'
540
+ text '>'
541
+ text '>'
542
+ statement
543
+ text '{ }'"
544
+ `);
545
+ });
546
+
547
+ test("parse type in <template> in global var", () => {
548
+ const src = `var<private> x:array<MyStruct, 8>;`;
549
+
550
+ const ast = parseTest(src);
551
+ const astString = astToString(ast.moduleElem);
552
+ expect(astString).toMatchInlineSnapshot(`
553
+ "module
554
+ gvar %x : array<MyStruct, '8'>
555
+ text 'var<'
556
+ type private
557
+ ref private
558
+ text '> '
559
+ typeDecl %x : array<MyStruct, '8'>
560
+ decl %x
561
+ text ':'
562
+ type array<MyStruct, '8'>
563
+ ref array
564
+ text '<'
565
+ type MyStruct
566
+ ref MyStruct
567
+ text ', '
568
+ expression '8'
569
+ text '8'
570
+ text '>'
571
+ text ';'"
572
+ `);
573
+ });
574
+
575
+ test("parse for(;;) {} not as a fn call", () => {
576
+ const src = `
577
+ fn main() {
578
+ for (var a = 1; a < 10; a++) {}
579
+ }
580
+ `;
581
+ const ast = parseTest(src);
582
+ const astString = astToString(ast.moduleElem);
583
+ expect(astString).toMatchInlineSnapshot(`
584
+ "module
585
+ text '
586
+ '
587
+ fn main()
588
+ decl %main
589
+ statement
590
+ text '{
591
+ for ('
592
+ var %a
593
+ text 'var '
594
+ typeDecl %a
595
+ decl %a
596
+ text ' = 1'
597
+ text '; '
598
+ ref a
599
+ text ' < 10; '
600
+ ref a
601
+ text '++) '
602
+ statement
603
+ text '{}'
604
+ text '
605
+ }'
606
+ text '
607
+ '"
608
+ `);
609
+ });
610
+
611
+ test("eolf followed by blank line", () => {
612
+ const src = `
613
+ fn foo() { }
614
+ `;
615
+ const ast = parseTest(src);
616
+ const astString = astToString(ast.moduleElem);
617
+ expect(astString).toMatchInlineSnapshot(`
618
+ "module
619
+ text '
620
+ '
621
+ fn foo()
622
+ decl %foo
623
+ statement
624
+ text '{ }'
625
+ text '
626
+ '"
627
+ `);
628
+ });
629
+
630
+ test("parse fn with attributes and suffix comma", () => {
631
+ const src = `
632
+ @compute
633
+ @workgroup_size(workgroupThreads, 1, 1)
634
+ fn main(
635
+ @builtin(global_invocation_id) grid: vec3<u32>,
636
+ @builtin(local_invocation_index) localIndex: u32,
637
+ ) { }
638
+ `;
639
+ const ast = parseTest(src);
640
+ const astString = astToString(ast.moduleElem);
641
+ expect(astString).toMatchInlineSnapshot(`
642
+ "module
643
+ text '
644
+ '
645
+ fn main(grid: vec3<u32>, localIndex: u32) @compute @workgroup_size
646
+ attribute @compute
647
+ attribute @workgroup_size(ref workgroupThreads, '1', '1')
648
+ expression ref workgroupThreads
649
+ ref workgroupThreads
650
+ expression '1'
651
+ text '1'
652
+ expression '1'
653
+ text '1'
654
+ decl %main
655
+ param
656
+ attribute @builtin(global_invocation_id)
657
+ text ' '
658
+ decl %grid
659
+ typeDecl %grid : vec3<u32>
660
+ text ': '
661
+ type vec3<u32>
662
+ ref vec3
663
+ text '<'
664
+ type u32
665
+ ref u32
666
+ text '>'
667
+ param
668
+ attribute @builtin(local_invocation_index)
669
+ text ' '
670
+ decl %localIndex
671
+ typeDecl %localIndex : u32
672
+ text ': '
673
+ type u32
674
+ ref u32
675
+ statement
676
+ text '{ }'
677
+ text '
678
+ '"
679
+ `);
680
+ });
681
+
682
+ test("parse fn", () => {
683
+ const src = `fn foo(x: i32, y: u32) -> f32 { return 1.0; }`;
684
+ const ast = parseTest(src);
685
+ const astString = astToString(ast.moduleElem);
686
+ expect(astString).toMatchInlineSnapshot(`
687
+ "module
688
+ fn foo(x: i32, y: u32) -> f32
689
+ decl %foo
690
+ param
691
+ decl %x
692
+ typeDecl %x : i32
693
+ text ': '
694
+ type i32
695
+ ref i32
696
+ param
697
+ decl %y
698
+ typeDecl %y : u32
699
+ text ': '
700
+ type u32
701
+ ref u32
702
+ type f32
703
+ ref f32
704
+ statement
705
+ text '{ return 1.0; }'"
706
+ `);
707
+ });
708
+
709
+ test("parse @attribute before fn", () => {
710
+ const src = `@compute fn main() {} `;
711
+ const ast = parseTest(src);
712
+ const astString = astToString(ast.moduleElem);
713
+ expect(astString).toMatchInlineSnapshot(`
714
+ "module
715
+ fn main() @compute
716
+ attribute @compute
717
+ decl %main
718
+ statement
719
+ text '{}'
720
+ text ' '"
721
+ `);
722
+ });
723
+
724
+ test("import package::foo::bar;", ctx => {
725
+ const src = ctx.task.name;
726
+ const ast = parseTest(src);
727
+ const astString = astToString(ast.moduleElem);
728
+ expect(astString).toMatchInlineSnapshot(`
729
+ "module
730
+ import package::foo::bar;"
731
+ `);
732
+ });
733
+
734
+ // TODO
735
+ test.skip("parse foo::bar(); ", () => {
736
+ const src = "fn main() { foo::bar(); }";
737
+ const ast = parseTest(src);
738
+ const astString = astToString(ast.moduleElem);
739
+ expect(astString).toMatchInlineSnapshot();
740
+ });
741
+
742
+ // TODO
743
+ test.skip("parse let x: foo::bar; ", () => {
744
+ const src = "fn main() { let x: foo::bar = 1; }";
745
+ const ast = parseTest(src);
746
+ const astString = astToString(ast.moduleElem);
747
+ expect(astString).toMatchInlineSnapshot();
748
+ });
749
+
750
+ // TODO (consdier should this be legal?)
751
+ test.skip("parse var x: foo.bar;", () => {
752
+ const src = `
753
+ import foo::bar;
754
+ var<private> x: foo::bar;
755
+ fn main() { }
756
+ `;
757
+
758
+ const ast = parseTest(src);
759
+ const astString = astToString(ast.moduleElem);
760
+ expect(astString).toMatchInlineSnapshot();
761
+ });
762
+
763
+ test("parse switch statement", () => {
764
+ const src = `
765
+ fn main(x: i32) {
766
+ switch (x) {
767
+ case 1: { break; }
768
+ default: { break; }
769
+ }
770
+ }
771
+ `;
772
+ const ast = parseTest(src);
773
+ const astString = astToString(ast.moduleElem);
774
+ expect(astString).toMatchInlineSnapshot(`
775
+ "module
776
+ text '
777
+ '
778
+ fn main(x: i32)
779
+ decl %main
780
+ param
781
+ decl %x
782
+ typeDecl %x : i32
783
+ text ': '
784
+ type i32
785
+ ref i32
786
+ statement
787
+ text '{
788
+ switch ('
789
+ ref x
790
+ text ') {
791
+ '
792
+ switch-clause
793
+ text 'case 1: '
794
+ statement
795
+ text '{ break; }'
796
+ text '
797
+ '
798
+ switch-clause
799
+ text 'default: '
800
+ statement
801
+ text '{ break; }'
802
+ text '
803
+ }
804
+ }'
805
+ text '
806
+ '"
807
+ `);
808
+ });
809
+
810
+ test("parse switch statement-2", () => {
811
+ const src = `
812
+
813
+ fn main(x: u32) {
814
+ switch ( code ) {
815
+ case 5u: { if 1 > 0 { } }
816
+ default: { break; }
817
+ }
818
+ }
819
+ `;
820
+ const ast = parseTest(src);
821
+ const astString = astToString(ast.moduleElem);
822
+ expect(astString).toMatchInlineSnapshot(`
823
+ "module
824
+ text '
825
+
826
+ '
827
+ fn main(x: u32)
828
+ decl %main
829
+ param
830
+ decl %x
831
+ typeDecl %x : u32
832
+ text ': '
833
+ type u32
834
+ ref u32
835
+ statement
836
+ text '{
837
+ switch ( '
838
+ ref code
839
+ text ' ) {
840
+ '
841
+ switch-clause
842
+ text 'case 5u: '
843
+ statement
844
+ text '{ if 1 > 0 '
845
+ statement
846
+ text '{ }'
847
+ text ' }'
848
+ text '
849
+ '
850
+ switch-clause
851
+ text 'default: '
852
+ statement
853
+ text '{ break; }'
854
+ text '
855
+ }
856
+ }'
857
+ text '
858
+ '"
859
+ `);
860
+ });
861
+
862
+ test("parse struct constructor in assignment", () => {
863
+ const src = `
864
+ fn main() {
865
+ var x = AStruct(1u);
866
+ }
867
+ `;
868
+ const ast = parseTest(src);
869
+ const astString = astToString(ast.moduleElem);
870
+ expect(astString).toMatchInlineSnapshot(`
871
+ "module
872
+ text '
873
+ '
874
+ fn main()
875
+ decl %main
876
+ statement
877
+ text '{
878
+ '
879
+ var %x
880
+ text 'var '
881
+ typeDecl %x
882
+ decl %x
883
+ text ' = '
884
+ ref AStruct
885
+ text '(1u)'
886
+ text ';
887
+ }'
888
+ text '
889
+ '"
890
+ `);
891
+ });
892
+
893
+ test("parse struct.member (component_or_swizzle)", () => {
894
+ const src = `
895
+ fn main() {
896
+ let x = u.frame;
897
+ }
898
+ `;
899
+ const ast = parseTest(src);
900
+ const astString = astToString(ast.moduleElem);
901
+ expect(astString).toMatchInlineSnapshot(`
902
+ "module
903
+ text '
904
+ '
905
+ fn main()
906
+ decl %main
907
+ statement
908
+ text '{
909
+ let '
910
+ typeDecl %x
911
+ decl %x
912
+ text ' = '
913
+ memberRef u.frame
914
+ ref u
915
+ text '.'
916
+ name frame
917
+ text ';
918
+ }'
919
+ text '
920
+ '"
921
+ `);
922
+ });
923
+
924
+ test("var<workgroup> work: array<u32, 128>;", ctx => {
925
+ const ast = parseTest(ctx.task.name);
926
+ const astString = astToString(ast.moduleElem);
927
+ expect(astString).toMatchInlineSnapshot(`
928
+ "module
929
+ gvar %work : array<u32, '128'>
930
+ text 'var<'
931
+ type workgroup
932
+ ref workgroup
933
+ text '> '
934
+ typeDecl %work : array<u32, '128'>
935
+ decl %work
936
+ text ': '
937
+ type array<u32, '128'>
938
+ ref array
939
+ text '<'
940
+ type u32
941
+ ref u32
942
+ text ', '
943
+ expression '128'
944
+ text '128'
945
+ text '>'
946
+ text ';'"
947
+ `);
948
+ });
949
+
950
+ test("fn f() { _ = 1; }", ctx => {
951
+ const ast = parseTest(ctx.task.name);
952
+ const astString = astToString(ast.moduleElem);
953
+ expect(astString).toMatchInlineSnapshot(`
954
+ "module
955
+ fn f()
956
+ decl %f
957
+ statement
958
+ text '{ _ = 1; }'"
959
+ `);
960
+ });
961
+
962
+ test("var foo: vec2<f32 >= vec2( 0.5, -0.5);", ctx => {
963
+ const ast = parseTest(ctx.task.name);
964
+ const astString = astToString(ast.moduleElem);
965
+ expect(astString).toMatchInlineSnapshot(`
966
+ "module
967
+ gvar %foo : vec2<f32>
968
+ text 'var '
969
+ typeDecl %foo : vec2<f32>
970
+ decl %foo
971
+ text ': '
972
+ type vec2<f32>
973
+ ref vec2
974
+ text '<'
975
+ type f32
976
+ ref f32
977
+ text ' >'
978
+ text '= '
979
+ ref vec2
980
+ text '( 0.5, -0.5);'"
981
+ `);
982
+ });
983
+
984
+ test("fn main() { var tmp: array<i32, 1 << 1>=array(1, 2); }", ctx => {
985
+ const ast = parseTest(ctx.task.name);
986
+ const astString = astToString(ast.moduleElem);
987
+ expect(astString).toMatchInlineSnapshot(`
988
+ "module
989
+ fn main()
990
+ decl %main
991
+ statement
992
+ text '{ '
993
+ var %tmp : array<i32, '1 << 1'>
994
+ text 'var '
995
+ typeDecl %tmp : array<i32, '1 << 1'>
996
+ decl %tmp
997
+ text ': '
998
+ type array<i32, '1 << 1'>
999
+ ref array
1000
+ text '<'
1001
+ type i32
1002
+ ref i32
1003
+ text ', '
1004
+ expression '1 << 1'
1005
+ text '1 << 1'
1006
+ text '>'
1007
+ text '='
1008
+ ref array
1009
+ text '(1, 2)'
1010
+ text '; }'"
1011
+ `);
1012
+ });
1013
+
1014
+ test("import a::b::c;", ctx => {
1015
+ const ast = parseTest(ctx.task.name);
1016
+ const astString = astToString(ast.moduleElem);
1017
+ expect(astString).toMatchInlineSnapshot(`
1018
+ "module
1019
+ import a::b::c;"
1020
+ `);
1021
+ });
1022
+
1023
+ test("import package::file1::{foo, bar};", ctx => {
1024
+ const src = ctx.task.name;
1025
+ const ast = parseTest(src);
1026
+ const astString = astToString(ast.moduleElem);
1027
+ expect(astString).toMatchInlineSnapshot(`
1028
+ "module
1029
+ import package::file1::{foo, bar};"
1030
+ `);
1031
+ });
1032
+
1033
+ test("import package::file1::{foo, bar};", ctx => {
1034
+ const src = ctx.task.name;
1035
+ const ast = parseTest(src);
1036
+ const imps = ast.imports.map(t => importToString(t)).join("\n");
1037
+
1038
+ expect(imps).toMatchInlineSnapshot(`"package::file1::{foo, bar};"`);
1039
+ });
1040
+
1041
+ test("import foo_bar::boo;", ctx => {
1042
+ const ast = parseTest(ctx.task.name);
1043
+ const astString = astToString(ast.moduleElem);
1044
+ expect(astString).toMatchInlineSnapshot(`
1045
+ "module
1046
+ import foo_bar::boo;"
1047
+ `);
1048
+ });
1049
+
1050
+ test(`import a::{ b };`, ctx => {
1051
+ const ast = parseTest(ctx.task.name);
1052
+ const astString = astToString(ast.moduleElem);
1053
+ expect(astString).toMatchInlineSnapshot(`
1054
+ "module
1055
+ import a::{b};"
1056
+ `);
1057
+ });
1058
+
1059
+ test(`import a::{ b, c::{d, e}, f };`, ctx => {
1060
+ const src = ctx.task.name;
1061
+ const ast = parseTest(src);
1062
+ const astString = astToString(ast.moduleElem);
1063
+
1064
+ expect(astString).toMatchInlineSnapshot(`
1065
+ "module
1066
+ import a::{b, c::{d, e}, f};"
1067
+ `);
1068
+ });
1069
+
1070
+ test(`parse ptr`, ctx => {
1071
+ const src = `
1072
+ var particles: ptr<storage, f32, read_write>;
1073
+ `;
1074
+ const ast = parseTest(src);
1075
+ const astString = astToString(ast.moduleElem);
1076
+ expect(astString).toMatchInlineSnapshot(`
1077
+ "module
1078
+ text '
1079
+ '
1080
+ gvar %particles : ptr<storage, f32, read_write>
1081
+ text 'var '
1082
+ typeDecl %particles : ptr<storage, f32, read_write>
1083
+ decl %particles
1084
+ text ': '
1085
+ type ptr<storage, f32, read_write>
1086
+ ref ptr
1087
+ text '<'
1088
+ type storage
1089
+ ref storage
1090
+ text ', '
1091
+ type f32
1092
+ ref f32
1093
+ text ', '
1094
+ type read_write
1095
+ ref read_write
1096
+ text '>'
1097
+ text ';'
1098
+ text '
1099
+ '"
1100
+ `);
1101
+ });
1102
+
1103
+ test(`parse ptr with internal array`, ctx => {
1104
+ const src = `
1105
+ var particles: ptr<storage, array<f32>, read_write>;
1106
+ `;
1107
+ const ast = parseTest(src);
1108
+ const astString = astToString(ast.moduleElem);
1109
+ expect(astString).toMatchInlineSnapshot(`
1110
+ "module
1111
+ text '
1112
+ '
1113
+ gvar %particles : ptr<storage, array<f32>, read_write>
1114
+ text 'var '
1115
+ typeDecl %particles : ptr<storage, array<f32>, read_write>
1116
+ decl %particles
1117
+ text ': '
1118
+ type ptr<storage, array<f32>, read_write>
1119
+ ref ptr
1120
+ text '<'
1121
+ type storage
1122
+ ref storage
1123
+ text ', '
1124
+ type array<f32>
1125
+ ref array
1126
+ text '<'
1127
+ type f32
1128
+ ref f32
1129
+ text '>'
1130
+ text ', '
1131
+ type read_write
1132
+ ref read_write
1133
+ text '>'
1134
+ text ';'
1135
+ text '
1136
+ '"
1137
+ `);
1138
+ });
1139
+
1140
+ test(`parse binding struct`, ctx => {
1141
+ const src = `
1142
+ struct Bindings {
1143
+ @group(0) @binding(0) particles: ptr<storage, array<f32>, read_write>,
1144
+ }
1145
+ `;
1146
+ const ast = parseTest(src);
1147
+ const astString = astToString(ast.moduleElem);
1148
+ expect(astString).toMatchInlineSnapshot(`
1149
+ "module
1150
+ text '
1151
+ '
1152
+ struct Bindings
1153
+ text 'struct '
1154
+ decl %Bindings
1155
+ text ' {
1156
+ '
1157
+ member @group @binding particles: ptr<storage, array<f32>, read_write>
1158
+ attribute @group('0')
1159
+ expression '0'
1160
+ text '0'
1161
+ text ' '
1162
+ attribute @binding('0')
1163
+ expression '0'
1164
+ text '0'
1165
+ text ' '
1166
+ name particles
1167
+ text ': '
1168
+ type ptr<storage, array<f32>, read_write>
1169
+ ref ptr
1170
+ text '<'
1171
+ type storage
1172
+ ref storage
1173
+ text ', '
1174
+ type array<f32>
1175
+ ref array
1176
+ text '<'
1177
+ type f32
1178
+ ref f32
1179
+ text '>'
1180
+ text ', '
1181
+ type read_write
1182
+ ref read_write
1183
+ text '>'
1184
+ text ',
1185
+ }'
1186
+ text '
1187
+ '"
1188
+ `);
1189
+ });
1190
+
1191
+ test(`parse struct reference`, () => {
1192
+ const src = `
1193
+ fn f() { let x = a.b[0]; };
1194
+ `;
1195
+ const ast = parseTest(src);
1196
+ const astString = astToString(ast.moduleElem);
1197
+ expect(astString).toMatchInlineSnapshot(`
1198
+ "module
1199
+ text '
1200
+ '
1201
+ fn f()
1202
+ decl %f
1203
+ statement
1204
+ text '{ let '
1205
+ typeDecl %x
1206
+ decl %x
1207
+ text ' = '
1208
+ memberRef a.b[0]
1209
+ ref a
1210
+ text '.'
1211
+ name b
1212
+ stuff
1213
+ text '[0]'
1214
+ text '; }'
1215
+ text ';
1216
+ '"
1217
+ `);
1218
+ });
1219
+
1220
+ test("member reference with extra components", () => {
1221
+ const src = `
1222
+ fn foo() {
1223
+ output[ out + 0u ] = c.p0.t0.x;
1224
+ }
1225
+ `;
1226
+ const ast = parseTest(src);
1227
+ const astString = astToString(ast.moduleElem);
1228
+ expect(astString).toMatchInlineSnapshot(`
1229
+ "module
1230
+ text '
1231
+ '
1232
+ fn foo()
1233
+ decl %foo
1234
+ statement
1235
+ text '{
1236
+ '
1237
+ ref output
1238
+ text '[ '
1239
+ ref out
1240
+ text ' + 0u ] = '
1241
+ memberRef c.p0.t0.x
1242
+ ref c
1243
+ text '.'
1244
+ name p0
1245
+ stuff
1246
+ text '.t0.x'
1247
+ text ';
1248
+ }'
1249
+ text '
1250
+ '"
1251
+ `);
1252
+ });
1253
+
1254
+ test("parse let declaration", () => {
1255
+ const src = `
1256
+ fn vertexMain() {
1257
+ let char = array<u32, 2>(0, 0);
1258
+ }
1259
+ `;
1260
+ const ast = parseTest(src);
1261
+ const astString = astToString(ast.moduleElem);
1262
+ expect(astString).toMatchInlineSnapshot(`
1263
+ "module
1264
+ text '
1265
+ '
1266
+ fn vertexMain()
1267
+ decl %vertexMain
1268
+ statement
1269
+ text '{
1270
+ let '
1271
+ typeDecl %char
1272
+ decl %char
1273
+ text ' = '
1274
+ ref array
1275
+ text '<'
1276
+ type u32
1277
+ ref u32
1278
+ text ', '
1279
+ expression '2'
1280
+ text '2'
1281
+ text '>(0, 0);
1282
+ }'
1283
+ text '
1284
+ '"
1285
+ `);
1286
+ });
1287
+
1288
+ test("parse let declaration with type", () => {
1289
+ const src = `
1290
+ fn vertexMain() {
1291
+ let char : u32 = 0;
1292
+ }
1293
+ `;
1294
+ const ast = parseTest(src);
1295
+ const astString = astToString(ast.moduleElem);
1296
+ expect(astString).toMatchInlineSnapshot(`
1297
+ "module
1298
+ text '
1299
+ '
1300
+ fn vertexMain()
1301
+ decl %vertexMain
1302
+ statement
1303
+ text '{
1304
+ let '
1305
+ typeDecl %char : u32
1306
+ decl %char
1307
+ text ' : '
1308
+ type u32
1309
+ ref u32
1310
+ text ' = 0;
1311
+ }'
1312
+ text '
1313
+ '"
1314
+ `);
1315
+ });
1316
+
1317
+ test("separator in let assignment", () => {
1318
+ const src = `
1319
+ fn vertexMain() {
1320
+ let a = b::c;
1321
+ }
1322
+ `;
1323
+ const ast = parseTestRaw(src);
1324
+ const astString = astToString(ast.moduleElem);
1325
+ expect(astString).toMatchInlineSnapshot(`
1326
+ "module
1327
+ text '
1328
+ '
1329
+ fn vertexMain()
1330
+ decl %vertexMain
1331
+ statement
1332
+ text '{
1333
+ let '
1334
+ typeDecl %a
1335
+ decl %a
1336
+ text ' = '
1337
+ ref b::c
1338
+ text ';
1339
+ }'
1340
+ text '
1341
+ '"
1342
+ `);
1343
+ });
1344
+
1345
+ test("separator in fn call ", () => {
1346
+ const src = `
1347
+ fn vertexMain() {
1348
+ b::c();
1349
+ }
1350
+ `;
1351
+ const ast = parseTestRaw(src);
1352
+ const astString = astToString(ast.moduleElem);
1353
+ expect(astString).toMatchInlineSnapshot(`
1354
+ "module
1355
+ text '
1356
+ '
1357
+ fn vertexMain()
1358
+ decl %vertexMain
1359
+ statement
1360
+ text '{
1361
+ '
1362
+ ref b::c
1363
+ text '();
1364
+ }'
1365
+ text '
1366
+ '"
1367
+ `);
1368
+ });
1369
+
1370
+ test("binding struct", () => {
1371
+ const src = `
1372
+ struct Bindings {
1373
+ @group(0) @binding(0) particles: ptr<storage, array<f32>, read_write>,
1374
+ @group(0) @binding(1) uniforms: ptr<uniform, Uniforms>,
1375
+ @group(0) @binding(2) tex: texture_2d<rgba8unorm>,
1376
+ @group(0) @binding(3) samp: sampler,
1377
+ }
1378
+ `;
1379
+ const ast = parseTest(src);
1380
+ const astString = astToString(ast.moduleElem);
1381
+ expect(astString).toMatchInlineSnapshot(`
1382
+ "module
1383
+ text '
1384
+ '
1385
+ struct Bindings
1386
+ text 'struct '
1387
+ decl %Bindings
1388
+ text ' {
1389
+ '
1390
+ member @group @binding particles: ptr<storage, array<f32>, read_write>
1391
+ attribute @group('0')
1392
+ expression '0'
1393
+ text '0'
1394
+ text ' '
1395
+ attribute @binding('0')
1396
+ expression '0'
1397
+ text '0'
1398
+ text ' '
1399
+ name particles
1400
+ text ': '
1401
+ type ptr<storage, array<f32>, read_write>
1402
+ ref ptr
1403
+ text '<'
1404
+ type storage
1405
+ ref storage
1406
+ text ', '
1407
+ type array<f32>
1408
+ ref array
1409
+ text '<'
1410
+ type f32
1411
+ ref f32
1412
+ text '>'
1413
+ text ', '
1414
+ type read_write
1415
+ ref read_write
1416
+ text '>'
1417
+ text ',
1418
+ '
1419
+ member @group @binding uniforms: ptr<uniform, Uniforms>
1420
+ attribute @group('0')
1421
+ expression '0'
1422
+ text '0'
1423
+ text ' '
1424
+ attribute @binding('1')
1425
+ expression '1'
1426
+ text '1'
1427
+ text ' '
1428
+ name uniforms
1429
+ text ': '
1430
+ type ptr<uniform, Uniforms>
1431
+ ref ptr
1432
+ text '<'
1433
+ type uniform
1434
+ ref uniform
1435
+ text ', '
1436
+ type Uniforms
1437
+ ref Uniforms
1438
+ text '>'
1439
+ text ',
1440
+ '
1441
+ member @group @binding tex: texture_2d<rgba8unorm>
1442
+ attribute @group('0')
1443
+ expression '0'
1444
+ text '0'
1445
+ text ' '
1446
+ attribute @binding('2')
1447
+ expression '2'
1448
+ text '2'
1449
+ text ' '
1450
+ name tex
1451
+ text ': '
1452
+ type texture_2d<rgba8unorm>
1453
+ ref texture_2d
1454
+ text '<'
1455
+ type rgba8unorm
1456
+ ref rgba8unorm
1457
+ text '>'
1458
+ text ',
1459
+ '
1460
+ member @group @binding samp: sampler
1461
+ attribute @group('0')
1462
+ expression '0'
1463
+ text '0'
1464
+ text ' '
1465
+ attribute @binding('3')
1466
+ expression '3'
1467
+ text '3'
1468
+ text ' '
1469
+ name samp
1470
+ text ': '
1471
+ type sampler
1472
+ ref sampler
1473
+ text ',
1474
+ }'
1475
+ text '
1476
+ '"
1477
+ `);
1478
+ });
1479
+
1480
+ test("memberRefs with extra components", () => {
1481
+ const src = `
1482
+ fn main() {
1483
+ b.particles[0] = b.uniforms.foo;
1484
+ }
1485
+ `;
1486
+ const ast = parseTest(src);
1487
+ const astString = astToString(ast.moduleElem);
1488
+ expect(astString).toMatchInlineSnapshot(`
1489
+ "module
1490
+ text '
1491
+ '
1492
+ fn main()
1493
+ decl %main
1494
+ statement
1495
+ text '{
1496
+ '
1497
+ memberRef b.particles[0]
1498
+ ref b
1499
+ text '.'
1500
+ name particles
1501
+ stuff
1502
+ text '[0]'
1503
+ text ' = '
1504
+ memberRef b.uniforms.foo
1505
+ ref b
1506
+ text '.'
1507
+ name uniforms
1508
+ stuff
1509
+ text '.foo'
1510
+ text ';
1511
+ }'
1512
+ text '
1513
+ '"
1514
+ `);
1515
+ });
1516
+
1517
+ test("memberRef with ref in array", () => {
1518
+ const src = `
1519
+ fn main() {
1520
+ vsOut.barycenticCoord[vertNdx] = 1.0;
1521
+ }
1522
+ `;
1523
+ const ast = parseTest(src);
1524
+ const astString = astToString(ast.moduleElem);
1525
+ expect(astString).toMatchInlineSnapshot(`
1526
+ "module
1527
+ text '
1528
+ '
1529
+ fn main()
1530
+ decl %main
1531
+ statement
1532
+ text '{
1533
+ '
1534
+ memberRef vsOut.barycenticCoord[ vertNdx ]
1535
+ ref vsOut
1536
+ text '.'
1537
+ name barycenticCoord
1538
+ stuff
1539
+ text '['
1540
+ ref vertNdx
1541
+ text ']'
1542
+ text ' = 1.0;
1543
+ }'
1544
+ text '
1545
+ '"
1546
+ `);
1547
+ });
1548
+
1549
+ test("parse inline package reference", () => {
1550
+ const src = `
1551
+ fn main() {
1552
+ package::foo::bar();
1553
+ }
1554
+ `;
1555
+ const ast = parseTestRaw(src);
1556
+ const astString = astToString(ast.moduleElem);
1557
+ expect(astString).toMatchInlineSnapshot(`
1558
+ "module
1559
+ text '
1560
+ '
1561
+ fn main()
1562
+ decl %main
1563
+ statement
1564
+ text '{
1565
+ '
1566
+ ref package::foo::bar
1567
+ text '();
1568
+ }'
1569
+ text '
1570
+ '"
1571
+ `);
1572
+ });