• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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