1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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 
16 #ifndef ES2PANDA_IR_EXPRESSION_BINARY_EXPRESSION_H
17 #define ES2PANDA_IR_EXPRESSION_BINARY_EXPRESSION_H
18 
19 #include "checker/checkerContext.h"
20 #include "compiler/core/vReg.h"
21 #include "ir/expression.h"
22 
23 namespace ark::es2panda::checker {
24 class ETSAnalyzer;
25 }  // namespace ark::es2panda::checker
26 
27 namespace ark::es2panda::ir {
28 class BinaryExpression : public Expression {
29 public:
30     BinaryExpression() = delete;
31     ~BinaryExpression() override = default;
32 
33     NO_COPY_SEMANTIC(BinaryExpression);
34     NO_MOVE_SEMANTIC(BinaryExpression);
35 
BinaryExpression(Expression *const left, Expression *const right, lexer::TokenType const operatorType)36     explicit BinaryExpression(Expression *const left, Expression *const right, lexer::TokenType const operatorType)
37         : Expression(AstNodeType::BINARY_EXPRESSION), left_(left), right_(right), operator_(operatorType)
38     {
39     }
40 
41     // NOTE (csabahurton): friend relationship can be removed once there are getters for private fields
42     friend class checker::ETSAnalyzer;
43 
44     [[nodiscard]] const Expression *Left() const noexcept
45     {
46         return left_;
47     }
48 
49     [[nodiscard]] Expression *Left() noexcept
50     {
51         return left_;
52     }
53 
54     [[nodiscard]] const Expression *Right() const noexcept
55     {
56         return right_;
57     }
58 
59     [[nodiscard]] Expression *Right() noexcept
60     {
61         return right_;
62     }
63 
64     [[nodiscard]] const Expression *Result() const noexcept
65     {
66         return result_;
67     }
68 
69     [[nodiscard]] Expression *Result() noexcept
70     {
71         return result_;
72     }
73 
74     [[nodiscard]] lexer::TokenType OperatorType() const noexcept
75     {
76         return operator_;
77     }
78 
79     [[nodiscard]] bool IsLogical() const noexcept
80     {
81         return operator_ <= lexer::TokenType::PUNCTUATOR_LOGICAL_AND;
82     }
83 
84     [[nodiscard]] bool IsLogicalExtended() const noexcept
85     {
86         return operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND ||
87                operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR;
88     }
89 
90     [[nodiscard]] bool IsBitwise() const noexcept
91     {
92         return operator_ == lexer::TokenType::PUNCTUATOR_BITWISE_OR ||
93                operator_ == lexer::TokenType::PUNCTUATOR_BITWISE_XOR ||
94                operator_ == lexer::TokenType::PUNCTUATOR_BITWISE_AND ||
95                operator_ == lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL ||
96                operator_ == lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL ||
97                operator_ == lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL;
98     }
99 
100     [[nodiscard]] bool IsArithmetic() const noexcept
101     {
102         return operator_ == lexer::TokenType::PUNCTUATOR_PLUS || operator_ == lexer::TokenType::PUNCTUATOR_MINUS ||
103                operator_ == lexer::TokenType::PUNCTUATOR_MULTIPLY || operator_ == lexer::TokenType::PUNCTUATOR_DIVIDE ||
104                operator_ == lexer::TokenType::PUNCTUATOR_MOD || operator_ == lexer::TokenType::PUNCTUATOR_PLUS_EQUAL ||
105                operator_ == lexer::TokenType::PUNCTUATOR_MINUS_EQUAL ||
106                operator_ == lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL ||
107                operator_ == lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL ||
108                operator_ == lexer::TokenType::PUNCTUATOR_MOD_EQUAL || IsBitwise();
109     }
110 
111     void SetLeft(Expression *expr) noexcept
112     {
113         left_ = expr;
114         left_->SetParent(this);
115         SetStart(left_->Start());
116     }
117 
118     void SetRight(Expression *expr) noexcept
119     {
120         right_ = expr;
121         right_->SetParent(this);
122         SetEnd(right_->End());
123     }
124 
125     void SetResult(Expression *expr) noexcept
126     {
127         result_ = expr;
128         result_->SetParent(this);
129         SetStart(result_->Start());
130     }
131 
132     void SetOperator(lexer::TokenType operatorType) noexcept
133     {
134         operator_ = operatorType;
135         type_ = AstNodeType::BINARY_EXPRESSION;
136     }
137 
138     [[nodiscard]] checker::Type *OperationType() noexcept
139     {
140         return operationType_;
141     }
142 
143     void SetOperationType(checker::Type *const operationType) noexcept
144     {
145         operationType_ = operationType;
146     }
147 
148     [[nodiscard]] const checker::Type *OperationType() const noexcept
149     {
150         return operationType_;
151     }
152 
153     [[nodiscard]] BinaryExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override;
154 
155     void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
156     void Iterate(const NodeTraverser &cb) const override;
157     void Dump(ir::AstDumper *dumper) const override;
158     void Dump(ir::SrcDumper *dumper) const override;
159     void Compile(compiler::PandaGen *pg) const override;
160     void Compile(compiler::ETSGen *etsg) const override;
161     void CompileOperands(compiler::ETSGen *etsg, compiler::VReg lhs) const;
162     checker::Type *Check(checker::TSChecker *checker) override;
163     checker::Type *Check(checker::ETSChecker *checker) override;
164 
165     void Accept(ASTVisitorT *v) override
166     {
167         v->Accept(this);
168     }
169 
170 private:
171     Expression *left_ = nullptr;
172     Expression *right_ = nullptr;
173     Expression *result_ = nullptr;
174     lexer::TokenType operator_;
175     checker::Type *operationType_ {};
176 };
177 }  // namespace ark::es2panda::ir
178 
179 #endif
180