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 #include "binaryExpression.h"
17 
18 #include "compiler/core/pandagen.h"
19 #include "compiler/core/ETSGen.h"
20 #include "checker/TSchecker.h"
21 #include "ir/astNode.h"
22 #include "ir/expression.h"
23 #include "ir/srcDump.h"
24 #include "ir/visitor/AstVisitor.h"
25 
26 namespace ark::es2panda::ir {
TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)27 void BinaryExpression::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
28 {
29     if (auto *transformedNode = cb(left_); left_ != transformedNode) {
30         left_->SetTransformedNode(transformationName, transformedNode);
31         left_ = transformedNode->AsExpression();
32     }
33 
34     if (auto *transformedNode = cb(right_); right_ != transformedNode) {
35         right_->SetTransformedNode(transformationName, transformedNode);
36         right_ = transformedNode->AsExpression();
37     }
38 }
39 
Iterate(const NodeTraverser &cb) const40 void BinaryExpression::Iterate(const NodeTraverser &cb) const
41 {
42     cb(left_);
43     cb(right_);
44 }
45 
Dump(ir::AstDumper *dumper) const46 void BinaryExpression::Dump(ir::AstDumper *dumper) const
47 {
48     dumper->Add({{"type", IsLogical() ? "LogicalExpression" : "BinaryExpression"},
49                  {"operator", operator_},
50                  {"left", left_},
51                  {"right", right_}});
52 }
53 
Dump(ir::SrcDumper *dumper) const54 void BinaryExpression::Dump(ir::SrcDumper *dumper) const
55 {
56     ASSERT(left_ != nullptr);
57     ASSERT(right_ != nullptr);
58     dumper->Add("((");
59     left_->Dump(dumper);
60     dumper->Add(") ");
61     dumper->Add(TokenToString(operator_));
62     dumper->Add(" (");
63     right_->Dump(dumper);
64     dumper->Add("))");
65 }
66 
Compile(compiler::PandaGen *pg) const67 void BinaryExpression::Compile(compiler::PandaGen *pg) const
68 {
69     pg->GetAstCompiler()->Compile(this);
70 }
71 
Compile(compiler::ETSGen *etsg) const72 void BinaryExpression::Compile(compiler::ETSGen *etsg) const
73 {
74     etsg->GetAstCompiler()->Compile(this);
75 }
76 
CompileOperands(compiler::ETSGen *etsg, compiler::VReg lhs) const77 void BinaryExpression::CompileOperands(compiler::ETSGen *etsg, compiler::VReg lhs) const
78 {
79     left_->Compile(etsg);
80 
81     if (operator_ == lexer::TokenType::KEYW_INSTANCEOF) {
82         etsg->StoreAccumulator(left_, lhs);
83     } else {
84         etsg->ApplyConversionAndStoreAccumulator(left_, lhs, operationType_);
85     }
86 
87     right_->Compile(etsg);
88     etsg->ApplyConversion(right_, operationType_);
89 }
90 
Check(checker::TSChecker *checker)91 checker::Type *BinaryExpression::Check(checker::TSChecker *checker)
92 {
93     return checker->GetAnalyzer()->Check(this);
94 }
95 
Check(checker::ETSChecker *checker)96 checker::Type *BinaryExpression::Check(checker::ETSChecker *checker)
97 {
98     return checker->GetAnalyzer()->Check(this);
99 }
100 
Clone(ArenaAllocator *const allocator, AstNode *const parent)101 BinaryExpression *BinaryExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent)
102 {
103     auto *const left = left_ != nullptr ? left_->Clone(allocator, nullptr)->AsExpression() : nullptr;
104     auto *const right = right_ != nullptr ? right_->Clone(allocator, nullptr)->AsExpression() : nullptr;
105 
106     if (auto *const clone = allocator->New<BinaryExpression>(left, right, operator_); clone != nullptr) {
107         if (operationType_ != nullptr) {
108             clone->SetOperationType(operationType_);
109         }
110 
111         if (right != nullptr) {
112             right->SetParent(clone);
113         }
114 
115         if (left != nullptr) {
116             left->SetParent(clone);
117         }
118 
119         if (parent != nullptr) {
120             clone->SetParent(parent);
121         }
122 
123         clone->SetRange(Range());
124         return clone;
125     }
126 
127     throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
128 }
129 }  // namespace ark::es2panda::ir
130