• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ast/traverse_expressions.h"
16 #include "gmock/gmock.h"
17 #include "src/ast/test_helper.h"
18 
19 namespace tint {
20 namespace ast {
21 namespace {
22 
23 using ::testing::ElementsAre;
24 
25 using TraverseExpressionsTest = TestHelper;
26 
TEST_F(TraverseExpressionsTest,DescendIndexAccessor)27 TEST_F(TraverseExpressionsTest, DescendIndexAccessor) {
28   std::vector<const ast::Expression*> e = {Expr(1), Expr(1), Expr(1), Expr(1)};
29   std::vector<const ast::Expression*> i = {IndexAccessor(e[0], e[1]),
30                                            IndexAccessor(e[2], e[3])};
31   auto* root = IndexAccessor(i[0], i[1]);
32   {
33     std::vector<const ast::Expression*> l2r;
34     TraverseExpressions<TraverseOrder::LeftToRight>(
35         root, Diagnostics(), [&](const ast::Expression* expr) {
36           l2r.push_back(expr);
37           return ast::TraverseAction::Descend;
38         });
39     EXPECT_THAT(l2r, ElementsAre(root, i[0], e[0], e[1], i[1], e[2], e[3]));
40   }
41   {
42     std::vector<const ast::Expression*> r2l;
43     TraverseExpressions<TraverseOrder::RightToLeft>(
44         root, Diagnostics(), [&](const ast::Expression* expr) {
45           r2l.push_back(expr);
46           return ast::TraverseAction::Descend;
47         });
48     EXPECT_THAT(r2l, ElementsAre(root, i[1], e[3], e[2], i[0], e[1], e[0]));
49   }
50 }
51 
TEST_F(TraverseExpressionsTest,DescendBinaryExpression)52 TEST_F(TraverseExpressionsTest, DescendBinaryExpression) {
53   std::vector<const ast::Expression*> e = {Expr(1), Expr(1), Expr(1), Expr(1)};
54   std::vector<const ast::Expression*> i = {Add(e[0], e[1]), Sub(e[2], e[3])};
55   auto* root = Mul(i[0], i[1]);
56   {
57     std::vector<const ast::Expression*> l2r;
58     TraverseExpressions<TraverseOrder::LeftToRight>(
59         root, Diagnostics(), [&](const ast::Expression* expr) {
60           l2r.push_back(expr);
61           return ast::TraverseAction::Descend;
62         });
63     EXPECT_THAT(l2r, ElementsAre(root, i[0], e[0], e[1], i[1], e[2], e[3]));
64   }
65   {
66     std::vector<const ast::Expression*> r2l;
67     TraverseExpressions<TraverseOrder::RightToLeft>(
68         root, Diagnostics(), [&](const ast::Expression* expr) {
69           r2l.push_back(expr);
70           return ast::TraverseAction::Descend;
71         });
72     EXPECT_THAT(r2l, ElementsAre(root, i[1], e[3], e[2], i[0], e[1], e[0]));
73   }
74 }
75 
TEST_F(TraverseExpressionsTest,DescendBitcastExpression)76 TEST_F(TraverseExpressionsTest, DescendBitcastExpression) {
77   auto* e = Expr(1);
78   auto* b0 = Bitcast<i32>(e);
79   auto* b1 = Bitcast<i32>(b0);
80   auto* b2 = Bitcast<i32>(b1);
81   auto* root = Bitcast<i32>(b2);
82   {
83     std::vector<const ast::Expression*> l2r;
84     TraverseExpressions<TraverseOrder::LeftToRight>(
85         root, Diagnostics(), [&](const ast::Expression* expr) {
86           l2r.push_back(expr);
87           return ast::TraverseAction::Descend;
88         });
89     EXPECT_THAT(l2r, ElementsAre(root, b2, b1, b0, e));
90   }
91   {
92     std::vector<const ast::Expression*> r2l;
93     TraverseExpressions<TraverseOrder::RightToLeft>(
94         root, Diagnostics(), [&](const ast::Expression* expr) {
95           r2l.push_back(expr);
96           return ast::TraverseAction::Descend;
97         });
98     EXPECT_THAT(r2l, ElementsAre(root, b2, b1, b0, e));
99   }
100 }
101 
TEST_F(TraverseExpressionsTest,DescendCallExpression)102 TEST_F(TraverseExpressionsTest, DescendCallExpression) {
103   std::vector<const ast::Expression*> e = {Expr(1), Expr(1), Expr(1), Expr(1)};
104   std::vector<const ast::Expression*> c = {Call("a", e[0], e[1]),
105                                            Call("b", e[2], e[3])};
106   auto* root = Call("c", c[0], c[1]);
107   {
108     std::vector<const ast::Expression*> l2r;
109     TraverseExpressions<TraverseOrder::LeftToRight>(
110         root, Diagnostics(), [&](const ast::Expression* expr) {
111           l2r.push_back(expr);
112           return ast::TraverseAction::Descend;
113         });
114     EXPECT_THAT(l2r, ElementsAre(root, c[0], e[0], e[1], c[1], e[2], e[3]));
115   }
116   {
117     std::vector<const ast::Expression*> r2l;
118     TraverseExpressions<TraverseOrder::RightToLeft>(
119         root, Diagnostics(), [&](const ast::Expression* expr) {
120           r2l.push_back(expr);
121           return ast::TraverseAction::Descend;
122         });
123     EXPECT_THAT(r2l, ElementsAre(root, c[1], e[3], e[2], c[0], e[1], e[0]));
124   }
125 }
126 
127 // TODO(crbug.com/tint/1257): Test ignores member accessor 'member' field.
128 // Replace with the test below when fixed.
TEST_F(TraverseExpressionsTest,DescendMemberIndexExpression)129 TEST_F(TraverseExpressionsTest, DescendMemberIndexExpression) {
130   auto* e = Expr(1);
131   auto* m = MemberAccessor(e, Expr("a"));
132   auto* root = MemberAccessor(m, Expr("b"));
133   {
134     std::vector<const ast::Expression*> l2r;
135     TraverseExpressions<TraverseOrder::LeftToRight>(
136         root, Diagnostics(), [&](const ast::Expression* expr) {
137           l2r.push_back(expr);
138           return ast::TraverseAction::Descend;
139         });
140     EXPECT_THAT(l2r, ElementsAre(root, m, e));
141   }
142   {
143     std::vector<const ast::Expression*> r2l;
144     TraverseExpressions<TraverseOrder::RightToLeft>(
145         root, Diagnostics(), [&](const ast::Expression* expr) {
146           r2l.push_back(expr);
147           return ast::TraverseAction::Descend;
148         });
149     EXPECT_THAT(r2l, ElementsAre(root, m, e));
150   }
151 }
152 
153 // TODO(crbug.com/tint/1257): The correct test for DescendMemberIndexExpression.
TEST_F(TraverseExpressionsTest,DISABLED_DescendMemberIndexExpression)154 TEST_F(TraverseExpressionsTest, DISABLED_DescendMemberIndexExpression) {
155   auto* e = Expr(1);
156   std::vector<const ast::IdentifierExpression*> i = {Expr("a"), Expr("b")};
157   auto* m = MemberAccessor(e, i[0]);
158   auto* root = MemberAccessor(m, i[1]);
159   {
160     std::vector<const ast::Expression*> l2r;
161     TraverseExpressions<TraverseOrder::LeftToRight>(
162         root, Diagnostics(), [&](const ast::Expression* expr) {
163           l2r.push_back(expr);
164           return ast::TraverseAction::Descend;
165         });
166     EXPECT_THAT(l2r, ElementsAre(root, m, e, i[0], i[1]));
167   }
168   {
169     std::vector<const ast::Expression*> r2l;
170     TraverseExpressions<TraverseOrder::RightToLeft>(
171         root, Diagnostics(), [&](const ast::Expression* expr) {
172           r2l.push_back(expr);
173           return ast::TraverseAction::Descend;
174         });
175     EXPECT_THAT(r2l, ElementsAre(root, i[1], m, i[0], e));
176   }
177 }
178 
TEST_F(TraverseExpressionsTest,DescendUnaryExpression)179 TEST_F(TraverseExpressionsTest, DescendUnaryExpression) {
180   auto* e = Expr(1);
181   auto* u0 = AddressOf(e);
182   auto* u1 = Deref(u0);
183   auto* u2 = AddressOf(u1);
184   auto* root = Deref(u2);
185   {
186     std::vector<const ast::Expression*> l2r;
187     TraverseExpressions<TraverseOrder::LeftToRight>(
188         root, Diagnostics(), [&](const ast::Expression* expr) {
189           l2r.push_back(expr);
190           return ast::TraverseAction::Descend;
191         });
192     EXPECT_THAT(l2r, ElementsAre(root, u2, u1, u0, e));
193   }
194   {
195     std::vector<const ast::Expression*> r2l;
196     TraverseExpressions<TraverseOrder::RightToLeft>(
197         root, Diagnostics(), [&](const ast::Expression* expr) {
198           r2l.push_back(expr);
199           return ast::TraverseAction::Descend;
200         });
201     EXPECT_THAT(r2l, ElementsAre(root, u2, u1, u0, e));
202   }
203 }
204 
TEST_F(TraverseExpressionsTest,Skip)205 TEST_F(TraverseExpressionsTest, Skip) {
206   std::vector<const ast::Expression*> e = {Expr(1), Expr(1), Expr(1), Expr(1)};
207   std::vector<const ast::Expression*> i = {IndexAccessor(e[0], e[1]),
208                                            IndexAccessor(e[2], e[3])};
209   auto* root = IndexAccessor(i[0], i[1]);
210   std::vector<const ast::Expression*> order;
211   TraverseExpressions<TraverseOrder::LeftToRight>(
212       root, Diagnostics(), [&](const ast::Expression* expr) {
213         order.push_back(expr);
214         return expr == i[0] ? ast::TraverseAction::Skip
215                             : ast::TraverseAction::Descend;
216       });
217   EXPECT_THAT(order, ElementsAre(root, i[0], i[1], e[2], e[3]));
218 }
219 
TEST_F(TraverseExpressionsTest,Stop)220 TEST_F(TraverseExpressionsTest, Stop) {
221   std::vector<const ast::Expression*> e = {Expr(1), Expr(1), Expr(1), Expr(1)};
222   std::vector<const ast::Expression*> i = {IndexAccessor(e[0], e[1]),
223                                            IndexAccessor(e[2], e[3])};
224   auto* root = IndexAccessor(i[0], i[1]);
225   std::vector<const ast::Expression*> order;
226   TraverseExpressions<TraverseOrder::LeftToRight>(
227       root, Diagnostics(), [&](const ast::Expression* expr) {
228         order.push_back(expr);
229         return expr == i[0] ? ast::TraverseAction::Stop
230                             : ast::TraverseAction::Descend;
231       });
232   EXPECT_THAT(order, ElementsAre(root, i[0]));
233 }
234 
235 }  // namespace
236 }  // namespace ast
237 }  // namespace tint
238