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,FunctionHeader)22 TEST_F(ParserImplTest, FunctionHeader) {
23 auto p = parser("fn main(a : i32, b: f32)");
24 auto f = p->function_header();
25 ASSERT_FALSE(p->has_error()) << p->error();
26 EXPECT_TRUE(f.matched);
27 EXPECT_FALSE(f.errored);
28
29 EXPECT_EQ(f->name, "main");
30 ASSERT_EQ(f->params.size(), 2u);
31 EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
32 EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
33 EXPECT_TRUE(f->return_type->Is<ast::Void>());
34 }
35
TEST_F(ParserImplTest,FunctionHeader_TrailingComma)36 TEST_F(ParserImplTest, FunctionHeader_TrailingComma) {
37 auto p = parser("fn main(a :i32,)");
38 auto f = p->function_header();
39 EXPECT_TRUE(f.matched);
40 EXPECT_FALSE(f.errored);
41
42 EXPECT_EQ(f->name, "main");
43 ASSERT_EQ(f->params.size(), 1u);
44 EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
45 EXPECT_TRUE(f->return_type->Is<ast::Void>());
46 }
47
TEST_F(ParserImplTest,FunctionHeader_DecoratedReturnType)48 TEST_F(ParserImplTest, FunctionHeader_DecoratedReturnType) {
49 auto p = parser("fn main() -> [[location(1)]] f32");
50 auto f = p->function_header();
51 ASSERT_FALSE(p->has_error()) << p->error();
52 EXPECT_TRUE(f.matched);
53 EXPECT_FALSE(f.errored);
54
55 EXPECT_EQ(f->name, "main");
56 EXPECT_EQ(f->params.size(), 0u);
57 EXPECT_TRUE(f->return_type->Is<ast::F32>());
58 ASSERT_EQ(f->return_type_decorations.size(), 1u);
59 auto* loc = f->return_type_decorations[0]->As<ast::LocationDecoration>();
60 ASSERT_TRUE(loc != nullptr);
61 EXPECT_EQ(loc->value, 1u);
62 }
63
TEST_F(ParserImplTest,FunctionHeader_InvariantReturnType)64 TEST_F(ParserImplTest, FunctionHeader_InvariantReturnType) {
65 auto p = parser("fn main() -> [[invariant]] f32");
66 auto f = p->function_header();
67 ASSERT_FALSE(p->has_error()) << p->error();
68 EXPECT_TRUE(f.matched);
69 EXPECT_FALSE(f.errored);
70
71 EXPECT_EQ(f->name, "main");
72 EXPECT_EQ(f->params.size(), 0u);
73 EXPECT_TRUE(f->return_type->Is<ast::F32>());
74 ASSERT_EQ(f->return_type_decorations.size(), 1u);
75 EXPECT_TRUE(f->return_type_decorations[0]->Is<ast::InvariantDecoration>());
76 }
77
TEST_F(ParserImplTest,FunctionHeader_DecoratedReturnType_WithArrayStride)78 TEST_F(ParserImplTest, FunctionHeader_DecoratedReturnType_WithArrayStride) {
79 auto p = parser("fn main() -> [[location(1), stride(16)]] array<f32, 4>");
80 auto f = p->function_header();
81 ASSERT_FALSE(p->has_error()) << p->error();
82 EXPECT_TRUE(f.matched);
83 EXPECT_FALSE(f.errored);
84
85 EXPECT_EQ(f->name, "main");
86 EXPECT_EQ(f->params.size(), 0u);
87 ASSERT_EQ(f->return_type_decorations.size(), 1u);
88 auto* loc = f->return_type_decorations[0]->As<ast::LocationDecoration>();
89 ASSERT_TRUE(loc != nullptr);
90 EXPECT_EQ(loc->value, 1u);
91
92 auto* array_type = f->return_type->As<ast::Array>();
93 ASSERT_EQ(array_type->decorations.size(), 1u);
94 auto* stride = array_type->decorations[0]->As<ast::StrideDecoration>();
95 ASSERT_TRUE(stride != nullptr);
96 EXPECT_EQ(stride->stride, 16u);
97 }
98
TEST_F(ParserImplTest,FunctionHeader_MissingIdent)99 TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
100 auto p = parser("fn ()");
101 auto f = p->function_header();
102 EXPECT_FALSE(f.matched);
103 EXPECT_TRUE(f.errored);
104 EXPECT_TRUE(p->has_error());
105 EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
106 }
107
TEST_F(ParserImplTest,FunctionHeader_InvalidIdent)108 TEST_F(ParserImplTest, FunctionHeader_InvalidIdent) {
109 auto p = parser("fn 133main() -> i32");
110 auto f = p->function_header();
111 EXPECT_FALSE(f.matched);
112 EXPECT_TRUE(f.errored);
113 EXPECT_TRUE(p->has_error());
114 EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
115 }
116
TEST_F(ParserImplTest,FunctionHeader_MissingParenLeft)117 TEST_F(ParserImplTest, FunctionHeader_MissingParenLeft) {
118 auto p = parser("fn main) -> i32");
119 auto f = p->function_header();
120 EXPECT_FALSE(f.matched);
121 EXPECT_TRUE(f.errored);
122 EXPECT_TRUE(p->has_error());
123 EXPECT_EQ(p->error(), "1:8: expected '(' for function declaration");
124 }
125
TEST_F(ParserImplTest,FunctionHeader_InvalidParamList)126 TEST_F(ParserImplTest, FunctionHeader_InvalidParamList) {
127 auto p = parser("fn main(a :i32, ,) -> i32");
128 auto f = p->function_header();
129 EXPECT_FALSE(f.matched);
130 EXPECT_TRUE(f.errored);
131 EXPECT_TRUE(p->has_error());
132 EXPECT_EQ(p->error(), "1:17: expected ')' for function declaration");
133 }
134
TEST_F(ParserImplTest,FunctionHeader_MissingParenRight)135 TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
136 auto p = parser("fn main( -> i32");
137 auto f = p->function_header();
138 EXPECT_FALSE(f.matched);
139 EXPECT_TRUE(f.errored);
140 EXPECT_TRUE(p->has_error());
141 EXPECT_EQ(p->error(), "1:10: expected ')' for function declaration");
142 }
143
TEST_F(ParserImplTest,FunctionHeader_MissingReturnType)144 TEST_F(ParserImplTest, FunctionHeader_MissingReturnType) {
145 auto p = parser("fn main() ->");
146 auto f = p->function_header();
147 EXPECT_FALSE(f.matched);
148 EXPECT_TRUE(f.errored);
149 EXPECT_TRUE(p->has_error());
150 EXPECT_EQ(p->error(), "1:13: unable to determine function return type");
151 }
152
153 } // namespace
154 } // namespace wgsl
155 } // namespace reader
156 } // namespace tint
157