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