1/**
2 * Copyright (c) 2021 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_BINDER_BINDER_H
17#define ES2PANDA_BINDER_BINDER_H
18
19#include <binder/scope.h>
20#include <binder/variableFlags.h>
21#include <lexer/token/sourceLocation.h>
22#include <macros.h>
23#include <parser/program/program.h>
24
25namespace panda::es2panda::ir {
26class AstNode;
27class BlockStatement;
28class CatchClause;
29class ClassDefinition;
30class Expression;
31class ExportNamedDeclaration;
32class ForUpdateStatement;
33class Identifier;
34class PrivateIdentifier;
35class ScriptFunction;
36class Statement;
37class VariableDeclarator;
38class TSFunctionType;
39}  // namespace panda::es2panda::ir
40
41namespace panda::es2panda::binder {
42class Scope;
43class VariableScope;
44
45class Binder {
46public:
47    explicit Binder(parser::Program *program, ScriptExtension extension)
48        : program_(program),
49          functionScopes_(Allocator()->Adapter()),
50          functionNames_(Allocator()->Adapter()),
51          anonymousFunctionNames_(Allocator()->Adapter()),
52          functionHashNames_(Allocator()->Adapter()),
53          variableNames_(Allocator()->Adapter()),
54          specialFuncNameIndexMap_(Allocator()->Adapter()),
55          extension_(extension)
56    {
57        if (extension_ == ScriptExtension::TS) {
58            bindingOptions_ = ResolveBindingOptions::ALL;
59            return;
60        }
61
62        bindingOptions_ = ResolveBindingOptions::BINDINGS;
63    }
64
65    NO_COPY_SEMANTIC(Binder);
66    DEFAULT_MOVE_SEMANTIC(Binder);
67    ~Binder() = default;
68
69    void InitTopScope();
70    void IdentifierAnalysis(ResolveBindingFlags flags = ResolveBindingFlags::ALL);
71
72    template <typename T, typename... Args>
73    T *AddDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args);
74
75    template <typename T, typename... Args>
76    T *AddDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args);
77
78    template <typename T, typename... Args>
79    T *AddTsDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args);
80
81    template <typename T, typename... Args>
82    T *AddTsDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args);
83
84    ParameterDecl *AddParamDecl(const ir::AstNode *param);
85
86    Scope *GetScope() const
87    {
88        return scope_;
89    }
90
91    FunctionScope *TopScope() const
92    {
93        return topScope_;
94    }
95
96    [[noreturn]] void ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name);
97    [[noreturn]] void ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util::StringView &name);
98    [[noreturn]] void ThrowInvalidDstrTarget(const lexer::SourcePosition &pos, const util::StringView &name);
99    [[noreturn]] void ThrowInvalidAnnotationDeclaration(const lexer::SourcePosition &pos, const util::StringView &name);
100
101    void CheckMandatoryArguments(const ir::Identifier *ident);
102
103    template <typename T>
104    friend class LexicalScope;
105
106    inline ArenaAllocator *Allocator() const
107    {
108        return program_->Allocator();
109    }
110
111    const ArenaVector<FunctionScope *> &Functions() const
112    {
113        return functionScopes_;
114    }
115
116    ArenaVector<FunctionScope *> Functions()
117    {
118        return functionScopes_;
119    }
120
121    const parser::Program *Program() const
122    {
123        return program_;
124    }
125
126    void SetProgram(parser::Program *program)
127    {
128        program_ = program;
129    }
130
131    ArenaUnorderedMap<util::StringView, int32_t> &GetScopeNames()
132    {
133        return topScope_->GetScopeNames();
134    }
135
136    const ArenaUnorderedMap<const ir::ScriptFunction *, util::StringView> &AnonymousFunctionNames() const
137    {
138        return anonymousFunctionNames_;
139    }
140
141    const ArenaUnorderedMap<std::string, std::string> &SpecialFuncNameIndexMap() const
142    {
143        return specialFuncNameIndexMap_;
144    }
145
146    void AddDeclarationName(const util::StringView &name, DeclType type = DeclType::NONE);
147
148    bool HasVariableName(const util::StringView &name) const;
149
150    std::vector<Variable *> FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope,
151        ScopeFindResult &res);
152
153    static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments";
154    static constexpr std::string_view MANDATORY_PARAM_FUNC = "4funcObj";
155    static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "4newTarget";
156    static constexpr std::string_view MANDATORY_PARAM_THIS = "this";
157
158    static constexpr std::string_view CJS_MANDATORY_PARAM_EXPORTS = "exports";
159    static constexpr std::string_view CJS_MANDATORY_PARAM_REQUIRE = "require";
160    static constexpr std::string_view CJS_MANDATORY_PARAM_MODULE = "module";
161    static constexpr std::string_view CJS_MANDATORY_PARAM_FILENAME = "__filename";
162    static constexpr std::string_view CJS_MANDATORY_PARAM_DIRNAME = "__dirname";
163
164    static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0;
165    static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3;
166    static constexpr uint32_t CJS_MANDATORY_PARAMS_NUMBER = 8;
167
168    static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "0funcObj";
169    static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "0newTarget";
170    static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "0this";
171
172    static constexpr std::string_view MAIN_FUNC_NAME = "func_main_0";
173    static constexpr std::string_view ANONYMOUS_FUNC_NAME = "";
174    static constexpr std::string_view ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER = "#";
175
176private:
177    using MandatoryParams = std::array<std::string_view, MANDATORY_PARAMS_NUMBER>;
178    using CommonjsMandatoryParams = std::array<std::string_view, CJS_MANDATORY_PARAMS_NUMBER>;
179
180    static constexpr MandatoryParams FUNCTION_MANDATORY_PARAMS = {MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET,
181                                                                  MANDATORY_PARAM_THIS};
182
183    static constexpr MandatoryParams ARROW_MANDATORY_PARAMS = {MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET,
184                                                               LEXICAL_MANDATORY_PARAM_THIS};
185
186    static constexpr MandatoryParams CTOR_ARROW_MANDATORY_PARAMS = {
187        LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
188
189    static constexpr CommonjsMandatoryParams CJS_MAINFUNC_MANDATORY_PARAMS = {
190        MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS,
191        CJS_MANDATORY_PARAM_EXPORTS, CJS_MANDATORY_PARAM_REQUIRE, CJS_MANDATORY_PARAM_MODULE,
192        CJS_MANDATORY_PARAM_FILENAME, CJS_MANDATORY_PARAM_DIRNAME};
193
194    void AddMandatoryParam(const std::string_view &name);
195
196    template<typename T>
197    void AddMandatoryParams(const T &params)
198    {
199        for (auto iter = params.rbegin(); iter != params.rend(); iter++) {
200            AddMandatoryParam(*iter);
201        }
202    }
203
204    void AddMandatoryParams();
205    void AssignIndexToModuleVariable();
206    void BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func = nullptr);
207    void LegacyBuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func = nullptr);
208    void BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc);
209    void BuildClassDefinition(ir::ClassDefinition *classDef);
210    void LookupReference(const util::StringView &name);
211    void InstantiateArguments();
212    void BuildVarDeclarator(ir::VariableDeclarator *varDecl);
213    void BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode);
214    void BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt);
215    void BuildForInOfLoop(const ir::Statement *parent, binder::LoopScope *loopScope, ir::AstNode *left,
216                          ir::Expression *right, ir::Statement *body);
217    void BuildCatchClause(ir::CatchClause *catchClauseStmt);
218    void LookupIdentReference(ir::Identifier *ident);
219    void ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode);
220    void ResolveReferences(const ir::AstNode *parent);
221    void ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl);
222    void StoreAndCheckSpecialFunctionName(std::string &internalNameStr, std::string recordName);
223    void ReplaceConstReferenceWithInitialization(const ir::Identifier *ident, const Decl *decl);
224    void CheckPrivateDeclaration(const ir::PrivateIdentifier *privateIdent);
225
226    // TypeScript specific functions
227    void BuildTSSignatureDeclarationBaseParams(const ir::AstNode *typeNode);
228    void BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode *parent, ir::AstNode *typeNode);
229
230    parser::Program *program_ {};
231    FunctionScope *topScope_ {};
232    Scope *scope_ {};
233    ArenaVector<FunctionScope *> functionScopes_;
234    ResolveBindingOptions bindingOptions_;
235    ArenaSet<util::StringView> functionNames_;
236    ArenaUnorderedMap<const ir::ScriptFunction *, util::StringView> anonymousFunctionNames_;
237    ArenaUnorderedMap<std::string, size_t> functionHashNames_;
238    ArenaSet<util::StringView> variableNames_;
239    uint32_t globalIndexForSpecialFunc_ {0};
240    ArenaUnorderedMap<std::string, std::string> specialFuncNameIndexMap_;
241    ResolveBindingFlags bindingFlags_ {ResolveBindingFlags::ALL};
242    ScriptExtension extension_;
243    bool inSendableClass_ {false};
244    bool inSendableFunction_ {false};
245};
246
247template <typename T>
248class LexicalScope {
249public:
250    template <typename... Args>
251    explicit LexicalScope(Binder *binder, Args &&... args)
252        : LexicalScope(binder->Allocator()->New<T>(binder->Allocator(), binder->scope_, std::forward<Args>(args)...),
253                       binder)
254    {
255    }
256
257    T *GetScope() const
258    {
259        return scope_;
260    }
261
262    ~LexicalScope()
263    {
264        ASSERT(binder_);
265        binder_->scope_ = prevScope_;
266    }
267
268    [[nodiscard]] static LexicalScope<T> Enter(Binder *binder, T *scope)
269    {
270        LexicalScope<T> lexScope(scope, binder);
271        return lexScope;
272    }
273
274    DEFAULT_MOVE_SEMANTIC(LexicalScope);
275
276private:
277    NO_COPY_SEMANTIC(LexicalScope);
278
279    explicit LexicalScope(T *scope, Binder *binder) : binder_(binder), scope_(scope), prevScope_(binder->scope_)
280    {
281        binder_->scope_ = scope_;
282    }
283
284    Binder *binder_ {};
285    T *scope_ {};
286    Scope *prevScope_ {};
287};
288
289template <typename T, typename... Args>
290T *Binder::AddTsDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args)
291{
292    T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
293    if (decl == nullptr) {
294        throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding ts decl during binder");
295    }
296    decl->SetDeclare(isDeclare);
297
298    if (scope_->AddTsDecl(Allocator(), decl, program_->Extension())) {
299        AddDeclarationName(decl->Name());
300        return decl;
301    }
302
303    ThrowRedeclaration(pos, decl->Name());
304}
305
306template <typename T, typename... Args>
307T *Binder::AddTsDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args)
308{
309    T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
310    if (decl == nullptr) {
311        throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding ts decl during binder");
312    }
313    decl->AddFlag(flag);
314    decl->SetDeclare(isDeclare);
315
316    if (scope_->AddTsDecl(Allocator(), decl, program_->Extension())) {
317        AddDeclarationName(decl->Name());
318        return decl;
319    }
320
321    ThrowRedeclaration(pos, decl->Name());
322}
323
324template <typename T, typename... Args>
325T *Binder::AddDecl(const lexer::SourcePosition &pos, bool isDeclare, Args &&... args)
326{
327    T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
328    if (decl == nullptr) {
329        throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding decl during binder");
330    }
331    decl->SetDeclare(isDeclare);
332
333    if (scope_->AddDecl(Allocator(), decl, program_->Extension())) {
334        AddDeclarationName(decl->Name(), decl->Type());
335        return decl;
336    }
337
338    ThrowRedeclaration(pos, decl->Name());
339}
340
341template <typename T, typename... Args>
342T *Binder::AddDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, bool isDeclare, Args &&... args)
343{
344    T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
345    if (decl == nullptr) {
346        throw Error(ErrorType::GENERIC, "Unsuccessful allocation in adding decl during binder");
347    }
348    decl->AddFlag(flag);
349    decl->SetDeclare(isDeclare);
350
351    if (scope_->AddDecl(Allocator(), decl, program_->Extension())) {
352        AddDeclarationName(decl->Name(), decl->Type());
353        return decl;
354    }
355
356    ThrowRedeclaration(pos, decl->Name());
357}
358
359class ClassTdz {
360public:
361    explicit ClassTdz(const ir::AstNode *parent, const ir::AstNode *childNode, Scope *scope);
362
363    ~ClassTdz()
364    {
365        if (variable_) {
366            variable_->AddFlag(VariableFlags::INITIALIZED);
367        }
368    }
369
370private:
371    Variable *variable_ {};
372};
373
374}  // namespace panda::es2panda::binder
375
376#endif
377