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