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 "forUpdateStatement.h" 17 18#include <binder/binder.h> 19#include <binder/scope.h> 20#include <compiler/base/condition.h> 21#include <compiler/base/lreference.h> 22#include <compiler/core/labelTarget.h> 23#include <compiler/core/pandagen.h> 24#include <compiler/core/dynamicContext.h> 25#include <typescript/checker.h> 26#include <ir/astDump.h> 27#include <ir/expression.h> 28 29namespace panda::es2panda::ir { 30 31void ForUpdateStatement::Iterate(const NodeTraverser &cb) const 32{ 33 if (init_) { 34 cb(init_); 35 } 36 if (test_) { 37 cb(test_); 38 } 39 if (update_) { 40 cb(update_); 41 } 42 43 cb(body_); 44} 45 46void ForUpdateStatement::Dump(ir::AstDumper *dumper) const 47{ 48 dumper->Add({{"type", "ForUpdateStatement"}, 49 {"init", AstDumper::Nullable(init_)}, 50 {"test", AstDumper::Nullable(test_)}, 51 {"update", AstDumper::Nullable(update_)}, 52 {"body", body_}}); 53} 54 55void ForUpdateStatement::Compile(compiler::PandaGen *pg) const 56{ 57 compiler::LocalRegScope loopRegScope(pg, scope_); 58 compiler::LabelTarget labelTarget(pg); 59 compiler::LoopEnvScope envScope(pg, labelTarget, scope_); 60 61 if (init_) { 62 ASSERT(init_->IsVariableDeclaration() || init_->IsExpression()); 63 init_->Compile(pg); 64 } 65 66 auto *startLabel = pg->AllocLabel(); 67 pg->SetLabel(this, startLabel); 68 69 { 70 if (test_) { 71 compiler::Condition::Compile(pg, test_, labelTarget.BreakTarget()); 72 } 73 74 body_->Compile(pg); 75 pg->SetLabel(this, labelTarget.ContinueTarget()); 76 envScope.CopyPerIterationCtx(); 77 } 78 79 if (update_) { 80 update_->Compile(pg); 81 } 82 83 pg->Branch(this, startLabel); 84 pg->SetLabel(this, labelTarget.BreakTarget()); 85} 86 87checker::Type *ForUpdateStatement::Check(checker::Checker *checker) const 88{ 89 checker::ScopeContext scopeCtx(checker, scope_); 90 91 if (init_) { 92 init_->Check(checker); 93 } 94 95 if (test_) { 96 checker::Type *testType = test_->Check(checker); 97 checker->CheckTruthinessOfType(testType, Start()); 98 } 99 100 if (update_) { 101 update_->Check(checker); 102 } 103 104 body_->Check(checker); 105 106 return nullptr; 107} 108 109void ForUpdateStatement::UpdateSelf(const NodeUpdater &cb, binder::Binder *binder) 110{ 111 auto *loopScope = Scope(); 112 auto loopCtx = binder::LexicalScope<binder::LoopScope>::Enter(binder, loopScope); 113 114 if (init_) { 115 init_ = std::get<ir::AstNode *>(cb(init_)); 116 } 117 118 if (test_) { 119 test_ = std::get<ir::AstNode *>(cb(test_))->AsExpression(); 120 } 121 122 if (update_) { 123 update_ = std::get<ir::AstNode *>(cb(update_))->AsExpression(); 124 } 125 126 body_ = UpdateChildStatement(cb, binder, body_); 127} 128 129} // namespace panda::es2panda::ir 130