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 ¶ms)
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