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