13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "scope.h" 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_ci#include <binder/declaration.h> 193af6ab5fSopenharmony_ci#include <util/helpers.h> 203af6ab5fSopenharmony_ci#include <binder/tsBinding.h> 213af6ab5fSopenharmony_ci#include <binder/variable.h> 223af6ab5fSopenharmony_ci#include <binder/variableFlags.h> 233af6ab5fSopenharmony_ci#include <ir/astNode.h> 243af6ab5fSopenharmony_ci#include <ir/base/scriptFunction.h> 253af6ab5fSopenharmony_ci#include <ir/base/classDefinition.h> 263af6ab5fSopenharmony_ci#include <ir/expressions/identifier.h> 273af6ab5fSopenharmony_ci#include <ir/expressions/literals/stringLiteral.h> 283af6ab5fSopenharmony_ci#include <ir/expressions/privateIdentifier.h> 293af6ab5fSopenharmony_ci#include <ir/module/exportAllDeclaration.h> 303af6ab5fSopenharmony_ci#include <ir/module/exportNamedDeclaration.h> 313af6ab5fSopenharmony_ci#include <ir/module/exportSpecifier.h> 323af6ab5fSopenharmony_ci#include <ir/module/importDeclaration.h> 333af6ab5fSopenharmony_ci#include <ir/ts/tsModuleDeclaration.h> 343af6ab5fSopenharmony_ci#include <ir/ts/tsEnumDeclaration.h> 353af6ab5fSopenharmony_ci#include <macros.h> 363af6ab5fSopenharmony_ci#include <util/concurrent.h> 373af6ab5fSopenharmony_ci#include <util/ustring.h> 383af6ab5fSopenharmony_ci 393af6ab5fSopenharmony_ci#include <algorithm> 403af6ab5fSopenharmony_ci#include <sstream> 413af6ab5fSopenharmony_ci 423af6ab5fSopenharmony_cinamespace panda::es2panda::binder { 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_ciVariableScope *Scope::EnclosingVariableScope() 453af6ab5fSopenharmony_ci{ 463af6ab5fSopenharmony_ci Scope *iter = this; 473af6ab5fSopenharmony_ci 483af6ab5fSopenharmony_ci while (iter) { 493af6ab5fSopenharmony_ci if (iter->IsVariableScope()) { 503af6ab5fSopenharmony_ci return iter->AsVariableScope(); 513af6ab5fSopenharmony_ci } 523af6ab5fSopenharmony_ci 533af6ab5fSopenharmony_ci iter = iter->Parent(); 543af6ab5fSopenharmony_ci } 553af6ab5fSopenharmony_ci 563af6ab5fSopenharmony_ci return nullptr; 573af6ab5fSopenharmony_ci} 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_ciFunctionScope *Scope::EnclosingFunctionVariableScope() 603af6ab5fSopenharmony_ci{ 613af6ab5fSopenharmony_ci Scope *iter = this; 623af6ab5fSopenharmony_ci while (iter) { 633af6ab5fSopenharmony_ci if (iter->IsFunctionVariableScope()) { 643af6ab5fSopenharmony_ci return iter->AsFunctionVariableScope(); 653af6ab5fSopenharmony_ci } 663af6ab5fSopenharmony_ci 673af6ab5fSopenharmony_ci iter = iter->Parent(); 683af6ab5fSopenharmony_ci } 693af6ab5fSopenharmony_ci 703af6ab5fSopenharmony_ci return nullptr; 713af6ab5fSopenharmony_ci} 723af6ab5fSopenharmony_ci 733af6ab5fSopenharmony_ciVariable *Scope::FindLocal(const util::StringView &name, ResolveBindingOptions options) const 743af6ab5fSopenharmony_ci{ 753af6ab5fSopenharmony_ci if (options & ResolveBindingOptions::INTERFACES) { 763af6ab5fSopenharmony_ci const std::string &interfaceName = binder::TSBinding::ToTSBinding(name); 773af6ab5fSopenharmony_ci 783af6ab5fSopenharmony_ci auto res = bindings_.find(util::StringView{interfaceName}); 793af6ab5fSopenharmony_ci if (res != bindings_.end()) { 803af6ab5fSopenharmony_ci return res->second; 813af6ab5fSopenharmony_ci } 823af6ab5fSopenharmony_ci 833af6ab5fSopenharmony_ci if (!(options & ResolveBindingOptions::BINDINGS)) { 843af6ab5fSopenharmony_ci return nullptr; 853af6ab5fSopenharmony_ci } 863af6ab5fSopenharmony_ci } 873af6ab5fSopenharmony_ci 883af6ab5fSopenharmony_ci auto res = bindings_.find(name); 893af6ab5fSopenharmony_ci if (res == bindings_.end()) { 903af6ab5fSopenharmony_ci return nullptr; 913af6ab5fSopenharmony_ci } 923af6ab5fSopenharmony_ci 933af6ab5fSopenharmony_ci return res->second; 943af6ab5fSopenharmony_ci} 953af6ab5fSopenharmony_ci 963af6ab5fSopenharmony_civoid Scope::CalculateLevelInCorrespondingFunctionScope(const FunctionParamScope *scope, uint32_t &lexLevel, 973af6ab5fSopenharmony_ci uint32_t &sendableLevel) const 983af6ab5fSopenharmony_ci{ 993af6ab5fSopenharmony_ci auto *funcVariableScope = scope->GetFunctionScope(); 1003af6ab5fSopenharmony_ci // we may only have function param scope without function scope in TS here 1013af6ab5fSopenharmony_ci if (funcVariableScope == nullptr) { 1023af6ab5fSopenharmony_ci return; 1033af6ab5fSopenharmony_ci } 1043af6ab5fSopenharmony_ci 1053af6ab5fSopenharmony_ci if (funcVariableScope->NeedLexEnv()) { 1063af6ab5fSopenharmony_ci lexLevel++; 1073af6ab5fSopenharmony_ci } 1083af6ab5fSopenharmony_ci 1093af6ab5fSopenharmony_ci if (funcVariableScope->NeedSendableEnv()) { 1103af6ab5fSopenharmony_ci sendableLevel++; 1113af6ab5fSopenharmony_ci } 1123af6ab5fSopenharmony_ci} 1133af6ab5fSopenharmony_ci 1143af6ab5fSopenharmony_ciScopeFindResult Scope::Find(const util::StringView &name, ResolveBindingOptions options) const 1153af6ab5fSopenharmony_ci{ 1163af6ab5fSopenharmony_ci uint32_t level = 0; 1173af6ab5fSopenharmony_ci uint32_t lexLevel = 0; 1183af6ab5fSopenharmony_ci uint32_t sendableLevel = 0; 1193af6ab5fSopenharmony_ci const auto *iter = this; 1203af6ab5fSopenharmony_ci ir::ScriptFunction *concurrentFunc = nullptr; 1213af6ab5fSopenharmony_ci // If the first scope is functionParamScope, it means its corresponding functionScope is not 1223af6ab5fSopenharmony_ci // iterated. so by default we set prevScopeNotFunctionScope as true so under such case, 1233af6ab5fSopenharmony_ci // functionScopeNotIterated will be true. 1243af6ab5fSopenharmony_ci bool prevScopeNotFunctionScope = true; 1253af6ab5fSopenharmony_ci bool lexical = false; 1263af6ab5fSopenharmony_ci 1273af6ab5fSopenharmony_ci while (iter != nullptr) { 1283af6ab5fSopenharmony_ci bool functionScopeNotIterated = iter->IsFunctionParamScope() && prevScopeNotFunctionScope; 1293af6ab5fSopenharmony_ci Variable *v = iter->FindLocal(name, options); 1303af6ab5fSopenharmony_ci 1313af6ab5fSopenharmony_ci if (v != nullptr) { 1323af6ab5fSopenharmony_ci return {name, const_cast<Scope *>(iter), level, lexLevel, sendableLevel, v, concurrentFunc}; 1333af6ab5fSopenharmony_ci } 1343af6ab5fSopenharmony_ci 1353af6ab5fSopenharmony_ci if (iter->IsFunctionVariableScope() && !lexical) { 1363af6ab5fSopenharmony_ci lexical = true; 1373af6ab5fSopenharmony_ci } 1383af6ab5fSopenharmony_ci 1393af6ab5fSopenharmony_ci if (iter->IsFunctionScope() && !concurrentFunc) { 1403af6ab5fSopenharmony_ci if (iter->Node()->AsScriptFunction()->IsConcurrent()) { 1413af6ab5fSopenharmony_ci concurrentFunc = const_cast<ir::ScriptFunction *>(iter->Node()->AsScriptFunction()); 1423af6ab5fSopenharmony_ci } 1433af6ab5fSopenharmony_ci } 1443af6ab5fSopenharmony_ci 1453af6ab5fSopenharmony_ci if (iter->IsVariableScope()) { 1463af6ab5fSopenharmony_ci if (lexical) { 1473af6ab5fSopenharmony_ci level++; 1483af6ab5fSopenharmony_ci } 1493af6ab5fSopenharmony_ci 1503af6ab5fSopenharmony_ci if (iter->AsVariableScope()->NeedLexEnv()) { 1513af6ab5fSopenharmony_ci lexLevel++; 1523af6ab5fSopenharmony_ci } 1533af6ab5fSopenharmony_ci 1543af6ab5fSopenharmony_ci if (iter->AsVariableScope()->NeedSendableEnv()) { 1553af6ab5fSopenharmony_ci sendableLevel++; 1563af6ab5fSopenharmony_ci } 1573af6ab5fSopenharmony_ci } else if (functionScopeNotIterated) { 1583af6ab5fSopenharmony_ci level++; 1593af6ab5fSopenharmony_ci CalculateLevelInCorrespondingFunctionScope(iter->AsFunctionParamScope(), lexLevel, sendableLevel); 1603af6ab5fSopenharmony_ci } 1613af6ab5fSopenharmony_ci 1623af6ab5fSopenharmony_ci prevScopeNotFunctionScope = !iter->IsFunctionVariableScope(); 1633af6ab5fSopenharmony_ci iter = iter->Parent(); 1643af6ab5fSopenharmony_ci } 1653af6ab5fSopenharmony_ci 1663af6ab5fSopenharmony_ci return {name, nullptr, 0, 0, 0, nullptr, concurrentFunc}; 1673af6ab5fSopenharmony_ci} 1683af6ab5fSopenharmony_ci 1693af6ab5fSopenharmony_cistd::pair<uint32_t, uint32_t> Scope::Find(const ir::Expression *expr, bool onlyLevel) const 1703af6ab5fSopenharmony_ci{ 1713af6ab5fSopenharmony_ci uint32_t lexLevel = 0; 1723af6ab5fSopenharmony_ci const auto *iter = this; 1733af6ab5fSopenharmony_ci 1743af6ab5fSopenharmony_ci while (iter != nullptr) { 1753af6ab5fSopenharmony_ci if (iter->Type() == ScopeType::CLASS) { 1763af6ab5fSopenharmony_ci if (onlyLevel) { 1773af6ab5fSopenharmony_ci return {lexLevel, 0}; 1783af6ab5fSopenharmony_ci } 1793af6ab5fSopenharmony_ci return {lexLevel, iter->AsClassScope()->GetSlot(expr)}; 1803af6ab5fSopenharmony_ci } 1813af6ab5fSopenharmony_ci 1823af6ab5fSopenharmony_ci if (iter->IsVariableScope()) { 1833af6ab5fSopenharmony_ci if (iter->AsVariableScope()->NeedLexEnv()) { 1843af6ab5fSopenharmony_ci lexLevel++; 1853af6ab5fSopenharmony_ci } 1863af6ab5fSopenharmony_ci } 1873af6ab5fSopenharmony_ci iter = iter->Parent(); 1883af6ab5fSopenharmony_ci } 1893af6ab5fSopenharmony_ci 1903af6ab5fSopenharmony_ci UNREACHABLE(); 1913af6ab5fSopenharmony_ci} 1923af6ab5fSopenharmony_ci 1933af6ab5fSopenharmony_cibool ClassScope::IsVariableScope() const 1943af6ab5fSopenharmony_ci{ 1953af6ab5fSopenharmony_ci // sendable class does not need a lexical env, handle it's scope as a non-variable scope 1963af6ab5fSopenharmony_ci return !node_->AsClassDefinition()->IsSendable(); 1973af6ab5fSopenharmony_ci} 1983af6ab5fSopenharmony_ci 1993af6ab5fSopenharmony_ciResult ClassScope::GetPrivateProperty(const util::StringView &name, bool isSetter) const 2003af6ab5fSopenharmony_ci{ 2013af6ab5fSopenharmony_ci if (name.Is("#method")) { 2023af6ab5fSopenharmony_ci return {instanceMethodValidation_, false, false, false, false, 0}; 2033af6ab5fSopenharmony_ci } 2043af6ab5fSopenharmony_ci 2053af6ab5fSopenharmony_ci uint32_t slot{0}; 2063af6ab5fSopenharmony_ci bool setter{false}; 2073af6ab5fSopenharmony_ci bool getter{false}; 2083af6ab5fSopenharmony_ci 2093af6ab5fSopenharmony_ci if (privateNames_.find(name) != privateNames_.end()) { 2103af6ab5fSopenharmony_ci slot = privateNames_.find(name)->second; 2113af6ab5fSopenharmony_ci } else { 2123af6ab5fSopenharmony_ci auto accessor = isSetter ? privateSetters_ : privateGetters_; 2133af6ab5fSopenharmony_ci auto unexpectedAccessor = isSetter ? privateGetters_ : privateSetters_; 2143af6ab5fSopenharmony_ci 2153af6ab5fSopenharmony_ci if (accessor.find(name) != accessor.end()) { 2163af6ab5fSopenharmony_ci setter = isSetter; 2173af6ab5fSopenharmony_ci getter = !setter; 2183af6ab5fSopenharmony_ci slot = accessor.find(name)->second; 2193af6ab5fSopenharmony_ci } else { 2203af6ab5fSopenharmony_ci getter = isSetter; 2213af6ab5fSopenharmony_ci setter = !getter; 2223af6ab5fSopenharmony_ci slot = unexpectedAccessor.find(name)->second; 2233af6ab5fSopenharmony_ci } 2243af6ab5fSopenharmony_ci } 2253af6ab5fSopenharmony_ci 2263af6ab5fSopenharmony_ci uint32_t validateMethodSlot{0}; 2273af6ab5fSopenharmony_ci 2283af6ab5fSopenharmony_ci if (IsMethod(slot)) { 2293af6ab5fSopenharmony_ci validateMethodSlot = IsStaticMethod(slot) ? staticMethodValidation_ : instanceMethodValidation_; 2303af6ab5fSopenharmony_ci } 2313af6ab5fSopenharmony_ci 2323af6ab5fSopenharmony_ci return {slot, IsMethod(slot), IsStaticMethod(slot), getter, setter, validateMethodSlot}; 2333af6ab5fSopenharmony_ci} 2343af6ab5fSopenharmony_ci 2353af6ab5fSopenharmony_civoid ClassScope::AddPrivateName(std::vector<const ir::Statement *> privateProperties, uint32_t privateFieldCnt, 2363af6ab5fSopenharmony_ci uint32_t instancePrivateMethodCnt, uint32_t staticPrivateMethodCnt) 2373af6ab5fSopenharmony_ci{ 2383af6ab5fSopenharmony_ci privateFieldCnt_ = privateFieldCnt; 2393af6ab5fSopenharmony_ci instancePrivateMethodStartSlot_ = slotIndex_ + privateFieldCnt_; 2403af6ab5fSopenharmony_ci staticPrivateMethodStartSlot_ = instancePrivateMethodStartSlot_ + instancePrivateMethodCnt; 2413af6ab5fSopenharmony_ci uint32_t instancePrivateMethodSlot = instancePrivateMethodStartSlot_; 2423af6ab5fSopenharmony_ci uint32_t staticPrivateMethodSlot = staticPrivateMethodStartSlot_; 2433af6ab5fSopenharmony_ci for (const auto *stmt : privateProperties) { 2443af6ab5fSopenharmony_ci if (stmt->IsClassProperty()) { 2453af6ab5fSopenharmony_ci privateNames_[stmt->AsClassProperty()->Key()->AsPrivateIdentifier()->Name()] = slotIndex_++; 2463af6ab5fSopenharmony_ci continue; 2473af6ab5fSopenharmony_ci } 2483af6ab5fSopenharmony_ci ASSERT(stmt->IsMethodDefinition()); 2493af6ab5fSopenharmony_ci auto *methodDef = stmt->AsMethodDefinition(); 2503af6ab5fSopenharmony_ci uint32_t *start = methodDef->IsStatic() ? &staticPrivateMethodSlot : &instancePrivateMethodSlot; 2513af6ab5fSopenharmony_ci auto name = methodDef->Key()->AsPrivateIdentifier()->Name(); 2523af6ab5fSopenharmony_ci switch (methodDef->Kind()) { 2533af6ab5fSopenharmony_ci case ir::MethodDefinitionKind::GET: { 2543af6ab5fSopenharmony_ci privateGetters_[name] = (*start)++; 2553af6ab5fSopenharmony_ci continue; 2563af6ab5fSopenharmony_ci } 2573af6ab5fSopenharmony_ci case ir::MethodDefinitionKind::SET: { 2583af6ab5fSopenharmony_ci privateSetters_[name] = (*start)++; 2593af6ab5fSopenharmony_ci continue; 2603af6ab5fSopenharmony_ci } 2613af6ab5fSopenharmony_ci default: { 2623af6ab5fSopenharmony_ci privateNames_[name]= (*start)++; 2633af6ab5fSopenharmony_ci continue; 2643af6ab5fSopenharmony_ci } 2653af6ab5fSopenharmony_ci } 2663af6ab5fSopenharmony_ci } 2673af6ab5fSopenharmony_ci slotIndex_ = staticPrivateMethodSlot; 2683af6ab5fSopenharmony_ci privateMethodEndSlot_ = slotIndex_; 2693af6ab5fSopenharmony_ci if (instancePrivateMethodCnt != 0) { 2703af6ab5fSopenharmony_ci instanceMethodValidation_ = slotIndex_++; 2713af6ab5fSopenharmony_ci } 2723af6ab5fSopenharmony_ci 2733af6ab5fSopenharmony_ci if (staticPrivateMethodCnt != 0) { 2743af6ab5fSopenharmony_ci staticMethodValidation_ = slotIndex_++; 2753af6ab5fSopenharmony_ci } 2763af6ab5fSopenharmony_ci} 2773af6ab5fSopenharmony_ci 2783af6ab5fSopenharmony_ciutil::StringView ClassScope::GetSelfScopeName() 2793af6ab5fSopenharmony_ci{ 2803af6ab5fSopenharmony_ci if (hasSelfScopeNameSet_) { 2813af6ab5fSopenharmony_ci return selfScopeName_; 2823af6ab5fSopenharmony_ci } 2833af6ab5fSopenharmony_ci 2843af6ab5fSopenharmony_ci std::stringstream scopeName; 2853af6ab5fSopenharmony_ci 2863af6ab5fSopenharmony_ci if (node_ && node_->IsClassDefinition() && node_->AsClassDefinition()->Ident()) { 2873af6ab5fSopenharmony_ci util::StringView selfName = node_->AsClassDefinition()->Ident()->Name(); 2883af6ab5fSopenharmony_ci scopeName << selfName; 2893af6ab5fSopenharmony_ci return util::UString(scopeName.str(), allocator_).View(); 2903af6ab5fSopenharmony_ci } 2913af6ab5fSopenharmony_ci // To get the name for anonymous class 2923af6ab5fSopenharmony_ci if (node_ && node_->Parent() && node_->Parent()->Parent()) { 2933af6ab5fSopenharmony_ci scopeName << util::Helpers::GetName(allocator_, node_->Parent()->Parent()); 2943af6ab5fSopenharmony_ci return util::UString(scopeName.str(), allocator_).View(); 2953af6ab5fSopenharmony_ci } 2963af6ab5fSopenharmony_ci 2973af6ab5fSopenharmony_ci return util::UString(scopeName.str(), allocator_).View(); 2983af6ab5fSopenharmony_ci} 2993af6ab5fSopenharmony_ci 3003af6ab5fSopenharmony_ciutil::StringView ClassScope::GetScopeTag() 3013af6ab5fSopenharmony_ci{ 3023af6ab5fSopenharmony_ci return util::UString(util::Helpers::CLASS_SCOPE_TAG.data(), allocator_).View(); 3033af6ab5fSopenharmony_ci} 3043af6ab5fSopenharmony_ci 3053af6ab5fSopenharmony_ciPrivateNameFindResult Scope::FindPrivateName(const util::StringView &name, bool isSetter) const 3063af6ab5fSopenharmony_ci{ 3073af6ab5fSopenharmony_ci uint32_t lexLevel = 0; 3083af6ab5fSopenharmony_ci const auto *iter = this; 3093af6ab5fSopenharmony_ci 3103af6ab5fSopenharmony_ci while (iter != nullptr) { 3113af6ab5fSopenharmony_ci if (iter->Type() == ScopeType::CLASS) { 3123af6ab5fSopenharmony_ci const auto *classScope = iter->AsClassScope(); 3133af6ab5fSopenharmony_ci if (name.Is("#method") || classScope->HasPrivateName(name)) { 3143af6ab5fSopenharmony_ci return {lexLevel, classScope->GetPrivateProperty(name, isSetter)}; 3153af6ab5fSopenharmony_ci } 3163af6ab5fSopenharmony_ci } 3173af6ab5fSopenharmony_ci 3183af6ab5fSopenharmony_ci if (iter->IsVariableScope()) { 3193af6ab5fSopenharmony_ci if (iter->AsVariableScope()->NeedLexEnv()) { 3203af6ab5fSopenharmony_ci lexLevel++; 3213af6ab5fSopenharmony_ci } 3223af6ab5fSopenharmony_ci } 3233af6ab5fSopenharmony_ci iter = iter->Parent(); 3243af6ab5fSopenharmony_ci } 3253af6ab5fSopenharmony_ci 3263af6ab5fSopenharmony_ci UNREACHABLE(); 3273af6ab5fSopenharmony_ci} 3283af6ab5fSopenharmony_ci 3293af6ab5fSopenharmony_ciDecl *Scope::FindDecl(const util::StringView &name) const 3303af6ab5fSopenharmony_ci{ 3313af6ab5fSopenharmony_ci for (auto *it : decls_) { 3323af6ab5fSopenharmony_ci if (it->Name() == name) { 3333af6ab5fSopenharmony_ci return it; 3343af6ab5fSopenharmony_ci } 3353af6ab5fSopenharmony_ci } 3363af6ab5fSopenharmony_ci 3373af6ab5fSopenharmony_ci return nullptr; 3383af6ab5fSopenharmony_ci} 3393af6ab5fSopenharmony_ci 3403af6ab5fSopenharmony_cibool Scope::HasVarDecl(const util::StringView &name) const 3413af6ab5fSopenharmony_ci{ 3423af6ab5fSopenharmony_ci for (auto *it : decls_) { 3433af6ab5fSopenharmony_ci if (it->Name() == name && it->IsVarDecl()) { 3443af6ab5fSopenharmony_ci return true; 3453af6ab5fSopenharmony_ci } 3463af6ab5fSopenharmony_ci } 3473af6ab5fSopenharmony_ci 3483af6ab5fSopenharmony_ci return false; 3493af6ab5fSopenharmony_ci} 3503af6ab5fSopenharmony_ci 3513af6ab5fSopenharmony_cistd::tuple<Scope *, bool> Scope::IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor) 3523af6ab5fSopenharmony_ci{ 3533af6ab5fSopenharmony_ci auto *iter = this; 3543af6ab5fSopenharmony_ci 3553af6ab5fSopenharmony_ci while (true) { 3563af6ab5fSopenharmony_ci auto *v = iter->FindLocal(name); 3573af6ab5fSopenharmony_ci 3583af6ab5fSopenharmony_ci if (v && visitor(v)) { 3593af6ab5fSopenharmony_ci return {iter, true}; 3603af6ab5fSopenharmony_ci } 3613af6ab5fSopenharmony_ci 3623af6ab5fSopenharmony_ci if (iter->IsFunctionVariableScope()) { 3633af6ab5fSopenharmony_ci break; 3643af6ab5fSopenharmony_ci } 3653af6ab5fSopenharmony_ci 3663af6ab5fSopenharmony_ci iter = iter->Parent(); 3673af6ab5fSopenharmony_ci } 3683af6ab5fSopenharmony_ci 3693af6ab5fSopenharmony_ci return {iter, false}; 3703af6ab5fSopenharmony_ci} 3713af6ab5fSopenharmony_ci 3723af6ab5fSopenharmony_civoid Scope::SetFullScopeNames() 3733af6ab5fSopenharmony_ci{ 3743af6ab5fSopenharmony_ci if (hasFullScopeNameSet_) { 3753af6ab5fSopenharmony_ci return; 3763af6ab5fSopenharmony_ci } 3773af6ab5fSopenharmony_ci hasFullScopeNameSet_ = true; 3783af6ab5fSopenharmony_ci if (!hasSelfScopeNameSet_) { 3793af6ab5fSopenharmony_ci SetSelfScopeName(GetSelfScopeName()); 3803af6ab5fSopenharmony_ci } 3813af6ab5fSopenharmony_ci 3823af6ab5fSopenharmony_ci std::stringstream selfScopeStream; 3833af6ab5fSopenharmony_ci OptimizeSelfScopeName(selfScopeStream); 3843af6ab5fSopenharmony_ci std::stringstream fullScopeName; 3853af6ab5fSopenharmony_ci Scope *parent = GetParentWithScopeName(); 3863af6ab5fSopenharmony_ci if (parent) { 3873af6ab5fSopenharmony_ci fullScopeName << parent->GetFullScopeName() << 3883af6ab5fSopenharmony_ci GetScopeTag() << 3893af6ab5fSopenharmony_ci selfScopeStream.str(); 3903af6ab5fSopenharmony_ci if (scopeDuplicateIndex_ > 0) { 3913af6ab5fSopenharmony_ci fullScopeName << util::Helpers::DUPLICATED_SEPERATOR << 3923af6ab5fSopenharmony_ci std::hex << scopeDuplicateIndex_; 3933af6ab5fSopenharmony_ci } 3943af6ab5fSopenharmony_ci } 3953af6ab5fSopenharmony_ci 3963af6ab5fSopenharmony_ci fullScopeName_ = util::UString(fullScopeName.str(), allocator_).View(); 3973af6ab5fSopenharmony_ci} 3983af6ab5fSopenharmony_ci 3993af6ab5fSopenharmony_civoid Scope::OptimizeSelfScopeName(std::stringstream &selfScopeStream) 4003af6ab5fSopenharmony_ci{ 4013af6ab5fSopenharmony_ci bool useIndex = false; 4023af6ab5fSopenharmony_ci auto it = topScope_->scopeNames_.find(selfScopeName_); 4033af6ab5fSopenharmony_ci if (it == topScope_->scopeNames_.end()) { 4043af6ab5fSopenharmony_ci std::stringstream indexScopeName; 4053af6ab5fSopenharmony_ci indexScopeName << util::Helpers::INDEX_NAME_SPICIFIER << std::hex << topScope_->scopeNames_.size(); 4063af6ab5fSopenharmony_ci if (selfScopeName_.Length() > indexScopeName.str().length()) { 4073af6ab5fSopenharmony_ci topScope_->scopeNames_.insert( 4083af6ab5fSopenharmony_ci {selfScopeName_, (int32_t)topScope_->scopeNames_.size()} 4093af6ab5fSopenharmony_ci ); 4103af6ab5fSopenharmony_ci selfScopeStream << indexScopeName.str(); 4113af6ab5fSopenharmony_ci useIndex = true; 4123af6ab5fSopenharmony_ci } 4133af6ab5fSopenharmony_ci } else { 4143af6ab5fSopenharmony_ci selfScopeStream << util::Helpers::INDEX_NAME_SPICIFIER << std::hex << it->second; 4153af6ab5fSopenharmony_ci useIndex = true; 4163af6ab5fSopenharmony_ci } 4173af6ab5fSopenharmony_ci 4183af6ab5fSopenharmony_ci if (!useIndex) { 4193af6ab5fSopenharmony_ci selfScopeStream << selfScopeName_; 4203af6ab5fSopenharmony_ci } 4213af6ab5fSopenharmony_ci} 4223af6ab5fSopenharmony_ci 4233af6ab5fSopenharmony_cibool Scope::AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 4243af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 4253af6ab5fSopenharmony_ci{ 4263af6ab5fSopenharmony_ci VariableFlags flags = VariableFlags::NONE; 4273af6ab5fSopenharmony_ci switch (newDecl->Type()) { 4283af6ab5fSopenharmony_ci case DeclType::VAR: { 4293af6ab5fSopenharmony_ci auto [scope, shadowed] = IterateShadowedVariables( 4303af6ab5fSopenharmony_ci newDecl->Name(), [](const Variable *v) { return !v->HasFlag(VariableFlags::VAR); }); 4313af6ab5fSopenharmony_ci 4323af6ab5fSopenharmony_ci if (shadowed) { 4333af6ab5fSopenharmony_ci return false; 4343af6ab5fSopenharmony_ci } 4353af6ab5fSopenharmony_ci 4363af6ab5fSopenharmony_ci VariableFlags varFlags = VariableFlags::HOIST_VAR; 4373af6ab5fSopenharmony_ci if (scope->IsGlobalScope()) { 4383af6ab5fSopenharmony_ci scope->Bindings().insert({newDecl->Name(), allocator->New<GlobalVariable>(newDecl, varFlags)}); 4393af6ab5fSopenharmony_ci } else { 4403af6ab5fSopenharmony_ci scope->PropagateBinding<LocalVariable>(allocator, newDecl->Name(), newDecl, varFlags); 4413af6ab5fSopenharmony_ci } 4423af6ab5fSopenharmony_ci 4433af6ab5fSopenharmony_ci return true; 4443af6ab5fSopenharmony_ci } 4453af6ab5fSopenharmony_ci case DeclType::ENUM_LITERAL: { 4463af6ab5fSopenharmony_ci return tsBindings_.AddTSVariable<TSBindingType::ENUMLITERAL>( 4473af6ab5fSopenharmony_ci newDecl->Name(), allocator->New<EnumLiteralVariable>(newDecl, VariableFlags::ENUM_LITERAL)); 4483af6ab5fSopenharmony_ci } 4493af6ab5fSopenharmony_ci case DeclType::INTERFACE: { 4503af6ab5fSopenharmony_ci bindings_.insert({newDecl->Name(), allocator->New<LocalVariable>(newDecl, VariableFlags::INTERFACE)}); 4513af6ab5fSopenharmony_ci return true; 4523af6ab5fSopenharmony_ci } 4533af6ab5fSopenharmony_ci case DeclType::FUNC: { 4543af6ab5fSopenharmony_ci flags = VariableFlags::HOIST; 4553af6ab5fSopenharmony_ci [[fallthrough]]; 4563af6ab5fSopenharmony_ci } 4573af6ab5fSopenharmony_ci default: { 4583af6ab5fSopenharmony_ci if (currentVariable) { 4593af6ab5fSopenharmony_ci return false; 4603af6ab5fSopenharmony_ci } 4613af6ab5fSopenharmony_ci 4623af6ab5fSopenharmony_ci if (HasVarDecl(newDecl->Name())) { 4633af6ab5fSopenharmony_ci return false; 4643af6ab5fSopenharmony_ci } 4653af6ab5fSopenharmony_ci 4663af6ab5fSopenharmony_ci bindings_.insert({newDecl->Name(), allocator->New<LocalVariable>(newDecl, flags)}); 4673af6ab5fSopenharmony_ci return true; 4683af6ab5fSopenharmony_ci } 4693af6ab5fSopenharmony_ci } 4703af6ab5fSopenharmony_ci} 4713af6ab5fSopenharmony_ci 4723af6ab5fSopenharmony_cibool ParamScope::AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags) 4733af6ab5fSopenharmony_ci{ 4743af6ab5fSopenharmony_ci CHECK_NOT_NULL(newDecl); 4753af6ab5fSopenharmony_ci ASSERT(newDecl->IsParameterDecl()); 4763af6ab5fSopenharmony_ci 4773af6ab5fSopenharmony_ci if (currentVariable) { 4783af6ab5fSopenharmony_ci return false; 4793af6ab5fSopenharmony_ci } 4803af6ab5fSopenharmony_ci 4813af6ab5fSopenharmony_ci auto *param = allocator->New<LocalVariable>(newDecl, flags); 4823af6ab5fSopenharmony_ci 4833af6ab5fSopenharmony_ci params_.push_back(param); 4843af6ab5fSopenharmony_ci bindings_.insert({newDecl->Name(), param}); 4853af6ab5fSopenharmony_ci return true; 4863af6ab5fSopenharmony_ci} 4873af6ab5fSopenharmony_ci 4883af6ab5fSopenharmony_cistd::tuple<ParameterDecl *, const ir::AstNode *> ParamScope::AddParamDecl(ArenaAllocator *allocator, 4893af6ab5fSopenharmony_ci const ir::AstNode *param) 4903af6ab5fSopenharmony_ci{ 4913af6ab5fSopenharmony_ci const auto [name, pattern] = util::Helpers::ParamName(allocator, param, params_.size()); 4923af6ab5fSopenharmony_ci 4933af6ab5fSopenharmony_ci auto *decl = NewDecl<ParameterDecl>(allocator, name); 4943af6ab5fSopenharmony_ci CHECK_NOT_NULL(decl); 4953af6ab5fSopenharmony_ci 4963af6ab5fSopenharmony_ci if (!AddParam(allocator, FindLocal(name), decl, VariableFlags::VAR)) { 4973af6ab5fSopenharmony_ci return {decl, param}; 4983af6ab5fSopenharmony_ci } 4993af6ab5fSopenharmony_ci 5003af6ab5fSopenharmony_ci if (!pattern) { 5013af6ab5fSopenharmony_ci decl->BindNode(param); 5023af6ab5fSopenharmony_ci return {decl, nullptr}; 5033af6ab5fSopenharmony_ci } 5043af6ab5fSopenharmony_ci 5053af6ab5fSopenharmony_ci std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(param); 5063af6ab5fSopenharmony_ci 5073af6ab5fSopenharmony_ci for (const auto *binding : bindings) { 5083af6ab5fSopenharmony_ci auto *varDecl = NewDecl<VarDecl>(allocator, binding->Name()); 5093af6ab5fSopenharmony_ci CHECK_NOT_NULL(varDecl); 5103af6ab5fSopenharmony_ci varDecl->BindNode(binding); 5113af6ab5fSopenharmony_ci 5123af6ab5fSopenharmony_ci if (FindLocal(varDecl->Name())) { 5133af6ab5fSopenharmony_ci return {decl, binding}; 5143af6ab5fSopenharmony_ci } 5153af6ab5fSopenharmony_ci 5163af6ab5fSopenharmony_ci auto *paramVar = allocator->New<LocalVariable>(varDecl, VariableFlags::VAR); 5173af6ab5fSopenharmony_ci bindings_.insert({varDecl->Name(), paramVar}); 5183af6ab5fSopenharmony_ci } 5193af6ab5fSopenharmony_ci 5203af6ab5fSopenharmony_ci return {decl, nullptr}; 5213af6ab5fSopenharmony_ci} 5223af6ab5fSopenharmony_ci 5233af6ab5fSopenharmony_civoid FunctionParamScope::BindName(ArenaAllocator *allocator, util::StringView name) 5243af6ab5fSopenharmony_ci{ 5253af6ab5fSopenharmony_ci nameVar_ = AddDecl<ConstDecl, LocalVariable>(allocator, name, VariableFlags::INITIALIZED); 5263af6ab5fSopenharmony_ci functionScope_->Bindings().insert({name, nameVar_}); 5273af6ab5fSopenharmony_ci} 5283af6ab5fSopenharmony_ci 5293af6ab5fSopenharmony_cibool FunctionParamScope::AddBinding([[maybe_unused]] ArenaAllocator *allocator, 5303af6ab5fSopenharmony_ci [[maybe_unused]] Variable *currentVariable, [[maybe_unused]] Decl *newDecl, 5313af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 5323af6ab5fSopenharmony_ci{ 5333af6ab5fSopenharmony_ci UNREACHABLE(); 5343af6ab5fSopenharmony_ci} 5353af6ab5fSopenharmony_ci 5363af6ab5fSopenharmony_ciconst util::StringView &FunctionParamScope::GetFullScopeName() 5373af6ab5fSopenharmony_ci{ 5383af6ab5fSopenharmony_ci if (functionScope_) { 5393af6ab5fSopenharmony_ci return functionScope_->GetFullScopeName(); 5403af6ab5fSopenharmony_ci } 5413af6ab5fSopenharmony_ci 5423af6ab5fSopenharmony_ci // FunctionParam should have the same name with FunctionScope 5433af6ab5fSopenharmony_ci // Get scope name from parent in case the functionScope_ is nullptr 5443af6ab5fSopenharmony_ci if (parent_) { 5453af6ab5fSopenharmony_ci return parent_->GetFullScopeName(); 5463af6ab5fSopenharmony_ci } 5473af6ab5fSopenharmony_ci 5483af6ab5fSopenharmony_ci return fullScopeName_; 5493af6ab5fSopenharmony_ci} 5503af6ab5fSopenharmony_ci 5513af6ab5fSopenharmony_ciuint32_t FunctionParamScope::GetDuplicateScopeIndex(const util::StringView &childScopeName) 5523af6ab5fSopenharmony_ci{ 5533af6ab5fSopenharmony_ci if (functionScope_) { 5543af6ab5fSopenharmony_ci return functionScope_->GetDuplicateScopeIndex(childScopeName); 5553af6ab5fSopenharmony_ci } 5563af6ab5fSopenharmony_ci 5573af6ab5fSopenharmony_ci if (parent_) { 5583af6ab5fSopenharmony_ci return parent_->GetDuplicateScopeIndex(childScopeName); 5593af6ab5fSopenharmony_ci } 5603af6ab5fSopenharmony_ci 5613af6ab5fSopenharmony_ci return 0; 5623af6ab5fSopenharmony_ci} 5633af6ab5fSopenharmony_ci 5643af6ab5fSopenharmony_civoid FunctionScope::BindNameWithScopeInfo(util::StringView name, util::StringView recordName) 5653af6ab5fSopenharmony_ci{ 5663af6ab5fSopenharmony_ci name_ = name; 5673af6ab5fSopenharmony_ci std::stringstream internalName; 5683af6ab5fSopenharmony_ci internalName << recordName << util::Helpers::FUNC_NAME_SEPARATOR; 5693af6ab5fSopenharmony_ci 5703af6ab5fSopenharmony_ci Scope *parent = GetParentWithScopeName(); 5713af6ab5fSopenharmony_ci if (parent != nullptr) { 5723af6ab5fSopenharmony_ci internalName << parent->GetFullScopeName(); 5733af6ab5fSopenharmony_ci } 5743af6ab5fSopenharmony_ci internalName << GetScopeTag() << util::Helpers::FUNC_NAME_SEPARATOR << GetSelfScopeName(); 5753af6ab5fSopenharmony_ci if (scopeDuplicateIndex_ > 0) { 5763af6ab5fSopenharmony_ci internalName << util::Helpers::DUPLICATED_SEPERATOR << 5773af6ab5fSopenharmony_ci std::hex << scopeDuplicateIndex_; 5783af6ab5fSopenharmony_ci } 5793af6ab5fSopenharmony_ci internalName_ = util::UString(internalName.str(), allocator_).View(); 5803af6ab5fSopenharmony_ci} 5813af6ab5fSopenharmony_ci 5823af6ab5fSopenharmony_cibool FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 5833af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 5843af6ab5fSopenharmony_ci{ 5853af6ab5fSopenharmony_ci switch (newDecl->Type()) { 5863af6ab5fSopenharmony_ci case DeclType::VAR: { 5873af6ab5fSopenharmony_ci return AddVar<LocalVariable>(allocator, currentVariable, newDecl); 5883af6ab5fSopenharmony_ci } 5893af6ab5fSopenharmony_ci case DeclType::FUNC: { 5903af6ab5fSopenharmony_ci return AddFunction<LocalVariable>(allocator, currentVariable, newDecl, extension); 5913af6ab5fSopenharmony_ci } 5923af6ab5fSopenharmony_ci case DeclType::CLASS: { 5933af6ab5fSopenharmony_ci return AddClass<LocalVariable>(allocator, currentVariable, newDecl); 5943af6ab5fSopenharmony_ci } 5953af6ab5fSopenharmony_ci case DeclType::ENUM_LITERAL: { 5963af6ab5fSopenharmony_ci return AddTSBinding<EnumLiteralVariable>(allocator, newDecl, VariableFlags::ENUM_LITERAL); 5973af6ab5fSopenharmony_ci } 5983af6ab5fSopenharmony_ci case DeclType::NAMESPACE: { 5993af6ab5fSopenharmony_ci return AddTSBinding<NamespaceVariable>(allocator, newDecl, VariableFlags::NAMESPACE); 6003af6ab5fSopenharmony_ci } 6013af6ab5fSopenharmony_ci case DeclType::IMPORT_EQUALS: { 6023af6ab5fSopenharmony_ci return AddTSBinding<ImportEqualsVariable>(allocator, newDecl, VariableFlags::IMPORT_EQUALS); 6033af6ab5fSopenharmony_ci } 6043af6ab5fSopenharmony_ci case DeclType::INTERFACE: { 6053af6ab5fSopenharmony_ci return AddTSBinding<LocalVariable>(allocator, currentVariable, newDecl, VariableFlags::INTERFACE); 6063af6ab5fSopenharmony_ci } 6073af6ab5fSopenharmony_ci default: { 6083af6ab5fSopenharmony_ci return AddLexical<LocalVariable>(allocator, currentVariable, newDecl); 6093af6ab5fSopenharmony_ci } 6103af6ab5fSopenharmony_ci } 6113af6ab5fSopenharmony_ci} 6123af6ab5fSopenharmony_ci 6133af6ab5fSopenharmony_civoid FunctionScope::SetSelfScopeName(const util::StringView &ident) 6143af6ab5fSopenharmony_ci{ 6153af6ab5fSopenharmony_ci Scope::SetSelfScopeName(ident); 6163af6ab5fSopenharmony_ci paramScope_->selfScopeName_ = selfScopeName_; 6173af6ab5fSopenharmony_ci paramScope_->hasSelfScopeNameSet_ = true; 6183af6ab5fSopenharmony_ci hasSelfScopeNameSet_ = true; 6193af6ab5fSopenharmony_ci} 6203af6ab5fSopenharmony_ci 6213af6ab5fSopenharmony_ciutil::StringView FunctionScope::GetScopeTag() 6223af6ab5fSopenharmony_ci{ 6233af6ab5fSopenharmony_ci if (IsFunctionScope() && (node_->IsScriptFunction() && node_->AsScriptFunction()->IsConstructor())) { 6243af6ab5fSopenharmony_ci return util::UString(util::Helpers::CTOR_TAG.data(), allocator_).View(); 6253af6ab5fSopenharmony_ci } 6263af6ab5fSopenharmony_ci if (parent_ && parent_->Parent() && parent_->Parent()->IsClassScope()) { 6273af6ab5fSopenharmony_ci bool hasNodeParent = node_ && node_->Parent() && node_->Parent()->Parent(); 6283af6ab5fSopenharmony_ci const ir::AstNode *nodeParent = hasNodeParent ? node_->Parent()->Parent() : nullptr; 6293af6ab5fSopenharmony_ci if (nodeParent && nodeParent->IsMethodDefinition() && nodeParent->AsMethodDefinition()->IsStatic()) { 6303af6ab5fSopenharmony_ci return util::UString(util::Helpers::STATIC_METHOD_TAG.data(), allocator_).View(); 6313af6ab5fSopenharmony_ci } 6323af6ab5fSopenharmony_ci return util::UString(util::Helpers::METHOD_TAG.data(), allocator_).View(); 6333af6ab5fSopenharmony_ci } 6343af6ab5fSopenharmony_ci return util::UString(util::Helpers::FUNCTION_TAG.data(), allocator_).View(); 6353af6ab5fSopenharmony_ci} 6363af6ab5fSopenharmony_ci 6373af6ab5fSopenharmony_ciutil::StringView FunctionScope::GetSelfScopeName() 6383af6ab5fSopenharmony_ci{ 6393af6ab5fSopenharmony_ci if (hasSelfScopeNameSet_) { 6403af6ab5fSopenharmony_ci return selfScopeName_; 6413af6ab5fSopenharmony_ci } 6423af6ab5fSopenharmony_ci 6433af6ab5fSopenharmony_ci if (node_ && node_->IsScriptFunction()) { 6443af6ab5fSopenharmony_ci auto selfName = util::Helpers::FunctionName(allocator_, node_->AsScriptFunction()); 6453af6ab5fSopenharmony_ci if (!util::Helpers::IsSpecialScopeName(selfName)) { 6463af6ab5fSopenharmony_ci return selfName; 6473af6ab5fSopenharmony_ci } 6483af6ab5fSopenharmony_ci } 6493af6ab5fSopenharmony_ci return util::UString(util::Helpers::STRING_EMPTY.data(), allocator_).View(); 6503af6ab5fSopenharmony_ci} 6513af6ab5fSopenharmony_ci 6523af6ab5fSopenharmony_ciutil::StringView TSModuleScope::GetSelfScopeName() 6533af6ab5fSopenharmony_ci{ 6543af6ab5fSopenharmony_ci if (hasSelfScopeNameSet_) { 6553af6ab5fSopenharmony_ci return selfScopeName_; 6563af6ab5fSopenharmony_ci } 6573af6ab5fSopenharmony_ci throw Error(ErrorType::GENERIC, "namespace or module name should be set in Binder::ResolveReference()"); 6583af6ab5fSopenharmony_ci} 6593af6ab5fSopenharmony_ci 6603af6ab5fSopenharmony_ciutil::StringView TSModuleScope::GetScopeTag() 6613af6ab5fSopenharmony_ci{ 6623af6ab5fSopenharmony_ci return util::UString(util::Helpers::NAMESPACE_TAG.data(), allocator_).View(); 6633af6ab5fSopenharmony_ci} 6643af6ab5fSopenharmony_ci 6653af6ab5fSopenharmony_cibool TSEnumScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 6663af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 6673af6ab5fSopenharmony_ci{ 6683af6ab5fSopenharmony_ci ASSERT(newDecl->Type() == DeclType::ENUM); 6693af6ab5fSopenharmony_ci return enumMemberBindings_->insert({newDecl->Name(), allocator->New<EnumVariable>(newDecl, false)}).second; 6703af6ab5fSopenharmony_ci} 6713af6ab5fSopenharmony_ci 6723af6ab5fSopenharmony_civoid TSEnumScope::SetSelfScopeName(const util::StringView &ident) 6733af6ab5fSopenharmony_ci{ 6743af6ab5fSopenharmony_ci if (!hasSelfScopeNameSet_) { 6753af6ab5fSopenharmony_ci FunctionScope::SetSelfScopeName(GetSelfScopeName()); 6763af6ab5fSopenharmony_ci } 6773af6ab5fSopenharmony_ci} 6783af6ab5fSopenharmony_ci 6793af6ab5fSopenharmony_ciutil::StringView TSEnumScope::GetSelfScopeName() 6803af6ab5fSopenharmony_ci{ 6813af6ab5fSopenharmony_ci if (hasSelfScopeNameSet_) { 6823af6ab5fSopenharmony_ci return selfScopeName_; 6833af6ab5fSopenharmony_ci } 6843af6ab5fSopenharmony_ci 6853af6ab5fSopenharmony_ci std::stringstream scopeName; 6863af6ab5fSopenharmony_ci if (node_ && node_->IsScriptFunction()) { 6873af6ab5fSopenharmony_ci auto scriptFunction = node_->AsScriptFunction(); 6883af6ab5fSopenharmony_ci if (scriptFunction->Params().size() > 0 && scriptFunction->Params()[0]->IsIdentifier()) { 6893af6ab5fSopenharmony_ci scopeName << scriptFunction->Params()[0]->AsIdentifier()->Name(); 6903af6ab5fSopenharmony_ci } 6913af6ab5fSopenharmony_ci } 6923af6ab5fSopenharmony_ci return util::UString(scopeName.str(), allocator_).View(); 6933af6ab5fSopenharmony_ci} 6943af6ab5fSopenharmony_ci 6953af6ab5fSopenharmony_ciutil::StringView TSEnumScope::GetScopeTag() 6963af6ab5fSopenharmony_ci{ 6973af6ab5fSopenharmony_ci return util::UString(util::Helpers::ENUM_TAG.data(), allocator_).View(); 6983af6ab5fSopenharmony_ci} 6993af6ab5fSopenharmony_ci 7003af6ab5fSopenharmony_cibool GlobalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 7013af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 7023af6ab5fSopenharmony_ci{ 7033af6ab5fSopenharmony_ci switch (newDecl->Type()) { 7043af6ab5fSopenharmony_ci case DeclType::VAR: { 7053af6ab5fSopenharmony_ci return AddVar<GlobalVariable>(allocator, currentVariable, newDecl); 7063af6ab5fSopenharmony_ci } 7073af6ab5fSopenharmony_ci case DeclType::FUNC: { 7083af6ab5fSopenharmony_ci return AddFunction<GlobalVariable>(allocator, currentVariable, newDecl, extension); 7093af6ab5fSopenharmony_ci } 7103af6ab5fSopenharmony_ci case DeclType::CLASS: { 7113af6ab5fSopenharmony_ci return AddClass<LocalVariable>(allocator, currentVariable, newDecl); 7123af6ab5fSopenharmony_ci } 7133af6ab5fSopenharmony_ci case DeclType::ENUM_LITERAL: { 7143af6ab5fSopenharmony_ci return AddTSBinding<EnumLiteralVariable>(allocator, newDecl, VariableFlags::ENUM_LITERAL); 7153af6ab5fSopenharmony_ci } 7163af6ab5fSopenharmony_ci case DeclType::NAMESPACE: { 7173af6ab5fSopenharmony_ci return AddTSBinding<NamespaceVariable>(allocator, newDecl, VariableFlags::NAMESPACE); 7183af6ab5fSopenharmony_ci } 7193af6ab5fSopenharmony_ci case DeclType::IMPORT_EQUALS: { 7203af6ab5fSopenharmony_ci return AddTSBinding<ImportEqualsVariable>(allocator, newDecl, VariableFlags::IMPORT_EQUALS); 7213af6ab5fSopenharmony_ci } 7223af6ab5fSopenharmony_ci case DeclType::INTERFACE: { 7233af6ab5fSopenharmony_ci return AddTSBinding<LocalVariable>(allocator, currentVariable, newDecl, VariableFlags::INTERFACE); 7243af6ab5fSopenharmony_ci } 7253af6ab5fSopenharmony_ci default: { 7263af6ab5fSopenharmony_ci return AddLexical<LocalVariable>(allocator, currentVariable, newDecl); 7273af6ab5fSopenharmony_ci } 7283af6ab5fSopenharmony_ci } 7293af6ab5fSopenharmony_ci 7303af6ab5fSopenharmony_ci return true; 7313af6ab5fSopenharmony_ci} 7323af6ab5fSopenharmony_ci 7333af6ab5fSopenharmony_civoid GlobalScope::SetSelfScopeName([[maybe_unused]] const util::StringView &ident) 7343af6ab5fSopenharmony_ci{ 7353af6ab5fSopenharmony_ci hasSelfScopeNameSet_ = true; 7363af6ab5fSopenharmony_ci} 7373af6ab5fSopenharmony_ci 7383af6ab5fSopenharmony_ci// ModuleScope 7393af6ab5fSopenharmony_ci 7403af6ab5fSopenharmony_civoid ModuleScope::ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName) 7413af6ab5fSopenharmony_ci{ 7423af6ab5fSopenharmony_ci auto res = bindings_.find(localName); 7433af6ab5fSopenharmony_ci // Since the module's exported [localName] has been validated before, 7443af6ab5fSopenharmony_ci // [localName] must have a binding now. 7453af6ab5fSopenharmony_ci ASSERT(res != bindings_.end()); 7463af6ab5fSopenharmony_ci if (!res->second->IsModuleVariable()) { 7473af6ab5fSopenharmony_ci auto *decl = res->second->Declaration(); 7483af6ab5fSopenharmony_ci decl->AddFlag(DeclarationFlags::EXPORT); 7493af6ab5fSopenharmony_ci VariableFlags flags = res->second->Flags(); 7503af6ab5fSopenharmony_ci res->second = allocator->New<ModuleVariable>(decl, flags | VariableFlags::LOCAL_EXPORT); 7513af6ab5fSopenharmony_ci } 7523af6ab5fSopenharmony_ci} 7533af6ab5fSopenharmony_ci 7543af6ab5fSopenharmony_civoid ModuleScope::AssignIndexToModuleVariable(util::StringView name, uint32_t index) 7553af6ab5fSopenharmony_ci{ 7563af6ab5fSopenharmony_ci auto *moduleVar = FindLocal(name); 7573af6ab5fSopenharmony_ci CHECK_NOT_NULL(moduleVar); 7583af6ab5fSopenharmony_ci ASSERT(moduleVar->IsModuleVariable()); 7593af6ab5fSopenharmony_ci moduleVar->AsModuleVariable()->AssignIndex(index); 7603af6ab5fSopenharmony_ci} 7613af6ab5fSopenharmony_ci 7623af6ab5fSopenharmony_cibool ModuleScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 7633af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 7643af6ab5fSopenharmony_ci{ 7653af6ab5fSopenharmony_ci switch (newDecl->Type()) { 7663af6ab5fSopenharmony_ci case DeclType::VAR: { 7673af6ab5fSopenharmony_ci auto [scope, shadowed] = IterateShadowedVariables( 7683af6ab5fSopenharmony_ci newDecl->Name(), [](const Variable *v) { return !v->HasFlag(VariableFlags::VAR); }); 7693af6ab5fSopenharmony_ci 7703af6ab5fSopenharmony_ci if (shadowed) { 7713af6ab5fSopenharmony_ci return false; 7723af6ab5fSopenharmony_ci } 7733af6ab5fSopenharmony_ci return newDecl->IsImportOrExportDecl() ? 7743af6ab5fSopenharmony_ci AddVar<ModuleVariable>(allocator, currentVariable, newDecl) : 7753af6ab5fSopenharmony_ci AddVar<LocalVariable>(allocator, currentVariable, newDecl); 7763af6ab5fSopenharmony_ci } 7773af6ab5fSopenharmony_ci case DeclType::FUNC: { 7783af6ab5fSopenharmony_ci if (currentVariable) { 7793af6ab5fSopenharmony_ci auto decl = currentVariable->Declaration(); 7803af6ab5fSopenharmony_ci if (!decl->IsClassDecl() || !decl->AsClassDecl()->IsDeclare()) { 7813af6ab5fSopenharmony_ci return false; 7823af6ab5fSopenharmony_ci } 7833af6ab5fSopenharmony_ci } 7843af6ab5fSopenharmony_ci return newDecl->IsImportOrExportDecl() ? 7853af6ab5fSopenharmony_ci AddFunction<ModuleVariable>(allocator, currentVariable, newDecl, extension) : 7863af6ab5fSopenharmony_ci AddFunction<LocalVariable>(allocator, currentVariable, newDecl, extension); 7873af6ab5fSopenharmony_ci } 7883af6ab5fSopenharmony_ci case DeclType::CLASS: { 7893af6ab5fSopenharmony_ci return newDecl->IsImportOrExportDecl() ? 7903af6ab5fSopenharmony_ci AddClass<ModuleVariable>(allocator, currentVariable, newDecl) : 7913af6ab5fSopenharmony_ci AddClass<LocalVariable>(allocator, currentVariable, newDecl); 7923af6ab5fSopenharmony_ci } 7933af6ab5fSopenharmony_ci case DeclType::ENUM_LITERAL: { 7943af6ab5fSopenharmony_ci return AddTSBinding<EnumLiteralVariable>(allocator, newDecl, VariableFlags::ENUM_LITERAL); 7953af6ab5fSopenharmony_ci } 7963af6ab5fSopenharmony_ci case DeclType::NAMESPACE: { 7973af6ab5fSopenharmony_ci return AddTSBinding<NamespaceVariable>(allocator, newDecl, VariableFlags::NAMESPACE); 7983af6ab5fSopenharmony_ci } 7993af6ab5fSopenharmony_ci case DeclType::IMPORT_EQUALS: { 8003af6ab5fSopenharmony_ci return AddTSBinding<ImportEqualsVariable>(allocator, newDecl, VariableFlags::IMPORT_EQUALS); 8013af6ab5fSopenharmony_ci } 8023af6ab5fSopenharmony_ci case DeclType::INTERFACE: { 8033af6ab5fSopenharmony_ci return AddTSBinding<LocalVariable>(allocator, currentVariable, newDecl, VariableFlags::INTERFACE); 8043af6ab5fSopenharmony_ci } 8053af6ab5fSopenharmony_ci default: { 8063af6ab5fSopenharmony_ci if (currentVariable) { 8073af6ab5fSopenharmony_ci return false; 8083af6ab5fSopenharmony_ci } 8093af6ab5fSopenharmony_ci return newDecl->IsImportOrExportDecl() ? 8103af6ab5fSopenharmony_ci AddLexical<ModuleVariable>(allocator, currentVariable, newDecl) : 8113af6ab5fSopenharmony_ci AddLexical<LocalVariable>(allocator, currentVariable, newDecl); 8123af6ab5fSopenharmony_ci } 8133af6ab5fSopenharmony_ci } 8143af6ab5fSopenharmony_ci} 8153af6ab5fSopenharmony_ci 8163af6ab5fSopenharmony_civoid ModuleScope::SetSelfScopeName([[maybe_unused]] const util::StringView &ident) 8173af6ab5fSopenharmony_ci{ 8183af6ab5fSopenharmony_ci hasSelfScopeNameSet_ = true; 8193af6ab5fSopenharmony_ci} 8203af6ab5fSopenharmony_ci 8213af6ab5fSopenharmony_ci// LocalScope 8223af6ab5fSopenharmony_ci 8233af6ab5fSopenharmony_cibool LocalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 8243af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 8253af6ab5fSopenharmony_ci{ 8263af6ab5fSopenharmony_ci return AddLocal(allocator, currentVariable, newDecl, extension); 8273af6ab5fSopenharmony_ci} 8283af6ab5fSopenharmony_ci 8293af6ab5fSopenharmony_civoid LoopScope::InitVariable() 8303af6ab5fSopenharmony_ci{ 8313af6ab5fSopenharmony_ci for (const auto &[name, var] : bindings_) { 8323af6ab5fSopenharmony_ci if (!var->Declaration()->IsLetOrConstOrClassDecl()) { 8333af6ab5fSopenharmony_ci continue; 8343af6ab5fSopenharmony_ci } 8353af6ab5fSopenharmony_ci 8363af6ab5fSopenharmony_ci var->AddFlag(VariableFlags::INITIALIZED); 8373af6ab5fSopenharmony_ci if (var->LexicalBound()) { 8383af6ab5fSopenharmony_ci var->AddFlag(VariableFlags::PER_ITERATION); 8393af6ab5fSopenharmony_ci } 8403af6ab5fSopenharmony_ci } 8413af6ab5fSopenharmony_ci} 8423af6ab5fSopenharmony_ci 8433af6ab5fSopenharmony_cibool CatchParamScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 8443af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 8453af6ab5fSopenharmony_ci{ 8463af6ab5fSopenharmony_ci return AddParam(allocator, currentVariable, newDecl, VariableFlags::INITIALIZED); 8473af6ab5fSopenharmony_ci} 8483af6ab5fSopenharmony_ci 8493af6ab5fSopenharmony_cibool CatchScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 8503af6ab5fSopenharmony_ci [[maybe_unused]] ScriptExtension extension) 8513af6ab5fSopenharmony_ci{ 8523af6ab5fSopenharmony_ci if (!newDecl->IsVarDecl() && paramScope_->FindLocal(newDecl->Name())) { 8533af6ab5fSopenharmony_ci return false; 8543af6ab5fSopenharmony_ci } 8553af6ab5fSopenharmony_ci 8563af6ab5fSopenharmony_ci return AddLocal(allocator, currentVariable, newDecl, extension); 8573af6ab5fSopenharmony_ci} 8583af6ab5fSopenharmony_ci} // namespace panda::es2panda::binder 859