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,34 @@
1
+ import { expect, test } from "vitest";
2
+ import { normalize } from "../PathUtil.js";
3
+
4
+ // ../../../lib/webgpu-samples/src/anim/anim.wgsl
5
+
6
+ test("normalize ./foo", () => {
7
+ const n = normalize("./foo");
8
+ expect(n).toBe("foo");
9
+ });
10
+
11
+ test("normalize ./foo/./", () => {
12
+ const n = normalize("./foo/./");
13
+ expect(n).toBe("foo");
14
+ });
15
+
16
+ test("normalize foo/bar/..", () => {
17
+ const n = normalize("foo/bar/..");
18
+ expect(n).toBe("foo");
19
+ });
20
+
21
+ test("normalize ./foo/bar/../.", () => {
22
+ const n = normalize("./foo/bar/../.");
23
+ expect(n).toBe("foo");
24
+ });
25
+
26
+ test("normalize ../foo", () => {
27
+ const n = normalize("../foo");
28
+ expect(n).toBe("../foo");
29
+ });
30
+
31
+ test("normalize ../../foo", () => {
32
+ const n = normalize("../../foo");
33
+ expect(n).toBe("../../foo");
34
+ });
@@ -0,0 +1,21 @@
1
+ import { or, parserToString, seq } from "mini-parse";
2
+ import { expect, test } from "vitest";
3
+ // import { weslRoot } from "../WESLGrammar.ts";
4
+
5
+ test("print grammar", () => {
6
+ const p: any = or("a", "b", () => p);
7
+ const s = seq("a", "b", () => p);
8
+ const result = parserToString(s);
9
+ expect(result).toMatchInlineSnapshot(`
10
+ "collect
11
+ 'a'
12
+ 'b'
13
+ fn()
14
+ or
15
+ 'a'
16
+ 'b'
17
+ fn()
18
+ ->or
19
+ "
20
+ `);
21
+ });
@@ -0,0 +1,272 @@
1
+ import { expect, test } from "vitest";
2
+ import { parseWESL } from "../ParseWESL.ts";
3
+ import { scopeToString } from "../debug/ScopeToString.ts";
4
+ import { DeclIdent } from "../Scope.ts";
5
+
6
+ test("scope from simple fn", () => {
7
+ const src = `
8
+ fn main() {
9
+ var x: i32 = 1;
10
+ }
11
+ `;
12
+ const { rootScope } = parseWESL(src);
13
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
14
+ "{ %main
15
+ { %x, i32 }
16
+ }"
17
+ `);
18
+ });
19
+
20
+ test("scope from fn with reference", () => {
21
+ const src = `
22
+ fn main() {
23
+ var x: i32 = 1;
24
+ x++;
25
+ }
26
+ `;
27
+ const { rootScope } = parseWESL(src);
28
+ const scopeIdents = rootScope.idents.map(i => i.originalName);
29
+ expect(scopeIdents).toEqual(["main"]);
30
+ const firstChildIdents = rootScope.children[0].idents.map(
31
+ i => i.originalName,
32
+ );
33
+ expect(firstChildIdents).toEqual(["x", "i32", "x"]);
34
+ });
35
+
36
+ test("two fns", () => {
37
+ const src = `
38
+ fn foo() {}
39
+ fn bar() {}
40
+ `;
41
+ const { rootScope } = parseWESL(src);
42
+ const scopeIdents = rootScope.idents.map(i => i.originalName);
43
+ expect(scopeIdents).toEqual(["foo", "bar"]);
44
+ });
45
+
46
+ test("two fns, one with a decl", () => {
47
+ const src = `
48
+ fn foo() {
49
+ var a:u32;
50
+ }
51
+ fn bar() {}
52
+ `;
53
+ const { rootScope } = parseWESL(src);
54
+ const scopeIdents = rootScope.idents.map(i => i.originalName);
55
+ expect(scopeIdents).toEqual(["foo", "bar"]);
56
+ });
57
+
58
+ test("fn ref", () => {
59
+ const src = `
60
+ fn foo() {
61
+ bar();
62
+ }
63
+ fn bar() {}
64
+ `;
65
+ const result = parseWESL(src);
66
+ const { children } = result.rootScope;
67
+ expect(children.length).toBe(2);
68
+ const firstChildIdents = children[0].idents.map(i => i.originalName);
69
+ expect(firstChildIdents).toEqual(["bar"]);
70
+ });
71
+
72
+ test("struct", () => {
73
+ const src = `
74
+ struct A {
75
+ a: B,
76
+ }
77
+ `;
78
+ const { rootScope } = parseWESL(src);
79
+ const scopeIdents = rootScope.idents.map(i => i.originalName);
80
+ expect(scopeIdents).toEqual(["A"]);
81
+
82
+ const { children } = rootScope;
83
+ expect(children.length).toBe(1);
84
+ const firstChildIdents = children[0].idents.map(i => i.originalName);
85
+ expect(firstChildIdents).toEqual(["B"]);
86
+ });
87
+
88
+ test("alias", () => {
89
+ const src = `
90
+ alias A = B;
91
+ `;
92
+ const { rootScope } = parseWESL(src);
93
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
94
+ "{ %A
95
+ { B }
96
+ }"
97
+ `);
98
+ });
99
+
100
+ test("switch", () => {
101
+ const src = `
102
+ fn main() {
103
+ var code = 1u;
104
+ switch ( code ) {
105
+ case 5u: { if 1 > 0 { var x = 7;} }
106
+ default: { break; }
107
+ }
108
+ }`;
109
+ const { rootScope } = parseWESL(src);
110
+
111
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
112
+ "{ %main
113
+ { %code, code
114
+ {
115
+ { %x }
116
+ }
117
+ { }
118
+ }
119
+ }"
120
+ `);
121
+ });
122
+
123
+ test("for()", () => {
124
+ const src = `
125
+ fn main() {
126
+ var i = 1.0;
127
+ for (var i = 0; i < 10; i++) { }
128
+ }`;
129
+ const { rootScope } = parseWESL(src);
130
+
131
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
132
+ "{ %main
133
+ { %i
134
+ { %i, i, i }
135
+ }
136
+ }"
137
+ `);
138
+ });
139
+
140
+ test("fn with param", () => {
141
+ const src = `
142
+ fn main(i: i32) {
143
+ var x = 10 + i;
144
+ for (var i = 0; i < x; i++) { }
145
+ }`;
146
+ const { rootScope } = parseWESL(src);
147
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
148
+ "{ %main
149
+ { %i, i32, %x, i
150
+ { %i, i, x, i }
151
+ }
152
+ }"
153
+ `);
154
+ });
155
+
156
+ test("fn decl scope", () => {
157
+ const src = `
158
+ fn main(i: i32) {
159
+ var x = i;
160
+ }`;
161
+ const { rootScope } = parseWESL(src);
162
+ const mainIdent = rootScope.idents[0] as DeclIdent;
163
+ expect(scopeToString(mainIdent.scope)).toMatchInlineSnapshot(
164
+ `"{ %i, i32, %x, i }"`,
165
+ );
166
+ });
167
+
168
+ test("builtin scope", () => {
169
+ const src = `fn main( @builtin(vertex_index) a: u32) { }`;
170
+ const { rootScope } = parseWESL(src);
171
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
172
+ "{ %main
173
+ { %a, u32 }
174
+ }"
175
+ `);
176
+ });
177
+
178
+ test("texture_storage_2d", () => {
179
+ const src = `
180
+ @binding(3) @group(0) var tex_out : texture_storage_2d<rgba8unorm, write>;
181
+ `;
182
+ const { rootScope } = parseWESL(src);
183
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`"{ %tex_out }"`);
184
+ });
185
+
186
+ test("ptr 2 params", () => {
187
+ const src = `
188
+ fn foo(ptr: ptr<private, u32>) { }
189
+ `;
190
+ const { rootScope } = parseWESL(src);
191
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
192
+ "{ %foo
193
+ { %ptr, u32 }
194
+ }"
195
+ `);
196
+ });
197
+
198
+ test("ptr 3 params", () => {
199
+ const src = `
200
+ fn foo(ptr: ptr<storage, array<u32, 128>, read>) { }
201
+ `;
202
+ const { rootScope } = parseWESL(src);
203
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
204
+ "{ %foo
205
+ { %ptr, array, u32 }
206
+ }"
207
+ `);
208
+ });
209
+
210
+ test("larger example", () => {
211
+ const src = `
212
+ struct UBO { width : u32, }
213
+
214
+ struct Buffer { weights : array<f32>, }
215
+
216
+ @binding(0) @group(0) var<uniform> ubo : UBO;
217
+ @binding(1) @group(0) var<storage, read> buf_in : Buffer;
218
+ @binding(2) @group(0) var<storage, read_write> buf_out : Buffer;
219
+ @binding(3) @group(0) var tex_in : texture_2d<f32>;
220
+ @binding(3) @group(0) var tex_out : texture_storage_2d<rgba8unorm, write>;
221
+
222
+ @compute @workgroup_size(64)
223
+ fn import_level(@builtin(global_invocation_id) coord : vec3u) {
224
+ _ = &buf_in;
225
+ let offset = coord.x + coord.y * ubo.width;
226
+ buf_out.weights[offset] = textureLoad(tex_in, vec2i(coord.xy), 0).w;
227
+ }
228
+
229
+ @compute @workgroup_size(64)
230
+ fn export_level(@builtin(global_invocation_id) coord : vec3u) {
231
+ if (all(coord.xy < vec2u(textureDimensions(tex_out)))) {
232
+ let dst_offset = coord.x + coord.y * ubo.width;
233
+ let src_offset = coord.x*2u + coord.y*2u * ubo.width;
234
+
235
+ let a = buf_in.weights[src_offset + 0u];
236
+ let b = buf_in.weights[src_offset + 1u];
237
+ let c = buf_in.weights[src_offset + 0u + ubo.width];
238
+ let d = buf_in.weights[src_offset + 1u + ubo.width];
239
+ let sum = dot(vec4f(a, b, c, d), vec4f(1.0));
240
+
241
+ buf_out.weights[dst_offset] = sum / 4.0;
242
+
243
+ let probabilities = vec4f(a, a+b, a+b+c, sum) / max(sum, 0.0001);
244
+ textureStore(tex_out, vec2i(coord.xy), probabilities);
245
+ }
246
+ }
247
+ `;
248
+
249
+ const { rootScope } = parseWESL(src);
250
+ expect(scopeToString(rootScope)).toMatchInlineSnapshot(`
251
+ "{ %UBO, %Buffer, %ubo, UBO, %buf_in, Buffer, %buf_out,
252
+ Buffer, %tex_in, texture_2d, f32, %tex_out, %import_level,
253
+ %export_level
254
+ { u32 }
255
+ { array, f32 }
256
+ { %coord, vec3u, buf_in, %offset, coord, coord, ubo,
257
+ buf_out, offset, textureLoad, tex_in, vec2i, coord
258
+ }
259
+ { %coord, vec3u, all, coord, vec2u, textureDimensions,
260
+ tex_out
261
+ { %dst_offset, coord, coord, ubo, %src_offset, coord,
262
+ coord, ubo, %a, buf_in, src_offset, %b, buf_in,
263
+ src_offset, %c, buf_in, src_offset, ubo, %d, buf_in,
264
+ src_offset, ubo, %sum, dot, vec4f, a, b, c, d, vec4f,
265
+ buf_out, dst_offset, sum, %probabilities, vec4f, a, a,
266
+ b, a, b, c, sum, max, sum, textureStore, tex_out,
267
+ vec2i, coord, probabilities
268
+ }
269
+ }
270
+ }"
271
+ `);
272
+ });
@@ -0,0 +1,103 @@
1
+ import { SrcMap } from "mini-parse";
2
+ import { expect, test } from "vitest";
3
+ import { sliceReplace } from "../Slicer.js";
4
+
5
+ test("slice middle", () => {
6
+ const src = "aaabbbc";
7
+ const srcMap = sliceReplace(src, [{ start: 3, end: 6, replacement: "X" }]);
8
+ const { dest, entries } = srcMap;
9
+ expect(dest).toBe("aaaXc");
10
+ expect(entries).toMatchInlineSnapshot(`
11
+ [
12
+ {
13
+ "destEnd": 3,
14
+ "destStart": 0,
15
+ "src": "aaabbbc",
16
+ "srcEnd": 3,
17
+ "srcStart": 0,
18
+ },
19
+ {
20
+ "destEnd": 4,
21
+ "destStart": 3,
22
+ "src": "aaabbbc",
23
+ "srcEnd": 6,
24
+ "srcStart": 3,
25
+ },
26
+ {
27
+ "destEnd": 5,
28
+ "destStart": 4,
29
+ "src": "aaabbbc",
30
+ "srcEnd": 7,
31
+ "srcStart": 6,
32
+ },
33
+ ]
34
+ `);
35
+ });
36
+
37
+ test("slice end", () => {
38
+ const src = "aaabbb";
39
+ const srcMap = sliceReplace(src, [{ start: 3, end: 6, replacement: "X" }]);
40
+ expect(srcMap.dest).toBe("aaaX");
41
+ validateDestCovered(srcMap);
42
+ });
43
+
44
+ test("slice beginning", () => {
45
+ const src = "aaabbb";
46
+ const srcMap = sliceReplace(src, [{ start: 0, end: 3, replacement: "X" }]);
47
+ validateDestCovered(srcMap);
48
+ expect(srcMap.dest).toBe("Xbbb");
49
+ });
50
+
51
+ test("slice multiple", () => {
52
+ const src = "aaabbbc";
53
+ const srcMap = sliceReplace(src, [
54
+ { start: 3, end: 6, replacement: "B" },
55
+ { start: 0, end: 3, replacement: "A" },
56
+ ]);
57
+ validateDestCovered(srcMap);
58
+ expect(srcMap.dest).toBe("ABc");
59
+ expect(srcMap.entries.length).toBe(3);
60
+ });
61
+
62
+ test("slice none", () => {
63
+ const src = "aaabbbc";
64
+ const srcMap = sliceReplace(src, []);
65
+ validateDestCovered(srcMap);
66
+ expect(srcMap.dest).toBe(src);
67
+ });
68
+
69
+ test("slice none with start and end", () => {
70
+ const src = "aaabbbc";
71
+ const srcMap = sliceReplace(src, [], 3, 6);
72
+ validateDestCovered(srcMap);
73
+ expect(srcMap.dest).toBe("bbb");
74
+ });
75
+
76
+ test("slice one with start and end", () => {
77
+ const src = "aaabbbc";
78
+
79
+ const slices = [{ start: 3, end: 6, replacement: "B" }];
80
+ const srcMap = sliceReplace(src, slices, 2);
81
+ validateDestCovered(srcMap);
82
+ expect(srcMap.dest).toBe("aBc");
83
+ });
84
+
85
+ test("slice with empty replacement", () => {
86
+ const src = "aaabbbc";
87
+
88
+ const slices = [{ start: 3, end: 6, replacement: "" }];
89
+ const srcMap = sliceReplace(src, slices);
90
+ validateDestCovered(srcMap);
91
+ expect(srcMap.dest).toBe("aaac");
92
+ });
93
+
94
+ /** verify that the srcMap covers every part of the destination text */
95
+ function validateDestCovered(srcMap: SrcMap): void {
96
+ const { dest, entries } = srcMap;
97
+ let destPos = 0;
98
+ entries.forEach(e => {
99
+ expect(e.destStart).toBe(destPos);
100
+ destPos = e.destEnd;
101
+ });
102
+ expect(destPos).toBe(dest.length);
103
+ }
@@ -0,0 +1,4 @@
1
+ import { enableTracing } from "mini-parse";
2
+
3
+ // enable parser tracing features
4
+ enableTracing();
@@ -0,0 +1,52 @@
1
+ import { _withBaseLogger, NoTags, Parser, TagRecord } from "mini-parse";
2
+ import {
3
+ expectNoLog,
4
+ logCatch,
5
+ testParse,
6
+ TestParseResult,
7
+ } from "mini-parse/test-util";
8
+ import { linkWesl } from "../Linker.js";
9
+ import { mainTokens } from "../WESLTokens.js";
10
+ import { parseWESL, syntheticWeslParseState, WeslAST } from "../ParseWESL.js";
11
+
12
+ export function testAppParse<T, N extends TagRecord = NoTags>(
13
+ parser: Parser<T, N>,
14
+ src: string,
15
+ ): TestParseResult<T, N, WeslAST> {
16
+ const appState = syntheticWeslParseState();
17
+ return testParse(parser, src, mainTokens, appState);
18
+ }
19
+
20
+ /** Convenience wrapper to link wgsl for tests.
21
+ * The first module is named "package::root",
22
+ * subsequent modules are named "package::file1", "package::file2", etc.
23
+ */
24
+ export function link2Test(...rawWgsl: string[]): string {
25
+ const [root, ...rest] = rawWgsl;
26
+ const restWgsl = Object.fromEntries(
27
+ rest.map((src, i) => [`package::file${i + 1}`, src]),
28
+ );
29
+ const wesl = { "package::root": root, ...restWgsl };
30
+
31
+ const srcMap = linkWesl(wesl, "root");
32
+ return srcMap.dest;
33
+ }
34
+
35
+ /** link wesl for tests, and return the console log as well */
36
+ export function linkWithLog(...rawWgsl: string[]): {
37
+ log: string;
38
+ result: string;
39
+ } {
40
+ const { log, logged } = logCatch();
41
+ let result = "???";
42
+ _withBaseLogger(log, () => {
43
+ try {
44
+ result = link2Test(...rawWgsl);
45
+ } catch (e) {}
46
+ });
47
+ return { result, log: logged() };
48
+ }
49
+
50
+ export function parse2Test(src: string): WeslAST {
51
+ return expectNoLog(() => parseWESL(src, undefined, 500));
52
+ }
@@ -0,0 +1,22 @@
1
+ import { expect, test } from "vitest";
2
+ import { overlapTail, scan } from "../Util.js";
3
+
4
+ test("scan", () => {
5
+ const result = scan([1, 2, 1], (a, b: string) => b.slice(a), "foobar");
6
+ expect(result).toEqual(["foobar", "oobar", "bar", "ar"]);
7
+ });
8
+
9
+ test("overlap 0", () => {
10
+ const result = overlapTail([2, 3], [4, 5]);
11
+ expect(result).toBeUndefined();
12
+ });
13
+
14
+ test("overlap 1", () => {
15
+ const result = overlapTail([2, 3], [3, 4, 5]);
16
+ expect(result).toEqual([4, 5]);
17
+ });
18
+
19
+ test("overlap 2", () => {
20
+ const result = overlapTail([2, 3], [2, 3]);
21
+ expect(result).toEqual([]);
22
+ });
File without changes
@@ -0,0 +1,25 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`parse import foo/bar 1`] = `
4
+ [
5
+ {
6
+ "end": 14,
7
+ "imports": ImportTree {
8
+ "segments": [
9
+ SimpleSegment {
10
+ "args": undefined,
11
+ "as": undefined,
12
+ "name": "foo",
13
+ },
14
+ SimpleSegment {
15
+ "args": undefined,
16
+ "as": undefined,
17
+ "name": "bar",
18
+ },
19
+ ],
20
+ },
21
+ "kind": "treeImport",
22
+ "start": 0,
23
+ },
24
+ ]
25
+ `;
@@ -0,0 +1,119 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`parse foo::bar(); 1`] = `
4
+ [
5
+ {
6
+ "calls": [
7
+ {
8
+ "end": 20,
9
+ "kind": "call",
10
+ "name": "foo::bar",
11
+ "start": 12,
12
+ },
13
+ ],
14
+ "end": 25,
15
+ "kind": "fn",
16
+ "name": "main",
17
+ "nameElem": {
18
+ "end": 7,
19
+ "kind": "fnName",
20
+ "name": "main",
21
+ "start": 3,
22
+ },
23
+ "start": 0,
24
+ "typeRefs": [],
25
+ },
26
+ ]
27
+ `;
28
+
29
+ exports[`parse let x: foo::bar; 1`] = `
30
+ [
31
+ {
32
+ "calls": [],
33
+ "end": 34,
34
+ "kind": "fn",
35
+ "name": "main",
36
+ "nameElem": {
37
+ "end": 7,
38
+ "kind": "fnName",
39
+ "name": "main",
40
+ "start": 3,
41
+ },
42
+ "start": 0,
43
+ "typeRefs": [
44
+ {
45
+ "end": 27,
46
+ "kind": "typeRef",
47
+ "name": "foo::bar",
48
+ "start": 19,
49
+ },
50
+ ],
51
+ },
52
+ ]
53
+ `;
54
+
55
+ exports[`parse unicode ident 1`] = `
56
+ "module
57
+ text '
58
+ '
59
+ fn Δέλτα()
60
+ text 'fn '
61
+ decl %Δέλτα
62
+ text '(){}'
63
+ text '
64
+ '
65
+ fn réflexion()
66
+ text 'fn '
67
+ decl %réflexion
68
+ text '(){}'
69
+ text '
70
+ '
71
+ fn Кызыл()
72
+ text 'fn '
73
+ decl %Кызыл
74
+ text '(){}'
75
+ text '
76
+ '
77
+ fn 𐰓𐰏𐰇()
78
+ text 'fn '
79
+ decl %𐰓𐰏𐰇
80
+ text '(){}'
81
+ text '
82
+ '
83
+ fn 朝焼け()
84
+ text 'fn '
85
+ decl %朝焼け
86
+ text '(){}'
87
+ text '
88
+ '
89
+ fn سلام()
90
+ text 'fn '
91
+ decl %سلام
92
+ text '(){}'
93
+ text '
94
+ '
95
+ fn 검정()
96
+ text 'fn '
97
+ decl %검정
98
+ text '(){}'
99
+ text '
100
+ '
101
+ fn שָׁלוֹם()
102
+ text 'fn '
103
+ decl %שָׁלוֹם
104
+ text '(){}'
105
+ text '
106
+ '
107
+ fn गुलाबी()
108
+ text 'fn '
109
+ decl %गुलाबी
110
+ text '(){}'
111
+ text '
112
+ '
113
+ fn փիրուզ()
114
+ text 'fn '
115
+ decl %փիրուզ
116
+ text '(){}'
117
+ text '
118
+ '"
119
+ `;