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