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