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