1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/reader/wgsl/parser_impl_test_helper.h"
16
17 namespace tint {
18 namespace reader {
19 namespace wgsl {
20 namespace {
21
TEST_F(ParserImplTest,GlobalDecl_Semicolon)22 TEST_F(ParserImplTest, GlobalDecl_Semicolon) {
23 auto p = parser(";");
24 p->expect_global_decl();
25 ASSERT_FALSE(p->has_error()) << p->error();
26 }
27
TEST_F(ParserImplTest,GlobalDecl_GlobalVariable)28 TEST_F(ParserImplTest, GlobalDecl_GlobalVariable) {
29 auto p = parser("var<private> a : vec2<i32> = vec2<i32>(1, 2);");
30 p->expect_global_decl();
31 ASSERT_FALSE(p->has_error()) << p->error();
32
33 auto program = p->program();
34 ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
35
36 auto* v = program.AST().GlobalVariables()[0];
37 EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
38 }
39
TEST_F(ParserImplTest,GlobalDecl_GlobalVariable_Inferred_Invalid)40 TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred_Invalid) {
41 auto p = parser("var<private> a = vec2<i32>(1, 2);");
42 p->expect_global_decl();
43 ASSERT_TRUE(p->has_error());
44 EXPECT_EQ(p->error(), "1:16: expected ':' for variable declaration");
45 }
46
TEST_F(ParserImplTest,GlobalDecl_GlobalVariable_MissingSemicolon)47 TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_MissingSemicolon) {
48 auto p = parser("var<private> a : vec2<i32>");
49 p->expect_global_decl();
50 ASSERT_TRUE(p->has_error());
51 EXPECT_EQ(p->error(), "1:27: expected ';' for variable declaration");
52 }
53
TEST_F(ParserImplTest,GlobalDecl_GlobalConstant)54 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant) {
55 auto p = parser("let a : i32 = 2;");
56 p->expect_global_decl();
57 ASSERT_FALSE(p->has_error()) << p->error();
58
59 auto program = p->program();
60 ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
61
62 auto* v = program.AST().GlobalVariables()[0];
63 EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
64 }
65
TEST_F(ParserImplTest,GlobalDecl_GlobalConstant_Invalid)66 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_Invalid) {
67 auto p = parser("let a : vec2<i32> 1.0;");
68 p->expect_global_decl();
69 ASSERT_TRUE(p->has_error());
70 EXPECT_EQ(p->error(), "1:19: expected ';' for let declaration");
71 }
72
TEST_F(ParserImplTest,GlobalDecl_GlobalConstant_MissingSemicolon)73 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_MissingSemicolon) {
74 auto p = parser("let a : vec2<i32> = vec2<i32>(1, 2)");
75 p->expect_global_decl();
76 ASSERT_TRUE(p->has_error());
77 EXPECT_EQ(p->error(), "1:36: expected ';' for let declaration");
78 }
79
TEST_F(ParserImplTest,GlobalDecl_TypeAlias)80 TEST_F(ParserImplTest, GlobalDecl_TypeAlias) {
81 auto p = parser("type A = i32;");
82 p->expect_global_decl();
83 ASSERT_FALSE(p->has_error()) << p->error();
84
85 auto program = p->program();
86 ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
87 ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Alias>());
88 EXPECT_EQ(program.Symbols().NameFor(
89 program.AST().TypeDecls()[0]->As<ast::Alias>()->name),
90 "A");
91 }
92
TEST_F(ParserImplTest,GlobalDecl_TypeAlias_StructIdent)93 TEST_F(ParserImplTest, GlobalDecl_TypeAlias_StructIdent) {
94 auto p = parser(R"(struct A {
95 a : f32;
96 };
97 type B = A;)");
98 p->expect_global_decl();
99 p->expect_global_decl();
100 ASSERT_FALSE(p->has_error()) << p->error();
101
102 auto program = p->program();
103 ASSERT_EQ(program.AST().TypeDecls().size(), 2u);
104 ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Struct>());
105 auto* str = program.AST().TypeDecls()[0]->As<ast::Struct>();
106 EXPECT_EQ(str->name, program.Symbols().Get("A"));
107
108 ASSERT_TRUE(program.AST().TypeDecls()[1]->Is<ast::Alias>());
109 auto* alias = program.AST().TypeDecls()[1]->As<ast::Alias>();
110 EXPECT_EQ(alias->name, program.Symbols().Get("B"));
111 auto* tn = alias->type->As<ast::TypeName>();
112 EXPECT_NE(tn, nullptr);
113 EXPECT_EQ(tn->name, str->name);
114 }
115
TEST_F(ParserImplTest,GlobalDecl_TypeAlias_MissingSemicolon)116 TEST_F(ParserImplTest, GlobalDecl_TypeAlias_MissingSemicolon) {
117 auto p = parser("type A = i32");
118 p->expect_global_decl();
119 ASSERT_TRUE(p->has_error());
120 EXPECT_EQ(p->error(), "1:13: expected ';' for type alias");
121 }
122
TEST_F(ParserImplTest,GlobalDecl_Function)123 TEST_F(ParserImplTest, GlobalDecl_Function) {
124 auto p = parser("fn main() { return; }");
125 p->expect_global_decl();
126 ASSERT_FALSE(p->has_error()) << p->error();
127
128 auto program = p->program();
129 ASSERT_EQ(program.AST().Functions().size(), 1u);
130 EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol),
131 "main");
132 }
133
TEST_F(ParserImplTest,GlobalDecl_Function_WithDecoration)134 TEST_F(ParserImplTest, GlobalDecl_Function_WithDecoration) {
135 auto p = parser("[[workgroup_size(2)]] fn main() { return; }");
136 p->expect_global_decl();
137 ASSERT_FALSE(p->has_error()) << p->error();
138
139 auto program = p->program();
140 ASSERT_EQ(program.AST().Functions().size(), 1u);
141 EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol),
142 "main");
143 }
144
TEST_F(ParserImplTest,GlobalDecl_Function_Invalid)145 TEST_F(ParserImplTest, GlobalDecl_Function_Invalid) {
146 auto p = parser("fn main() -> { return; }");
147 p->expect_global_decl();
148 ASSERT_TRUE(p->has_error());
149 EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
150 }
151
TEST_F(ParserImplTest,GlobalDecl_ParsesStruct)152 TEST_F(ParserImplTest, GlobalDecl_ParsesStruct) {
153 auto p = parser("struct A { b: i32; c: f32;};");
154 p->expect_global_decl();
155 ASSERT_FALSE(p->has_error()) << p->error();
156
157 auto program = p->program();
158 ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
159
160 auto* t = program.AST().TypeDecls()[0];
161 ASSERT_NE(t, nullptr);
162 ASSERT_TRUE(t->Is<ast::Struct>());
163
164 auto* str = t->As<ast::Struct>();
165 EXPECT_EQ(str->name, program.Symbols().Get("A"));
166 EXPECT_EQ(str->members.size(), 2u);
167 }
168
TEST_F(ParserImplTest,GlobalDecl_Struct_WithStride)169 TEST_F(ParserImplTest, GlobalDecl_Struct_WithStride) {
170 auto p = parser("struct A { data: [[stride(4)]] array<f32>; };");
171
172 p->expect_global_decl();
173 ASSERT_FALSE(p->has_error()) << p->error();
174
175 auto program = p->program();
176 ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
177
178 auto* t = program.AST().TypeDecls()[0];
179 ASSERT_NE(t, nullptr);
180 ASSERT_TRUE(t->Is<ast::Struct>());
181
182 auto* str = t->As<ast::Struct>();
183 EXPECT_EQ(str->name, program.Symbols().Get("A"));
184 EXPECT_EQ(str->members.size(), 1u);
185 EXPECT_FALSE(str->IsBlockDecorated());
186
187 const auto* ty = str->members[0]->type;
188 ASSERT_TRUE(ty->Is<ast::Array>());
189 const auto* arr = ty->As<ast::Array>();
190
191 ASSERT_EQ(arr->decorations.size(), 1u);
192 auto* stride = arr->decorations[0];
193 ASSERT_TRUE(stride->Is<ast::StrideDecoration>());
194 ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride, 4u);
195 }
196
TEST_F(ParserImplTest,GlobalDecl_Struct_WithDecoration)197 TEST_F(ParserImplTest, GlobalDecl_Struct_WithDecoration) {
198 auto p = parser("[[block]] struct A { data: f32; };");
199 p->expect_global_decl();
200 ASSERT_FALSE(p->has_error()) << p->error();
201
202 auto program = p->program();
203 ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
204
205 auto* t = program.AST().TypeDecls()[0];
206 ASSERT_NE(t, nullptr);
207 ASSERT_TRUE(t->Is<ast::Struct>());
208
209 auto* str = t->As<ast::Struct>();
210 EXPECT_EQ(str->name, program.Symbols().Get("A"));
211 EXPECT_EQ(str->members.size(), 1u);
212 EXPECT_TRUE(str->IsBlockDecorated());
213 }
214
TEST_F(ParserImplTest,GlobalDecl_Struct_Invalid)215 TEST_F(ParserImplTest, GlobalDecl_Struct_Invalid) {
216 auto p = parser("[[block]] A {};");
217 p->expect_global_decl();
218 ASSERT_TRUE(p->has_error());
219 EXPECT_EQ(p->error(), "1:11: expected declaration after decorations");
220 }
221
TEST_F(ParserImplTest,GlobalDecl_StructMissing_Semi)222 TEST_F(ParserImplTest, GlobalDecl_StructMissing_Semi) {
223 auto p = parser("[[block]] struct A {}");
224 p->expect_global_decl();
225 ASSERT_TRUE(p->has_error());
226 EXPECT_EQ(p->error(), "1:22: expected ';' for struct declaration");
227 }
228
229 } // namespace
230 } // namespace wgsl
231 } // namespace reader
232 } // namespace tint
233