13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 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#ifndef ES2PANDA_COMPILER_SCOPES_SCOPE_H
173af6ab5fSopenharmony_ci#define ES2PANDA_COMPILER_SCOPES_SCOPE_H
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "varbinder/declaration.h"
203af6ab5fSopenharmony_ci#include "varbinder/variable.h"
213af6ab5fSopenharmony_ci#include "es2panda.h"
223af6ab5fSopenharmony_ci#include "util/enumbitops.h"
233af6ab5fSopenharmony_ci#include "util/ustring.h"
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_ci#include <map>
263af6ab5fSopenharmony_ci#include <unordered_map>
273af6ab5fSopenharmony_ci#include <vector>
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_cinamespace ark::es2panda::public_lib {
303af6ab5fSopenharmony_cistruct Context;
313af6ab5fSopenharmony_ci}  // namespace ark::es2panda::public_lib
323af6ab5fSopenharmony_ci
333af6ab5fSopenharmony_cinamespace ark::es2panda::compiler {
343af6ab5fSopenharmony_ciclass IRNode;
353af6ab5fSopenharmony_ci}  // namespace ark::es2panda::compiler
363af6ab5fSopenharmony_ci
373af6ab5fSopenharmony_cinamespace ark::es2panda::varbinder {
383af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
393af6ab5fSopenharmony_ci#define DECLARE_CLASSES(type, className) class className;
403af6ab5fSopenharmony_ciSCOPE_TYPES(DECLARE_CLASSES)
413af6ab5fSopenharmony_ci#undef DECLARE_CLASSES
423af6ab5fSopenharmony_ci
433af6ab5fSopenharmony_ciclass Scope;
443af6ab5fSopenharmony_ciclass VariableScope;
453af6ab5fSopenharmony_ciclass Variable;
463af6ab5fSopenharmony_ci
473af6ab5fSopenharmony_citemplate <typename ScopeT,
483af6ab5fSopenharmony_ci          std::enable_if_t<std::is_pointer_v<ScopeT> && std::is_base_of_v<Scope, std::remove_pointer_t<ScopeT>>, bool> =
493af6ab5fSopenharmony_ci              true>
503af6ab5fSopenharmony_ciclass ScopeFindResultT {
513af6ab5fSopenharmony_cipublic:
523af6ab5fSopenharmony_ci    ScopeFindResultT() = default;
533af6ab5fSopenharmony_ci    ScopeFindResultT(util::StringView n, ScopeT s, uint32_t l, Variable *v) : ScopeFindResultT(n, s, l, l, v) {}
543af6ab5fSopenharmony_ci    ScopeFindResultT(ScopeT s, uint32_t l, uint32_t ll, Variable *v) : scope(s), level(l), lexLevel(ll), variable(v) {}
553af6ab5fSopenharmony_ci    ScopeFindResultT(util::StringView n, ScopeT s, uint32_t l, uint32_t ll, Variable *v)
563af6ab5fSopenharmony_ci        : name(n), scope(s), level(l), lexLevel(ll), variable(v)
573af6ab5fSopenharmony_ci    {
583af6ab5fSopenharmony_ci    }
593af6ab5fSopenharmony_ci
603af6ab5fSopenharmony_ci    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
613af6ab5fSopenharmony_ci    util::StringView name {};
623af6ab5fSopenharmony_ci    ScopeT scope {};
633af6ab5fSopenharmony_ci    uint32_t level {};
643af6ab5fSopenharmony_ci    uint32_t lexLevel {};
653af6ab5fSopenharmony_ci    Variable *variable {};
663af6ab5fSopenharmony_ci    // NOLINTEND(misc-non-private-member-variables-in-classes)
673af6ab5fSopenharmony_ci};
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ciusing ConstScopeFindResult = ScopeFindResultT<const Scope *>;
703af6ab5fSopenharmony_ciusing ScopeFindResult = ScopeFindResultT<Scope *>;
713af6ab5fSopenharmony_ci
723af6ab5fSopenharmony_ciclass Scope {
733af6ab5fSopenharmony_cipublic:
743af6ab5fSopenharmony_ci    virtual ~Scope() = default;
753af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(Scope);
763af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(Scope);
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ci    using VariableMap = ArenaUnorderedMap<util::StringView, Variable *>;
793af6ab5fSopenharmony_ci    using InsertResult = std::pair<VariableMap::const_iterator, bool>;
803af6ab5fSopenharmony_ci
813af6ab5fSopenharmony_ci    virtual ScopeType Type() const = 0;
823af6ab5fSopenharmony_ci
833af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
843af6ab5fSopenharmony_ci#define DECLARE_CHECKS_CASTS(scopeType, className)        \
853af6ab5fSopenharmony_ci    bool Is##className() const                            \
863af6ab5fSopenharmony_ci    {                                                     \
873af6ab5fSopenharmony_ci        return Type() == ScopeType::scopeType;            \
883af6ab5fSopenharmony_ci    }                                                     \
893af6ab5fSopenharmony_ci    className *As##className()                            \
903af6ab5fSopenharmony_ci    {                                                     \
913af6ab5fSopenharmony_ci        ASSERT(Is##className());                          \
923af6ab5fSopenharmony_ci        return reinterpret_cast<className *>(this);       \
933af6ab5fSopenharmony_ci    }                                                     \
943af6ab5fSopenharmony_ci    const className *As##className() const                \
953af6ab5fSopenharmony_ci    {                                                     \
963af6ab5fSopenharmony_ci        ASSERT(Is##className());                          \
973af6ab5fSopenharmony_ci        return reinterpret_cast<const className *>(this); \
983af6ab5fSopenharmony_ci    }
993af6ab5fSopenharmony_ci    SCOPE_TYPES(DECLARE_CHECKS_CASTS)
1003af6ab5fSopenharmony_ci#undef DECLARE_CHECKS_CASTS
1013af6ab5fSopenharmony_ci
1023af6ab5fSopenharmony_ci    bool IsVariableScope() const
1033af6ab5fSopenharmony_ci    {
1043af6ab5fSopenharmony_ci        return Type() > ScopeType::LOCAL;
1053af6ab5fSopenharmony_ci    }
1063af6ab5fSopenharmony_ci
1073af6ab5fSopenharmony_ci    bool IsFunctionVariableScope() const
1083af6ab5fSopenharmony_ci    {
1093af6ab5fSopenharmony_ci        return Type() >= ScopeType::FUNCTION;
1103af6ab5fSopenharmony_ci    }
1113af6ab5fSopenharmony_ci
1123af6ab5fSopenharmony_ci    FunctionScope *AsFunctionVariableScope()
1133af6ab5fSopenharmony_ci    {
1143af6ab5fSopenharmony_ci        ASSERT(IsFunctionVariableScope());
1153af6ab5fSopenharmony_ci        return reinterpret_cast<FunctionScope *>(this);
1163af6ab5fSopenharmony_ci    }
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci    const FunctionScope *AsFunctionVariableScope() const
1193af6ab5fSopenharmony_ci    {
1203af6ab5fSopenharmony_ci        ASSERT(IsFunctionVariableScope());
1213af6ab5fSopenharmony_ci        return reinterpret_cast<const FunctionScope *>(this);
1223af6ab5fSopenharmony_ci    }
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    VariableScope *AsVariableScope()
1253af6ab5fSopenharmony_ci    {
1263af6ab5fSopenharmony_ci        ASSERT(IsVariableScope());
1273af6ab5fSopenharmony_ci        return reinterpret_cast<VariableScope *>(this);
1283af6ab5fSopenharmony_ci    }
1293af6ab5fSopenharmony_ci
1303af6ab5fSopenharmony_ci    const VariableScope *AsVariableScope() const
1313af6ab5fSopenharmony_ci    {
1323af6ab5fSopenharmony_ci        ASSERT(IsVariableScope());
1333af6ab5fSopenharmony_ci        return reinterpret_cast<const VariableScope *>(this);
1343af6ab5fSopenharmony_ci    }
1353af6ab5fSopenharmony_ci
1363af6ab5fSopenharmony_ci    VariableScope *EnclosingVariableScope();
1373af6ab5fSopenharmony_ci
1383af6ab5fSopenharmony_ci    const VariableScope *EnclosingVariableScope() const;
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci    ClassScope *EnclosingClassScope();
1413af6ab5fSopenharmony_ci    const ClassScope *EnclosingClassScope() const;
1423af6ab5fSopenharmony_ci
1433af6ab5fSopenharmony_ci    void AddFlag(ScopeFlags flag)
1443af6ab5fSopenharmony_ci    {
1453af6ab5fSopenharmony_ci        flags_ |= flag;
1463af6ab5fSopenharmony_ci    }
1473af6ab5fSopenharmony_ci
1483af6ab5fSopenharmony_ci    void ClearFlag(ScopeFlags flag)
1493af6ab5fSopenharmony_ci    {
1503af6ab5fSopenharmony_ci        flags_ &= ~flag;
1513af6ab5fSopenharmony_ci    }
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_ci    bool HasFlag(ScopeFlags flag) const
1543af6ab5fSopenharmony_ci    {
1553af6ab5fSopenharmony_ci        return (flags_ & flag) != 0;
1563af6ab5fSopenharmony_ci    }
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_ci    ArenaVector<Decl *> &Decls()
1593af6ab5fSopenharmony_ci    {
1603af6ab5fSopenharmony_ci        return decls_;
1613af6ab5fSopenharmony_ci    }
1623af6ab5fSopenharmony_ci
1633af6ab5fSopenharmony_ci    const ArenaVector<Decl *> &Decls() const
1643af6ab5fSopenharmony_ci    {
1653af6ab5fSopenharmony_ci        return decls_;
1663af6ab5fSopenharmony_ci    }
1673af6ab5fSopenharmony_ci
1683af6ab5fSopenharmony_ci    void SetParent(Scope *parent)
1693af6ab5fSopenharmony_ci    {
1703af6ab5fSopenharmony_ci        parent_ = parent;
1713af6ab5fSopenharmony_ci    }
1723af6ab5fSopenharmony_ci
1733af6ab5fSopenharmony_ci    Scope *Parent()
1743af6ab5fSopenharmony_ci    {
1753af6ab5fSopenharmony_ci        return parent_;
1763af6ab5fSopenharmony_ci    }
1773af6ab5fSopenharmony_ci
1783af6ab5fSopenharmony_ci    const Scope *Parent() const
1793af6ab5fSopenharmony_ci    {
1803af6ab5fSopenharmony_ci        return parent_;
1813af6ab5fSopenharmony_ci    }
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci    const compiler::IRNode *ScopeStart() const
1843af6ab5fSopenharmony_ci    {
1853af6ab5fSopenharmony_ci        return startIns_;
1863af6ab5fSopenharmony_ci    }
1873af6ab5fSopenharmony_ci
1883af6ab5fSopenharmony_ci    const compiler::IRNode *ScopeEnd() const
1893af6ab5fSopenharmony_ci    {
1903af6ab5fSopenharmony_ci        return endIns_;
1913af6ab5fSopenharmony_ci    }
1923af6ab5fSopenharmony_ci
1933af6ab5fSopenharmony_ci    void SetScopeStart(const compiler::IRNode *ins)
1943af6ab5fSopenharmony_ci    {
1953af6ab5fSopenharmony_ci        startIns_ = ins;
1963af6ab5fSopenharmony_ci    }
1973af6ab5fSopenharmony_ci
1983af6ab5fSopenharmony_ci    void SetScopeEnd(const compiler::IRNode *ins)
1993af6ab5fSopenharmony_ci    {
2003af6ab5fSopenharmony_ci        endIns_ = ins;
2013af6ab5fSopenharmony_ci    }
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_ci    ir::AstNode *Node()
2043af6ab5fSopenharmony_ci    {
2053af6ab5fSopenharmony_ci        return node_;
2063af6ab5fSopenharmony_ci    }
2073af6ab5fSopenharmony_ci
2083af6ab5fSopenharmony_ci    const ir::AstNode *Node() const
2093af6ab5fSopenharmony_ci    {
2103af6ab5fSopenharmony_ci        return node_;
2113af6ab5fSopenharmony_ci    }
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_ci    void BindNode(ir::AstNode *node)
2143af6ab5fSopenharmony_ci    {
2153af6ab5fSopenharmony_ci        node_ = node;
2163af6ab5fSopenharmony_ci    }
2173af6ab5fSopenharmony_ci
2183af6ab5fSopenharmony_ci    Variable *AddDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
2193af6ab5fSopenharmony_ci    {
2203af6ab5fSopenharmony_ci        decls_.push_back(decl);
2213af6ab5fSopenharmony_ci        auto options = decl->IsTypeAliasDecl() ? varbinder::ResolveBindingOptions::TYPE_ALIASES
2223af6ab5fSopenharmony_ci                                               : varbinder::ResolveBindingOptions::BINDINGS;
2233af6ab5fSopenharmony_ci        return AddBinding(allocator, FindLocal(decl->Name(), options), decl, extension);
2243af6ab5fSopenharmony_ci    }
2253af6ab5fSopenharmony_ci
2263af6ab5fSopenharmony_ci    Variable *AddTsDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension)
2273af6ab5fSopenharmony_ci    {
2283af6ab5fSopenharmony_ci        decls_.push_back(decl);
2293af6ab5fSopenharmony_ci        return AddBinding(allocator, FindLocal(decl->Name(), ResolveBindingOptions::ALL), decl, extension);
2303af6ab5fSopenharmony_ci    }
2313af6ab5fSopenharmony_ci
2323af6ab5fSopenharmony_ci    template <typename T, typename... Args>
2333af6ab5fSopenharmony_ci    T *NewDecl(ArenaAllocator *allocator, Args &&...args);
2343af6ab5fSopenharmony_ci
2353af6ab5fSopenharmony_ci    template <typename DeclType, typename VariableType>
2363af6ab5fSopenharmony_ci    VariableType *AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags);
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_ci    template <typename DeclType = varbinder::LetDecl, typename VariableType = varbinder::LocalVariable>
2393af6ab5fSopenharmony_ci    static VariableType *CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags,
2403af6ab5fSopenharmony_ci                                   ir::AstNode *node);
2413af6ab5fSopenharmony_ci
2423af6ab5fSopenharmony_ci    template <typename T, typename... Args>
2433af6ab5fSopenharmony_ci    Variable *PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&...args);
2443af6ab5fSopenharmony_ci
2453af6ab5fSopenharmony_ci    virtual InsertResult InsertBinding(const util::StringView &name, Variable *var);
2463af6ab5fSopenharmony_ci    virtual InsertResult TryInsertBinding(const util::StringView &name, Variable *var);
2473af6ab5fSopenharmony_ci    virtual void MergeBindings(VariableMap const &bindings);
2483af6ab5fSopenharmony_ci    virtual VariableMap::size_type EraseBinding(const util::StringView &name);
2493af6ab5fSopenharmony_ci
2503af6ab5fSopenharmony_ci    const VariableMap &Bindings() const
2513af6ab5fSopenharmony_ci    {
2523af6ab5fSopenharmony_ci        return bindings_;
2533af6ab5fSopenharmony_ci    }
2543af6ab5fSopenharmony_ci
2553af6ab5fSopenharmony_ci    ArenaMap<util::StringView, Variable *> OrderedBindings(ArenaAllocator *allocator) const
2563af6ab5fSopenharmony_ci    {
2573af6ab5fSopenharmony_ci        ArenaMap<util::StringView, Variable *> result(allocator->Adapter());
2583af6ab5fSopenharmony_ci        result.insert(bindings_.begin(), bindings_.end());
2593af6ab5fSopenharmony_ci        return result;
2603af6ab5fSopenharmony_ci    }
2613af6ab5fSopenharmony_ci
2623af6ab5fSopenharmony_ci    virtual Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
2633af6ab5fSopenharmony_ci                                 [[maybe_unused]] ScriptExtension extension) = 0;
2643af6ab5fSopenharmony_ci
2653af6ab5fSopenharmony_ci    virtual Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const;
2663af6ab5fSopenharmony_ci
2673af6ab5fSopenharmony_ci    bool IsSuperscopeOf(const varbinder::Scope *subscope) const;
2683af6ab5fSopenharmony_ci
2693af6ab5fSopenharmony_ci    ConstScopeFindResult Find(const util::StringView &name,
2703af6ab5fSopenharmony_ci                              ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
2713af6ab5fSopenharmony_ci
2723af6ab5fSopenharmony_ci    ScopeFindResult Find(const util::StringView &name, ResolveBindingOptions options = ResolveBindingOptions::BINDINGS);
2733af6ab5fSopenharmony_ci
2743af6ab5fSopenharmony_ci    ConstScopeFindResult FindInGlobal(const util::StringView &name,
2753af6ab5fSopenharmony_ci                                      ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
2763af6ab5fSopenharmony_ci
2773af6ab5fSopenharmony_ci    ConstScopeFindResult FindInFunctionScope(const util::StringView &name,
2783af6ab5fSopenharmony_ci                                             ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const;
2793af6ab5fSopenharmony_ci
2803af6ab5fSopenharmony_ci    Decl *FindDecl(const util::StringView &name) const;
2813af6ab5fSopenharmony_ci
2823af6ab5fSopenharmony_ciprotected:
2833af6ab5fSopenharmony_ci    explicit Scope(ArenaAllocator *allocator, Scope *parent)
2843af6ab5fSopenharmony_ci        : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter())
2853af6ab5fSopenharmony_ci    {
2863af6ab5fSopenharmony_ci    }
2873af6ab5fSopenharmony_ci
2883af6ab5fSopenharmony_ci    explicit Scope(ArenaAllocator *allocator, Scope *parent, ScopeFlags flags)
2893af6ab5fSopenharmony_ci        : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter()), flags_(flags)
2903af6ab5fSopenharmony_ci    {
2913af6ab5fSopenharmony_ci    }
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci    /**
2943af6ab5fSopenharmony_ci     * @return true - if the variable is shadowed
2953af6ab5fSopenharmony_ci     *         false - otherwise
2963af6ab5fSopenharmony_ci     */
2973af6ab5fSopenharmony_ci    using VariableVisitor = std::function<bool(const Variable *)>;
2983af6ab5fSopenharmony_ci
2993af6ab5fSopenharmony_ci    /**
3003af6ab5fSopenharmony_ci     * @return true - if the variable is shadowed
3013af6ab5fSopenharmony_ci     *         false - otherwise
3023af6ab5fSopenharmony_ci     */
3033af6ab5fSopenharmony_ci    std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitor &visitor);
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_ci    Variable *AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
3063af6ab5fSopenharmony_ci                       [[maybe_unused]] ScriptExtension extension);
3073af6ab5fSopenharmony_ci
3083af6ab5fSopenharmony_ci    Variable *AddLocalVar(ArenaAllocator *allocator, Decl *newDecl);
3093af6ab5fSopenharmony_ci
3103af6ab5fSopenharmony_ciprivate:
3113af6ab5fSopenharmony_ci    template <
3123af6ab5fSopenharmony_ci        typename ResultT, typename ScopeT,
3133af6ab5fSopenharmony_ci        std::enable_if_t<std::is_same_v<ResultT, ConstScopeFindResult> || std::is_same_v<ResultT, ScopeFindResult>,
3143af6ab5fSopenharmony_ci                         bool> = true,
3153af6ab5fSopenharmony_ci        std::enable_if_t<std::is_pointer_v<ScopeT> && std::is_base_of_v<Scope, std::remove_pointer_t<ScopeT>>, bool> =
3163af6ab5fSopenharmony_ci            true>
3173af6ab5fSopenharmony_ci    static ResultT FindImpl(ScopeT &&scope, const util::StringView &name, const ResolveBindingOptions options)
3183af6ab5fSopenharmony_ci    {
3193af6ab5fSopenharmony_ci        uint32_t level = 0;
3203af6ab5fSopenharmony_ci        uint32_t lexLevel = 0;
3213af6ab5fSopenharmony_ci        // iter will be the EXACT type of scope with cv-qualifiers
3223af6ab5fSopenharmony_ci        auto &&iter = scope;
3233af6ab5fSopenharmony_ci
3243af6ab5fSopenharmony_ci        if (iter->IsFunctionParamScope()) {
3253af6ab5fSopenharmony_ci            auto *const v = iter->FindLocal(name, options);
3263af6ab5fSopenharmony_ci
3273af6ab5fSopenharmony_ci            if (v != nullptr) {
3283af6ab5fSopenharmony_ci                return {name, iter, level, lexLevel, v};
3293af6ab5fSopenharmony_ci            }
3303af6ab5fSopenharmony_ci
3313af6ab5fSopenharmony_ci            level++;
3323af6ab5fSopenharmony_ci            const auto *const funcVariableScope = iter->AsFunctionParamScope()->GetFunctionScope();
3333af6ab5fSopenharmony_ci
3343af6ab5fSopenharmony_ci            if (funcVariableScope != nullptr && funcVariableScope->NeedLexEnv()) {
3353af6ab5fSopenharmony_ci                lexLevel++;
3363af6ab5fSopenharmony_ci            }
3373af6ab5fSopenharmony_ci
3383af6ab5fSopenharmony_ci            iter = iter->Parent();
3393af6ab5fSopenharmony_ci        }
3403af6ab5fSopenharmony_ci
3413af6ab5fSopenharmony_ci        while (iter != nullptr) {
3423af6ab5fSopenharmony_ci            auto *const v = iter->FindLocal(name, options);
3433af6ab5fSopenharmony_ci
3443af6ab5fSopenharmony_ci            if (v != nullptr) {
3453af6ab5fSopenharmony_ci                return {name, iter, level, lexLevel, v};
3463af6ab5fSopenharmony_ci            }
3473af6ab5fSopenharmony_ci
3483af6ab5fSopenharmony_ci            if (iter->IsVariableScope()) {
3493af6ab5fSopenharmony_ci                level++;
3503af6ab5fSopenharmony_ci
3513af6ab5fSopenharmony_ci                if (iter->AsVariableScope()->NeedLexEnv()) {
3523af6ab5fSopenharmony_ci                    lexLevel++;
3533af6ab5fSopenharmony_ci                }
3543af6ab5fSopenharmony_ci            }
3553af6ab5fSopenharmony_ci
3563af6ab5fSopenharmony_ci            iter = iter->Parent();
3573af6ab5fSopenharmony_ci        }
3583af6ab5fSopenharmony_ci
3593af6ab5fSopenharmony_ci        return {name, nullptr, 0, 0, nullptr};
3603af6ab5fSopenharmony_ci    }
3613af6ab5fSopenharmony_ci
3623af6ab5fSopenharmony_ci    Scope *parent_ {};
3633af6ab5fSopenharmony_ci    ArenaVector<Decl *> decls_;
3643af6ab5fSopenharmony_ci    VariableMap bindings_;
3653af6ab5fSopenharmony_ci    ir::AstNode *node_ {};
3663af6ab5fSopenharmony_ci    ScopeFlags flags_ {};
3673af6ab5fSopenharmony_ci    const compiler::IRNode *startIns_ {};
3683af6ab5fSopenharmony_ci    const compiler::IRNode *endIns_ {};
3693af6ab5fSopenharmony_ci};
3703af6ab5fSopenharmony_ci
3713af6ab5fSopenharmony_ciclass VariableScope : public Scope {
3723af6ab5fSopenharmony_cipublic:
3733af6ab5fSopenharmony_ci    ~VariableScope() override = default;
3743af6ab5fSopenharmony_ci    NO_COPY_SEMANTIC(VariableScope);
3753af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(VariableScope);
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_ci    uint32_t NextSlot()
3783af6ab5fSopenharmony_ci    {
3793af6ab5fSopenharmony_ci        return slotIndex_++;
3803af6ab5fSopenharmony_ci    }
3813af6ab5fSopenharmony_ci
3823af6ab5fSopenharmony_ci    uint32_t LexicalSlots() const
3833af6ab5fSopenharmony_ci    {
3843af6ab5fSopenharmony_ci        return slotIndex_;
3853af6ab5fSopenharmony_ci    }
3863af6ab5fSopenharmony_ci
3873af6ab5fSopenharmony_ci    bool NeedLexEnv() const
3883af6ab5fSopenharmony_ci    {
3893af6ab5fSopenharmony_ci        return slotIndex_ != 0;
3903af6ab5fSopenharmony_ci    }
3913af6ab5fSopenharmony_ci
3923af6ab5fSopenharmony_ci    uint32_t EvalBindings() const
3933af6ab5fSopenharmony_ci    {
3943af6ab5fSopenharmony_ci        return evalBindings_;
3953af6ab5fSopenharmony_ci    }
3963af6ab5fSopenharmony_ci
3973af6ab5fSopenharmony_ci    void CheckDirectEval(public_lib::Context *context);
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_ciprotected:
4003af6ab5fSopenharmony_ci    explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {}
4013af6ab5fSopenharmony_ci
4023af6ab5fSopenharmony_ci    template <typename T>
4033af6ab5fSopenharmony_ci    Variable *AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
4043af6ab5fSopenharmony_ci
4053af6ab5fSopenharmony_ci    template <typename T>
4063af6ab5fSopenharmony_ci    Variable *AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
4073af6ab5fSopenharmony_ci                          [[maybe_unused]] ScriptExtension extension);
4083af6ab5fSopenharmony_ci
4093af6ab5fSopenharmony_ci    template <typename T>
4103af6ab5fSopenharmony_ci    Variable *AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
4113af6ab5fSopenharmony_ci
4123af6ab5fSopenharmony_ci    template <typename T>
4133af6ab5fSopenharmony_ci    Variable *AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
4143af6ab5fSopenharmony_ci
4153af6ab5fSopenharmony_ci    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
4163af6ab5fSopenharmony_ci    uint32_t evalBindings_ {};
4173af6ab5fSopenharmony_ci    uint32_t slotIndex_ {};
4183af6ab5fSopenharmony_ci    // NOLINTEND(misc-non-private-member-variables-in-classes)
4193af6ab5fSopenharmony_ci};
4203af6ab5fSopenharmony_ci
4213af6ab5fSopenharmony_ciclass ParamScope : public Scope {
4223af6ab5fSopenharmony_cipublic:
4233af6ab5fSopenharmony_ci    ScopeType Type() const override
4243af6ab5fSopenharmony_ci    {
4253af6ab5fSopenharmony_ci        return ScopeType::PARAM;
4263af6ab5fSopenharmony_ci    }
4273af6ab5fSopenharmony_ci
4283af6ab5fSopenharmony_ci    ArenaVector<LocalVariable *> &Params()
4293af6ab5fSopenharmony_ci    {
4303af6ab5fSopenharmony_ci        return params_;
4313af6ab5fSopenharmony_ci    }
4323af6ab5fSopenharmony_ci
4333af6ab5fSopenharmony_ci    const ArenaVector<LocalVariable *> &Params() const
4343af6ab5fSopenharmony_ci    {
4353af6ab5fSopenharmony_ci        return params_;
4363af6ab5fSopenharmony_ci    }
4373af6ab5fSopenharmony_ci
4383af6ab5fSopenharmony_ci    std::tuple<ParameterDecl *, ir::AstNode *, Variable *> AddParamDecl(ArenaAllocator *allocator, ir::AstNode *param);
4393af6ab5fSopenharmony_ci
4403af6ab5fSopenharmony_ciprotected:
4413af6ab5fSopenharmony_ci    explicit ParamScope(ArenaAllocator *allocator, Scope *parent)
4423af6ab5fSopenharmony_ci        : Scope(allocator, parent), params_(allocator->Adapter())
4433af6ab5fSopenharmony_ci    {
4443af6ab5fSopenharmony_ci    }
4453af6ab5fSopenharmony_ci
4463af6ab5fSopenharmony_ci    Variable *AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags);
4473af6ab5fSopenharmony_ci
4483af6ab5fSopenharmony_ci    // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
4493af6ab5fSopenharmony_ci    ArenaVector<LocalVariable *> params_;
4503af6ab5fSopenharmony_ci};
4513af6ab5fSopenharmony_ci
4523af6ab5fSopenharmony_ciclass FunctionScope;
4533af6ab5fSopenharmony_ci
4543af6ab5fSopenharmony_ciclass FunctionParamScope : public ParamScope {
4553af6ab5fSopenharmony_cipublic:
4563af6ab5fSopenharmony_ci    explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
4573af6ab5fSopenharmony_ci
4583af6ab5fSopenharmony_ci    FunctionScope *GetFunctionScope() const
4593af6ab5fSopenharmony_ci    {
4603af6ab5fSopenharmony_ci        return functionScope_;
4613af6ab5fSopenharmony_ci    }
4623af6ab5fSopenharmony_ci
4633af6ab5fSopenharmony_ci    void BindFunctionScope(FunctionScope *funcScope)
4643af6ab5fSopenharmony_ci    {
4653af6ab5fSopenharmony_ci        functionScope_ = funcScope;
4663af6ab5fSopenharmony_ci    }
4673af6ab5fSopenharmony_ci
4683af6ab5fSopenharmony_ci    LocalVariable *NameVar() const
4693af6ab5fSopenharmony_ci    {
4703af6ab5fSopenharmony_ci        return nameVar_;
4713af6ab5fSopenharmony_ci    }
4723af6ab5fSopenharmony_ci
4733af6ab5fSopenharmony_ci    void BindName(ArenaAllocator *allocator, util::StringView name);
4743af6ab5fSopenharmony_ci
4753af6ab5fSopenharmony_ci    ScopeType Type() const override
4763af6ab5fSopenharmony_ci    {
4773af6ab5fSopenharmony_ci        return ScopeType::FUNCTION_PARAM;
4783af6ab5fSopenharmony_ci    }
4793af6ab5fSopenharmony_ci
4803af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
4813af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
4823af6ab5fSopenharmony_ci
4833af6ab5fSopenharmony_ci    friend class FunctionScope;
4843af6ab5fSopenharmony_ci    template <typename E, typename T>
4853af6ab5fSopenharmony_ci    friend class ScopeWithParamScope;
4863af6ab5fSopenharmony_ci
4873af6ab5fSopenharmony_ciprivate:
4883af6ab5fSopenharmony_ci    FunctionScope *functionScope_ {};
4893af6ab5fSopenharmony_ci    LocalVariable *nameVar_ {};
4903af6ab5fSopenharmony_ci};
4913af6ab5fSopenharmony_ci
4923af6ab5fSopenharmony_citemplate <typename E, typename T>
4933af6ab5fSopenharmony_ciclass ScopeWithParamScope : public E {
4943af6ab5fSopenharmony_cipublic:
4953af6ab5fSopenharmony_ci    explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent), paramScope_(nullptr)
4963af6ab5fSopenharmony_ci    {
4973af6ab5fSopenharmony_ci    }
4983af6ab5fSopenharmony_ci
4993af6ab5fSopenharmony_ci    void BindParamScope(T *paramScope)
5003af6ab5fSopenharmony_ci    {
5013af6ab5fSopenharmony_ci        AssignParamScope(paramScope);
5023af6ab5fSopenharmony_ci        this->MergeBindings(paramScope->Bindings());
5033af6ab5fSopenharmony_ci    }
5043af6ab5fSopenharmony_ci
5053af6ab5fSopenharmony_ci    void AssignParamScope(T *paramScope)
5063af6ab5fSopenharmony_ci    {
5073af6ab5fSopenharmony_ci        ASSERT(this->Parent() == paramScope);
5083af6ab5fSopenharmony_ci        paramScope_ = paramScope;
5093af6ab5fSopenharmony_ci    }
5103af6ab5fSopenharmony_ci
5113af6ab5fSopenharmony_ci    T *ParamScope()
5123af6ab5fSopenharmony_ci    {
5133af6ab5fSopenharmony_ci        return paramScope_;
5143af6ab5fSopenharmony_ci    }
5153af6ab5fSopenharmony_ci
5163af6ab5fSopenharmony_ci    const T *ParamScope() const
5173af6ab5fSopenharmony_ci    {
5183af6ab5fSopenharmony_ci        return paramScope_;
5193af6ab5fSopenharmony_ci    }
5203af6ab5fSopenharmony_ci
5213af6ab5fSopenharmony_ciprotected:
5223af6ab5fSopenharmony_ci    // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
5233af6ab5fSopenharmony_ci    T *paramScope_;
5243af6ab5fSopenharmony_ci};
5253af6ab5fSopenharmony_ci
5263af6ab5fSopenharmony_ciclass LocalScope : public Scope {
5273af6ab5fSopenharmony_cipublic:
5283af6ab5fSopenharmony_ci    explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {}
5293af6ab5fSopenharmony_ci    explicit LocalScope(ArenaAllocator *allocator, Scope *parent, ScopeFlags flags) : Scope(allocator, parent, flags) {}
5303af6ab5fSopenharmony_ci
5313af6ab5fSopenharmony_ci    ScopeType Type() const override
5323af6ab5fSopenharmony_ci    {
5333af6ab5fSopenharmony_ci        return ScopeType::LOCAL;
5343af6ab5fSopenharmony_ci    }
5353af6ab5fSopenharmony_ci
5363af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
5373af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
5383af6ab5fSopenharmony_ci};
5393af6ab5fSopenharmony_ci
5403af6ab5fSopenharmony_ciclass LocalScopeWithTypeAlias : public LocalScope {
5413af6ab5fSopenharmony_cipublic:
5423af6ab5fSopenharmony_ci    explicit LocalScopeWithTypeAlias(ArenaAllocator *allocator, Scope *parent)
5433af6ab5fSopenharmony_ci        : LocalScope(allocator, parent),
5443af6ab5fSopenharmony_ci          typeAliasScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::TYPE_ALIAS))
5453af6ab5fSopenharmony_ci    {
5463af6ab5fSopenharmony_ci    }
5473af6ab5fSopenharmony_ci    explicit LocalScopeWithTypeAlias(ArenaAllocator *allocator, Scope *parent, ScopeFlags flags)
5483af6ab5fSopenharmony_ci        : LocalScope(allocator, parent, flags),
5493af6ab5fSopenharmony_ci          typeAliasScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::TYPE_ALIAS))
5503af6ab5fSopenharmony_ci    {
5513af6ab5fSopenharmony_ci    }
5523af6ab5fSopenharmony_ci
5533af6ab5fSopenharmony_ci    Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const override;
5543af6ab5fSopenharmony_ci
5553af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
5563af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
5573af6ab5fSopenharmony_ci
5583af6ab5fSopenharmony_ci    const LocalScope *TypeAliasScope() const
5593af6ab5fSopenharmony_ci    {
5603af6ab5fSopenharmony_ci        return typeAliasScope_;
5613af6ab5fSopenharmony_ci    }
5623af6ab5fSopenharmony_ci
5633af6ab5fSopenharmony_ci    LocalScope *TypeAliasScope()
5643af6ab5fSopenharmony_ci    {
5653af6ab5fSopenharmony_ci        return typeAliasScope_;
5663af6ab5fSopenharmony_ci    }
5673af6ab5fSopenharmony_ci
5683af6ab5fSopenharmony_ciprivate:
5693af6ab5fSopenharmony_ci    LocalScope *typeAliasScope_;
5703af6ab5fSopenharmony_ci};
5713af6ab5fSopenharmony_ci
5723af6ab5fSopenharmony_ciclass FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> {
5733af6ab5fSopenharmony_cipublic:
5743af6ab5fSopenharmony_ci    explicit FunctionScope(ArenaAllocator *allocator, Scope *parent)
5753af6ab5fSopenharmony_ci        : ScopeWithParamScope(allocator, parent),
5763af6ab5fSopenharmony_ci          typeAliasScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::TYPE_ALIAS))
5773af6ab5fSopenharmony_ci    {
5783af6ab5fSopenharmony_ci    }
5793af6ab5fSopenharmony_ci
5803af6ab5fSopenharmony_ci    ScopeType Type() const override
5813af6ab5fSopenharmony_ci    {
5823af6ab5fSopenharmony_ci        return ScopeType::FUNCTION;
5833af6ab5fSopenharmony_ci    }
5843af6ab5fSopenharmony_ci
5853af6ab5fSopenharmony_ci    void BindName(util::StringView name)
5863af6ab5fSopenharmony_ci    {
5873af6ab5fSopenharmony_ci        name_ = name;
5883af6ab5fSopenharmony_ci    }
5893af6ab5fSopenharmony_ci
5903af6ab5fSopenharmony_ci    void BindInternalName(util::StringView internalName)
5913af6ab5fSopenharmony_ci    {
5923af6ab5fSopenharmony_ci        internalName_ = internalName;
5933af6ab5fSopenharmony_ci    }
5943af6ab5fSopenharmony_ci
5953af6ab5fSopenharmony_ci    const util::StringView &Name() const
5963af6ab5fSopenharmony_ci    {
5973af6ab5fSopenharmony_ci        return name_;
5983af6ab5fSopenharmony_ci    }
5993af6ab5fSopenharmony_ci
6003af6ab5fSopenharmony_ci    const util::StringView &InternalName() const
6013af6ab5fSopenharmony_ci    {
6023af6ab5fSopenharmony_ci        return internalName_;
6033af6ab5fSopenharmony_ci    }
6043af6ab5fSopenharmony_ci
6053af6ab5fSopenharmony_ci    const LocalScope *TypeAliasScope() const
6063af6ab5fSopenharmony_ci    {
6073af6ab5fSopenharmony_ci        return typeAliasScope_;
6083af6ab5fSopenharmony_ci    }
6093af6ab5fSopenharmony_ci
6103af6ab5fSopenharmony_ci    Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const override;
6113af6ab5fSopenharmony_ci
6123af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
6133af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
6143af6ab5fSopenharmony_ci
6153af6ab5fSopenharmony_ciprivate:
6163af6ab5fSopenharmony_ci    util::StringView name_ {};
6173af6ab5fSopenharmony_ci    util::StringView internalName_ {};
6183af6ab5fSopenharmony_ci    LocalScope *typeAliasScope_;
6193af6ab5fSopenharmony_ci};
6203af6ab5fSopenharmony_ci
6213af6ab5fSopenharmony_ciclass ClassScope : public LocalScopeWithTypeAlias {
6223af6ab5fSopenharmony_cipublic:
6233af6ab5fSopenharmony_ci    explicit ClassScope(ArenaAllocator *allocator, Scope *parent)
6243af6ab5fSopenharmony_ci        : LocalScopeWithTypeAlias(allocator, parent),
6253af6ab5fSopenharmony_ci          staticDeclScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::STATIC_DECL_SCOPE)),
6263af6ab5fSopenharmony_ci          staticFieldScope_(allocator->New<LocalScope>(allocator, staticDeclScope_, ScopeFlags::STATIC_FIELD_SCOPE)),
6273af6ab5fSopenharmony_ci          staticMethodScope_(allocator->New<LocalScope>(allocator, staticFieldScope_, ScopeFlags::STATIC_METHOD_SCOPE)),
6283af6ab5fSopenharmony_ci          instanceDeclScope_(allocator->New<LocalScope>(allocator, staticMethodScope_, ScopeFlags::DECL_SCOPE)),
6293af6ab5fSopenharmony_ci          instanceFieldScope_(allocator->New<LocalScope>(allocator, instanceDeclScope_, ScopeFlags::FIELD_SCOPE)),
6303af6ab5fSopenharmony_ci          instanceMethodScope_(allocator->New<LocalScope>(allocator, instanceFieldScope_, ScopeFlags::METHOD_SCOPE))
6313af6ab5fSopenharmony_ci    {
6323af6ab5fSopenharmony_ci    }
6333af6ab5fSopenharmony_ci
6343af6ab5fSopenharmony_ci    ScopeType Type() const override
6353af6ab5fSopenharmony_ci    {
6363af6ab5fSopenharmony_ci        return ScopeType::CLASS;
6373af6ab5fSopenharmony_ci    }
6383af6ab5fSopenharmony_ci
6393af6ab5fSopenharmony_ci    LocalScope *StaticDeclScope()
6403af6ab5fSopenharmony_ci    {
6413af6ab5fSopenharmony_ci        return staticDeclScope_;
6423af6ab5fSopenharmony_ci    }
6433af6ab5fSopenharmony_ci
6443af6ab5fSopenharmony_ci    const LocalScope *StaticDeclScope() const
6453af6ab5fSopenharmony_ci    {
6463af6ab5fSopenharmony_ci        return staticDeclScope_;
6473af6ab5fSopenharmony_ci    }
6483af6ab5fSopenharmony_ci
6493af6ab5fSopenharmony_ci    LocalScope *StaticFieldScope()
6503af6ab5fSopenharmony_ci    {
6513af6ab5fSopenharmony_ci        return staticFieldScope_;
6523af6ab5fSopenharmony_ci    }
6533af6ab5fSopenharmony_ci
6543af6ab5fSopenharmony_ci    const LocalScope *StaticFieldScope() const
6553af6ab5fSopenharmony_ci    {
6563af6ab5fSopenharmony_ci        return staticFieldScope_;
6573af6ab5fSopenharmony_ci    }
6583af6ab5fSopenharmony_ci
6593af6ab5fSopenharmony_ci    LocalScope *StaticMethodScope()
6603af6ab5fSopenharmony_ci    {
6613af6ab5fSopenharmony_ci        return staticMethodScope_;
6623af6ab5fSopenharmony_ci    }
6633af6ab5fSopenharmony_ci
6643af6ab5fSopenharmony_ci    const LocalScope *StaticMethodScope() const
6653af6ab5fSopenharmony_ci    {
6663af6ab5fSopenharmony_ci        return staticMethodScope_;
6673af6ab5fSopenharmony_ci    }
6683af6ab5fSopenharmony_ci
6693af6ab5fSopenharmony_ci    LocalScope *InstanceFieldScope()
6703af6ab5fSopenharmony_ci    {
6713af6ab5fSopenharmony_ci        return instanceFieldScope_;
6723af6ab5fSopenharmony_ci    }
6733af6ab5fSopenharmony_ci
6743af6ab5fSopenharmony_ci    const LocalScope *InstanceFieldScope() const
6753af6ab5fSopenharmony_ci    {
6763af6ab5fSopenharmony_ci        return instanceFieldScope_;
6773af6ab5fSopenharmony_ci    }
6783af6ab5fSopenharmony_ci
6793af6ab5fSopenharmony_ci    LocalScope *InstanceMethodScope()
6803af6ab5fSopenharmony_ci    {
6813af6ab5fSopenharmony_ci        return instanceMethodScope_;
6823af6ab5fSopenharmony_ci    }
6833af6ab5fSopenharmony_ci
6843af6ab5fSopenharmony_ci    const LocalScope *InstanceMethodScope() const
6853af6ab5fSopenharmony_ci    {
6863af6ab5fSopenharmony_ci        return instanceMethodScope_;
6873af6ab5fSopenharmony_ci    }
6883af6ab5fSopenharmony_ci
6893af6ab5fSopenharmony_ci    LocalScope *InstanceDeclScope()
6903af6ab5fSopenharmony_ci    {
6913af6ab5fSopenharmony_ci        return instanceDeclScope_;
6923af6ab5fSopenharmony_ci    }
6933af6ab5fSopenharmony_ci
6943af6ab5fSopenharmony_ci    const LocalScope *InstanceDeclScope() const
6953af6ab5fSopenharmony_ci    {
6963af6ab5fSopenharmony_ci        return instanceDeclScope_;
6973af6ab5fSopenharmony_ci    }
6983af6ab5fSopenharmony_ci
6993af6ab5fSopenharmony_ci    uint32_t GetAndIncrementAnonymousClassIdx() const
7003af6ab5fSopenharmony_ci    {
7013af6ab5fSopenharmony_ci        return anonymousClassIdx_++;
7023af6ab5fSopenharmony_ci    }
7033af6ab5fSopenharmony_ci
7043af6ab5fSopenharmony_ci    Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const override;
7053af6ab5fSopenharmony_ci
7063af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
7073af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
7083af6ab5fSopenharmony_ci
7093af6ab5fSopenharmony_ci    class BindingProps {
7103af6ab5fSopenharmony_ci    public:
7113af6ab5fSopenharmony_ci        BindingProps() = default;
7123af6ab5fSopenharmony_ci
7133af6ab5fSopenharmony_ci        void SetFlagsType(VariableFlags flagsType)
7143af6ab5fSopenharmony_ci        {
7153af6ab5fSopenharmony_ci            flags_ |= flagsType;
7163af6ab5fSopenharmony_ci        }
7173af6ab5fSopenharmony_ci        void SetBindingProps(VariableFlags flags, ir::Identifier *ident, LocalScope *targetScope)
7183af6ab5fSopenharmony_ci        {
7193af6ab5fSopenharmony_ci            flags_ |= flags;
7203af6ab5fSopenharmony_ci            ident_ = ident;
7213af6ab5fSopenharmony_ci            targetScope_ = targetScope;
7223af6ab5fSopenharmony_ci        }
7233af6ab5fSopenharmony_ci        VariableFlags GetFlags() const
7243af6ab5fSopenharmony_ci        {
7253af6ab5fSopenharmony_ci            return flags_;
7263af6ab5fSopenharmony_ci        }
7273af6ab5fSopenharmony_ci        ir::Identifier *GetIdent()
7283af6ab5fSopenharmony_ci        {
7293af6ab5fSopenharmony_ci            return ident_;
7303af6ab5fSopenharmony_ci        }
7313af6ab5fSopenharmony_ci        LocalScope *GetTargetScope()
7323af6ab5fSopenharmony_ci        {
7333af6ab5fSopenharmony_ci            return targetScope_;
7343af6ab5fSopenharmony_ci        }
7353af6ab5fSopenharmony_ci
7363af6ab5fSopenharmony_ci    private:
7373af6ab5fSopenharmony_ci        VariableFlags flags_ = VariableFlags::NONE;
7383af6ab5fSopenharmony_ci        ir::Identifier *ident_ {};
7393af6ab5fSopenharmony_ci        LocalScope *targetScope_ {};
7403af6ab5fSopenharmony_ci    };
7413af6ab5fSopenharmony_ci
7423af6ab5fSopenharmony_ci    void SetBindingProps(Decl *newDecl, BindingProps *props, bool isStatic);
7433af6ab5fSopenharmony_ci
7443af6ab5fSopenharmony_ciprivate:
7453af6ab5fSopenharmony_ci    LocalScope *staticDeclScope_;
7463af6ab5fSopenharmony_ci    LocalScope *staticFieldScope_;
7473af6ab5fSopenharmony_ci    LocalScope *staticMethodScope_;
7483af6ab5fSopenharmony_ci    LocalScope *instanceDeclScope_;
7493af6ab5fSopenharmony_ci    LocalScope *instanceFieldScope_;
7503af6ab5fSopenharmony_ci    LocalScope *instanceMethodScope_;
7513af6ab5fSopenharmony_ci    mutable uint32_t anonymousClassIdx_ {1};
7523af6ab5fSopenharmony_ci};
7533af6ab5fSopenharmony_ci
7543af6ab5fSopenharmony_ciclass CatchParamScope : public ParamScope {
7553af6ab5fSopenharmony_cipublic:
7563af6ab5fSopenharmony_ci    explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {}
7573af6ab5fSopenharmony_ci
7583af6ab5fSopenharmony_ci    ScopeType Type() const override
7593af6ab5fSopenharmony_ci    {
7603af6ab5fSopenharmony_ci        return ScopeType::CATCH_PARAM;
7613af6ab5fSopenharmony_ci    }
7623af6ab5fSopenharmony_ci
7633af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
7643af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
7653af6ab5fSopenharmony_ci
7663af6ab5fSopenharmony_ci    friend class CatchScope;
7673af6ab5fSopenharmony_ci};
7683af6ab5fSopenharmony_ci
7693af6ab5fSopenharmony_ciclass CatchScope : public ScopeWithParamScope<LocalScopeWithTypeAlias, CatchParamScope> {
7703af6ab5fSopenharmony_cipublic:
7713af6ab5fSopenharmony_ci    explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {}
7723af6ab5fSopenharmony_ci
7733af6ab5fSopenharmony_ci    ScopeType Type() const override
7743af6ab5fSopenharmony_ci    {
7753af6ab5fSopenharmony_ci        return ScopeType::CATCH;
7763af6ab5fSopenharmony_ci    }
7773af6ab5fSopenharmony_ci
7783af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
7793af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
7803af6ab5fSopenharmony_ci};
7813af6ab5fSopenharmony_ci
7823af6ab5fSopenharmony_ciclass LoopScope;
7833af6ab5fSopenharmony_ci
7843af6ab5fSopenharmony_ciclass LoopDeclarationScope : public VariableScope {
7853af6ab5fSopenharmony_cipublic:
7863af6ab5fSopenharmony_ci    explicit LoopDeclarationScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {}
7873af6ab5fSopenharmony_ci
7883af6ab5fSopenharmony_ci    ScopeType Type() const override
7893af6ab5fSopenharmony_ci    {
7903af6ab5fSopenharmony_ci        return loopType_;
7913af6ab5fSopenharmony_ci    }
7923af6ab5fSopenharmony_ci
7933af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
7943af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override
7953af6ab5fSopenharmony_ci    {
7963af6ab5fSopenharmony_ci        return AddLocal(allocator, currentVariable, newDecl, extension);
7973af6ab5fSopenharmony_ci    }
7983af6ab5fSopenharmony_ci
7993af6ab5fSopenharmony_ci    Scope *InitScope()
8003af6ab5fSopenharmony_ci    {
8013af6ab5fSopenharmony_ci        if (NeedLexEnv()) {
8023af6ab5fSopenharmony_ci            return initScope_;
8033af6ab5fSopenharmony_ci        }
8043af6ab5fSopenharmony_ci
8053af6ab5fSopenharmony_ci        return this;
8063af6ab5fSopenharmony_ci    }
8073af6ab5fSopenharmony_ci
8083af6ab5fSopenharmony_ci    void ConvertToVariableScope(ArenaAllocator *allocator);
8093af6ab5fSopenharmony_ci
8103af6ab5fSopenharmony_ciprivate:
8113af6ab5fSopenharmony_ci    friend class LoopScope;
8123af6ab5fSopenharmony_ci    LoopScope *loopScope_ {};
8133af6ab5fSopenharmony_ci    LocalScope *initScope_ {};
8143af6ab5fSopenharmony_ci    ScopeType loopType_ {ScopeType::LOCAL};
8153af6ab5fSopenharmony_ci};
8163af6ab5fSopenharmony_ci
8173af6ab5fSopenharmony_ciclass LoopScope : public VariableScope {
8183af6ab5fSopenharmony_cipublic:
8193af6ab5fSopenharmony_ci    explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent)
8203af6ab5fSopenharmony_ci    {
8213af6ab5fSopenharmony_ci        // NOTE(kkonkuznetsov): currently LoopScope type has ScopeType::LOCAL
8223af6ab5fSopenharmony_ci        // therefore it does not respond to IsLoopScope() because it checks for type.
8233af6ab5fSopenharmony_ci        // This LOOP_SCOPE flag can be used to check that scope is actually a loop scope.
8243af6ab5fSopenharmony_ci        AddFlag(ScopeFlags::LOOP_SCOPE);
8253af6ab5fSopenharmony_ci    }
8263af6ab5fSopenharmony_ci
8273af6ab5fSopenharmony_ci    LoopDeclarationScope *DeclScope()
8283af6ab5fSopenharmony_ci    {
8293af6ab5fSopenharmony_ci        return declScope_;
8303af6ab5fSopenharmony_ci    }
8313af6ab5fSopenharmony_ci
8323af6ab5fSopenharmony_ci    void BindDecls(LoopDeclarationScope *declScope)
8333af6ab5fSopenharmony_ci    {
8343af6ab5fSopenharmony_ci        declScope_ = declScope;
8353af6ab5fSopenharmony_ci        declScope_->loopScope_ = this;
8363af6ab5fSopenharmony_ci    }
8373af6ab5fSopenharmony_ci
8383af6ab5fSopenharmony_ci    ScopeType Type() const override
8393af6ab5fSopenharmony_ci    {
8403af6ab5fSopenharmony_ci        return loopType_;
8413af6ab5fSopenharmony_ci    }
8423af6ab5fSopenharmony_ci
8433af6ab5fSopenharmony_ci    void ConvertToVariableScope(ArenaAllocator *allocator);
8443af6ab5fSopenharmony_ci
8453af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
8463af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override
8473af6ab5fSopenharmony_ci    {
8483af6ab5fSopenharmony_ci        return AddLocal(allocator, currentVariable, newDecl, extension);
8493af6ab5fSopenharmony_ci    }
8503af6ab5fSopenharmony_ci
8513af6ab5fSopenharmony_ciprotected:
8523af6ab5fSopenharmony_ci    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
8533af6ab5fSopenharmony_ci    LoopDeclarationScope *declScope_ {};
8543af6ab5fSopenharmony_ci    ScopeType loopType_ {ScopeType::LOCAL};
8553af6ab5fSopenharmony_ci    // NOLINTEND(misc-non-private-member-variables-in-classes)
8563af6ab5fSopenharmony_ci};
8573af6ab5fSopenharmony_ci
8583af6ab5fSopenharmony_ciclass GlobalScope : public FunctionScope {
8593af6ab5fSopenharmony_cipublic:
8603af6ab5fSopenharmony_ci    explicit GlobalScope(ArenaAllocator *allocator)
8613af6ab5fSopenharmony_ci        : FunctionScope(allocator, nullptr), foreignBindings_(allocator->Adapter())
8623af6ab5fSopenharmony_ci    {
8633af6ab5fSopenharmony_ci        auto *paramScope = allocator->New<FunctionParamScope>(allocator, this);
8643af6ab5fSopenharmony_ci        paramScope_ = paramScope;
8653af6ab5fSopenharmony_ci        paramScope_->BindFunctionScope(this);
8663af6ab5fSopenharmony_ci    }
8673af6ab5fSopenharmony_ci
8683af6ab5fSopenharmony_ci    ScopeType Type() const override
8693af6ab5fSopenharmony_ci    {
8703af6ab5fSopenharmony_ci        return ScopeType::GLOBAL;
8713af6ab5fSopenharmony_ci    }
8723af6ab5fSopenharmony_ci
8733af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
8743af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
8753af6ab5fSopenharmony_ci
8763af6ab5fSopenharmony_ci    InsertResult InsertBinding(const util::StringView &name, Variable *var) override;
8773af6ab5fSopenharmony_ci    InsertResult TryInsertBinding(const util::StringView &name, Variable *var) override;
8783af6ab5fSopenharmony_ci    void MergeBindings(VariableMap const &bindings) override;
8793af6ab5fSopenharmony_ci    VariableMap::size_type EraseBinding(const util::StringView &name) override;
8803af6ab5fSopenharmony_ci
8813af6ab5fSopenharmony_ci    InsertResult InsertForeignBinding(const util::StringView &name, Variable *var);
8823af6ab5fSopenharmony_ci    [[nodiscard]] bool IsForeignBinding(const util::StringView &name) const;
8833af6ab5fSopenharmony_ci
8843af6ab5fSopenharmony_ci    InsertResult InsertDynamicBinding(const util::StringView &name, Variable *var);
8853af6ab5fSopenharmony_ci
8863af6ab5fSopenharmony_ciprivate:
8873af6ab5fSopenharmony_ci    InsertResult InsertImpl(const util::StringView &name, Variable *var, bool isForeign, bool isDynamic);
8883af6ab5fSopenharmony_ci
8893af6ab5fSopenharmony_ci    ArenaUnorderedMap<util::StringView, bool> foreignBindings_;
8903af6ab5fSopenharmony_ci};
8913af6ab5fSopenharmony_ci
8923af6ab5fSopenharmony_ciclass ModuleScope : public GlobalScope {
8933af6ab5fSopenharmony_cipublic:
8943af6ab5fSopenharmony_ci    template <typename K, typename V>
8953af6ab5fSopenharmony_ci    using ModuleEntry = ArenaVector<std::pair<K, V>>;
8963af6ab5fSopenharmony_ci    using ImportDeclList = ArenaVector<ImportDecl *>;
8973af6ab5fSopenharmony_ci    using ExportDeclList = ArenaVector<ExportDecl *>;
8983af6ab5fSopenharmony_ci    using LocalExportNameMap = ArenaMultiMap<varbinder::Variable *, util::StringView>;
8993af6ab5fSopenharmony_ci
9003af6ab5fSopenharmony_ci    explicit ModuleScope(ArenaAllocator *allocator)
9013af6ab5fSopenharmony_ci        : GlobalScope(allocator),
9023af6ab5fSopenharmony_ci          allocator_(allocator),
9033af6ab5fSopenharmony_ci          imports_(allocator_->Adapter()),
9043af6ab5fSopenharmony_ci          exports_(allocator_->Adapter()),
9053af6ab5fSopenharmony_ci          localExports_(allocator_->Adapter())
9063af6ab5fSopenharmony_ci    {
9073af6ab5fSopenharmony_ci    }
9083af6ab5fSopenharmony_ci
9093af6ab5fSopenharmony_ci    ScopeType Type() const override
9103af6ab5fSopenharmony_ci    {
9113af6ab5fSopenharmony_ci        return ScopeType::MODULE;
9123af6ab5fSopenharmony_ci    }
9133af6ab5fSopenharmony_ci
9143af6ab5fSopenharmony_ci    const ModuleEntry<ir::ImportDeclaration *, ImportDeclList> &Imports() const
9153af6ab5fSopenharmony_ci    {
9163af6ab5fSopenharmony_ci        return imports_;
9173af6ab5fSopenharmony_ci    }
9183af6ab5fSopenharmony_ci
9193af6ab5fSopenharmony_ci    const ModuleEntry<ir::AstNode *, ExportDeclList> &Exports() const
9203af6ab5fSopenharmony_ci    {
9213af6ab5fSopenharmony_ci        return exports_;
9223af6ab5fSopenharmony_ci    }
9233af6ab5fSopenharmony_ci
9243af6ab5fSopenharmony_ci    const LocalExportNameMap &LocalExports() const
9253af6ab5fSopenharmony_ci    {
9263af6ab5fSopenharmony_ci        return localExports_;
9273af6ab5fSopenharmony_ci    }
9283af6ab5fSopenharmony_ci
9293af6ab5fSopenharmony_ci    void AddImportDecl(ir::ImportDeclaration *importDecl, ImportDeclList &&decls);
9303af6ab5fSopenharmony_ci
9313af6ab5fSopenharmony_ci    void AddExportDecl(ir::AstNode *exportDecl, ExportDecl *decl);
9323af6ab5fSopenharmony_ci
9333af6ab5fSopenharmony_ci    void AddExportDecl(ir::AstNode *exportDecl, ExportDeclList &&decls);
9343af6ab5fSopenharmony_ci
9353af6ab5fSopenharmony_ci    Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
9363af6ab5fSopenharmony_ci                         [[maybe_unused]] ScriptExtension extension) override;
9373af6ab5fSopenharmony_ci
9383af6ab5fSopenharmony_ci    bool ExportAnalysis();
9393af6ab5fSopenharmony_ci
9403af6ab5fSopenharmony_ciprivate:
9413af6ab5fSopenharmony_ci    Variable *AddImport(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl);
9423af6ab5fSopenharmony_ci
9433af6ab5fSopenharmony_ci    ArenaAllocator *allocator_;
9443af6ab5fSopenharmony_ci    ModuleEntry<ir::ImportDeclaration *, ImportDeclList> imports_;
9453af6ab5fSopenharmony_ci    ModuleEntry<ir::AstNode *, ExportDeclList> exports_;
9463af6ab5fSopenharmony_ci    LocalExportNameMap localExports_;
9473af6ab5fSopenharmony_ci};
9483af6ab5fSopenharmony_ci
9493af6ab5fSopenharmony_citemplate <typename T>
9503af6ab5fSopenharmony_ciVariable *VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
9513af6ab5fSopenharmony_ci{
9523af6ab5fSopenharmony_ci    if (!currentVariable) {
9533af6ab5fSopenharmony_ci        return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, VariableFlags::HOIST_VAR)).first->second;
9543af6ab5fSopenharmony_ci    }
9553af6ab5fSopenharmony_ci
9563af6ab5fSopenharmony_ci    switch (currentVariable->Declaration()->Type()) {
9573af6ab5fSopenharmony_ci        case DeclType::VAR: {
9583af6ab5fSopenharmony_ci            currentVariable->Reset(newDecl, VariableFlags::HOIST_VAR);
9593af6ab5fSopenharmony_ci            [[fallthrough]];
9603af6ab5fSopenharmony_ci        }
9613af6ab5fSopenharmony_ci        case DeclType::PARAM:
9623af6ab5fSopenharmony_ci        case DeclType::FUNC: {
9633af6ab5fSopenharmony_ci            return currentVariable;
9643af6ab5fSopenharmony_ci        }
9653af6ab5fSopenharmony_ci        default: {
9663af6ab5fSopenharmony_ci            return nullptr;
9673af6ab5fSopenharmony_ci        }
9683af6ab5fSopenharmony_ci    }
9693af6ab5fSopenharmony_ci}
9703af6ab5fSopenharmony_ci
9713af6ab5fSopenharmony_citemplate <typename T>
9723af6ab5fSopenharmony_ciVariable *VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl,
9733af6ab5fSopenharmony_ci                                     [[maybe_unused]] ScriptExtension extension)
9743af6ab5fSopenharmony_ci{
9753af6ab5fSopenharmony_ci    VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST;
9763af6ab5fSopenharmony_ci
9773af6ab5fSopenharmony_ci    if (!currentVariable) {
9783af6ab5fSopenharmony_ci        return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, flags)).first->second;
9793af6ab5fSopenharmony_ci    }
9803af6ab5fSopenharmony_ci
9813af6ab5fSopenharmony_ci    if (extension != ScriptExtension::JS || IsModuleScope()) {
9823af6ab5fSopenharmony_ci        return nullptr;
9833af6ab5fSopenharmony_ci    }
9843af6ab5fSopenharmony_ci
9853af6ab5fSopenharmony_ci    switch (currentVariable->Declaration()->Type()) {
9863af6ab5fSopenharmony_ci        case DeclType::VAR:
9873af6ab5fSopenharmony_ci        case DeclType::FUNC: {
9883af6ab5fSopenharmony_ci            currentVariable->Reset(newDecl, VariableFlags::HOIST_VAR);
9893af6ab5fSopenharmony_ci            return currentVariable;
9903af6ab5fSopenharmony_ci        }
9913af6ab5fSopenharmony_ci        default: {
9923af6ab5fSopenharmony_ci            return nullptr;
9933af6ab5fSopenharmony_ci        }
9943af6ab5fSopenharmony_ci    }
9953af6ab5fSopenharmony_ci}
9963af6ab5fSopenharmony_ci
9973af6ab5fSopenharmony_citemplate <typename T>
9983af6ab5fSopenharmony_ciVariable *VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable,
9993af6ab5fSopenharmony_ci                                      Decl *newDecl, VariableFlags flags)
10003af6ab5fSopenharmony_ci{
10013af6ab5fSopenharmony_ci    ASSERT(!currentVariable);
10023af6ab5fSopenharmony_ci    return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, flags)).first->second;
10033af6ab5fSopenharmony_ci}
10043af6ab5fSopenharmony_ci
10053af6ab5fSopenharmony_citemplate <typename T>
10063af6ab5fSopenharmony_ciVariable *VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl)
10073af6ab5fSopenharmony_ci{
10083af6ab5fSopenharmony_ci    if (currentVariable) {
10093af6ab5fSopenharmony_ci        return nullptr;
10103af6ab5fSopenharmony_ci    }
10113af6ab5fSopenharmony_ci
10123af6ab5fSopenharmony_ci    return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, VariableFlags::NONE)).first->second;
10133af6ab5fSopenharmony_ci}
10143af6ab5fSopenharmony_ci
10153af6ab5fSopenharmony_citemplate <typename T, typename... Args>
10163af6ab5fSopenharmony_ciT *Scope::NewDecl(ArenaAllocator *allocator, Args &&...args)
10173af6ab5fSopenharmony_ci{
10183af6ab5fSopenharmony_ci    T *decl = allocator->New<T>(std::forward<Args>(args)...);
10193af6ab5fSopenharmony_ci    decls_.push_back(decl);
10203af6ab5fSopenharmony_ci
10213af6ab5fSopenharmony_ci    return decl;
10223af6ab5fSopenharmony_ci}
10233af6ab5fSopenharmony_ci
10243af6ab5fSopenharmony_citemplate <typename DeclType, typename VariableType>
10253af6ab5fSopenharmony_ciVariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags)
10263af6ab5fSopenharmony_ci{
10273af6ab5fSopenharmony_ci    if (FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS)) {
10283af6ab5fSopenharmony_ci        return nullptr;
10293af6ab5fSopenharmony_ci    }
10303af6ab5fSopenharmony_ci
10313af6ab5fSopenharmony_ci    auto *decl = allocator->New<DeclType>(name);
10323af6ab5fSopenharmony_ci    auto *variable = allocator->New<VariableType>(decl, flags);
10333af6ab5fSopenharmony_ci
10343af6ab5fSopenharmony_ci    decls_.push_back(decl);
10353af6ab5fSopenharmony_ci    bindings_.insert({decl->Name(), variable});
10363af6ab5fSopenharmony_ci    variable->SetScope(this);
10373af6ab5fSopenharmony_ci
10383af6ab5fSopenharmony_ci    return variable;
10393af6ab5fSopenharmony_ci}
10403af6ab5fSopenharmony_ci
10413af6ab5fSopenharmony_citemplate <typename DeclType, typename VariableType>
10423af6ab5fSopenharmony_ciVariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags, ir::AstNode *node)
10433af6ab5fSopenharmony_ci{
10443af6ab5fSopenharmony_ci    auto *decl = allocator->New<DeclType>(name);
10453af6ab5fSopenharmony_ci    auto *variable = allocator->New<VariableType>(decl, flags);
10463af6ab5fSopenharmony_ci    decl->BindNode(node);
10473af6ab5fSopenharmony_ci    return variable;
10483af6ab5fSopenharmony_ci}
10493af6ab5fSopenharmony_ci
10503af6ab5fSopenharmony_citemplate <typename T, typename... Args>
10513af6ab5fSopenharmony_ciVariable *Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&...args)
10523af6ab5fSopenharmony_ci{
10533af6ab5fSopenharmony_ci    auto res = bindings_.find(name);
10543af6ab5fSopenharmony_ci    if (res == bindings_.end()) {
10553af6ab5fSopenharmony_ci        return bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)}).first->second;
10563af6ab5fSopenharmony_ci    }
10573af6ab5fSopenharmony_ci
10583af6ab5fSopenharmony_ci    res->second->Reset(std::forward<Args>(args)...);
10593af6ab5fSopenharmony_ci    return res->second;
10603af6ab5fSopenharmony_ci}
10613af6ab5fSopenharmony_ci}  // namespace ark::es2panda::varbinder
10623af6ab5fSopenharmony_ci
10633af6ab5fSopenharmony_ci#endif
1064