1/** 2 * Copyright (c) 2021 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 "compiler/base/condition.h" 19#include "compiler/core/pandagen.h" 20#include "ir/astDump.h" 21#include "ir/statements/blockStatement.h" 22#include "ir/expression.h" 23#include "typescript/checker.h" 24 25namespace panda::es2panda::ir { 26 27void IfStatement::Iterate(const NodeTraverser &cb) const 28{ 29 cb(test_); 30 cb(consequent_); 31 32 if (alternate_) { 33 cb(alternate_); 34 } 35} 36 37void IfStatement::Dump(ir::AstDumper *dumper) const 38{ 39 dumper->Add({{"type", "IfStatement"}, 40 {"test", test_}, 41 {"consequent", consequent_}, 42 {"alternate", AstDumper::Nullable(alternate_)}}); 43} 44 45void IfStatement::Compile(compiler::PandaGen *pg) const 46{ 47 auto *consequentEnd = pg->AllocLabel(); 48 compiler::Label *statementEnd = consequentEnd; 49 50 compiler::Condition::Compile(pg, test_, consequentEnd); 51 consequent_->Compile(pg); 52 53 if (alternate_) { 54 statementEnd = pg->AllocLabel(); 55 pg->Branch(pg->Insns().back()->Node(), statementEnd); 56 57 pg->SetLabel(this, consequentEnd); 58 alternate_->Compile(pg); 59 } 60 61 pg->SetLabel(this, statementEnd); 62} 63 64checker::Type *IfStatement::Check(checker::Checker *checker) const 65{ 66 checker::Type *testType = test_->Check(checker); 67 checker->CheckTruthinessOfType(testType, Start()); 68 checker->CheckTestingKnownTruthyCallableOrAwaitableType(test_, testType, consequent_); 69 70 consequent_->Check(checker); 71 72 if (alternate_) { 73 alternate_->Check(checker); 74 } 75 76 return nullptr; 77} 78 79void IfStatement::UpdateSelf(const NodeUpdater &cb, binder::Binder *binder) 80{ 81 test_ = std::get<ir::AstNode *>(cb(test_))->AsExpression(); 82 consequent_ = UpdateIfStatementChildStatement(cb, binder, consequent_); 83 84 if (alternate_) { 85 alternate_ = UpdateIfStatementChildStatement(cb, binder, alternate_); 86 } 87} 88 89Statement *IfStatement::UpdateIfStatementChildStatement(const NodeUpdater &cb, 90 const binder::Binder *binder, 91 Statement *statement) const 92{ 93 auto newStatement = cb(statement); 94 if (std::holds_alternative<ir::AstNode *>(newStatement)) { 95 return std::get<ir::AstNode *>(newStatement)->AsStatement(); 96 } 97 98 ASSERT(std::holds_alternative<std::vector<ir::AstNode *>>(newStatement)); 99 ArenaVector<ir::Statement *> statements(binder->Allocator()->Adapter()); 100 auto newStatements = std::get<std::vector<ir::AstNode *>>(newStatement); 101 for (auto *it : newStatements) { 102 statements.push_back(it->AsStatement()); 103 } 104 return binder->Allocator()->New<ir::BlockStatement>(nullptr, std::move(statements)); 105} 106 107} // namespace panda::es2panda::ir 108