1 /**
2 * Copyright (c) 2021-2024 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_VARBINDER_VARBINDER_H
17 #define ES2PANDA_VARBINDER_VARBINDER_H
18
19 #include "varbinder/scope.h"
20 #include "varbinder/variableFlags.h"
21 #include "lexer/token/sourceLocation.h"
22 #include "macros.h"
23
24 namespace ark::es2panda::parser {
25 class Program;
26 enum class ScriptKind;
27 } // namespace ark::es2panda::parser
28
29 namespace ark::es2panda::ir {
30 class AstNode;
31 class BlockStatement;
32 class CatchClause;
33 class ClassDefinition;
34 class Expression;
35 class ForUpdateStatement;
36 class Identifier;
37 class ScriptFunction;
38 class Statement;
39 class VariableDeclarator;
40 class TSFunctionType;
41 class ThisExpression;
42 class MemberExpression;
43 class ClassStaticBlock;
44 } // namespace ark::es2panda::ir
45
46 namespace ark::es2panda::public_lib {
47 struct Context;
48 } // namespace ark::es2panda::public_lib
49
50 namespace ark::es2panda::varbinder {
51 class ETSBinder;
52
53 class VarBinder {
54 public:
VarBinder(ArenaAllocator * allocator)55 explicit VarBinder(ArenaAllocator *allocator) : allocator_(allocator), functionScopes_(allocator_->Adapter()) {}
56
57 NO_COPY_SEMANTIC(VarBinder);
58 NO_MOVE_SEMANTIC(VarBinder);
59 virtual ~VarBinder() = default;
60
61 void InitTopScope();
62 virtual void IdentifierAnalysis();
63
64 template <typename T, typename... Args>
65 T *AddDecl(const lexer::SourcePosition &pos, Args &&...args);
66
67 template <typename T, typename... Args>
68 T *AddTsDecl(const lexer::SourcePosition &pos, Args &&...args);
69
70 template <typename T, typename... Args>
71 std::tuple<T *, varbinder::Variable *> NewVarDecl(const lexer::SourcePosition &pos, Args &&...args);
72
73 std::tuple<ParameterDecl *, Variable *> AddParamDecl(ir::AstNode *param);
74
SetProgram(parser::Program * program)75 void SetProgram(parser::Program *program)
76 {
77 program_ = program;
78 }
79
Program()80 parser::Program *Program()
81 {
82 return program_;
83 }
84
Program()85 const parser::Program *Program() const
86 {
87 ASSERT(program_);
88 return program_;
89 }
90
SetContext(public_lib::Context * context)91 void SetContext(public_lib::Context *context)
92 {
93 ASSERT(!context_);
94 context_ = context;
95 }
96
GetContext()97 public_lib::Context *GetContext() const
98 {
99 ASSERT(context_);
100 return context_;
101 }
102
SetGenStdLib(bool genStdLib)103 void SetGenStdLib(bool genStdLib)
104 {
105 genStdLib_ = genStdLib;
106 }
107
IsGenStdLib()108 bool IsGenStdLib()
109 {
110 return genStdLib_;
111 }
112
GetScope()113 Scope *GetScope() const
114 {
115 return scope_;
116 }
117
ResetAllScopes(GlobalScope * topScope,VariableScope * varScope,Scope * scope)118 void ResetAllScopes(GlobalScope *topScope, VariableScope *varScope, Scope *scope)
119 {
120 topScope_ = topScope;
121 varScope_ = varScope;
122 scope_ = scope;
123 }
124
ResetTopScope(GlobalScope * topScope)125 void ResetTopScope(GlobalScope *topScope)
126 {
127 ASSERT(topScope_ == scope_);
128 topScope_ = topScope;
129 varScope_ = topScope_;
130 scope_ = topScope_;
131 }
132
TopScope()133 GlobalScope *TopScope() const
134 {
135 return topScope_;
136 }
137
VarScope()138 VariableScope *VarScope() const
139 {
140 return varScope_;
141 }
142
IsETSBinder()143 bool IsETSBinder() const
144 {
145 return Extension() == ScriptExtension::ETS;
146 }
147
AsETSBinder()148 ETSBinder *AsETSBinder()
149 {
150 ASSERT(Extension() == ScriptExtension::ETS);
151 return reinterpret_cast<ETSBinder *>(this);
152 }
153
154 [[noreturn]] void ThrowPrivateFieldMismatch(const lexer::SourcePosition &pos, const util::StringView &name) const;
155 [[noreturn]] void ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name) const;
156 [[noreturn]] void ThrowUnresolvableVariable(const lexer::SourcePosition &pos, const util::StringView &name) const;
157 [[noreturn]] void ThrowUnresolvableType(const lexer::SourcePosition &pos, const util::StringView &name) const;
158 [[noreturn]] void ThrowTDZ(const lexer::SourcePosition &pos, const util::StringView &name) const;
159 [[noreturn]] void ThrowInvalidCapture(const lexer::SourcePosition &pos, const util::StringView &name) const;
160 [[noreturn]] void ThrowError(const lexer::SourcePosition &pos, const std::string_view &msg) const;
161
162 void PropagateDirectEval() const;
163
164 template <typename T>
165 friend class LexicalScope;
166
Allocator()167 inline ArenaAllocator *Allocator() const
168 {
169 return allocator_;
170 }
171
Functions()172 const ArenaVector<FunctionScope *> &Functions() const
173 {
174 return functionScopes_;
175 }
176
Functions()177 ArenaVector<FunctionScope *> &Functions()
178 {
179 return functionScopes_;
180 }
181
Extension()182 virtual ScriptExtension Extension() const
183 {
184 return ScriptExtension::JS;
185 }
186
BindingOptions()187 virtual ResolveBindingOptions BindingOptions() const
188 {
189 return ResolveBindingOptions::BINDINGS;
190 }
191
192 LocalVariable *AddMandatoryParam(const std::string_view &name);
193
194 static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments";
195 static constexpr std::string_view MANDATORY_PARAM_FUNC = "=f";
196 static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "=nt";
197 static constexpr std::string_view MANDATORY_PARAM_THIS = "=t";
198
199 static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0;
200 static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3;
201
202 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "!f";
203 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "!nt";
204 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "!t";
205
206 static constexpr std::string_view LEXICAL_CONTEXT_PARAM = "=eval";
207 static constexpr std::string_view MAIN = "main";
208 static constexpr uint32_t LEXICAL_CONTEXT_PARAM_REG = MANDATORY_PARAMS_NUMBER;
209 static constexpr std::string_view STAR_IMPORT = "*";
210
211 void ResolveReferenceDoWhileHelper(ir::AstNode *childNode);
212 void ResolveReferenceWhileHelper(ir::AstNode *childNode);
213 void ResolveReference(ir::AstNode *childNode);
214
215 protected:
216 template <size_t N>
217 using MandatoryParams = std::array<std::string_view, N>;
218
219 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> FUNCTION_MANDATORY_PARAMS = {
220 MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS};
221
222 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER + 1> EVAL_SCRIPT_MANDATORY_PARAMS = {
223 MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS, LEXICAL_CONTEXT_PARAM};
224
225 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> ARROW_MANDATORY_PARAMS = {
226 MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
227
228 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> CTOR_ARROW_MANDATORY_PARAMS = {
229 LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
230
231 void LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj);
232 template <size_t N>
233 void AddMandatoryParams(const MandatoryParams<N> ¶ms);
234 void AddMandatoryParams();
235 void LookupReference(const util::StringView &name);
236 void InstantiateArguments();
237 bool InstantiateArgumentsImpl(Scope **scope, Scope *iter, const ir::AstNode *node);
238 void InstantiatePrivateContext(const ir::Identifier *ident) const;
239 void BuildVarDeclarator(ir::VariableDeclarator *varDecl);
240 void BuildVarDeclaratorId(ir::AstNode *childNode);
241 void BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt);
242 void BuildForInOfLoop(varbinder::LoopScope *loopScope, ir::AstNode *left, ir::Expression *right,
243 ir::Statement *body);
244 void BuildCatchClause(ir::CatchClause *catchClauseStmt);
245 void BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl);
246 void ResolveReferences(const ir::AstNode *parent);
247 void VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func);
248 void VisitScriptFunction(ir::ScriptFunction *func);
249 util::StringView BuildFunctionName(util::StringView name, uint32_t idx);
250
251 void AddCompilableFunctionScope(varbinder::FunctionScope *funcScope);
252
253 void InitializeClassBinding(ir::ClassDefinition *classDef);
254 void InitializeClassIdent(ir::ClassDefinition *classDef);
255
256 virtual void LookupIdentReference(ir::Identifier *ident);
HandleCustomNodes(ir::AstNode * childNode)257 virtual void HandleCustomNodes(ir::AstNode *childNode)
258 {
259 ResolveReferences(childNode);
260 }
BuildSignatureDeclarationBaseParams(ir::AstNode * typeNode)261 virtual void BuildSignatureDeclarationBaseParams([[maybe_unused]] ir::AstNode *typeNode) {};
262 virtual void BuildClassDefinition(ir::ClassDefinition *classDef);
263 virtual void BuildClassProperty(const ir::ClassProperty *prop);
264 virtual bool BuildInternalName(ir::ScriptFunction *scriptFunc);
265 virtual void AddCompilableFunction(ir::ScriptFunction *func);
266
267 private:
268 parser::Program *program_ {};
269 ArenaAllocator *allocator_ {};
270 public_lib::Context *context_ {};
271 GlobalScope *topScope_ {};
272 Scope *scope_ {};
273 VariableScope *varScope_ {};
274 ArenaVector<FunctionScope *> functionScopes_;
275 ResolveBindingOptions bindingOptions_ {};
276 bool genStdLib_ {false};
277 };
278
279 template <typename T>
280 class LexicalScope {
281 public:
282 template <typename... Args>
LexicalScope(VarBinder * varbinder,Args &&...args)283 explicit LexicalScope(VarBinder *varbinder, Args &&...args)
284 : LexicalScope(
285 varbinder->Allocator()->New<T>(varbinder->Allocator(), varbinder->scope_, std::forward<Args>(args)...),
286 varbinder)
287 {
288 }
289
GetScope()290 T *GetScope() const
291 {
292 return scope_;
293 }
294
~LexicalScope()295 ~LexicalScope()
296 {
297 ASSERT(varbinder_);
298 varbinder_->scope_ = prevScope_;
299 varbinder_->varScope_ = prevVarScope_;
300 }
301
302 [[nodiscard]] static LexicalScope<T> Enter(VarBinder *varbinder, T *scope, bool checkEval = true)
303 {
304 LexicalScope<T> lexScope(scope, varbinder);
305 if (!checkEval || varbinder->Extension() == ScriptExtension::TS) {
306 return lexScope;
307 }
308
309 // NOLINTNEXTLINE(readability-braces-around-statements)
310 if constexpr (std::is_same_v<T, FunctionParamScope>) {
311 varbinder->varScope_ = scope->GetFunctionScope();
312 varbinder->varScope_->CheckDirectEval(varbinder->context_);
313 // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
314 } else if constexpr (std::is_same_v<T, FunctionScope>) {
315 varbinder->varScope_ = scope;
316 varbinder->varScope_->CheckDirectEval(varbinder->context_);
317 // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
318 } else if constexpr (std::is_same_v<T, LoopScope>) {
319 if (scope->IsLoopScope()) {
320 varbinder->varScope_ = scope;
321 varbinder->varScope_->CheckDirectEval(varbinder->context_);
322 }
323 // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
324 } else if constexpr (std::is_same_v<T, LoopDeclarationScope>) {
325 if (scope->IsLoopDeclarationScope()) {
326 varbinder->varScope_ = scope;
327 varbinder->varScope_->CheckDirectEval(varbinder->context_);
328 }
329 }
330
331 return lexScope;
332 }
333
334 DEFAULT_MOVE_SEMANTIC(LexicalScope);
335
336 private:
337 NO_COPY_SEMANTIC(LexicalScope);
338
LexicalScope(T * scope,VarBinder * varbinder)339 explicit LexicalScope(T *scope, VarBinder *varbinder)
340 : varbinder_(varbinder), scope_(scope), prevScope_(varbinder->scope_), prevVarScope_(varbinder->varScope_)
341 {
342 varbinder_->scope_ = scope_;
343 }
344
345 VarBinder *varbinder_ {};
346 T *scope_ {};
347 Scope *prevScope_ {};
348 VariableScope *prevVarScope_ {};
349 };
350
351 template <size_t N>
AddMandatoryParams(const MandatoryParams<N> & params)352 void VarBinder::AddMandatoryParams(const MandatoryParams<N> ¶ms)
353 {
354 ASSERT(scope_->IsFunctionVariableScope());
355
356 auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope_->AsFunctionVariableScope()->ParamScope());
357
358 for (auto iter = params.rbegin(); iter != params.rend(); iter++) {
359 AddMandatoryParam(*iter);
360 }
361 }
362
363 template <typename T, typename... Args>
AddTsDecl(const lexer::SourcePosition & pos,Args &&...args)364 T *VarBinder::AddTsDecl(const lexer::SourcePosition &pos, Args &&...args)
365 {
366 T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
367
368 if (scope_->AddTsDecl(Allocator(), decl, Extension()) != nullptr) {
369 return decl;
370 }
371
372 ThrowRedeclaration(pos, decl->Name());
373 }
374
375 template <typename T, typename... Args>
AddDecl(const lexer::SourcePosition & pos,Args &&...args)376 T *VarBinder::AddDecl(const lexer::SourcePosition &pos, Args &&...args)
377 {
378 T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
379
380 if (scope_->AddDecl(Allocator(), decl, Extension()) != nullptr) {
381 return decl;
382 }
383
384 ThrowRedeclaration(pos, decl->Name());
385 }
386
387 template <typename T, typename... Args>
NewVarDecl(const lexer::SourcePosition & pos,Args &&...args)388 std::tuple<T *, varbinder::Variable *> VarBinder::NewVarDecl(const lexer::SourcePosition &pos, Args &&...args)
389 {
390 T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
391 varbinder::Variable *var = scope_->AddDecl(Allocator(), decl, Extension());
392
393 if (var != nullptr) {
394 return {decl, var};
395 }
396
397 ThrowRedeclaration(pos, decl->Name());
398 }
399 } // namespace ark::es2panda::varbinder
400
401 #endif
402