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 "etsParameterExpression.h" 17 18#include "checker/ETSchecker.h" 19#include "checker/ets/typeRelationContext.h" 20#include "checker/TSchecker.h" 21#include "compiler/core/ETSGen.h" 22#include "compiler/core/pandagen.h" 23#include "ir/astDump.h" 24#include "ir/srcDump.h" 25#include "ir/typeNode.h" 26#include "ir/expressions/identifier.h" 27#include "ir/base/spreadElement.h" 28 29namespace ark::es2panda::ir { 30 31ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, Expression *const initializer) 32 : Expression(AstNodeType::ETS_PARAMETER_EXPRESSION), initializer_(initializer) 33{ 34 ASSERT(identOrSpread != nullptr); 35 identOrSpread->SetParent(this); 36 37 if (identOrSpread->IsIdentifier()) { 38 ident_ = identOrSpread->AsIdentifier(); 39 } else if (identOrSpread->IsRestElement()) { 40 spread_ = identOrSpread->AsRestElement(); 41 ASSERT(spread_->Argument()->IsIdentifier()); 42 ident_ = spread_->Argument()->AsIdentifier(); 43 ident_->SetParent(spread_); 44 initializer_ = nullptr; // Just in case! 45 } else { 46 UNREACHABLE(); 47 } 48} 49 50const Identifier *ETSParameterExpression::Ident() const noexcept 51{ 52 return ident_; 53} 54 55Identifier *ETSParameterExpression::Ident() noexcept 56{ 57 return ident_; 58} 59 60const SpreadElement *ETSParameterExpression::RestParameter() const noexcept 61{ 62 return spread_; 63} 64 65SpreadElement *ETSParameterExpression::RestParameter() noexcept 66{ 67 return spread_; 68} 69 70const Expression *ETSParameterExpression::Initializer() const noexcept 71{ 72 return initializer_; 73} 74 75Expression *ETSParameterExpression::Initializer() noexcept 76{ 77 return initializer_; 78} 79 80varbinder::Variable *ETSParameterExpression::Variable() const noexcept 81{ 82 return ident_->Variable(); 83} 84 85TypeNode const *ETSParameterExpression::TypeAnnotation() const noexcept 86{ 87 return !IsRestParameter() ? ident_->TypeAnnotation() : spread_->TypeAnnotation(); 88} 89 90TypeNode *ETSParameterExpression::TypeAnnotation() noexcept 91{ 92 return !IsRestParameter() ? ident_->TypeAnnotation() : spread_->TypeAnnotation(); 93} 94 95void ETSParameterExpression::SetVariable(varbinder::Variable *const variable) noexcept 96{ 97 ident_->SetVariable(variable); 98} 99 100void ETSParameterExpression::SetLexerSaved(util::StringView s) noexcept 101{ 102 savedLexer_ = s; 103} 104 105util::StringView ETSParameterExpression::LexerSaved() const noexcept 106{ 107 return savedLexer_; 108} 109 110void ETSParameterExpression::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) 111{ 112 if (IsRestParameter()) { 113 if (auto *transformedNode = cb(spread_); spread_ != transformedNode) { 114 spread_->SetTransformedNode(transformationName, transformedNode); 115 spread_ = transformedNode->AsRestElement(); 116 } 117 ident_ = spread_->Argument()->AsIdentifier(); 118 } else { 119 if (auto *transformedNode = cb(ident_); ident_ != transformedNode) { 120 ident_->SetTransformedNode(transformationName, transformedNode); 121 ident_ = transformedNode->AsIdentifier(); 122 } 123 } 124 125 if (IsDefault()) { 126 if (auto *transformedNode = cb(initializer_); initializer_ != transformedNode) { 127 initializer_->SetTransformedNode(transformationName, transformedNode); 128 initializer_ = transformedNode->AsExpression(); 129 } 130 } 131} 132 133void ETSParameterExpression::Iterate(const NodeTraverser &cb) const 134{ 135 if (IsRestParameter()) { 136 cb(spread_); 137 } else { 138 cb(ident_); 139 } 140 141 if (IsDefault()) { 142 cb(initializer_); 143 } 144} 145 146void ETSParameterExpression::Dump(ir::AstDumper *const dumper) const 147{ 148 if (!IsRestParameter()) { 149 dumper->Add( 150 {{"type", "ETSParameterExpression"}, {"name", ident_}, {"initializer", AstDumper::Optional(initializer_)}}); 151 } else { 152 dumper->Add({{"type", "ETSParameterExpression"}, {"rest parameter", spread_}}); 153 } 154} 155 156void ETSParameterExpression::Dump(ir::SrcDumper *const dumper) const 157{ 158 if (IsRestParameter()) { 159 spread_->Dump(dumper); 160 } else { 161 if (ident_ != nullptr) { 162 ASSERT(ident_->IsAnnotatedExpression()); 163 ident_->Dump(dumper); 164 if (initializer_ != nullptr && initializer_->IsUndefinedLiteral()) { 165 dumper->Add("?"); 166 } 167 auto typeAnnotation = ident_->AsAnnotatedExpression()->TypeAnnotation(); 168 if (typeAnnotation != nullptr) { 169 dumper->Add(": "); 170 typeAnnotation->Dump(dumper); 171 } 172 } 173 if (initializer_ != nullptr && !initializer_->IsUndefinedLiteral()) { 174 dumper->Add(" = "); 175 initializer_->Dump(dumper); 176 } 177 } 178} 179 180void ETSParameterExpression::Compile(compiler::PandaGen *const pg) const 181{ 182 pg->GetAstCompiler()->Compile(this); 183} 184 185void ETSParameterExpression::Compile(compiler::ETSGen *const etsg) const 186{ 187 etsg->GetAstCompiler()->Compile(this); 188} 189 190checker::Type *ETSParameterExpression::Check(checker::TSChecker *const checker) 191{ 192 return checker->GetAnalyzer()->Check(this); 193} 194 195checker::Type *ETSParameterExpression::Check(checker::ETSChecker *const checker) 196{ 197 return checker->GetAnalyzer()->Check(this); 198} 199 200ETSParameterExpression *ETSParameterExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) 201{ 202 auto *const identOrSpread = spread_ != nullptr ? spread_->Clone(allocator, nullptr)->AsAnnotatedExpression() 203 : ident_->Clone(allocator, nullptr)->AsAnnotatedExpression(); 204 auto *const initializer = 205 initializer_ != nullptr ? initializer_->Clone(allocator, nullptr)->AsExpression() : nullptr; 206 207 if (auto *const clone = allocator->New<ETSParameterExpression>(identOrSpread, initializer); clone != nullptr) { 208 identOrSpread->SetParent(clone); 209 210 if (initializer != nullptr) { 211 initializer->SetParent(clone); 212 } 213 214 if (parent != nullptr) { 215 clone->SetParent(parent); 216 } 217 218 clone->SetRequiredParams(extraValue_); 219 return clone; 220 } 221 222 throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); 223} 224} // namespace ark::es2panda::ir 225