• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 namespace ark::es2panda::ir {
25 
ScriptFunction(ArenaAllocator * allocator,ScriptFunctionData && data)26 ScriptFunction::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 
FormalParamsLength() const48 std::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 
SetIdent(Identifier * id)63 void ScriptFunction::SetIdent(Identifier *id) noexcept
64 {
65     id_ = id;
66     id_->SetParent(this);
67 }
68 
Clone(ArenaAllocator * allocator,AstNode * parent)69 ScriptFunction *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 
TransformChildren(const NodeTransformer & cb,std::string_view const transformationName)90 void 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 
Iterate(const NodeTraverser & cb) const109 void 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 
SetReturnTypeAnnotation(TypeNode * node)120 void ScriptFunction::SetReturnTypeAnnotation(TypeNode *node) noexcept
121 {
122     irSignature_.SetReturnType(node);
123     if (node != nullptr) {
124         node->SetParent(this);
125     }
126 }
127 
Dump(ir::AstDumper * dumper) const128 void 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 
Dump(ir::SrcDumper * dumper) const148 void 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         param->Dump(dumper);
158         if (param != Params().back()) {
159             dumper->Add(", ");
160         }
161     }
162     dumper->Add(")");
163     if (ReturnTypeAnnotation() != nullptr) {
164         dumper->Add(": ");
165         ReturnTypeAnnotation()->Dump(dumper);
166     }
167 
168     if (IsThrowing()) {
169         dumper->Add(" throws");
170     }
171 
172     if (HasBody()) {
173         if (body_->IsBlockStatement()) {
174             dumper->Add(" {");
175             if (!body_->AsBlockStatement()->Statements().empty()) {
176                 dumper->IncrIndent();
177                 dumper->Endl();
178                 body_->Dump(dumper);
179                 dumper->DecrIndent();
180                 dumper->Endl();
181             }
182             dumper->Add("}");
183         } else {
184             dumper->Add(" ");
185             body_->Dump(dumper);
186         }
187     }
188     if (!IsArrow()) {
189         dumper->Endl();
190     }
191 }
192 
Compile(compiler::PandaGen * pg) const193 void ScriptFunction::Compile(compiler::PandaGen *pg) const
194 {
195     pg->GetAstCompiler()->Compile(this);
196 }
Compile(compiler::ETSGen * etsg) const197 void ScriptFunction::Compile(compiler::ETSGen *etsg) const
198 {
199     etsg->GetAstCompiler()->Compile(this);
200 }
201 
Check(checker::TSChecker * checker)202 checker::Type *ScriptFunction::Check(checker::TSChecker *checker)
203 {
204     return checker->GetAnalyzer()->Check(this);
205 }
206 
Check(checker::ETSChecker * checker)207 checker::Type *ScriptFunction::Check(checker::ETSChecker *checker)
208 {
209     return checker->GetAnalyzer()->Check(this);
210 }
211 }  // namespace ark::es2panda::ir
212