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#include "scope.h" 17 18#include <binder/declaration.h> 19#include <util/helpers.h> 20#include <binder/tsBinding.h> 21#include <binder/variable.h> 22#include <binder/variableFlags.h> 23#include <ir/astNode.h> 24#include <ir/base/scriptFunction.h> 25#include <ir/base/classDefinition.h> 26#include <ir/expressions/identifier.h> 27#include <ir/expressions/literals/stringLiteral.h> 28#include <ir/expressions/privateIdentifier.h> 29#include <ir/module/exportAllDeclaration.h> 30#include <ir/module/exportNamedDeclaration.h> 31#include <ir/module/exportSpecifier.h> 32#include <ir/module/importDeclaration.h> 33#include <ir/ts/tsModuleDeclaration.h> 34#include <ir/ts/tsEnumDeclaration.h> 35#include <macros.h> 36#include <util/concurrent.h> 37#include <util/ustring.h> 38 39#include <algorithm> 40#include <sstream> 41 42namespace panda::es2panda::binder { 43 44VariableScope *Scope::EnclosingVariableScope() 45{ 46 Scope *iter = this; 47 48 while (iter) { 49 if (iter->IsVariableScope()) { 50 return iter->AsVariableScope(); 51 } 52 53 iter = iter->Parent(); 54 } 55 56 return nullptr; 57} 58 59FunctionScope *Scope::EnclosingFunctionVariableScope() 60{ 61 Scope *iter = this; 62 while (iter) { 63 if (iter->IsFunctionVariableScope()) { 64 return iter->AsFunctionVariableScope(); 65 } 66 67 iter = iter->Parent(); 68 } 69 70 return nullptr; 71} 72 73Variable *Scope::FindLocal(const util::StringView &name, ResolveBindingOptions options) const 74{ 75 if (options & ResolveBindingOptions::INTERFACES) { 76 const std::string &interfaceName = binder::TSBinding::ToTSBinding(name); 77 78 auto res = bindings_.find(util::StringView{interfaceName}); 79 if (res != bindings_.end()) { 80 return res->second; 81 } 82 83 if (!(options & ResolveBindingOptions::BINDINGS)) { 84 return nullptr; 85 } 86 } 87 88 auto res = bindings_.find(name); 89 if (res == bindings_.end()) { 90 return nullptr; 91 } 92 93 return res->second; 94} 95 96void Scope::CalculateLevelInCorrespondingFunctionScope(const FunctionParamScope *scope, uint32_t &lexLevel, 97 uint32_t &sendableLevel) const 98{ 99 auto *funcVariableScope = scope->GetFunctionScope(); 100 // we may only have function param scope without function scope in TS here 101 if (funcVariableScope == nullptr) { 102 return; 103 } 104 105 if (funcVariableScope->NeedLexEnv()) { 106 lexLevel++; 107 } 108 109 if (funcVariableScope->NeedSendableEnv()) { 110 sendableLevel++; 111 } 112} 113 114ScopeFindResult Scope::Find(const util::StringView &name, ResolveBindingOptions options) const 115{ 116 uint32_t level = 0; 117 uint32_t lexLevel = 0; 118 uint32_t sendableLevel = 0; 119 const auto *iter = this; 120 ir::ScriptFunction *concurrentFunc = nullptr; 121 // If the first scope is functionParamScope, it means its corresponding functionScope is not 122 // iterated. so by default we set prevScopeNotFunctionScope as true so under such case, 123 // functionScopeNotIterated will be true. 124 bool prevScopeNotFunctionScope = true; 125 bool lexical = false; 126 127 while (iter != nullptr) { 128 bool functionScopeNotIterated = iter->IsFunctionParamScope() && prevScopeNotFunctionScope; 129 Variable *v = iter->FindLocal(name, options); 130 131 if (v != nullptr) { 132 return {name, const_cast<Scope *>(iter), level, lexLevel, sendableLevel, v, concurrentFunc}; 133 } 134 135 if (iter->IsFunctionVariableScope() && !lexical) { 136 lexical = true; 137 } 138 139 if (iter->IsFunctionScope() && !concurrentFunc) { 140 if (iter->Node()->AsScriptFunction()->IsConcurrent()) { 141 concurrentFunc = const_cast<ir::ScriptFunction *>(iter->Node()->AsScriptFunction()); 142 } 143 } 144 145 if (iter->IsVariableScope()) { 146 if (lexical) { 147 level++; 148 } 149 150 if (iter->AsVariableScope()->NeedLexEnv()) { 151 lexLevel++; 152 } 153 154 if (iter->AsVariableScope()->NeedSendableEnv()) { 155 sendableLevel++; 156 } 157 } else if (functionScopeNotIterated) { 158 level++; 159 CalculateLevelInCorrespondingFunctionScope(iter->AsFunctionParamScope(), lexLevel, sendableLevel); 160 } 161 162 prevScopeNotFunctionScope = !iter->IsFunctionVariableScope(); 163 iter = iter->Parent(); 164 } 165 166 return {name, nullptr, 0, 0, 0, nullptr, concurrentFunc}; 167} 168 169std::pair<uint32_t, uint32_t> Scope::Find(const ir::Expression *expr, bool onlyLevel) const 170{ 171 uint32_t lexLevel = 0; 172 const auto *iter = this; 173 174 while (iter != nullptr) { 175 if (iter->Type() == ScopeType::CLASS) { 176 if (onlyLevel) { 177 return {lexLevel, 0}; 178 } 179 return {lexLevel, iter->AsClassScope()->GetSlot(expr)}; 180 } 181 182 if (iter->IsVariableScope()) { 183 if (iter->AsVariableScope()->NeedLexEnv()) { 184 lexLevel++; 185 } 186 } 187 iter = iter->Parent(); 188 } 189 190 UNREACHABLE(); 191} 192 193bool ClassScope::IsVariableScope() const 194{ 195 // sendable class does not need a lexical env, handle it's scope as a non-variable scope 196 return !node_->AsClassDefinition()->IsSendable(); 197} 198 199Result ClassScope::GetPrivateProperty(const util::StringView &name, bool isSetter) const 200{ 201 if (name.Is("#method")) { 202 return {instanceMethodValidation_, false, false, false, false, 0}; 203 } 204 205 uint32_t slot{0}; 206 bool setter{false}; 207 bool getter{false}; 208 209 if (privateNames_.find(name) != privateNames_.end()) { 210 slot = privateNames_.find(name)->second; 211 } else { 212 auto accessor = isSetter ? privateSetters_ : privateGetters_; 213 auto unexpectedAccessor = isSetter ? privateGetters_ : privateSetters_; 214 215 if (accessor.find(name) != accessor.end()) { 216 setter = isSetter; 217 getter = !setter; 218 slot = accessor.find(name)->second; 219 } else { 220 getter = isSetter; 221 setter = !getter; 222 slot = unexpectedAccessor.find(name)->second; 223 } 224 } 225 226 uint32_t validateMethodSlot{0}; 227 228 if (IsMethod(slot)) { 229 validateMethodSlot = IsStaticMethod(slot) ? staticMethodValidation_ : instanceMethodValidation_; 230 } 231 232 return {slot, IsMethod(slot), IsStaticMethod(slot), getter, setter, validateMethodSlot}; 233} 234 235void ClassScope::AddPrivateName(std::vector<const ir::Statement *> privateProperties, uint32_t privateFieldCnt, 236 uint32_t instancePrivateMethodCnt, uint32_t staticPrivateMethodCnt) 237{ 238 privateFieldCnt_ = privateFieldCnt; 239 instancePrivateMethodStartSlot_ = slotIndex_ + privateFieldCnt_; 240 staticPrivateMethodStartSlot_ = instancePrivateMethodStartSlot_ + instancePrivateMethodCnt; 241 uint32_t instancePrivateMethodSlot = instancePrivateMethodStartSlot_; 242 uint32_t staticPrivateMethodSlot = staticPrivateMethodStartSlot_; 243 for (const auto *stmt : privateProperties) { 244 if (stmt->IsClassProperty()) { 245 privateNames_[stmt->AsClassProperty()->Key()->AsPrivateIdentifier()->Name()] = slotIndex_++; 246 continue; 247 } 248 ASSERT(stmt->IsMethodDefinition()); 249 auto *methodDef = stmt->AsMethodDefinition(); 250 uint32_t *start = methodDef->IsStatic() ? &staticPrivateMethodSlot : &instancePrivateMethodSlot; 251 auto name = methodDef->Key()->AsPrivateIdentifier()->Name(); 252 switch (methodDef->Kind()) { 253 case ir::MethodDefinitionKind::GET: { 254 privateGetters_[name] = (*start)++; 255 continue; 256 } 257 case ir::MethodDefinitionKind::SET: { 258 privateSetters_[name] = (*start)++; 259 continue; 260 } 261 default: { 262 privateNames_[name]= (*start)++; 263 continue; 264 } 265 } 266 } 267 slotIndex_ = staticPrivateMethodSlot; 268 privateMethodEndSlot_ = slotIndex_; 269 if (instancePrivateMethodCnt != 0) { 270 instanceMethodValidation_ = slotIndex_++; 271 } 272 273 if (staticPrivateMethodCnt != 0) { 274 staticMethodValidation_ = slotIndex_++; 275 } 276} 277 278util::StringView ClassScope::GetSelfScopeName() 279{ 280 if (hasSelfScopeNameSet_) { 281 return selfScopeName_; 282 } 283 284 std::stringstream scopeName; 285 286 if (node_ && node_->IsClassDefinition() && node_->AsClassDefinition()->Ident()) { 287 util::StringView selfName = node_->AsClassDefinition()->Ident()->Name(); 288 scopeName << selfName; 289 return util::UString(scopeName.str(), allocator_).View(); 290 } 291 // To get the name for anonymous class 292 if (node_ && node_->Parent() && node_->Parent()->Parent()) { 293 scopeName << util::Helpers::GetName(allocator_, node_->Parent()->Parent()); 294 return util::UString(scopeName.str(), allocator_).View(); 295 } 296 297 return util::UString(scopeName.str(), allocator_).View(); 298} 299 300util::StringView ClassScope::GetScopeTag() 301{ 302 return util::UString(util::Helpers::CLASS_SCOPE_TAG.data(), allocator_).View(); 303} 304 305PrivateNameFindResult Scope::FindPrivateName(const util::StringView &name, bool isSetter) const 306{ 307 uint32_t lexLevel = 0; 308 const auto *iter = this; 309 310 while (iter != nullptr) { 311 if (iter->Type() == ScopeType::CLASS) { 312 const auto *classScope = iter->AsClassScope(); 313 if (name.Is("#method") || classScope->HasPrivateName(name)) { 314 return {lexLevel, classScope->GetPrivateProperty(name, isSetter)}; 315 } 316 } 317 318 if (iter->IsVariableScope()) { 319 if (iter->AsVariableScope()->NeedLexEnv()) { 320 lexLevel++; 321 } 322 } 323 iter = iter->Parent(); 324 } 325 326 UNREACHABLE(); 327} 328 329Decl *Scope::FindDecl(const util::StringView &name) const 330{ 331 for (auto *it : decls_) { 332 if (it->Name() == name) { 333 return it; 334 } 335 } 336 337 return nullptr; 338} 339 340bool Scope::HasVarDecl(const util::StringView &name) const 341{ 342 for (auto *it : decls_) { 343 if (it->Name() == name && it->IsVarDecl()) { 344 return true; 345 } 346 } 347 348 return false; 349} 350 351std::tuple<Scope *, bool> Scope::IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor) 352{ 353 auto *iter = this; 354 355 while (true) { 356 auto *v = iter->FindLocal(name); 357 358 if (v && visitor(v)) { 359 return {iter, true}; 360 } 361 362 if (iter->IsFunctionVariableScope()) { 363 break; 364 } 365 366 iter = iter->Parent(); 367 } 368 369 return {iter, false}; 370} 371 372void Scope::SetFullScopeNames() 373{ 374 if (hasFullScopeNameSet_) { 375 return; 376 } 377 hasFullScopeNameSet_ = true; 378 if (!hasSelfScopeNameSet_) { 379 SetSelfScopeName(GetSelfScopeName()); 380 } 381 382 std::stringstream selfScopeStream; 383 OptimizeSelfScopeName(selfScopeStream); 384 std::stringstream fullScopeName; 385 Scope *parent = GetParentWithScopeName(); 386 if (parent) { 387 fullScopeName << parent->GetFullScopeName() << 388 GetScopeTag() << 389 selfScopeStream.str(); 390 if (scopeDuplicateIndex_ > 0) { 391 fullScopeName << util::Helpers::DUPLICATED_SEPERATOR << 392 std::hex << scopeDuplicateIndex_; 393 } 394 } 395 396 fullScopeName_ = util::UString(fullScopeName.str(), allocator_).View(); 397} 398 399void Scope::OptimizeSelfScopeName(std::stringstream &selfScopeStream) 400{ 401 bool useIndex = false; 402 auto it = topScope_->scopeNames_.find(selfScopeName_); 403 if (it == topScope_->scopeNames_.end()) { 404 std::stringstream indexScopeName; 405 indexScopeName << util::Helpers::INDEX_NAME_SPICIFIER << std::hex << topScope_->scopeNames_.size(); 406 if (selfScopeName_.Length() > indexScopeName.str().length()) { 407 topScope_->scopeNames_.insert( 408 {selfScopeName_, (int32_t)topScope_->scopeNames_.size()} 409 ); 410 selfScopeStream << indexScopeName.str(); 411 useIndex = true; 412 } 413 } else { 414 selfScopeStream << util::Helpers::INDEX_NAME_SPICIFIER << std::hex << it->second; 415 useIndex = true; 416 } 417 418 if (!useIndex) { 419 selfScopeStream << selfScopeName_; 420 } 421} 422 423bool Scope::AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 424 [[maybe_unused]] ScriptExtension extension) 425{ 426 VariableFlags flags = VariableFlags::NONE; 427 switch (newDecl->Type()) { 428 case DeclType::VAR: { 429 auto [scope, shadowed] = IterateShadowedVariables( 430 newDecl->Name(), [](const Variable *v) { return !v->HasFlag(VariableFlags::VAR); }); 431 432 if (shadowed) { 433 return false; 434 } 435 436 VariableFlags varFlags = VariableFlags::HOIST_VAR; 437 if (scope->IsGlobalScope()) { 438 scope->Bindings().insert({newDecl->Name(), allocator->New<GlobalVariable>(newDecl, varFlags)}); 439 } else { 440 scope->PropagateBinding<LocalVariable>(allocator, newDecl->Name(), newDecl, varFlags); 441 } 442 443 return true; 444 } 445 case DeclType::ENUM_LITERAL: { 446 return tsBindings_.AddTSVariable<TSBindingType::ENUMLITERAL>( 447 newDecl->Name(), allocator->New<EnumLiteralVariable>(newDecl, VariableFlags::ENUM_LITERAL)); 448 } 449 case DeclType::INTERFACE: { 450 bindings_.insert({newDecl->Name(), allocator->New<LocalVariable>(newDecl, VariableFlags::INTERFACE)}); 451 return true; 452 } 453 case DeclType::FUNC: { 454 flags = VariableFlags::HOIST; 455 [[fallthrough]]; 456 } 457 default: { 458 if (currentVariable) { 459 return false; 460 } 461 462 if (HasVarDecl(newDecl->Name())) { 463 return false; 464 } 465 466 bindings_.insert({newDecl->Name(), allocator->New<LocalVariable>(newDecl, flags)}); 467 return true; 468 } 469 } 470} 471 472bool ParamScope::AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags) 473{ 474 CHECK_NOT_NULL(newDecl); 475 ASSERT(newDecl->IsParameterDecl()); 476 477 if (currentVariable) { 478 return false; 479 } 480 481 auto *param = allocator->New<LocalVariable>(newDecl, flags); 482 483 params_.push_back(param); 484 bindings_.insert({newDecl->Name(), param}); 485 return true; 486} 487 488std::tuple<ParameterDecl *, const ir::AstNode *> ParamScope::AddParamDecl(ArenaAllocator *allocator, 489 const ir::AstNode *param) 490{ 491 const auto [name, pattern] = util::Helpers::ParamName(allocator, param, params_.size()); 492 493 auto *decl = NewDecl<ParameterDecl>(allocator, name); 494 CHECK_NOT_NULL(decl); 495 496 if (!AddParam(allocator, FindLocal(name), decl, VariableFlags::VAR)) { 497 return {decl, param}; 498 } 499 500 if (!pattern) { 501 decl->BindNode(param); 502 return {decl, nullptr}; 503 } 504 505 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(param); 506 507 for (const auto *binding : bindings) { 508 auto *varDecl = NewDecl<VarDecl>(allocator, binding->Name()); 509 CHECK_NOT_NULL(varDecl); 510 varDecl->BindNode(binding); 511 512 if (FindLocal(varDecl->Name())) { 513 return {decl, binding}; 514 } 515 516 auto *paramVar = allocator->New<LocalVariable>(varDecl, VariableFlags::VAR); 517 bindings_.insert({varDecl->Name(), paramVar}); 518 } 519 520 return {decl, nullptr}; 521} 522 523void FunctionParamScope::BindName(ArenaAllocator *allocator, util::StringView name) 524{ 525 nameVar_ = AddDecl<ConstDecl, LocalVariable>(allocator, name, VariableFlags::INITIALIZED); 526 functionScope_->Bindings().insert({name, nameVar_}); 527} 528 529bool FunctionParamScope::AddBinding([[maybe_unused]] ArenaAllocator *allocator, 530 [[maybe_unused]] Variable *currentVariable, [[maybe_unused]] Decl *newDecl, 531 [[maybe_unused]] ScriptExtension extension) 532{ 533 UNREACHABLE(); 534} 535 536const util::StringView &FunctionParamScope::GetFullScopeName() 537{ 538 if (functionScope_) { 539 return functionScope_->GetFullScopeName(); 540 } 541 542 // FunctionParam should have the same name with FunctionScope 543 // Get scope name from parent in case the functionScope_ is nullptr 544 if (parent_) { 545 return parent_->GetFullScopeName(); 546 } 547 548 return fullScopeName_; 549} 550 551uint32_t FunctionParamScope::GetDuplicateScopeIndex(const util::StringView &childScopeName) 552{ 553 if (functionScope_) { 554 return functionScope_->GetDuplicateScopeIndex(childScopeName); 555 } 556 557 if (parent_) { 558 return parent_->GetDuplicateScopeIndex(childScopeName); 559 } 560 561 return 0; 562} 563 564void FunctionScope::BindNameWithScopeInfo(util::StringView name, util::StringView recordName) 565{ 566 name_ = name; 567 std::stringstream internalName; 568 internalName << recordName << util::Helpers::FUNC_NAME_SEPARATOR; 569 570 Scope *parent = GetParentWithScopeName(); 571 if (parent != nullptr) { 572 internalName << parent->GetFullScopeName(); 573 } 574 internalName << GetScopeTag() << util::Helpers::FUNC_NAME_SEPARATOR << GetSelfScopeName(); 575 if (scopeDuplicateIndex_ > 0) { 576 internalName << util::Helpers::DUPLICATED_SEPERATOR << 577 std::hex << scopeDuplicateIndex_; 578 } 579 internalName_ = util::UString(internalName.str(), allocator_).View(); 580} 581 582bool FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 583 [[maybe_unused]] ScriptExtension extension) 584{ 585 switch (newDecl->Type()) { 586 case DeclType::VAR: { 587 return AddVar<LocalVariable>(allocator, currentVariable, newDecl); 588 } 589 case DeclType::FUNC: { 590 return AddFunction<LocalVariable>(allocator, currentVariable, newDecl, extension); 591 } 592 case DeclType::CLASS: { 593 return AddClass<LocalVariable>(allocator, currentVariable, newDecl); 594 } 595 case DeclType::ENUM_LITERAL: { 596 return AddTSBinding<EnumLiteralVariable>(allocator, newDecl, VariableFlags::ENUM_LITERAL); 597 } 598 case DeclType::NAMESPACE: { 599 return AddTSBinding<NamespaceVariable>(allocator, newDecl, VariableFlags::NAMESPACE); 600 } 601 case DeclType::IMPORT_EQUALS: { 602 return AddTSBinding<ImportEqualsVariable>(allocator, newDecl, VariableFlags::IMPORT_EQUALS); 603 } 604 case DeclType::INTERFACE: { 605 return AddTSBinding<LocalVariable>(allocator, currentVariable, newDecl, VariableFlags::INTERFACE); 606 } 607 default: { 608 return AddLexical<LocalVariable>(allocator, currentVariable, newDecl); 609 } 610 } 611} 612 613void FunctionScope::SetSelfScopeName(const util::StringView &ident) 614{ 615 Scope::SetSelfScopeName(ident); 616 paramScope_->selfScopeName_ = selfScopeName_; 617 paramScope_->hasSelfScopeNameSet_ = true; 618 hasSelfScopeNameSet_ = true; 619} 620 621util::StringView FunctionScope::GetScopeTag() 622{ 623 if (IsFunctionScope() && (node_->IsScriptFunction() && node_->AsScriptFunction()->IsConstructor())) { 624 return util::UString(util::Helpers::CTOR_TAG.data(), allocator_).View(); 625 } 626 if (parent_ && parent_->Parent() && parent_->Parent()->IsClassScope()) { 627 bool hasNodeParent = node_ && node_->Parent() && node_->Parent()->Parent(); 628 const ir::AstNode *nodeParent = hasNodeParent ? node_->Parent()->Parent() : nullptr; 629 if (nodeParent && nodeParent->IsMethodDefinition() && nodeParent->AsMethodDefinition()->IsStatic()) { 630 return util::UString(util::Helpers::STATIC_METHOD_TAG.data(), allocator_).View(); 631 } 632 return util::UString(util::Helpers::METHOD_TAG.data(), allocator_).View(); 633 } 634 return util::UString(util::Helpers::FUNCTION_TAG.data(), allocator_).View(); 635} 636 637util::StringView FunctionScope::GetSelfScopeName() 638{ 639 if (hasSelfScopeNameSet_) { 640 return selfScopeName_; 641 } 642 643 if (node_ && node_->IsScriptFunction()) { 644 auto selfName = util::Helpers::FunctionName(allocator_, node_->AsScriptFunction()); 645 if (!util::Helpers::IsSpecialScopeName(selfName)) { 646 return selfName; 647 } 648 } 649 return util::UString(util::Helpers::STRING_EMPTY.data(), allocator_).View(); 650} 651 652util::StringView TSModuleScope::GetSelfScopeName() 653{ 654 if (hasSelfScopeNameSet_) { 655 return selfScopeName_; 656 } 657 throw Error(ErrorType::GENERIC, "namespace or module name should be set in Binder::ResolveReference()"); 658} 659 660util::StringView TSModuleScope::GetScopeTag() 661{ 662 return util::UString(util::Helpers::NAMESPACE_TAG.data(), allocator_).View(); 663} 664 665bool TSEnumScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 666 [[maybe_unused]] ScriptExtension extension) 667{ 668 ASSERT(newDecl->Type() == DeclType::ENUM); 669 return enumMemberBindings_->insert({newDecl->Name(), allocator->New<EnumVariable>(newDecl, false)}).second; 670} 671 672void TSEnumScope::SetSelfScopeName(const util::StringView &ident) 673{ 674 if (!hasSelfScopeNameSet_) { 675 FunctionScope::SetSelfScopeName(GetSelfScopeName()); 676 } 677} 678 679util::StringView TSEnumScope::GetSelfScopeName() 680{ 681 if (hasSelfScopeNameSet_) { 682 return selfScopeName_; 683 } 684 685 std::stringstream scopeName; 686 if (node_ && node_->IsScriptFunction()) { 687 auto scriptFunction = node_->AsScriptFunction(); 688 if (scriptFunction->Params().size() > 0 && scriptFunction->Params()[0]->IsIdentifier()) { 689 scopeName << scriptFunction->Params()[0]->AsIdentifier()->Name(); 690 } 691 } 692 return util::UString(scopeName.str(), allocator_).View(); 693} 694 695util::StringView TSEnumScope::GetScopeTag() 696{ 697 return util::UString(util::Helpers::ENUM_TAG.data(), allocator_).View(); 698} 699 700bool GlobalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 701 [[maybe_unused]] ScriptExtension extension) 702{ 703 switch (newDecl->Type()) { 704 case DeclType::VAR: { 705 return AddVar<GlobalVariable>(allocator, currentVariable, newDecl); 706 } 707 case DeclType::FUNC: { 708 return AddFunction<GlobalVariable>(allocator, currentVariable, newDecl, extension); 709 } 710 case DeclType::CLASS: { 711 return AddClass<LocalVariable>(allocator, currentVariable, newDecl); 712 } 713 case DeclType::ENUM_LITERAL: { 714 return AddTSBinding<EnumLiteralVariable>(allocator, newDecl, VariableFlags::ENUM_LITERAL); 715 } 716 case DeclType::NAMESPACE: { 717 return AddTSBinding<NamespaceVariable>(allocator, newDecl, VariableFlags::NAMESPACE); 718 } 719 case DeclType::IMPORT_EQUALS: { 720 return AddTSBinding<ImportEqualsVariable>(allocator, newDecl, VariableFlags::IMPORT_EQUALS); 721 } 722 case DeclType::INTERFACE: { 723 return AddTSBinding<LocalVariable>(allocator, currentVariable, newDecl, VariableFlags::INTERFACE); 724 } 725 default: { 726 return AddLexical<LocalVariable>(allocator, currentVariable, newDecl); 727 } 728 } 729 730 return true; 731} 732 733void GlobalScope::SetSelfScopeName([[maybe_unused]] const util::StringView &ident) 734{ 735 hasSelfScopeNameSet_ = true; 736} 737 738// ModuleScope 739 740void ModuleScope::ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName) 741{ 742 auto res = bindings_.find(localName); 743 // Since the module's exported [localName] has been validated before, 744 // [localName] must have a binding now. 745 ASSERT(res != bindings_.end()); 746 if (!res->second->IsModuleVariable()) { 747 auto *decl = res->second->Declaration(); 748 decl->AddFlag(DeclarationFlags::EXPORT); 749 VariableFlags flags = res->second->Flags(); 750 res->second = allocator->New<ModuleVariable>(decl, flags | VariableFlags::LOCAL_EXPORT); 751 } 752} 753 754void ModuleScope::AssignIndexToModuleVariable(util::StringView name, uint32_t index) 755{ 756 auto *moduleVar = FindLocal(name); 757 CHECK_NOT_NULL(moduleVar); 758 ASSERT(moduleVar->IsModuleVariable()); 759 moduleVar->AsModuleVariable()->AssignIndex(index); 760} 761 762bool ModuleScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 763 [[maybe_unused]] ScriptExtension extension) 764{ 765 switch (newDecl->Type()) { 766 case DeclType::VAR: { 767 auto [scope, shadowed] = IterateShadowedVariables( 768 newDecl->Name(), [](const Variable *v) { return !v->HasFlag(VariableFlags::VAR); }); 769 770 if (shadowed) { 771 return false; 772 } 773 return newDecl->IsImportOrExportDecl() ? 774 AddVar<ModuleVariable>(allocator, currentVariable, newDecl) : 775 AddVar<LocalVariable>(allocator, currentVariable, newDecl); 776 } 777 case DeclType::FUNC: { 778 if (currentVariable) { 779 auto decl = currentVariable->Declaration(); 780 if (!decl->IsClassDecl() || !decl->AsClassDecl()->IsDeclare()) { 781 return false; 782 } 783 } 784 return newDecl->IsImportOrExportDecl() ? 785 AddFunction<ModuleVariable>(allocator, currentVariable, newDecl, extension) : 786 AddFunction<LocalVariable>(allocator, currentVariable, newDecl, extension); 787 } 788 case DeclType::CLASS: { 789 return newDecl->IsImportOrExportDecl() ? 790 AddClass<ModuleVariable>(allocator, currentVariable, newDecl) : 791 AddClass<LocalVariable>(allocator, currentVariable, newDecl); 792 } 793 case DeclType::ENUM_LITERAL: { 794 return AddTSBinding<EnumLiteralVariable>(allocator, newDecl, VariableFlags::ENUM_LITERAL); 795 } 796 case DeclType::NAMESPACE: { 797 return AddTSBinding<NamespaceVariable>(allocator, newDecl, VariableFlags::NAMESPACE); 798 } 799 case DeclType::IMPORT_EQUALS: { 800 return AddTSBinding<ImportEqualsVariable>(allocator, newDecl, VariableFlags::IMPORT_EQUALS); 801 } 802 case DeclType::INTERFACE: { 803 return AddTSBinding<LocalVariable>(allocator, currentVariable, newDecl, VariableFlags::INTERFACE); 804 } 805 default: { 806 if (currentVariable) { 807 return false; 808 } 809 return newDecl->IsImportOrExportDecl() ? 810 AddLexical<ModuleVariable>(allocator, currentVariable, newDecl) : 811 AddLexical<LocalVariable>(allocator, currentVariable, newDecl); 812 } 813 } 814} 815 816void ModuleScope::SetSelfScopeName([[maybe_unused]] const util::StringView &ident) 817{ 818 hasSelfScopeNameSet_ = true; 819} 820 821// LocalScope 822 823bool LocalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 824 [[maybe_unused]] ScriptExtension extension) 825{ 826 return AddLocal(allocator, currentVariable, newDecl, extension); 827} 828 829void LoopScope::InitVariable() 830{ 831 for (const auto &[name, var] : bindings_) { 832 if (!var->Declaration()->IsLetOrConstOrClassDecl()) { 833 continue; 834 } 835 836 var->AddFlag(VariableFlags::INITIALIZED); 837 if (var->LexicalBound()) { 838 var->AddFlag(VariableFlags::PER_ITERATION); 839 } 840 } 841} 842 843bool CatchParamScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 844 [[maybe_unused]] ScriptExtension extension) 845{ 846 return AddParam(allocator, currentVariable, newDecl, VariableFlags::INITIALIZED); 847} 848 849bool CatchScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 850 [[maybe_unused]] ScriptExtension extension) 851{ 852 if (!newDecl->IsVarDecl() && paramScope_->FindLocal(newDecl->Name())) { 853 return false; 854 } 855 856 return AddLocal(allocator, currentVariable, newDecl, extension); 857} 858} // namespace panda::es2panda::binder 859