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