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 #ifndef SRC_AST_BINARY_EXPRESSION_H_
16 #define SRC_AST_BINARY_EXPRESSION_H_
17
18 #include "src/ast/expression.h"
19
20 namespace tint {
21 namespace ast {
22
23 /// The operator type
24 enum class BinaryOp {
25 kNone = 0,
26 kAnd, // &
27 kOr, // |
28 kXor,
29 kLogicalAnd, // &&
30 kLogicalOr, // ||
31 kEqual,
32 kNotEqual,
33 kLessThan,
34 kGreaterThan,
35 kLessThanEqual,
36 kGreaterThanEqual,
37 kShiftLeft,
38 kShiftRight,
39 kAdd,
40 kSubtract,
41 kMultiply,
42 kDivide,
43 kModulo,
44 };
45
46 /// An binary expression
47 class BinaryExpression : public Castable<BinaryExpression, Expression> {
48 public:
49 /// Constructor
50 /// @param program_id the identifier of the program that owns this node
51 /// @param source the binary expression source
52 /// @param op the operation type
53 /// @param lhs the left side of the expression
54 /// @param rhs the right side of the expression
55 BinaryExpression(ProgramID program_id,
56 const Source& source,
57 BinaryOp op,
58 const Expression* lhs,
59 const Expression* rhs);
60 /// Move constructor
61 BinaryExpression(BinaryExpression&&);
62 ~BinaryExpression() override;
63
64 /// @returns true if the op is and
IsAnd()65 bool IsAnd() const { return op == BinaryOp::kAnd; }
66 /// @returns true if the op is or
IsOr()67 bool IsOr() const { return op == BinaryOp::kOr; }
68 /// @returns true if the op is xor
IsXor()69 bool IsXor() const { return op == BinaryOp::kXor; }
70 /// @returns true if the op is logical and
IsLogicalAnd()71 bool IsLogicalAnd() const { return op == BinaryOp::kLogicalAnd; }
72 /// @returns true if the op is logical or
IsLogicalOr()73 bool IsLogicalOr() const { return op == BinaryOp::kLogicalOr; }
74 /// @returns true if the op is equal
IsEqual()75 bool IsEqual() const { return op == BinaryOp::kEqual; }
76 /// @returns true if the op is not equal
IsNotEqual()77 bool IsNotEqual() const { return op == BinaryOp::kNotEqual; }
78 /// @returns true if the op is less than
IsLessThan()79 bool IsLessThan() const { return op == BinaryOp::kLessThan; }
80 /// @returns true if the op is greater than
IsGreaterThan()81 bool IsGreaterThan() const { return op == BinaryOp::kGreaterThan; }
82 /// @returns true if the op is less than equal
IsLessThanEqual()83 bool IsLessThanEqual() const { return op == BinaryOp::kLessThanEqual; }
84 /// @returns true if the op is greater than equal
IsGreaterThanEqual()85 bool IsGreaterThanEqual() const { return op == BinaryOp::kGreaterThanEqual; }
86 /// @returns true if the op is shift left
IsShiftLeft()87 bool IsShiftLeft() const { return op == BinaryOp::kShiftLeft; }
88 /// @returns true if the op is shift right
IsShiftRight()89 bool IsShiftRight() const { return op == BinaryOp::kShiftRight; }
90 /// @returns true if the op is add
IsAdd()91 bool IsAdd() const { return op == BinaryOp::kAdd; }
92 /// @returns true if the op is subtract
IsSubtract()93 bool IsSubtract() const { return op == BinaryOp::kSubtract; }
94 /// @returns true if the op is multiply
IsMultiply()95 bool IsMultiply() const { return op == BinaryOp::kMultiply; }
96 /// @returns true if the op is divide
IsDivide()97 bool IsDivide() const { return op == BinaryOp::kDivide; }
98 /// @returns true if the op is modulo
IsModulo()99 bool IsModulo() const { return op == BinaryOp::kModulo; }
100 /// @returns true if the op is an arithmetic operation
101 bool IsArithmetic() const;
102 /// @returns true if the op is a comparison operation
103 bool IsComparison() const;
104 /// @returns true if the op is a bitwise operation
105 bool IsBitwise() const;
106 /// @returns true if the op is a bit shift operation
107 bool IsBitshift() const;
108
109 /// Clones this node and all transitive child nodes using the `CloneContext`
110 /// `ctx`.
111 /// @param ctx the clone context
112 /// @return the newly cloned node
113 const BinaryExpression* Clone(CloneContext* ctx) const override;
114
115 /// the binary op type
116 const BinaryOp op;
117 /// the left side expression
118 const Expression* const lhs;
119 /// the right side expression
120 const Expression* const rhs;
121 };
122
IsArithmetic()123 inline bool BinaryExpression::IsArithmetic() const {
124 switch (op) {
125 case ast::BinaryOp::kAdd:
126 case ast::BinaryOp::kSubtract:
127 case ast::BinaryOp::kMultiply:
128 case ast::BinaryOp::kDivide:
129 case ast::BinaryOp::kModulo:
130 return true;
131 default:
132 return false;
133 }
134 }
135
IsComparison()136 inline bool BinaryExpression::IsComparison() const {
137 switch (op) {
138 case ast::BinaryOp::kEqual:
139 case ast::BinaryOp::kNotEqual:
140 case ast::BinaryOp::kLessThan:
141 case ast::BinaryOp::kLessThanEqual:
142 case ast::BinaryOp::kGreaterThan:
143 case ast::BinaryOp::kGreaterThanEqual:
144 return true;
145 default:
146 return false;
147 }
148 }
149
IsBitwise()150 inline bool BinaryExpression::IsBitwise() const {
151 switch (op) {
152 case ast::BinaryOp::kAnd:
153 case ast::BinaryOp::kOr:
154 case ast::BinaryOp::kXor:
155 return true;
156 default:
157 return false;
158 }
159 }
160
IsBitshift()161 inline bool BinaryExpression::IsBitshift() const {
162 switch (op) {
163 case ast::BinaryOp::kShiftLeft:
164 case ast::BinaryOp::kShiftRight:
165 return true;
166 default:
167 return false;
168 }
169 }
170
171 /// @returns the human readable name of the given BinaryOp
172 /// @param op the BinaryOp
FriendlyName(BinaryOp op)173 constexpr const char* FriendlyName(BinaryOp op) {
174 switch (op) {
175 case BinaryOp::kNone:
176 return "none";
177 case BinaryOp::kAnd:
178 return "and";
179 case BinaryOp::kOr:
180 return "or";
181 case BinaryOp::kXor:
182 return "xor";
183 case BinaryOp::kLogicalAnd:
184 return "logical_and";
185 case BinaryOp::kLogicalOr:
186 return "logical_or";
187 case BinaryOp::kEqual:
188 return "equal";
189 case BinaryOp::kNotEqual:
190 return "not_equal";
191 case BinaryOp::kLessThan:
192 return "less_than";
193 case BinaryOp::kGreaterThan:
194 return "greater_than";
195 case BinaryOp::kLessThanEqual:
196 return "less_than_equal";
197 case BinaryOp::kGreaterThanEqual:
198 return "greater_than_equal";
199 case BinaryOp::kShiftLeft:
200 return "shift_left";
201 case BinaryOp::kShiftRight:
202 return "shift_right";
203 case BinaryOp::kAdd:
204 return "add";
205 case BinaryOp::kSubtract:
206 return "subtract";
207 case BinaryOp::kMultiply:
208 return "multiply";
209 case BinaryOp::kDivide:
210 return "divide";
211 case BinaryOp::kModulo:
212 return "modulo";
213 }
214 return "INVALID";
215 }
216
217 /// @param out the std::ostream to write to
218 /// @param op the BinaryOp
219 /// @return the std::ostream so calls can be chained
220 inline std::ostream& operator<<(std::ostream& out, BinaryOp op) {
221 out << FriendlyName(op);
222 return out;
223 }
224
225 } // namespace ast
226 } // namespace tint
227
228 #endif // SRC_AST_BINARY_EXPRESSION_H_
229