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