wesl 0.6.0-pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2617 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +2617 -0
- package/dist/index.js.map +1 -0
- package/dist/linker/packages/linker/src/AbstractElems.d.ts +104 -0
- package/dist/linker/packages/linker/src/BindIdents.d.ts +16 -0
- package/dist/linker/packages/linker/src/CommentsGrammar.d.ts +6 -0
- package/dist/linker/packages/linker/src/FlattenTreeImport.d.ts +11 -0
- package/dist/linker/packages/linker/src/ImportGrammar.d.ts +13 -0
- package/dist/linker/packages/linker/src/ImportTree.d.ts +17 -0
- package/dist/linker/packages/linker/src/Linker.d.ts +26 -0
- package/dist/linker/packages/linker/src/LowerAndEmit.d.ts +25 -0
- package/dist/linker/packages/linker/src/ParseWESL.d.ts +36 -0
- package/dist/linker/packages/linker/src/ParsedRegistry.d.ts +26 -0
- package/dist/linker/packages/linker/src/PathUtil.d.ts +9 -0
- package/dist/linker/packages/linker/src/Scope.d.ts +55 -0
- package/dist/linker/packages/linker/src/Slicer.d.ts +26 -0
- package/dist/linker/packages/linker/src/StandardTypes.d.ts +6 -0
- package/dist/linker/packages/linker/src/Util.d.ts +26 -0
- package/dist/linker/packages/linker/src/WESLCollect.d.ts +29 -0
- package/dist/linker/packages/linker/src/WESLGrammar.d.ts +23 -0
- package/dist/linker/packages/linker/src/WESLTokens.d.ts +42 -0
- package/dist/linker/packages/linker/src/WgslBundle.d.ts +13 -0
- package/dist/linker/packages/linker/src/debug/ASTtoString.d.ts +3 -0
- package/dist/linker/packages/linker/src/debug/ImportToString.d.ts +2 -0
- package/dist/linker/packages/linker/src/debug/LineWrapper.d.ts +21 -0
- package/dist/linker/packages/linker/src/debug/ScopeToString.d.ts +4 -0
- package/dist/linker/packages/linker/src/index.d.ts +7 -0
- package/dist/linker/packages/linker/src/test/ErrorLogging.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Expression.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/FlattenTreeImport.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ImportCases.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ImportSyntaxCases.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/LinkGlob.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/LinkPackage.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Linker.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/MatchWgslD.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ParseComments.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ParseWESL.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/PathUtil.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/PrettyGrammar.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ScopeWESL.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Slicer.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/TestSetup.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/TestUtil.d.ts +15 -0
- package/dist/linker/packages/linker/src/test/Util.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/WgslTests.d.ts +0 -0
- package/dist/linker/packages/linker/src/test/shared/StringUtil.d.ts +8 -0
- package/dist/linker/packages/linker/src/test/shared/test/StringUtil.test.d.ts +1 -0
- package/dist/minified.cjs +2 -0
- package/dist/minified.cjs.map +1 -0
- package/dist/minified.js +2617 -0
- package/dist/minified.js.map +1 -0
- package/dist/wesl-testsuite/src/test-cases/BulkTests.d.ts +4 -0
- package/dist/wesl-testsuite/src/test-cases/ImportCases.d.ts +3 -0
- package/dist/wesl-testsuite/src/test-cases/ImportSyntaxCases.d.ts +3 -0
- package/package.json +45 -0
- package/src/AbstractElems.ts +148 -0
- package/src/BindIdents.ts +277 -0
- package/src/CommentsGrammar.ts +44 -0
- package/src/FlattenTreeImport.ts +59 -0
- package/src/ImportGrammar.ts +142 -0
- package/src/ImportTree.ts +19 -0
- package/src/Linker.ts +151 -0
- package/src/LowerAndEmit.ts +143 -0
- package/src/ParseWESL.ts +106 -0
- package/src/ParsedRegistry.ts +97 -0
- package/src/PathUtil.ts +52 -0
- package/src/Scope.ts +100 -0
- package/src/Slicer.ts +127 -0
- package/src/StandardTypes.ts +66 -0
- package/src/Util.ts +112 -0
- package/src/WESLCollect.ts +336 -0
- package/src/WESLGrammar.ts +538 -0
- package/src/WESLTokens.ts +97 -0
- package/src/WgslBundle.ts +16 -0
- package/src/debug/ASTtoString.ts +149 -0
- package/src/debug/ImportToString.ts +21 -0
- package/src/debug/LineWrapper.ts +65 -0
- package/src/debug/ScopeToString.ts +51 -0
- package/src/index.ts +7 -0
- package/src/test/ErrorLogging.test.ts +14 -0
- package/src/test/Expression.test.ts +22 -0
- package/src/test/FlattenTreeImport.test.ts +56 -0
- package/src/test/ImportCases.test.ts +440 -0
- package/src/test/ImportSyntaxCases.test.ts +22 -0
- package/src/test/LinkGlob.test.ts +25 -0
- package/src/test/LinkPackage.test.ts +26 -0
- package/src/test/Linker.test.ts +120 -0
- package/src/test/MatchWgslD.test.ts +16 -0
- package/src/test/ParseComments.test.ts +74 -0
- package/src/test/ParseWESL.test.ts +902 -0
- package/src/test/PathUtil.test.ts +34 -0
- package/src/test/PrettyGrammar.test.ts +21 -0
- package/src/test/ScopeWESL.test.ts +272 -0
- package/src/test/Slicer.test.ts +103 -0
- package/src/test/TestSetup.ts +4 -0
- package/src/test/TestUtil.ts +52 -0
- package/src/test/Util.test.ts +22 -0
- package/src/test/WgslTests.ts +0 -0
- package/src/test/__snapshots__/ParseDirectives.test.ts.snap +25 -0
- package/src/test/__snapshots__/ParseWESL.test.ts.snap +119 -0
- package/src/test/__snapshots__/ParseWESL2.test.ts.snap +67 -0
- package/src/test/__snapshots__/RustDirective.test.ts.snap +359 -0
- package/src/test/shared/StringUtil.ts +59 -0
- package/src/test/shared/test/StringUtil.test.ts +32 -0
- package/src/test/wgsl_1/main.wgsl +3 -0
- package/src/test/wgsl_1/util.wgsl +1 -0
- package/src/test/wgsl_2/main2.wgsl +3 -0
- package/src/test/wgsl_2/util2.wgsl +1 -0
|
@@ -0,0 +1,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,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
|
+
`;
|