1 // Copyright 2021 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/transform/for_loop_to_loop.h"
16
17 #include "src/transform/test_helper.h"
18
19 namespace tint {
20 namespace transform {
21 namespace {
22
23 using ForLoopToLoopTest = TransformTest;
24
TEST_F(ForLoopToLoopTest,EmptyModule)25 TEST_F(ForLoopToLoopTest, EmptyModule) {
26 auto* src = "";
27 auto* expect = src;
28
29 auto got = Run<ForLoopToLoop>(src);
30
31 EXPECT_EQ(expect, str(got));
32 }
33
34 // Test an empty for loop.
TEST_F(ForLoopToLoopTest,Empty)35 TEST_F(ForLoopToLoopTest, Empty) {
36 auto* src = R"(
37 fn f() {
38 for (;;) {
39 }
40 }
41 )";
42
43 auto* expect = R"(
44 fn f() {
45 loop {
46 }
47 }
48 )";
49
50 auto got = Run<ForLoopToLoop>(src);
51
52 EXPECT_EQ(expect, str(got));
53 }
54
55 // Test a for loop with non-empty body.
TEST_F(ForLoopToLoopTest,Body)56 TEST_F(ForLoopToLoopTest, Body) {
57 auto* src = R"(
58 fn f() {
59 for (;;) {
60 discard;
61 }
62 }
63 )";
64
65 auto* expect = R"(
66 fn f() {
67 loop {
68 discard;
69 }
70 }
71 )";
72
73 auto got = Run<ForLoopToLoop>(src);
74
75 EXPECT_EQ(expect, str(got));
76 }
77
78 // Test a for loop declaring a variable in the initializer statement.
TEST_F(ForLoopToLoopTest,InitializerStatementDecl)79 TEST_F(ForLoopToLoopTest, InitializerStatementDecl) {
80 auto* src = R"(
81 fn f() {
82 for (var i: i32;;) {
83
84 }
85 }
86 )";
87
88 auto* expect = R"(
89 fn f() {
90 {
91 var i : i32;
92 loop {
93 }
94 }
95 }
96 )";
97
98 auto got = Run<ForLoopToLoop>(src);
99
100 EXPECT_EQ(expect, str(got));
101 }
102
103 // Test a for loop declaring and initializing a variable in the initializer
104 // statement.
TEST_F(ForLoopToLoopTest,InitializerStatementDeclEqual)105 TEST_F(ForLoopToLoopTest, InitializerStatementDeclEqual) {
106 auto* src = R"(
107 fn f() {
108 for (var i: i32 = 0;;) {
109 }
110 }
111 )";
112
113 auto* expect = R"(
114 fn f() {
115 {
116 var i : i32 = 0;
117 loop {
118 }
119 }
120 }
121 )";
122
123 auto got = Run<ForLoopToLoop>(src);
124
125 EXPECT_EQ(expect, str(got));
126 }
127
128 // Test a for loop declaring a const variable in the initializer statement.
TEST_F(ForLoopToLoopTest,InitializerStatementConstDecl)129 TEST_F(ForLoopToLoopTest, InitializerStatementConstDecl) {
130 auto* src = R"(
131 fn f() {
132 for (let i: i32 = 0;;) {
133 }
134 }
135 )";
136
137 auto* expect = R"(
138 fn f() {
139 {
140 let i : i32 = 0;
141 loop {
142 }
143 }
144 }
145 )";
146
147 auto got = Run<ForLoopToLoop>(src);
148
149 EXPECT_EQ(expect, str(got));
150 }
151
152 // Test a for loop assigning a variable in the initializer statement.
TEST_F(ForLoopToLoopTest,InitializerStatementAssignment)153 TEST_F(ForLoopToLoopTest, InitializerStatementAssignment) {
154 auto* src = R"(
155 fn f() {
156 var i: i32;
157 for (i = 0;;) {
158
159 }
160 }
161 )";
162
163 auto* expect = R"(
164 fn f() {
165 var i : i32;
166 {
167 i = 0;
168 loop {
169 }
170 }
171 }
172 )";
173
174 auto got = Run<ForLoopToLoop>(src);
175
176 EXPECT_EQ(expect, str(got));
177 }
178
179 // Test a for loop calling a function in the initializer statement.
TEST_F(ForLoopToLoopTest,InitializerStatementFuncCall)180 TEST_F(ForLoopToLoopTest, InitializerStatementFuncCall) {
181 auto* src = R"(
182 fn a(x : i32, y : i32) {
183 }
184
185 fn f() {
186 var b : i32;
187 var c : i32;
188 for (a(b,c);;) { }
189 }
190 )";
191
192 auto* expect = R"(
193 fn a(x : i32, y : i32) {
194 }
195
196 fn f() {
197 var b : i32;
198 var c : i32;
199 {
200 a(b, c);
201 loop {
202 }
203 }
204 }
205 )";
206
207 auto got = Run<ForLoopToLoop>(src);
208
209 EXPECT_EQ(expect, str(got));
210 }
211
212 // Test a for loop with a break condition
TEST_F(ForLoopToLoopTest,BreakCondition)213 TEST_F(ForLoopToLoopTest, BreakCondition) {
214 auto* src = R"(
215 fn f() {
216 for (; 0 == 1;) {
217 }
218 }
219 )";
220
221 auto* expect = R"(
222 fn f() {
223 loop {
224 if (!((0 == 1))) {
225 break;
226 }
227 }
228 }
229 )";
230
231 auto got = Run<ForLoopToLoop>(src);
232
233 EXPECT_EQ(expect, str(got));
234 }
235
236 // Test a for loop assigning a variable in the continuing statement.
TEST_F(ForLoopToLoopTest,ContinuingAssignment)237 TEST_F(ForLoopToLoopTest, ContinuingAssignment) {
238 auto* src = R"(
239 fn f() {
240 var x: i32;
241 for (;;x = 2) {
242 }
243 }
244 )";
245
246 auto* expect = R"(
247 fn f() {
248 var x : i32;
249 loop {
250
251 continuing {
252 x = 2;
253 }
254 }
255 }
256 )";
257
258 auto got = Run<ForLoopToLoop>(src);
259
260 EXPECT_EQ(expect, str(got));
261 }
262
263 // Test a for loop calling a function in the continuing statement.
TEST_F(ForLoopToLoopTest,ContinuingFuncCall)264 TEST_F(ForLoopToLoopTest, ContinuingFuncCall) {
265 auto* src = R"(
266 fn a(x : i32, y : i32) {
267 }
268
269 fn f() {
270 var b : i32;
271 var c : i32;
272 for (;;a(b,c)) {
273 }
274 }
275 )";
276
277 auto* expect = R"(
278 fn a(x : i32, y : i32) {
279 }
280
281 fn f() {
282 var b : i32;
283 var c : i32;
284 loop {
285
286 continuing {
287 a(b, c);
288 }
289 }
290 }
291 )";
292
293 auto got = Run<ForLoopToLoop>(src);
294
295 EXPECT_EQ(expect, str(got));
296 }
297
298 // Test a for loop with all statements non-empty.
TEST_F(ForLoopToLoopTest,All)299 TEST_F(ForLoopToLoopTest, All) {
300 auto* src = R"(
301 fn f() {
302 var a : i32;
303 for(var i : i32 = 0; i < 4; i = i + 1) {
304 if (a == 0) {
305 continue;
306 }
307 a = a + 2;
308 }
309 }
310 )";
311
312 auto* expect = R"(
313 fn f() {
314 var a : i32;
315 {
316 var i : i32 = 0;
317 loop {
318 if (!((i < 4))) {
319 break;
320 }
321 if ((a == 0)) {
322 continue;
323 }
324 a = (a + 2);
325
326 continuing {
327 i = (i + 1);
328 }
329 }
330 }
331 }
332 )";
333
334 auto got = Run<ForLoopToLoop>(src);
335
336 EXPECT_EQ(expect, str(got));
337 }
338
339 } // namespace
340 } // namespace transform
341 } // namespace tint
342