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