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#ifndef ES2PANDA_PARSER_INCLUDE_AST_SCRIPT_FUNCTION_H
17#define ES2PANDA_PARSER_INCLUDE_AST_SCRIPT_FUNCTION_H
18
19#include "ir/statements/returnStatement.h"
20#include "checker/types/signature.h"
21#include "ir/astNode.h"
22#include "varbinder/scope.h"
23#include "util/enumbitops.h"
24#include "util/language.h"
25#include "scriptFunctionSignature.h"
26
27namespace ark::es2panda::checker {
28class Signature;
29
30}  // namespace ark::es2panda::checker
31
32namespace ark::es2panda::ir {
33class TSTypeParameterDeclaration;
34class TypeNode;
35
36class ScriptFunction : public AstNode {
37public:
38    // Need to reduce the number of constructor parameters to pass OHOS CI code check
39    struct ScriptFunctionData {
40        AstNode *body = nullptr;
41        FunctionSignature &&signature;
42        ir::ScriptFunctionFlags funcFlags = ir::ScriptFunctionFlags::NONE;
43        ir::ModifierFlags flags = ir::ModifierFlags::NONE;
44        bool declare = false;
45        ark::es2panda::Language lang {Language::Id::ETS};
46    };
47
48    ScriptFunction() = delete;
49    ~ScriptFunction() override = default;
50
51    NO_COPY_SEMANTIC(ScriptFunction);
52    NO_MOVE_SEMANTIC(ScriptFunction);
53
54    explicit ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data);
55
56    [[nodiscard]] const Identifier *Id() const noexcept
57    {
58        return id_;
59    }
60
61    [[nodiscard]] Identifier *Id() noexcept
62    {
63        return id_;
64    }
65
66    [[nodiscard]] const checker::Signature *Signature() const noexcept
67    {
68        return signature_;
69    }
70
71    [[nodiscard]] checker::Signature *Signature() noexcept
72    {
73        return signature_;
74    }
75
76    [[nodiscard]] const ArenaVector<Expression *> &Params() const noexcept
77    {
78        return irSignature_.Params();
79    }
80
81    [[nodiscard]] ArenaVector<Expression *> &Params() noexcept
82    {
83        return irSignature_.Params();
84    }
85
86    size_t DefaultParamIndex() const noexcept
87    {
88        return this->irSignature_.DefaultParamIndex();
89    }
90
91    const ArenaVector<ReturnStatement *> &ReturnStatements() const
92    {
93        return returnStatements_;
94    }
95
96    ArenaVector<ReturnStatement *> &ReturnStatements()
97    {
98        return returnStatements_;
99    }
100
101    [[nodiscard]] const TSTypeParameterDeclaration *TypeParams() const noexcept
102    {
103        return irSignature_.TypeParams();
104    }
105
106    [[nodiscard]] TSTypeParameterDeclaration *TypeParams() noexcept
107    {
108        return irSignature_.TypeParams();
109    }
110
111    [[nodiscard]] const AstNode *Body() const noexcept
112    {
113        return body_;
114    }
115
116    [[nodiscard]] AstNode *Body() noexcept
117    {
118        return body_;
119    }
120
121    void AddReturnStatement(ReturnStatement *returnStatement)
122    {
123        returnStatements_.push_back(returnStatement);
124    }
125
126    void SetBody(AstNode *body) noexcept
127    {
128        body_ = body;
129    }
130
131    [[nodiscard]] const TypeNode *ReturnTypeAnnotation() const noexcept
132    {
133        return irSignature_.ReturnType();
134    }
135
136    [[nodiscard]] TypeNode *ReturnTypeAnnotation() noexcept
137    {
138        return irSignature_.ReturnType();
139    }
140
141    void SetReturnTypeAnnotation(TypeNode *node) noexcept;
142
143    [[nodiscard]] bool IsEntryPoint() const noexcept
144    {
145        return (funcFlags_ & ir::ScriptFunctionFlags::ENTRY_POINT) != 0;
146    }
147
148    [[nodiscard]] bool IsGenerator() const noexcept
149    {
150        return (funcFlags_ & ir::ScriptFunctionFlags::GENERATOR) != 0;
151    }
152
153    [[nodiscard]] bool IsAsyncFunc() const noexcept
154    {
155        return (funcFlags_ & ir::ScriptFunctionFlags::ASYNC) != 0;
156    }
157
158    [[nodiscard]] bool IsAsyncImplFunc() const noexcept
159    {
160        return (funcFlags_ & ir::ScriptFunctionFlags::ASYNC_IMPL) != 0;
161    }
162
163    [[nodiscard]] bool IsArrow() const noexcept
164    {
165        return (funcFlags_ & ir::ScriptFunctionFlags::ARROW) != 0;
166    }
167
168    [[nodiscard]] bool IsOverload() const noexcept
169    {
170        return (funcFlags_ & ir::ScriptFunctionFlags::OVERLOAD) != 0;
171    }
172
173    [[nodiscard]] bool IsExternalOverload() const
174    {
175        return (funcFlags_ & ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD) != 0;
176    }
177
178    [[nodiscard]] bool IsConstructor() const noexcept
179    {
180        return (funcFlags_ & ir::ScriptFunctionFlags::CONSTRUCTOR) != 0;
181    }
182
183    [[nodiscard]] bool IsGetter() const noexcept
184    {
185        return (funcFlags_ & ir::ScriptFunctionFlags::GETTER) != 0;
186    }
187
188    [[nodiscard]] bool IsSetter() const noexcept
189    {
190        return (funcFlags_ & ir::ScriptFunctionFlags::SETTER) != 0;
191    }
192
193    [[nodiscard]] bool IsMethod() const noexcept
194    {
195        return (funcFlags_ & ir::ScriptFunctionFlags::METHOD) != 0;
196    }
197
198    [[nodiscard]] bool IsProxy() const noexcept
199    {
200        return (funcFlags_ & ir::ScriptFunctionFlags::PROXY) != 0;
201    }
202
203    [[nodiscard]] bool IsStaticBlock() const noexcept
204    {
205        return (funcFlags_ & ir::ScriptFunctionFlags::STATIC_BLOCK) != 0;
206    }
207
208    [[nodiscard]] bool IsEnum() const noexcept
209    {
210        return (funcFlags_ & ir::ScriptFunctionFlags::ENUM) != 0;
211    }
212
213    [[nodiscard]] bool IsHidden() const noexcept
214    {
215        return (funcFlags_ & ir::ScriptFunctionFlags::HIDDEN) != 0;
216    }
217
218    [[nodiscard]] bool IsExternal() const noexcept
219    {
220        return (funcFlags_ & ir::ScriptFunctionFlags::EXTERNAL) != 0;
221    }
222
223    [[nodiscard]] bool IsImplicitSuperCallNeeded() const noexcept
224    {
225        return (funcFlags_ & ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED) != 0;
226    }
227
228    [[nodiscard]] bool HasBody() const noexcept
229    {
230        return body_ != nullptr;
231    }
232
233    [[nodiscard]] bool HasRestParameter() const noexcept
234    {
235        return signature_->RestVar() != nullptr;
236    }
237
238    [[nodiscard]] bool HasReturnStatement() const noexcept
239    {
240        return (funcFlags_ & ir::ScriptFunctionFlags::HAS_RETURN) != 0;
241    }
242
243    [[nodiscard]] bool IsThrowing() const noexcept
244    {
245        return (funcFlags_ & ir::ScriptFunctionFlags::THROWS) != 0;
246    }
247
248    [[nodiscard]] bool IsRethrowing() const noexcept
249    {
250        return (funcFlags_ & ir::ScriptFunctionFlags::RETHROWS) != 0;
251    }
252
253    [[nodiscard]] bool IsDynamic() const noexcept
254    {
255        return lang_.IsDynamic();
256    }
257
258    [[nodiscard]] bool IsExtensionMethod() const noexcept
259    {
260        return (funcFlags_ & ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD) != 0;
261    }
262
263    [[nodiscard]] bool Declare() const noexcept
264    {
265        return declare_;
266    }
267
268    [[nodiscard]] ir::ScriptFunctionFlags Flags() const noexcept
269    {
270        return funcFlags_;
271    }
272
273    void SetIdent(Identifier *id) noexcept;
274
275    void SetSignature(checker::Signature *signature) noexcept
276    {
277        signature_ = signature;
278    }
279
280    void AddFlag(ir::ScriptFunctionFlags flags) noexcept
281    {
282        funcFlags_ |= flags;
283    }
284
285    void AddModifier(ir::ModifierFlags flags) noexcept
286    {
287        flags_ |= flags;
288    }
289
290    [[nodiscard]] std::size_t FormalParamsLength() const noexcept;
291
292    [[nodiscard]] bool IsScopeBearer() const noexcept override
293    {
294        return true;
295    }
296
297    [[nodiscard]] varbinder::FunctionScope *Scope() const noexcept override
298    {
299        return scope_;
300    }
301
302    void SetScope(varbinder::FunctionScope *scope) noexcept
303    {
304        scope_ = scope;
305    }
306
307    void ClearScope() noexcept override
308    {
309        scope_ = nullptr;
310    }
311
312    [[nodiscard]] es2panda::Language Language() const noexcept
313    {
314        return lang_;
315    }
316
317    [[nodiscard]] ScriptFunction *Clone(ArenaAllocator *allocator, AstNode *parent) override;
318
319    void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
320    void Iterate(const NodeTraverser &cb) const override;
321
322    void Dump(ir::AstDumper *dumper) const override;
323    void Dump(ir::SrcDumper *dumper) const override;
324    void Compile(compiler::PandaGen *pg) const override;
325    void Compile(compiler::ETSGen *etsg) const override;
326    checker::Type *Check(checker::TSChecker *checker) override;
327    checker::Type *Check(checker::ETSChecker *checker) override;
328
329    void Accept(ASTVisitorT *v) override
330    {
331        v->Accept(this);
332    }
333
334private:
335    Identifier *id_ {};
336    FunctionSignature irSignature_;
337    AstNode *body_;
338    varbinder::FunctionScope *scope_ {nullptr};
339    ir::ScriptFunctionFlags funcFlags_;
340    checker::Signature *signature_ {};
341    bool declare_;
342    es2panda::Language lang_;
343    ArenaVector<ReturnStatement *> returnStatements_;
344};
345}  // namespace ark::es2panda::ir
346
347#endif
348