1/* 2 * Copyright (c) 2022 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 "optionalChain.h" 17 18#include <compiler/core/pandagen.h> 19#include <ir/expressions/callExpression.h> 20 21namespace panda::es2panda::compiler { 22OptionalChain::OptionalChain(PandaGen *pg, const ir::AstNode *node) : pg_(pg), node_(node), prev_(pg->optionalChain_) 23{ 24 pg_->optionalChain_ = this; 25} 26 27OptionalChain::~OptionalChain() 28{ 29 if (label_) { 30 pg_->SetLabel(node_, label_); 31 } 32 pg_->optionalChain_ = prev_; 33} 34 35void OptionalChain::CheckNullish(bool optional, compiler::VReg obj) 36{ 37 if (!optional) { 38 return; 39 } 40 41 if (!label_) { 42 label_ = pg_->AllocLabel(); 43 } 44 45 RegScope rs(pg_); 46 47 auto *notNullish = pg_->AllocLabel(); 48 auto *nullish = pg_->AllocLabel(); 49 50 pg_->LoadConst(node_, Constant::JS_NULL); 51 pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, obj, nullish); 52 pg_->LoadConst(node_, Constant::JS_UNDEFINED); 53 pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, obj, nullish); 54 pg_->Branch(node_, notNullish); 55 pg_->SetLabel(node_, nullish); 56 57 pg_->LoadConst(node_, compiler::Constant::JS_UNDEFINED); 58 InitThisVRegForCallExpression(); 59 pg_->Branch(node_, label_); 60 pg_->SetLabel(node_, notNullish); 61 pg_->LoadAccumulator(node_, obj); 62} 63 64void OptionalChain::InitThisVRegForCallExpression() 65{ 66 auto *iter = node_->Parent(); 67 while (iter->IsTSNonNullExpression() || iter->IsTSAsExpression() || iter->IsTSTypeAssertion()) { 68 iter = iter->Parent(); 69 } 70 71 if (!iter->IsCallExpression()) { 72 return; 73 } 74 75 auto callExpr = iter->AsCallExpression(); 76 if (callExpr->HasThisVReg()) { 77 pg_->StoreAccumulator(node_, callExpr->GetThisVReg()); 78 } 79} 80 81} // namespace panda::es2panda::compiler 82