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 "assignmentExpression.h" 17 18#include "compiler/base/lreference.h" 19#include "compiler/core/pandagen.h" 20#include "compiler/core/ETSGen.h" 21#include "compiler/core/regScope.h" 22#include "ir/astDump.h" 23#include "ir/srcDump.h" 24#include "ir/base/spreadElement.h" 25#include "ir/expressions/arrayExpression.h" 26#include "ir/expressions/objectExpression.h" 27 28#include "checker/TSchecker.h" 29#include "checker/ts/destructuringContext.h" 30#include "checker/ets/typeRelationContext.h" 31 32namespace ark::es2panda::ir { 33 34bool AssignmentExpression::ConvertibleToAssignmentPatternLeft(bool mustBePattern) 35{ 36 switch (left_->Type()) { 37 case AstNodeType::ARRAY_EXPRESSION: { 38 return left_->AsArrayExpression()->ConvertibleToArrayPattern(); 39 } 40 case AstNodeType::SPREAD_ELEMENT: { 41 return mustBePattern && left_->AsSpreadElement()->ConvertibleToRest(false); 42 } 43 case AstNodeType::OBJECT_EXPRESSION: { 44 return left_->AsObjectExpression()->ConvertibleToObjectPattern(); 45 } 46 case AstNodeType::ASSIGNMENT_EXPRESSION: { 47 return left_->AsAssignmentExpression()->ConvertibleToAssignmentPattern(mustBePattern); 48 } 49 case AstNodeType::META_PROPERTY_EXPRESSION: 50 case AstNodeType::CHAIN_EXPRESSION: { 51 return false; 52 } 53 default: { 54 return true; 55 } 56 } 57} 58 59bool AssignmentExpression::ConvertibleToAssignmentPatternRight() 60{ 61 switch (right_->Type()) { 62 case AstNodeType::ARRAY_EXPRESSION: { 63 return right_->AsArrayExpression()->ConvertibleToArrayPattern(); 64 } 65 case AstNodeType::CHAIN_EXPRESSION: 66 case AstNodeType::SPREAD_ELEMENT: { 67 return false; 68 } 69 case AstNodeType::OBJECT_EXPRESSION: { 70 return right_->AsObjectExpression()->ConvertibleToObjectPattern(); 71 } 72 case AstNodeType::ASSIGNMENT_EXPRESSION: { 73 return right_->AsAssignmentExpression()->ConvertibleToAssignmentPattern(false); 74 } 75 default: { 76 return true; 77 } 78 } 79} 80 81bool AssignmentExpression::ConvertibleToAssignmentPattern(bool mustBePattern) 82{ 83 bool convResult = ConvertibleToAssignmentPatternLeft(mustBePattern); 84 if (mustBePattern) { 85 SetType(AstNodeType::ASSIGNMENT_PATTERN); 86 } 87 88 if (!right_->IsAssignmentExpression()) { 89 return convResult; 90 } 91 return ConvertibleToAssignmentPatternRight(); 92} 93 94void AssignmentExpression::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) 95{ 96 if (auto *transformedNode = cb(left_); left_ != transformedNode) { 97 left_->SetTransformedNode(transformationName, transformedNode); 98 left_ = transformedNode->AsExpression(); 99 } 100 101 if (auto *transformedNode = cb(right_); right_ != transformedNode) { 102 right_->SetTransformedNode(transformationName, transformedNode); 103 right_ = transformedNode->AsExpression(); 104 } 105} 106 107void AssignmentExpression::Iterate(const NodeTraverser &cb) const 108{ 109 cb(left_); 110 cb(right_); 111} 112 113void AssignmentExpression::Dump(ir::AstDumper *dumper) const 114{ 115 if (type_ == AstNodeType::ASSIGNMENT_EXPRESSION) { 116 dumper->Add({{"type", "AssignmentExpression"}, {"operator", operator_}, {"left", left_}, {"right", right_}}); 117 } else { 118 dumper->Add({{"type", "AssignmentPattern"}, {"left", left_}, {"right", right_}}); 119 } 120} 121 122void AssignmentExpression::Dump(ir::SrcDumper *dumper) const 123{ 124 ASSERT(left_); 125 left_->Dump(dumper); 126 dumper->Add(" "); 127 dumper->Add(TokenToString(operator_)); 128 dumper->Add(" "); 129 ASSERT(right_); 130 right_->Dump(dumper); 131} 132 133void AssignmentExpression::Compile(compiler::PandaGen *pg) const 134{ 135 pg->GetAstCompiler()->Compile(this); 136} 137 138void AssignmentExpression::Compile(compiler::ETSGen *etsg) const 139{ 140 etsg->GetAstCompiler()->Compile(this); 141} 142 143void AssignmentExpression::CompilePattern(compiler::PandaGen *pg) const 144{ 145 compiler::RegScope rs(pg); 146 auto lref = compiler::JSLReference::Create(pg, left_, false); 147 right_->Compile(pg); 148 lref.SetValue(); 149} 150 151checker::Type *AssignmentExpression::Check(checker::TSChecker *checker) 152{ 153 return checker->GetAnalyzer()->Check(this); 154} 155 156checker::Type *AssignmentExpression::Check([[maybe_unused]] checker::ETSChecker *checker) 157{ 158 return checker->GetAnalyzer()->Check(this); 159} 160 161AssignmentExpression::AssignmentExpression([[maybe_unused]] Tag const tag, AssignmentExpression const &other, 162 Expression *const left, Expression *const right) 163 : AssignmentExpression(other) 164{ 165 left_ = left; 166 if (left_ != nullptr) { 167 left_->SetParent(this); 168 } 169 170 right_ = right; 171 if (right_ != nullptr) { 172 right_->SetParent(this); 173 } 174} 175 176AssignmentExpression *AssignmentExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) 177{ 178 auto *const left = left_ != nullptr ? left_->Clone(allocator, nullptr)->AsExpression() : nullptr; 179 auto *const right = right_ != nullptr ? right_->Clone(allocator, nullptr)->AsExpression() : nullptr; 180 181 if (auto *const clone = allocator->New<AssignmentExpression>(Tag {}, *this, left, right); clone != nullptr) { 182 if (parent != nullptr) { 183 clone->SetParent(parent); 184 } 185 186 clone->SetRange(Range()); 187 return clone; 188 } 189 190 throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); 191} 192} // namespace ark::es2panda::ir 193