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 "spreadElement.h" 17#include "es2panda.h" 18 19#include "checker/TSchecker.h" 20#include "compiler/core/pandagen.h" 21#include "compiler/core/ETSGen.h" 22#include "ir/astDump.h" 23#include "ir/srcDump.h" 24#include "ir/base/decorator.h" 25#include "ir/typeNode.h" 26#include "ir/expressions/arrayExpression.h" 27#include "ir/expressions/objectExpression.h" 28 29namespace ark::es2panda::ir { 30SpreadElement::SpreadElement([[maybe_unused]] Tag const tag, SpreadElement const &other, 31 ArenaAllocator *const allocator) 32 : AnnotatedExpression(static_cast<AnnotatedExpression const &>(other), allocator), decorators_(allocator->Adapter()) 33{ 34 optional_ = other.optional_; 35 36 if (other.argument_ != nullptr) { 37 argument_ = other.argument_->Clone(allocator, this)->AsExpression(); 38 } 39 40 for (auto *decorator : other.decorators_) { 41 decorators_.emplace_back(decorator->Clone(allocator, this)); 42 } 43} 44 45SpreadElement *SpreadElement::Clone(ArenaAllocator *const allocator, AstNode *const parent) 46{ 47 if (auto *const clone = allocator->New<SpreadElement>(Tag {}, *this, allocator); clone != nullptr) { 48 if (parent != nullptr) { 49 clone->SetParent(parent); 50 } 51 return clone; 52 } 53 throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); 54} 55 56ValidationInfo SpreadElement::ValidateExpression() 57{ 58 ValidationInfo info; 59 60 switch (argument_->Type()) { 61 case AstNodeType::OBJECT_EXPRESSION: { 62 info = argument_->AsObjectExpression()->ValidateExpression(); 63 break; 64 } 65 case AstNodeType::ARRAY_EXPRESSION: { 66 info = argument_->AsArrayExpression()->ValidateExpression(); 67 break; 68 } 69 default: { 70 break; 71 } 72 } 73 74 return info; 75} 76 77bool SpreadElement::ConvertibleToRest(bool isDeclaration, bool allowPattern) 78{ 79 bool convResult = true; 80 81 switch (argument_->Type()) { 82 case AstNodeType::ARRAY_EXPRESSION: { 83 convResult = allowPattern && argument_->AsArrayExpression()->ConvertibleToArrayPattern(); 84 break; 85 } 86 case AstNodeType::OBJECT_EXPRESSION: { 87 convResult = allowPattern && argument_->AsObjectExpression()->ConvertibleToObjectPattern(); 88 break; 89 } 90 case AstNodeType::META_PROPERTY_EXPRESSION: 91 case AstNodeType::CHAIN_EXPRESSION: 92 case AstNodeType::ASSIGNMENT_EXPRESSION: { 93 convResult = false; 94 break; 95 } 96 case AstNodeType::MEMBER_EXPRESSION: { 97 convResult = !isDeclaration; 98 break; 99 } 100 default: { 101 break; 102 } 103 } 104 105 SetType(AstNodeType::REST_ELEMENT); 106 return convResult; 107} 108 109void SpreadElement::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) 110{ 111 for (auto *&it : decorators_) { 112 if (auto *transformedNode = cb(it); it != transformedNode) { 113 it->SetTransformedNode(transformationName, transformedNode); 114 it = transformedNode->AsDecorator(); 115 } 116 } 117 118 if (auto *transformedNode = cb(argument_); argument_ != transformedNode) { 119 argument_->SetTransformedNode(transformationName, transformedNode); 120 argument_ = transformedNode->AsExpression(); 121 } 122 123 if (auto *const typeAnnotation = TypeAnnotation(); typeAnnotation != nullptr) { 124 if (auto *transformedNode = cb(typeAnnotation); typeAnnotation != transformedNode) { 125 typeAnnotation->SetTransformedNode(transformationName, transformedNode); 126 SetTsTypeAnnotation(static_cast<TypeNode *>(transformedNode)); 127 } 128 } 129} 130 131void SpreadElement::Iterate(const NodeTraverser &cb) const 132{ 133 for (auto *it : decorators_) { 134 cb(it); 135 } 136 137 cb(argument_); 138 139 if (TypeAnnotation() != nullptr) { 140 cb(TypeAnnotation()); 141 } 142} 143 144void SpreadElement::Dump(ir::AstDumper *dumper) const 145{ 146 dumper->Add({{"type", (type_ == AstNodeType::SPREAD_ELEMENT) ? "SpreadElement" : "RestElement"}, 147 {"decorators", AstDumper::Optional(decorators_)}, 148 {"argument", argument_}, 149 {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}}); 150} 151 152void SpreadElement::Dump(ir::SrcDumper *dumper) const 153{ 154 dumper->Add("..."); 155 argument_->Dump(dumper); 156 auto type = TypeAnnotation(); 157 if (type != nullptr) { 158 dumper->Add(": "); 159 type->Dump(dumper); 160 } 161} 162 163void SpreadElement::Compile([[maybe_unused]] compiler::PandaGen *pg) const 164{ 165 pg->GetAstCompiler()->Compile(this); 166} 167void SpreadElement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const 168{ 169 etsg->GetAstCompiler()->Compile(this); 170} 171 172checker::Type *SpreadElement::Check([[maybe_unused]] checker::TSChecker *checker) 173{ 174 return checker->GetAnalyzer()->Check(this); 175} 176 177checker::Type *SpreadElement::Check([[maybe_unused]] checker::ETSChecker *checker) 178{ 179 return checker->GetAnalyzer()->Check(this); 180} 181} // namespace ark::es2panda::ir 182