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