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
ResetTopScope(GlobalScope * topScope)118 void ResetTopScope(GlobalScope *topScope)
119 {
120 ASSERT(topScope_ == scope_);
121 topScope_ = topScope;
122 varScope_ = topScope_;
123 scope_ = topScope_;
124 }
125
TopScope()126 GlobalScope *TopScope() const
127 {
128 return topScope_;
129 }
130
VarScope()131 VariableScope *VarScope() const
132 {
133 return varScope_;
134 }
135
IsETSBinder()136 bool IsETSBinder() const
137 {
138 return Extension() == ScriptExtension::ETS;
139 }
140
AsETSBinder()141 ETSBinder *AsETSBinder()
142 {
143 ASSERT(Extension() == ScriptExtension::ETS);
144 return reinterpret_cast<ETSBinder *>(this);
145 }
146
147 [[noreturn]] void ThrowPrivateFieldMismatch(const lexer::SourcePosition &pos, const util::StringView &name) const;
148 [[noreturn]] void ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name) const;
149 [[noreturn]] void ThrowUnresolvableVariable(const lexer::SourcePosition &pos, const util::StringView &name) const;
150 [[noreturn]] void ThrowUnresolvableType(const lexer::SourcePosition &pos, const util::StringView &name) const;
151 [[noreturn]] void ThrowTDZ(const lexer::SourcePosition &pos, const util::StringView &name) const;
152 [[noreturn]] void ThrowInvalidCapture(const lexer::SourcePosition &pos, const util::StringView &name) const;
153 [[noreturn]] void ThrowError(const lexer::SourcePosition &pos, const std::string_view &msg) const;
154
155 void PropagateDirectEval() const;
156
157 template <typename T>
158 friend class LexicalScope;
159
Allocator()160 inline ArenaAllocator *Allocator() const
161 {
162 return allocator_;
163 }
164
Functions()165 const ArenaVector<FunctionScope *> &Functions() const
166 {
167 return functionScopes_;
168 }
169
Functions()170 ArenaVector<FunctionScope *> &Functions()
171 {
172 return functionScopes_;
173 }
174
Extension()175 virtual ScriptExtension Extension() const
176 {
177 return ScriptExtension::JS;
178 }
179
BindingOptions()180 virtual ResolveBindingOptions BindingOptions() const
181 {
182 return ResolveBindingOptions::BINDINGS;
183 }
184
185 LocalVariable *AddMandatoryParam(const std::string_view &name);
186
187 static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments";
188 static constexpr std::string_view MANDATORY_PARAM_FUNC = "=f";
189 static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "=nt";
190 static constexpr std::string_view MANDATORY_PARAM_THIS = "=t";
191
192 static constexpr uint32_t MANDATORY_PARAM_FUNC_REG = 0;
193 static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3;
194
195 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "!f";
196 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "!nt";
197 static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "!t";
198
199 static constexpr std::string_view LEXICAL_CONTEXT_PARAM = "=eval";
200 static constexpr std::string_view MAIN = "main";
201 static constexpr uint32_t LEXICAL_CONTEXT_PARAM_REG = MANDATORY_PARAMS_NUMBER;
202 static constexpr std::string_view STAR_IMPORT = "*";
203
204 void ResolveReference(ir::AstNode *childNode);
205
206 protected:
207 template <size_t N>
208 using MandatoryParams = std::array<std::string_view, N>;
209
210 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> FUNCTION_MANDATORY_PARAMS = {
211 MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS};
212
213 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER + 1> EVAL_SCRIPT_MANDATORY_PARAMS = {
214 MANDATORY_PARAM_FUNC, MANDATORY_PARAM_NEW_TARGET, MANDATORY_PARAM_THIS, LEXICAL_CONTEXT_PARAM};
215
216 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> ARROW_MANDATORY_PARAMS = {
217 MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
218
219 static constexpr MandatoryParams<MANDATORY_PARAMS_NUMBER> CTOR_ARROW_MANDATORY_PARAMS = {
220 LEXICAL_MANDATORY_PARAM_FUNC, LEXICAL_MANDATORY_PARAM_NEW_TARGET, LEXICAL_MANDATORY_PARAM_THIS};
221
222 void LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj);
223 template <size_t N>
224 void AddMandatoryParams(const MandatoryParams<N> ¶ms);
225 void AddMandatoryParams();
226 void LookupReference(const util::StringView &name);
227 void InstantiateArguments();
228 bool InstantiateArgumentsImpl(Scope **scope, Scope *iter, const ir::AstNode *node);
229 void InstantiatePrivateContext(const ir::Identifier *ident) const;
230 void BuildVarDeclarator(ir::VariableDeclarator *varDecl);
231 void BuildVarDeclaratorId(ir::AstNode *childNode);
232 void BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt);
233 void BuildForInOfLoop(varbinder::LoopScope *loopScope, ir::AstNode *left, ir::Expression *right,
234 ir::Statement *body);
235 void BuildCatchClause(ir::CatchClause *catchClauseStmt);
236 void BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl);
237 void ResolveReferences(const ir::AstNode *parent);
238 void VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func);
239 void VisitScriptFunction(ir::ScriptFunction *func);
240 util::StringView BuildFunctionName(util::StringView name, uint32_t idx);
241
242 void AddCompilableFunctionScope(varbinder::FunctionScope *funcScope);
243
244 void InitializeClassBinding(ir::ClassDefinition *classDef);
245 void InitializeClassIdent(ir::ClassDefinition *classDef);
246
247 virtual void LookupIdentReference(ir::Identifier *ident);
HandleCustomNodes(ir::AstNode * childNode)248 virtual void HandleCustomNodes(ir::AstNode *childNode)
249 {
250 ResolveReferences(childNode);
251 }
BuildSignatureDeclarationBaseParams(ir::AstNode * typeNode)252 virtual void BuildSignatureDeclarationBaseParams([[maybe_unused]] ir::AstNode *typeNode) {};
253 virtual void BuildClassDefinition(ir::ClassDefinition *classDef);
254 virtual void BuildClassProperty(const ir::ClassProperty *prop);
255 virtual bool BuildInternalName(ir::ScriptFunction *scriptFunc);
256 virtual void AddCompilableFunction(ir::ScriptFunction *func);
257
258 private:
259 parser::Program *program_ {};
260 ArenaAllocator *allocator_ {};
261 public_lib::Context *context_ {};
262 GlobalScope *topScope_ {};
263 Scope *scope_ {};
264 VariableScope *varScope_ {};
265 ArenaVector<FunctionScope *> functionScopes_;
266 ResolveBindingOptions bindingOptions_ {};
267 bool genStdLib_ {false};
268 };
269
270 template <typename T>
271 class LexicalScope {
272 public:
273 template <typename... Args>
LexicalScope(VarBinder * varbinder,Args &&...args)274 explicit LexicalScope(VarBinder *varbinder, Args &&...args)
275 : LexicalScope(
276 varbinder->Allocator()->New<T>(varbinder->Allocator(), varbinder->scope_, std::forward<Args>(args)...),
277 varbinder)
278 {
279 }
280
GetScope()281 T *GetScope() const
282 {
283 return scope_;
284 }
285
~LexicalScope()286 ~LexicalScope()
287 {
288 ASSERT(varbinder_);
289 varbinder_->scope_ = prevScope_;
290 varbinder_->varScope_ = prevVarScope_;
291 }
292
293 [[nodiscard]] static LexicalScope<T> Enter(VarBinder *varbinder, T *scope, bool checkEval = true)
294 {
295 LexicalScope<T> lexScope(scope, varbinder);
296 if (!checkEval || varbinder->Extension() == ScriptExtension::TS) {
297 return lexScope;
298 }
299
300 // NOLINTNEXTLINE(readability-braces-around-statements)
301 if constexpr (std::is_same_v<T, FunctionParamScope>) {
302 varbinder->varScope_ = scope->GetFunctionScope();
303 varbinder->varScope_->CheckDirectEval(varbinder->context_);
304 // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
305 } else if constexpr (std::is_same_v<T, FunctionScope>) {
306 varbinder->varScope_ = scope;
307 varbinder->varScope_->CheckDirectEval(varbinder->context_);
308 // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
309 } else if constexpr (std::is_same_v<T, LoopScope>) {
310 if (scope->IsLoopScope()) {
311 varbinder->varScope_ = scope;
312 varbinder->varScope_->CheckDirectEval(varbinder->context_);
313 }
314 // NOLINTNEXTLINE(readability-braces-around-statements,readability-misleading-indentation)
315 } else if constexpr (std::is_same_v<T, LoopDeclarationScope>) {
316 if (scope->IsLoopDeclarationScope()) {
317 varbinder->varScope_ = scope;
318 varbinder->varScope_->CheckDirectEval(varbinder->context_);
319 }
320 }
321
322 return lexScope;
323 }
324
325 DEFAULT_MOVE_SEMANTIC(LexicalScope);
326
327 private:
328 NO_COPY_SEMANTIC(LexicalScope);
329
LexicalScope(T * scope,VarBinder * varbinder)330 explicit LexicalScope(T *scope, VarBinder *varbinder)
331 : varbinder_(varbinder), scope_(scope), prevScope_(varbinder->scope_), prevVarScope_(varbinder->varScope_)
332 {
333 varbinder_->scope_ = scope_;
334 }
335
336 VarBinder *varbinder_ {};
337 T *scope_ {};
338 Scope *prevScope_ {};
339 VariableScope *prevVarScope_ {};
340 };
341
342 template <size_t N>
AddMandatoryParams(const MandatoryParams<N> & params)343 void VarBinder::AddMandatoryParams(const MandatoryParams<N> ¶ms)
344 {
345 ASSERT(scope_->IsFunctionVariableScope());
346
347 auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope_->AsFunctionVariableScope()->ParamScope());
348
349 for (auto iter = params.rbegin(); iter != params.rend(); iter++) {
350 AddMandatoryParam(*iter);
351 }
352 }
353
354 template <typename T, typename... Args>
AddTsDecl(const lexer::SourcePosition & pos,Args &&...args)355 T *VarBinder::AddTsDecl(const lexer::SourcePosition &pos, Args &&...args)
356 {
357 T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
358
359 if (scope_->AddTsDecl(Allocator(), decl, Extension()) != nullptr) {
360 return decl;
361 }
362
363 ThrowRedeclaration(pos, decl->Name());
364 }
365
366 template <typename T, typename... Args>
AddDecl(const lexer::SourcePosition & pos,Args &&...args)367 T *VarBinder::AddDecl(const lexer::SourcePosition &pos, Args &&...args)
368 {
369 T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
370
371 if (scope_->AddDecl(Allocator(), decl, Extension()) != nullptr) {
372 return decl;
373 }
374
375 ThrowRedeclaration(pos, decl->Name());
376 }
377
378 template <typename T, typename... Args>
NewVarDecl(const lexer::SourcePosition & pos,Args &&...args)379 std::tuple<T *, varbinder::Variable *> VarBinder::NewVarDecl(const lexer::SourcePosition &pos, Args &&...args)
380 {
381 T *decl = Allocator()->New<T>(std::forward<Args>(args)...);
382 varbinder::Variable *var = scope_->AddDecl(Allocator(), decl, Extension());
383
384 if (var != nullptr) {
385 return {decl, var};
386 }
387
388 ThrowRedeclaration(pos, decl->Name());
389 }
390 } // namespace ark::es2panda::varbinder
391
392 #endif
393