• 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 
GetScopeNames()130     ArenaUnorderedMap<util::StringView, int32_t> &GetScopeNames()
131     {
132         return topScope_->GetScopeNames();
133     }
134 
AnonymousFunctionNames()135     const ArenaUnorderedMap<const ir::ScriptFunction *, util::StringView> &AnonymousFunctionNames() const
136     {
137         return anonymousFunctionNames_;
138     }
139 
SpecialFuncNameIndexMap()140     const ArenaUnorderedMap<std::string, std::string> &SpecialFuncNameIndexMap() const
141     {
142         return specialFuncNameIndexMap_;
143     }
144 
145     void AddDeclarationName(const util::StringView &name, DeclType type = DeclType::NONE);
146 
147     bool HasVariableName(const util::StringView &name) const;
148 
149     std::vector<Variable *> FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope,
150         ScopeFindResult &res);
151 
152     static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments";
153     static constexpr std::string_view MANDATORY_PARAM_FUNC = "4funcObj";
154     static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "4newTarget";
155     static constexpr std::string_view MANDATORY_PARAM_THIS = "this";
156 
157     static constexpr std::string_view CJS_MANDATORY_PARAM_EXPORTS = "exports";
158     static constexpr std::string_view CJS_MANDATORY_PARAM_REQUIRE = "require";
159     static constexpr std::string_view CJS_MANDATORY_PARAM_MODULE = "module";
160     static constexpr std::string_view CJS_MANDATORY_PARAM_FILENAME = "__filename";
161     static constexpr std::string_view CJS_MANDATORY_PARAM_DIRNAME = "__dirname";
162 
163     static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0;
164     static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3;
165     static constexpr uint32_t CJS_MANDATORY_PARAMS_NUMBER = 8;
166 
167     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "0funcObj";
168     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "0newTarget";
169     static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "0this";
170 
171     static constexpr std::string_view MAIN_FUNC_NAME = "func_main_0";
172     static constexpr std::string_view ANONYMOUS_FUNC_NAME = "";
173     static constexpr std::string_view ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER = "#";
174 
175 private:
176     using MandatoryParams = std::array<std::string_view, MANDATORY_PARAMS_NUMBER>;
177     using CommonjsMandatoryParams = std::array<std::string_view, CJS_MANDATORY_PARAMS_NUMBER>;
178 
179     static constexpr MandatoryParams FUNCTION_MANDATORY_PARAMS = {MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET,
180                                                                   MANDATORY_PARAM_THIS};
181 
182     static constexpr MandatoryParams ARROW_MANDATORY_PARAMS = {MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET,
183                                                                LEXICAL_MANDATORY_PARAM_THIS};
184 
185     static constexpr MandatoryParams CTOR_ARROW_MANDATORY_PARAMS = {
186         LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
187 
188     static constexpr CommonjsMandatoryParams CJS_MAINFUNC_MANDATORY_PARAMS = {
189         MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS,
190         CJS_MANDATORY_PARAM_EXPORTS, CJS_MANDATORY_PARAM_REQUIRE, CJS_MANDATORY_PARAM_MODULE,
191         CJS_MANDATORY_PARAM_FILENAME, CJS_MANDATORY_PARAM_DIRNAME};
192 
193     void AddMandatoryParam(const std::string_view &name);
194 
195     template<typename T>
AddMandatoryParams(const T & params)196     void AddMandatoryParams(const T &params)
197     {
198         for (auto iter = params.rbegin(); iter != params.rend(); iter++) {
199             AddMandatoryParam(*iter);
200         }
201     }
202 
203     void AddMandatoryParams();
204     void AssignIndexToModuleVariable();
205     void BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func = nullptr);
206     void LegacyBuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func = nullptr);
207     void BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc);
208     void BuildClassDefinition(ir::ClassDefinition *classDef);
209     void ProcessNodeInStaticInitializer(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 
247 template <typename T>
248 class LexicalScope {
249 public:
250     template <typename... Args>
LexicalScope(Binder * binder,Args &&...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 
GetScope()257     T *GetScope() const
258     {
259         return scope_;
260     }
261 
~LexicalScope()262     ~LexicalScope()
263     {
264         ASSERT(binder_);
265         binder_->scope_ = prevScope_;
266     }
267 
Enter(Binder * binder,T * scope)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 
276 private:
277     NO_COPY_SEMANTIC(LexicalScope);
278 
LexicalScope(T * scope,Binder * binder)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 
289 template <typename T, typename... Args>
AddTsDecl(const lexer::SourcePosition & pos,bool isDeclare,Args &&...args)290 T *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 
306 template <typename T, typename... Args>
AddTsDecl(const lexer::SourcePosition & pos,DeclarationFlags flag,bool isDeclare,Args &&...args)307 T *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 
324 template <typename T, typename... Args>
AddDecl(const lexer::SourcePosition & pos,bool isDeclare,Args &&...args)325 T *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 
341 template <typename T, typename... Args>
AddDecl(const lexer::SourcePosition & pos,DeclarationFlags flag,bool isDeclare,Args &&...args)342 T *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 
359 class ClassTdz {
360 public:
361     explicit ClassTdz(const ir::AstNode *parent, const ir::AstNode *childNode, Scope *scope);
362 
~ClassTdz()363     ~ClassTdz()
364     {
365         if (variable_) {
366             variable_->AddFlag(VariableFlags::INITIALIZED);
367         }
368     }
369 
370 private:
371     Variable *variable_ {};
372 };
373 
374 }  // namespace panda::es2panda::binder
375 
376 #endif
377