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 "ifStatement.h"
17 
18 #include "checker/TSchecker.h"
19 #include "compiler/core/ETSGen.h"
20 #include "compiler/core/pandagen.h"
21 #include "ir/astDump.h"
22 #include "ir/srcDump.h"
23 
24 namespace ark::es2panda::ir {
TransformChildren(const NodeTransformer &cb, std::string_view transformationName)25 void IfStatement::TransformChildren(const NodeTransformer &cb, std::string_view transformationName)
26 {
27     if (auto *transformedNode = cb(test_); test_ != transformedNode) {
28         test_->SetTransformedNode(transformationName, transformedNode);
29         test_ = transformedNode->AsExpression();
30     }
31 
32     if (auto *transformedNode = cb(consequent_); consequent_ != transformedNode) {
33         consequent_->SetTransformedNode(transformationName, transformedNode);
34         consequent_ = transformedNode->AsStatement();
35     }
36 
37     if (alternate_ != nullptr) {
38         if (auto *transformedNode = cb(alternate_); alternate_ != transformedNode) {
39             alternate_->SetTransformedNode(transformationName, transformedNode);
40             alternate_ = transformedNode->AsStatement();
41         }
42     }
43 }
44 
Iterate(const NodeTraverser &cb) const45 void IfStatement::Iterate(const NodeTraverser &cb) const
46 {
47     cb(test_);
48     cb(consequent_);
49 
50     if (alternate_ != nullptr) {
51         cb(alternate_);
52     }
53 }
54 
Dump(ir::AstDumper *dumper) const55 void IfStatement::Dump(ir::AstDumper *dumper) const
56 {
57     dumper->Add({{"type", "IfStatement"},
58                  {"test", test_},
59                  {"consequent", consequent_},
60                  {"alternate", AstDumper::Nullish(alternate_)}});
61 }
62 
Dump(ir::SrcDumper *dumper) const63 void IfStatement::Dump(ir::SrcDumper *dumper) const
64 {
65     ASSERT(test_);
66     dumper->Add("if (");
67     test_->Dump(dumper);
68     dumper->Add(") {");
69     if (consequent_ != nullptr) {
70         dumper->IncrIndent();
71         dumper->Endl();
72         dumper->DecrIndent();
73         consequent_->Dump(dumper);
74         dumper->Endl();
75     }
76     dumper->Add("}");
77     if (alternate_ != nullptr) {
78         dumper->Add(" else ");
79         if (alternate_->IsBlockStatement()) {
80             dumper->Add("{");
81             dumper->IncrIndent();
82             dumper->Endl();
83             dumper->DecrIndent();
84             alternate_->Dump(dumper);
85             dumper->Endl();
86             dumper->Add("}");
87         } else {
88             alternate_->Dump(dumper);
89         }
90     }
91 }
92 
Compile(compiler::PandaGen *pg) const93 void IfStatement::Compile(compiler::PandaGen *pg) const
94 {
95     pg->GetAstCompiler()->Compile(this);
96 }
97 
Compile(compiler::ETSGen *etsg) const98 void IfStatement::Compile(compiler::ETSGen *etsg) const
99 {
100     etsg->GetAstCompiler()->Compile(this);
101 }
102 
Check([[maybe_unused]] checker::TSChecker *checker)103 checker::Type *IfStatement::Check([[maybe_unused]] checker::TSChecker *checker)
104 {
105     return checker->GetAnalyzer()->Check(this);
106 }
107 
Check([[maybe_unused]] checker::ETSChecker *checker)108 checker::Type *IfStatement::Check([[maybe_unused]] checker::ETSChecker *checker)
109 {
110     return checker->GetAnalyzer()->Check(this);
111 }
112 
Clone(ArenaAllocator *const allocator, AstNode *const parent)113 IfStatement *IfStatement::Clone(ArenaAllocator *const allocator, AstNode *const parent)
114 {
115     auto *const test = test_->Clone(allocator, nullptr)->AsExpression();
116     auto *const consequent = consequent_->Clone(allocator, nullptr)->AsStatement();
117     auto *const alternate = alternate_ != nullptr ? consequent_->Clone(allocator, nullptr)->AsStatement() : nullptr;
118 
119     if (auto *const clone = allocator->New<IfStatement>(test, consequent, alternate); clone != nullptr) {
120         if (parent != nullptr) {
121             clone->SetParent(parent);
122         }
123 
124         test->SetParent(clone);
125         consequent->SetParent(clone);
126         if (alternate != nullptr) {
127             alternate->SetParent(clone);
128         }
129 
130         clone->SetRange(Range());
131         return clone;
132     }
133     throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
134 }
135 }  // namespace ark::es2panda::ir
136