• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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