blob: c4fec3a694da904999bc3b6767908c748732dd47 [file] [log] [blame]
dan sinclairb7edc4c2020-04-07 12:46:30 +00001// 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/type_determiner.h"
16
17#include <memory>
18#include <utility>
19
20#include "gtest/gtest.h"
dan sinclair6c498fc2020-04-07 12:47:23 +000021#include "src/ast/assignment_statement.h"
dan sinclairb7ea6e22020-04-07 12:54:10 +000022#include "src/ast/break_statement.h"
dan sinclair6010b292020-04-07 12:54:20 +000023#include "src/ast/case_statement.h"
dan sinclairaec965e2020-04-07 12:54:29 +000024#include "src/ast/continue_statement.h"
dan sinclair0cf685f2020-04-07 12:54:37 +000025#include "src/ast/else_statement.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000026#include "src/ast/float_literal.h"
dan sinclaircab0e732020-04-07 12:57:27 +000027#include "src/ast/identifier_expression.h"
dan sinclair91c44a52020-04-07 12:55:25 +000028#include "src/ast/if_statement.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000029#include "src/ast/int_literal.h"
dan sinclairbc71eda2020-04-07 12:55:51 +000030#include "src/ast/loop_statement.h"
dan sinclair45540b92020-04-07 12:56:08 +000031#include "src/ast/regardless_statement.h"
dan sinclairbf0fff82020-04-07 12:56:24 +000032#include "src/ast/return_statement.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000033#include "src/ast/scalar_constructor_expression.h"
dan sinclair18b32852020-04-07 12:56:45 +000034#include "src/ast/switch_statement.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000035#include "src/ast/type/f32_type.h"
dan sinclair6c498fc2020-04-07 12:47:23 +000036#include "src/ast/type/i32_type.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000037#include "src/ast/type/vector_type.h"
38#include "src/ast/type_constructor_expression.h"
dan sinclair9a84e5e2020-04-07 12:56:57 +000039#include "src/ast/unless_statement.h"
dan sinclairca893e32020-04-07 12:57:12 +000040#include "src/ast/variable_decl_statement.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000041
42namespace tint {
43namespace {
44
45class TypeDeterminerTest : public testing::Test {
46 public:
47 void SetUp() { td_ = std::make_unique<TypeDeterminer>(&ctx_); }
48
49 TypeDeterminer* td() const { return td_.get(); }
50
51 private:
52 Context ctx_;
53 std::unique_ptr<TypeDeterminer> td_;
54};
55
dan sinclair6c498fc2020-04-07 12:47:23 +000056TEST_F(TypeDeterminerTest, Stmt_Assign) {
57 ast::type::F32Type f32;
58 ast::type::I32Type i32;
59
60 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
61 std::make_unique<ast::IntLiteral>(&i32, 2));
62 auto lhs_ptr = lhs.get();
63
64 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
65 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
66 auto rhs_ptr = rhs.get();
67
68 ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
69
70 EXPECT_TRUE(td()->DetermineResultType(&assign));
71 ASSERT_NE(lhs_ptr->result_type(), nullptr);
72 ASSERT_NE(rhs_ptr->result_type(), nullptr);
73
74 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
75 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
76}
77
dan sinclairb7ea6e22020-04-07 12:54:10 +000078TEST_F(TypeDeterminerTest, Stmt_Break) {
79 ast::type::I32Type i32;
80
81 auto cond = std::make_unique<ast::ScalarConstructorExpression>(
82 std::make_unique<ast::IntLiteral>(&i32, 2));
83 auto cond_ptr = cond.get();
84
85 ast::BreakStatement brk(ast::StatementCondition::kIf, std::move(cond));
86
87 EXPECT_TRUE(td()->DetermineResultType(&brk));
88 ASSERT_NE(cond_ptr->result_type(), nullptr);
89 EXPECT_TRUE(cond_ptr->result_type()->IsI32());
90}
91
dan sinclair6010b292020-04-07 12:54:20 +000092TEST_F(TypeDeterminerTest, Stmt_Case) {
93 ast::type::I32Type i32;
94 ast::type::F32Type f32;
95
96 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
97 std::make_unique<ast::IntLiteral>(&i32, 2));
98 auto lhs_ptr = lhs.get();
99
100 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
101 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
102 auto rhs_ptr = rhs.get();
103
104 ast::StatementList body;
105 body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
106 std::move(rhs)));
107
108 ast::CaseStatement cse(std::make_unique<ast::IntLiteral>(&i32, 3),
109 std::move(body));
110
111 EXPECT_TRUE(td()->DetermineResultType(&cse));
112 ASSERT_NE(lhs_ptr->result_type(), nullptr);
113 ASSERT_NE(rhs_ptr->result_type(), nullptr);
114 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
115 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
116}
117
dan sinclairaec965e2020-04-07 12:54:29 +0000118TEST_F(TypeDeterminerTest, Stmt_Continue) {
119 ast::type::I32Type i32;
120
121 auto cond = std::make_unique<ast::ScalarConstructorExpression>(
122 std::make_unique<ast::IntLiteral>(&i32, 2));
123 auto cond_ptr = cond.get();
124
125 ast::ContinueStatement stmt(ast::StatementCondition::kIf, std::move(cond));
126
127 EXPECT_TRUE(td()->DetermineResultType(&stmt));
128 ASSERT_NE(cond_ptr->result_type(), nullptr);
129 EXPECT_TRUE(cond_ptr->result_type()->IsI32());
130}
131
dan sinclair0cf685f2020-04-07 12:54:37 +0000132TEST_F(TypeDeterminerTest, Stmt_Else) {
133 ast::type::I32Type i32;
134 ast::type::F32Type f32;
135
136 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
137 std::make_unique<ast::IntLiteral>(&i32, 2));
138 auto lhs_ptr = lhs.get();
139
140 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
141 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
142 auto rhs_ptr = rhs.get();
143
144 ast::StatementList body;
145 body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
146 std::move(rhs)));
147
148 ast::ElseStatement stmt(std::make_unique<ast::ScalarConstructorExpression>(
149 std::make_unique<ast::IntLiteral>(&i32, 3)),
150 std::move(body));
151
152 EXPECT_TRUE(td()->DetermineResultType(&stmt));
153 ASSERT_NE(stmt.condition()->result_type(), nullptr);
154 ASSERT_NE(lhs_ptr->result_type(), nullptr);
155 ASSERT_NE(rhs_ptr->result_type(), nullptr);
156 EXPECT_TRUE(stmt.condition()->result_type()->IsI32());
157 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
158 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
159}
160
dan sinclair91c44a52020-04-07 12:55:25 +0000161TEST_F(TypeDeterminerTest, Stmt_If) {
162 ast::type::I32Type i32;
163 ast::type::F32Type f32;
164
165 auto else_lhs = std::make_unique<ast::ScalarConstructorExpression>(
166 std::make_unique<ast::IntLiteral>(&i32, 2));
167 auto else_lhs_ptr = else_lhs.get();
168
169 auto else_rhs = std::make_unique<ast::ScalarConstructorExpression>(
170 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
171 auto else_rhs_ptr = else_rhs.get();
172
173 ast::StatementList else_body;
174 else_body.push_back(std::make_unique<ast::AssignmentStatement>(
175 std::move(else_lhs), std::move(else_rhs)));
176
177 auto else_stmt = std::make_unique<ast::ElseStatement>(
178 std::make_unique<ast::ScalarConstructorExpression>(
179 std::make_unique<ast::IntLiteral>(&i32, 3)),
180 std::move(else_body));
181
182 ast::ElseStatementList else_stmts;
183 else_stmts.push_back(std::move(else_stmt));
184
185 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
186 std::make_unique<ast::IntLiteral>(&i32, 2));
187 auto lhs_ptr = lhs.get();
188
189 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
190 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
191 auto rhs_ptr = rhs.get();
192
193 ast::StatementList body;
194 body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
195 std::move(rhs)));
196
197 ast::IfStatement stmt(std::make_unique<ast::ScalarConstructorExpression>(
198 std::make_unique<ast::IntLiteral>(&i32, 3)),
199 std::move(body));
200 stmt.set_else_statements(std::move(else_stmts));
201
202 EXPECT_TRUE(td()->DetermineResultType(&stmt));
203 ASSERT_NE(stmt.condition()->result_type(), nullptr);
204 ASSERT_NE(else_lhs_ptr->result_type(), nullptr);
205 ASSERT_NE(else_rhs_ptr->result_type(), nullptr);
206 ASSERT_NE(lhs_ptr->result_type(), nullptr);
207 ASSERT_NE(rhs_ptr->result_type(), nullptr);
208 EXPECT_TRUE(stmt.condition()->result_type()->IsI32());
209 EXPECT_TRUE(else_lhs_ptr->result_type()->IsI32());
210 EXPECT_TRUE(else_rhs_ptr->result_type()->IsF32());
211 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
212 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
213}
214
dan sinclairbc71eda2020-04-07 12:55:51 +0000215TEST_F(TypeDeterminerTest, Stmt_Loop) {
216 ast::type::I32Type i32;
217 ast::type::F32Type f32;
218
219 auto body_lhs = std::make_unique<ast::ScalarConstructorExpression>(
220 std::make_unique<ast::IntLiteral>(&i32, 2));
221 auto body_lhs_ptr = body_lhs.get();
222
223 auto body_rhs = std::make_unique<ast::ScalarConstructorExpression>(
224 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
225 auto body_rhs_ptr = body_rhs.get();
226
227 ast::StatementList body;
228 body.push_back(std::make_unique<ast::AssignmentStatement>(
229 std::move(body_lhs), std::move(body_rhs)));
230
231 auto continuing_lhs = std::make_unique<ast::ScalarConstructorExpression>(
232 std::make_unique<ast::IntLiteral>(&i32, 2));
233 auto continuing_lhs_ptr = continuing_lhs.get();
234
235 auto continuing_rhs = std::make_unique<ast::ScalarConstructorExpression>(
236 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
237 auto continuing_rhs_ptr = continuing_rhs.get();
238
239 ast::StatementList continuing;
240 continuing.push_back(std::make_unique<ast::AssignmentStatement>(
241 std::move(continuing_lhs), std::move(continuing_rhs)));
242
243 ast::LoopStatement stmt(std::move(body), std::move(continuing));
244
245 EXPECT_TRUE(td()->DetermineResultType(&stmt));
246 ASSERT_NE(body_lhs_ptr->result_type(), nullptr);
247 ASSERT_NE(body_rhs_ptr->result_type(), nullptr);
248 ASSERT_NE(continuing_lhs_ptr->result_type(), nullptr);
249 ASSERT_NE(continuing_rhs_ptr->result_type(), nullptr);
250 EXPECT_TRUE(body_lhs_ptr->result_type()->IsI32());
251 EXPECT_TRUE(body_rhs_ptr->result_type()->IsF32());
252 EXPECT_TRUE(continuing_lhs_ptr->result_type()->IsI32());
253 EXPECT_TRUE(continuing_rhs_ptr->result_type()->IsF32());
254}
255
dan sinclair45540b92020-04-07 12:56:08 +0000256TEST_F(TypeDeterminerTest, Stmt_Regardless) {
257 ast::type::I32Type i32;
258 ast::type::F32Type f32;
259
260 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
261 std::make_unique<ast::IntLiteral>(&i32, 2));
262 auto lhs_ptr = lhs.get();
263
264 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
265 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
266 auto rhs_ptr = rhs.get();
267
268 ast::StatementList body;
269 body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
270 std::move(rhs)));
271
272 ast::RegardlessStatement regardless(
273 std::make_unique<ast::ScalarConstructorExpression>(
274 std::make_unique<ast::IntLiteral>(&i32, 3)),
275 std::move(body));
276
277 EXPECT_TRUE(td()->DetermineResultType(&regardless));
278 ASSERT_NE(regardless.condition()->result_type(), nullptr);
279 ASSERT_NE(lhs_ptr->result_type(), nullptr);
280 ASSERT_NE(rhs_ptr->result_type(), nullptr);
281 EXPECT_TRUE(regardless.condition()->result_type()->IsI32());
282 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
283 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
284}
285
dan sinclairbf0fff82020-04-07 12:56:24 +0000286TEST_F(TypeDeterminerTest, Stmt_Return) {
287 ast::type::I32Type i32;
288
289 auto cond = std::make_unique<ast::ScalarConstructorExpression>(
290 std::make_unique<ast::IntLiteral>(&i32, 2));
291 auto cond_ptr = cond.get();
292
293 ast::ReturnStatement ret(std::move(cond));
294
295 EXPECT_TRUE(td()->DetermineResultType(&ret));
296 ASSERT_NE(cond_ptr->result_type(), nullptr);
297 EXPECT_TRUE(cond_ptr->result_type()->IsI32());
298}
299
dan sinclair18b32852020-04-07 12:56:45 +0000300TEST_F(TypeDeterminerTest, Stmt_Switch) {
301 ast::type::I32Type i32;
302 ast::type::F32Type f32;
303
304 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
305 std::make_unique<ast::IntLiteral>(&i32, 2));
306 auto lhs_ptr = lhs.get();
307
308 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
309 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
310 auto rhs_ptr = rhs.get();
311
312 ast::StatementList body;
313 body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
314 std::move(rhs)));
315
316 ast::CaseStatementList cases;
317 cases.push_back(std::make_unique<ast::CaseStatement>(
318 std::make_unique<ast::IntLiteral>(&i32, 3), std::move(body)));
319
320 ast::SwitchStatement stmt(std::make_unique<ast::ScalarConstructorExpression>(
321 std::make_unique<ast::IntLiteral>(&i32, 2)),
322 std::move(cases));
323
324 EXPECT_TRUE(td()->DetermineResultType(&stmt)) << td()->error();
325 ASSERT_NE(stmt.condition()->result_type(), nullptr);
326 ASSERT_NE(lhs_ptr->result_type(), nullptr);
327 ASSERT_NE(rhs_ptr->result_type(), nullptr);
328
329 EXPECT_TRUE(stmt.condition()->result_type()->IsI32());
330 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
331 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
332}
333
dan sinclair9a84e5e2020-04-07 12:56:57 +0000334TEST_F(TypeDeterminerTest, Stmt_Unless) {
335 ast::type::I32Type i32;
336 ast::type::F32Type f32;
337
338 auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
339 std::make_unique<ast::IntLiteral>(&i32, 2));
340 auto lhs_ptr = lhs.get();
341
342 auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
343 std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
344 auto rhs_ptr = rhs.get();
345
346 ast::StatementList body;
347 body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
348 std::move(rhs)));
349
350 ast::UnlessStatement unless(
351 std::make_unique<ast::ScalarConstructorExpression>(
352 std::make_unique<ast::IntLiteral>(&i32, 3)),
353 std::move(body));
354
355 EXPECT_TRUE(td()->DetermineResultType(&unless));
356 ASSERT_NE(unless.condition()->result_type(), nullptr);
357 ASSERT_NE(lhs_ptr->result_type(), nullptr);
358 ASSERT_NE(rhs_ptr->result_type(), nullptr);
359 EXPECT_TRUE(unless.condition()->result_type()->IsI32());
360 EXPECT_TRUE(lhs_ptr->result_type()->IsI32());
361 EXPECT_TRUE(rhs_ptr->result_type()->IsF32());
362}
363
dan sinclairca893e32020-04-07 12:57:12 +0000364TEST_F(TypeDeterminerTest, Stmt_VariableDecl) {
365 ast::type::I32Type i32;
366 auto var =
367 std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone, &i32);
368 var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
369 std::make_unique<ast::IntLiteral>(&i32, 2)));
370 auto init_ptr = var->constructor();
371
372 ast::VariableDeclStatement decl(std::move(var));
373
374 EXPECT_TRUE(td()->DetermineResultType(&decl));
375 ASSERT_NE(init_ptr->result_type(), nullptr);
376 EXPECT_TRUE(init_ptr->result_type()->IsI32());
377}
378
dan sinclairb7edc4c2020-04-07 12:46:30 +0000379TEST_F(TypeDeterminerTest, Expr_Constructor_Scalar) {
380 ast::type::F32Type f32;
381 ast::ScalarConstructorExpression s(
382 std::make_unique<ast::FloatLiteral>(&f32, 1.0f));
383
384 EXPECT_TRUE(td()->DetermineResultType(&s));
385 ASSERT_NE(s.result_type(), nullptr);
386 EXPECT_TRUE(s.result_type()->IsF32());
387}
388
389TEST_F(TypeDeterminerTest, Expr_Constructor_Type) {
390 ast::type::F32Type f32;
391 ast::type::VectorType vec(&f32, 3);
392
393 ast::ExpressionList vals;
394 vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
395 std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
396 vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
397 std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
398 vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
399 std::make_unique<ast::FloatLiteral>(&f32, 3.0f)));
400
401 ast::TypeConstructorExpression tc(&vec, std::move(vals));
402
403 EXPECT_TRUE(td()->DetermineResultType(&tc));
404 ASSERT_NE(tc.result_type(), nullptr);
405 ASSERT_TRUE(tc.result_type()->IsVector());
406 EXPECT_TRUE(tc.result_type()->AsVector()->type()->IsF32());
407 EXPECT_EQ(tc.result_type()->AsVector()->size(), 3);
408}
409
dan sinclaircab0e732020-04-07 12:57:27 +0000410TEST_F(TypeDeterminerTest, Expr_Identifier_GlobalVariable) {
411 ast::type::F32Type f32;
412
413 ast::Module m;
414 auto var =
415 std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
416 m.AddGlobalVariable(std::move(var));
417
418 // Register the global
419 EXPECT_TRUE(td()->Determine(&m));
420
421 ast::IdentifierExpression ident("my_var");
422 EXPECT_TRUE(td()->DetermineResultType(&ident));
423 ASSERT_NE(ident.result_type(), nullptr);
424 EXPECT_TRUE(ident.result_type()->IsF32());
425}
426
427TEST_F(TypeDeterminerTest, Expr_Identifier_FunctionVariable) {
428 ast::type::F32Type f32;
429
430 auto my_var = std::make_unique<ast::IdentifierExpression>("my_var");
431 auto my_var_ptr = my_var.get();
432
433 ast::StatementList body;
434 body.push_back(std::make_unique<ast::VariableDeclStatement>(
435 std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone,
436 &f32)));
437
438 body.push_back(std::make_unique<ast::AssignmentStatement>(
439 std::move(my_var),
440 std::make_unique<ast::IdentifierExpression>("my_var")));
441
442 ast::Function f("my_func", {}, &f32);
443 f.set_body(std::move(body));
444
445 EXPECT_TRUE(td()->DetermineFunction(&f));
446
447 ASSERT_NE(my_var_ptr->result_type(), nullptr);
448 EXPECT_TRUE(my_var_ptr->result_type()->IsF32());
449}
450
451TEST_F(TypeDeterminerTest, Expr_Identifier_Function) {
452 ast::type::F32Type f32;
453
454 ast::VariableList params;
455 auto func =
456 std::make_unique<ast::Function>("my_func", std::move(params), &f32);
457 ast::Module m;
458 m.AddFunction(std::move(func));
459
460 // Register the function
461 EXPECT_TRUE(td()->Determine(&m));
462
463 ast::IdentifierExpression ident("my_func");
464 EXPECT_TRUE(td()->DetermineResultType(&ident));
465 ASSERT_NE(ident.result_type(), nullptr);
466 EXPECT_TRUE(ident.result_type()->IsF32());
467}
468
dan sinclairb7edc4c2020-04-07 12:46:30 +0000469} // namespace
470} // namespace tint