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 "scriptFunction.h" 17 18#include "checker/TSchecker.h" 19#include "compiler/core/ETSGen.h" 20#include "compiler/core/pandagen.h" 21#include "ir/astDump.h" 22#include "ir/srcDump.h" 23 24namespace ark::es2panda::ir { 25 26ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data) 27 : AstNode(AstNodeType::SCRIPT_FUNCTION, data.flags), 28 irSignature_(std::move(data.signature)), 29 body_(data.body), 30 funcFlags_(data.funcFlags), 31 declare_(data.declare), 32 lang_(data.lang), 33 returnStatements_(allocator->Adapter()) 34{ 35 for (auto *param : irSignature_.Params()) { 36 param->SetParent(this); 37 } 38 39 if (auto *returnType = irSignature_.ReturnType(); returnType != nullptr) { 40 returnType->SetParent(this); 41 } 42 43 if (auto *typeParams = irSignature_.TypeParams(); typeParams != nullptr) { 44 typeParams->SetParent(this); 45 } 46} 47 48std::size_t ScriptFunction::FormalParamsLength() const noexcept 49{ 50 std::size_t length = 0U; 51 52 for (const auto *param : irSignature_.Params()) { 53 if (param->IsRestElement() || param->IsAssignmentPattern()) { 54 break; 55 } 56 57 ++length; 58 } 59 60 return length; 61} 62 63void ScriptFunction::SetIdent(Identifier *id) noexcept 64{ 65 id_ = id; 66 id_->SetParent(this); 67} 68 69ScriptFunction *ScriptFunction::Clone(ArenaAllocator *allocator, AstNode *parent) 70{ 71 ArenaVector<Expression *> params {allocator->Adapter()}; 72 for (auto *param : Params()) { 73 params.push_back(param->Clone(allocator, nullptr)->AsExpression()); 74 } 75 auto *res = util::NodeAllocator::ForceSetParent<ScriptFunction>( 76 allocator, allocator, 77 ScriptFunctionData { 78 body_ != nullptr ? body_->Clone(allocator, nullptr) : nullptr, 79 FunctionSignature { 80 TypeParams() != nullptr ? TypeParams()->Clone(allocator, nullptr)->AsTSTypeParameterDeclaration() 81 : nullptr, 82 std::move(params), 83 ReturnTypeAnnotation() != nullptr ? ReturnTypeAnnotation()->Clone(allocator, nullptr)->AsTypeNode() 84 : nullptr}, 85 funcFlags_, flags_, declare_, lang_}); 86 res->SetParent(parent); 87 return res; 88} 89 90void ScriptFunction::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) 91{ 92 if (id_ != nullptr) { 93 if (auto *transformedNode = cb(id_); id_ != transformedNode) { 94 id_->SetTransformedNode(transformationName, transformedNode); 95 id_ = transformedNode->AsIdentifier(); 96 } 97 } 98 99 irSignature_.TransformChildren(cb, transformationName); 100 101 if (body_ != nullptr) { 102 if (auto *transformedNode = cb(body_); body_ != transformedNode) { 103 body_->SetTransformedNode(transformationName, transformedNode); 104 body_ = transformedNode; 105 } 106 } 107} 108 109void ScriptFunction::Iterate(const NodeTraverser &cb) const 110{ 111 if (id_ != nullptr) { 112 cb(id_); 113 } 114 irSignature_.Iterate(cb); 115 if (body_ != nullptr) { 116 cb(body_); 117 } 118} 119 120void ScriptFunction::SetReturnTypeAnnotation(TypeNode *node) noexcept 121{ 122 irSignature_.SetReturnType(node); 123 if (node != nullptr) { 124 node->SetParent(this); 125 } 126} 127 128void ScriptFunction::Dump(ir::AstDumper *dumper) const 129{ 130 dumper->Add({{"type", "ScriptFunction"}, 131 {"id", AstDumper::Nullish(id_)}, 132 {"generator", IsGenerator()}, 133 {"async", IsAsyncFunc()}, 134 {"expression", ((funcFlags_ & ir::ScriptFunctionFlags::EXPRESSION) != 0)}, 135 {"params", irSignature_.Params()}, 136 {"returnType", AstDumper::Optional(irSignature_.ReturnType())}, 137 {"typeParameters", AstDumper::Optional(irSignature_.TypeParams())}, 138 {"declare", AstDumper::Optional(declare_)}, 139 {"body", AstDumper::Optional(body_)}}); 140 141 if (IsThrowing()) { 142 dumper->Add({"throwMarker", "throws"}); 143 } else if (IsRethrowing()) { 144 dumper->Add({"throwMarker", "rethrows"}); 145 } 146} 147 148void ScriptFunction::Dump(ir::SrcDumper *dumper) const 149{ 150 if (TypeParams() != nullptr) { 151 dumper->Add("<"); 152 TypeParams()->Dump(dumper); 153 dumper->Add(">"); 154 } 155 dumper->Add("("); 156 for (auto param : Params()) { 157 if (param->IsETSParameterExpression() && param->AsETSParameterExpression()->Ident() != nullptr && 158 param->AsETSParameterExpression()->Ident()->Name() == varbinder::VarBinder::MANDATORY_PARAM_THIS) { 159 continue; 160 } 161 param->Dump(dumper); 162 if (param != Params().back()) { 163 dumper->Add(", "); 164 } 165 } 166 dumper->Add(")"); 167 if (ReturnTypeAnnotation() != nullptr) { 168 dumper->Add(": "); 169 ReturnTypeAnnotation()->Dump(dumper); 170 } 171 172 if (IsThrowing()) { 173 dumper->Add(" throws"); 174 } 175 176 if (HasBody()) { 177 if (IsArrow()) { 178 dumper->Add(" =>"); 179 } 180 if (body_->IsBlockStatement()) { 181 dumper->Add(" {"); 182 if (!body_->AsBlockStatement()->Statements().empty()) { 183 dumper->IncrIndent(); 184 dumper->Endl(); 185 body_->Dump(dumper); 186 dumper->DecrIndent(); 187 dumper->Endl(); 188 } 189 dumper->Add("}"); 190 } else { 191 dumper->Add(" "); 192 body_->Dump(dumper); 193 } 194 } 195 if (!IsArrow()) { 196 dumper->Endl(); 197 } 198} 199 200void ScriptFunction::Compile(compiler::PandaGen *pg) const 201{ 202 pg->GetAstCompiler()->Compile(this); 203} 204void ScriptFunction::Compile(compiler::ETSGen *etsg) const 205{ 206 etsg->GetAstCompiler()->Compile(this); 207} 208 209checker::Type *ScriptFunction::Check(checker::TSChecker *checker) 210{ 211 return checker->GetAnalyzer()->Check(this); 212} 213 214checker::Type *ScriptFunction::Check(checker::ETSChecker *checker) 215{ 216 return checker->GetAnalyzer()->Check(this); 217} 218} // namespace ark::es2panda::ir 219