13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2023-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#include "util/errorHandler.h"
173af6ab5fSopenharmony_ci#include "scopesInitPhase.h"
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_cinamespace ark::es2panda::compiler {
203af6ab5fSopenharmony_ci
213af6ab5fSopenharmony_citemplate <typename T>
223af6ab5fSopenharmony_civarbinder::LexicalScope<T> LexicalScopeCreateOrEnter(varbinder::VarBinder *varBinder, ir::AstNode *ast)
233af6ab5fSopenharmony_ci{
243af6ab5fSopenharmony_ci    if (ast != nullptr && ast->Scope() != nullptr) {
253af6ab5fSopenharmony_ci        return varbinder::LexicalScope<T>::Enter(varBinder, reinterpret_cast<T *>(ast->Scope()));
263af6ab5fSopenharmony_ci    }
273af6ab5fSopenharmony_ci    return varbinder::LexicalScope<T>(varBinder);
283af6ab5fSopenharmony_ci}
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_citemplate <typename T, typename... Args>
313af6ab5fSopenharmony_ciT *AddOrGetDecl(varbinder::VarBinder *varBinder, util::StringView name, ir::AstNode *ast,
323af6ab5fSopenharmony_ci                const lexer::SourcePosition &pos, Args &&...args)
333af6ab5fSopenharmony_ci{
343af6ab5fSopenharmony_ci    if (auto *var = varBinder->GetScope()->FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS);
353af6ab5fSopenharmony_ci        var != nullptr && var->Declaration() != nullptr && var->Declaration()->Node() == ast) {
363af6ab5fSopenharmony_ci        return reinterpret_cast<T *>(var->Declaration());
373af6ab5fSopenharmony_ci    }
383af6ab5fSopenharmony_ci    return varBinder->AddDecl<T>(pos, args...);
393af6ab5fSopenharmony_ci}
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_cibool ScopesInitPhase::Perform(PhaseContext *ctx, parser::Program *program)
423af6ab5fSopenharmony_ci{
433af6ab5fSopenharmony_ci    Prepare(ctx, program);
443af6ab5fSopenharmony_ci    program->VarBinder()->InitTopScope();
453af6ab5fSopenharmony_ci    HandleBlockStmt(program->Ast(), GetScope());
463af6ab5fSopenharmony_ci    Finalize();
473af6ab5fSopenharmony_ci    return true;
483af6ab5fSopenharmony_ci}
493af6ab5fSopenharmony_ci
503af6ab5fSopenharmony_civoid ScopesInitPhase::VisitScriptFunction(ir::ScriptFunction *scriptFunction)
513af6ab5fSopenharmony_ci{
523af6ab5fSopenharmony_ci    if (auto *const id = scriptFunction->Id(); id != nullptr && id->Variable() == nullptr) {
533af6ab5fSopenharmony_ci        auto const *const curScope = VarBinder()->GetScope();
543af6ab5fSopenharmony_ci        auto const &functionName = id->Name();
553af6ab5fSopenharmony_ci        auto const res =
563af6ab5fSopenharmony_ci            curScope->Find(functionName, scriptFunction->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
573af6ab5fSopenharmony_ci                                                                    : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
583af6ab5fSopenharmony_ci        if (res.variable != nullptr && res.variable->Declaration()->IsFunctionDecl()) {
593af6ab5fSopenharmony_ci            id->SetVariable(res.variable);
603af6ab5fSopenharmony_ci        }
613af6ab5fSopenharmony_ci    }
623af6ab5fSopenharmony_ci
633af6ab5fSopenharmony_ci    HandleFunction(scriptFunction);
643af6ab5fSopenharmony_ci}
653af6ab5fSopenharmony_ci
663af6ab5fSopenharmony_civoid ScopesInitPhase::VisitBlockStatement(ir::BlockStatement *blockStmt)
673af6ab5fSopenharmony_ci{
683af6ab5fSopenharmony_ci    auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScopeWithTypeAlias>(VarBinder(), blockStmt);
693af6ab5fSopenharmony_ci    HandleBlockStmt(blockStmt, GetScope());
703af6ab5fSopenharmony_ci}
713af6ab5fSopenharmony_ci
723af6ab5fSopenharmony_civoid ScopesInitPhase::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
733af6ab5fSopenharmony_ci{
743af6ab5fSopenharmony_ci    ImportDeclarationContext importCtx(VarBinder());
753af6ab5fSopenharmony_ci    Iterate(importDeclaration);
763af6ab5fSopenharmony_ci    importCtx.BindImportDecl(importDeclaration);
773af6ab5fSopenharmony_ci}
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_civoid ScopesInitPhase::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
803af6ab5fSopenharmony_ci{
813af6ab5fSopenharmony_ci    Iterate(staticBlock);
823af6ab5fSopenharmony_ci}
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_civoid ScopesInitPhase::VisitMethodDefinition(ir::MethodDefinition *methodDefinition)
853af6ab5fSopenharmony_ci{
863af6ab5fSopenharmony_ci    Iterate(methodDefinition);
873af6ab5fSopenharmony_ci}
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_civarbinder::FunctionParamScope *ScopesInitPhase::HandleFunctionSig(ir::TSTypeParameterDeclaration *typeParams,
903af6ab5fSopenharmony_ci                                                                  const ir::FunctionSignature::FunctionParams &params,
913af6ab5fSopenharmony_ci                                                                  ir::TypeNode *returnType)
923af6ab5fSopenharmony_ci{
933af6ab5fSopenharmony_ci    auto typeParamsCtx = varbinder::LexicalScope<varbinder::LocalScope>(VarBinder());
943af6ab5fSopenharmony_ci    CallNode(typeParams);
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_ci    auto lexicalScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder());
973af6ab5fSopenharmony_ci    CallFuncParams(params);
983af6ab5fSopenharmony_ci    CallNode(returnType);
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci    return lexicalScope.GetScope();
1013af6ab5fSopenharmony_ci}
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_civoid ScopesInitPhase::HandleFunction(ir::ScriptFunction *function)
1043af6ab5fSopenharmony_ci{
1053af6ab5fSopenharmony_ci    CallNode(function->Id());
1063af6ab5fSopenharmony_ci    // NOTE(gogabr): this will skip type/value parameters when they are added to an existing function sig
1073af6ab5fSopenharmony_ci    auto funcParamScope = (function->Scope() == nullptr) ? HandleFunctionSig(function->TypeParams(), function->Params(),
1083af6ab5fSopenharmony_ci                                                                             function->ReturnTypeAnnotation())
1093af6ab5fSopenharmony_ci                                                         : function->Scope()->ParamScope();
1103af6ab5fSopenharmony_ci    auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false);
1113af6ab5fSopenharmony_ci
1123af6ab5fSopenharmony_ci    auto functionCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), function);
1133af6ab5fSopenharmony_ci    auto *functionScope = functionCtx.GetScope();
1143af6ab5fSopenharmony_ci    BindFunctionScopes(functionScope, funcParamScope);
1153af6ab5fSopenharmony_ci
1163af6ab5fSopenharmony_ci    if (function->Body() != nullptr && function->Body()->IsBlockStatement()) {
1173af6ab5fSopenharmony_ci        HandleBlockStmt(function->Body()->AsBlockStatement(), functionScope);
1183af6ab5fSopenharmony_ci    } else {
1193af6ab5fSopenharmony_ci        Iterate(function->Body());
1203af6ab5fSopenharmony_ci    }
1213af6ab5fSopenharmony_ci    BindScopeNode(functionScope, function);
1223af6ab5fSopenharmony_ci    funcParamScope->BindNode(function);
1233af6ab5fSopenharmony_ci}
1243af6ab5fSopenharmony_ci
1253af6ab5fSopenharmony_civoid ScopesInitPhase::HandleBlockStmt(ir::BlockStatement *block, varbinder::Scope *scope)
1263af6ab5fSopenharmony_ci{
1273af6ab5fSopenharmony_ci    if (block->Scope() == nullptr) {
1283af6ab5fSopenharmony_ci        BindScopeNode(scope, block);
1293af6ab5fSopenharmony_ci    }
1303af6ab5fSopenharmony_ci    Iterate(block);
1313af6ab5fSopenharmony_ci}
1323af6ab5fSopenharmony_ci
1333af6ab5fSopenharmony_civoid ScopesInitPhase::VisitClassDefinition(ir::ClassDefinition *classDef)
1343af6ab5fSopenharmony_ci{
1353af6ab5fSopenharmony_ci    auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
1363af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->PrivateId(), classDef, classDef->Start(),
1373af6ab5fSopenharmony_ci                                       classDef->PrivateId());
1383af6ab5fSopenharmony_ci    BindClassName(classDef);
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci    auto *classScope = classCtx.GetScope();
1413af6ab5fSopenharmony_ci    BindScopeNode(classScope, classDef);
1423af6ab5fSopenharmony_ci    Iterate(classDef);
1433af6ab5fSopenharmony_ci}
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_civoid ScopesInitPhase::VisitForUpdateStatement(ir::ForUpdateStatement *forUpdateStmt)
1463af6ab5fSopenharmony_ci{
1473af6ab5fSopenharmony_ci    auto declCtx = (forUpdateStmt->Scope() == nullptr)
1483af6ab5fSopenharmony_ci                       ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
1493af6ab5fSopenharmony_ci                       : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
1503af6ab5fSopenharmony_ci                             VarBinder(), forUpdateStmt->Scope()->DeclScope());
1513af6ab5fSopenharmony_ci    CallNode(forUpdateStmt->Init());
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_ci    auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forUpdateStmt);
1543af6ab5fSopenharmony_ci    AttachLabelToScope(forUpdateStmt);
1553af6ab5fSopenharmony_ci    CallNode(forUpdateStmt->Test());
1563af6ab5fSopenharmony_ci    CallNode(forUpdateStmt->Update());
1573af6ab5fSopenharmony_ci    CallNode(forUpdateStmt->Body());
1583af6ab5fSopenharmony_ci    lexicalScope.GetScope()->BindDecls(declCtx.GetScope());
1593af6ab5fSopenharmony_ci    HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forUpdateStmt);
1603af6ab5fSopenharmony_ci}
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_civoid ScopesInitPhase::VisitForInStatement(ir::ForInStatement *forInStmt)
1633af6ab5fSopenharmony_ci{
1643af6ab5fSopenharmony_ci    auto declCtx = (forInStmt->Scope() == nullptr)
1653af6ab5fSopenharmony_ci                       ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
1663af6ab5fSopenharmony_ci                       : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
1673af6ab5fSopenharmony_ci                             VarBinder(), forInStmt->Scope()->DeclScope());
1683af6ab5fSopenharmony_ci    CallNode(forInStmt->Left());
1693af6ab5fSopenharmony_ci
1703af6ab5fSopenharmony_ci    auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forInStmt);
1713af6ab5fSopenharmony_ci    CallNode(forInStmt->Right());
1723af6ab5fSopenharmony_ci    CallNode(forInStmt->Body());
1733af6ab5fSopenharmony_ci    HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forInStmt);
1743af6ab5fSopenharmony_ci}
1753af6ab5fSopenharmony_civoid ScopesInitPhase::VisitForOfStatement(ir::ForOfStatement *forOfStmt)
1763af6ab5fSopenharmony_ci{
1773af6ab5fSopenharmony_ci    auto declCtx = (forOfStmt->Scope() == nullptr)
1783af6ab5fSopenharmony_ci                       ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
1793af6ab5fSopenharmony_ci                       : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
1803af6ab5fSopenharmony_ci                             VarBinder(), forOfStmt->Scope()->DeclScope());
1813af6ab5fSopenharmony_ci    CallNode(forOfStmt->Left());
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci    auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forOfStmt);
1843af6ab5fSopenharmony_ci    AttachLabelToScope(forOfStmt);
1853af6ab5fSopenharmony_ci    CallNode(forOfStmt->Right());
1863af6ab5fSopenharmony_ci    CallNode(forOfStmt->Body());
1873af6ab5fSopenharmony_ci    HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forOfStmt);
1883af6ab5fSopenharmony_ci}
1893af6ab5fSopenharmony_ci
1903af6ab5fSopenharmony_civoid ScopesInitPhase::VisitCatchClause(ir::CatchClause *catchClause)
1913af6ab5fSopenharmony_ci{
1923af6ab5fSopenharmony_ci    auto catchParamCtx = (catchClause->Scope() == nullptr)
1933af6ab5fSopenharmony_ci                             ? varbinder::LexicalScope<varbinder::CatchParamScope>(VarBinder())
1943af6ab5fSopenharmony_ci                             : varbinder::LexicalScope<varbinder::CatchParamScope>::Enter(
1953af6ab5fSopenharmony_ci                                   VarBinder(), catchClause->Scope()->ParamScope());
1963af6ab5fSopenharmony_ci    auto *catchParamScope = catchParamCtx.GetScope();
1973af6ab5fSopenharmony_ci    auto *param = catchClause->Param();
1983af6ab5fSopenharmony_ci
1993af6ab5fSopenharmony_ci    CallNode(param);
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci    if (param != nullptr) {
2023af6ab5fSopenharmony_ci        auto [param_decl, var] = VarBinder()->AddParamDecl(param);
2033af6ab5fSopenharmony_ci        (void)param_decl;
2043af6ab5fSopenharmony_ci        if (param->IsIdentifier()) {
2053af6ab5fSopenharmony_ci            var->SetScope(catchParamScope);
2063af6ab5fSopenharmony_ci            param->AsIdentifier()->SetVariable(var);
2073af6ab5fSopenharmony_ci        }
2083af6ab5fSopenharmony_ci    }
2093af6ab5fSopenharmony_ci
2103af6ab5fSopenharmony_ci    // Catch Clause is scope bearer
2113af6ab5fSopenharmony_ci    catchParamScope->BindNode(catchClause);
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_ci    auto catchCtx = LexicalScopeCreateOrEnter<varbinder::CatchScope>(VarBinder(), catchClause);
2143af6ab5fSopenharmony_ci    auto *catchScope = catchCtx.GetScope();
2153af6ab5fSopenharmony_ci
2163af6ab5fSopenharmony_ci    catchScope->AssignParamScope(catchParamScope);
2173af6ab5fSopenharmony_ci    auto body = catchClause->Body();
2183af6ab5fSopenharmony_ci    HandleBlockStmt(body, catchScope);
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_ci    BindScopeNode(catchScope, catchClause);
2213af6ab5fSopenharmony_ci}
2223af6ab5fSopenharmony_ci
2233af6ab5fSopenharmony_civoid ScopesInitPhase::VisitVariableDeclarator(ir::VariableDeclarator *varDecl)
2243af6ab5fSopenharmony_ci{
2253af6ab5fSopenharmony_ci    auto init = varDecl->Id();
2263af6ab5fSopenharmony_ci    std::vector<ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
2273af6ab5fSopenharmony_ci    for (auto *binding : bindings) {
2283af6ab5fSopenharmony_ci        auto [decl, var] = AddOrGetVarDecl(varDecl->Flag(), varDecl->Start(), binding);
2293af6ab5fSopenharmony_ci        BindVarDecl(binding, init, decl, var);
2303af6ab5fSopenharmony_ci    }
2313af6ab5fSopenharmony_ci    Iterate(varDecl);
2323af6ab5fSopenharmony_ci}
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_civoid ScopesInitPhase::VisitSwitchStatement(ir::SwitchStatement *switchStmt)
2353af6ab5fSopenharmony_ci{
2363af6ab5fSopenharmony_ci    CallNode(switchStmt->Discriminant());
2373af6ab5fSopenharmony_ci    auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScopeWithTypeAlias>(VarBinder(), switchStmt);
2383af6ab5fSopenharmony_ci    AttachLabelToScope(switchStmt);
2393af6ab5fSopenharmony_ci    BindScopeNode(localCtx.GetScope(), switchStmt);
2403af6ab5fSopenharmony_ci    CallNode(switchStmt->Cases());
2413af6ab5fSopenharmony_ci}
2423af6ab5fSopenharmony_ci
2433af6ab5fSopenharmony_civoid ScopesInitPhase::VisitWhileStatement(ir::WhileStatement *whileStmt)
2443af6ab5fSopenharmony_ci{
2453af6ab5fSopenharmony_ci    CallNode(whileStmt->Test());
2463af6ab5fSopenharmony_ci    auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), whileStmt);
2473af6ab5fSopenharmony_ci    AttachLabelToScope(whileStmt);
2483af6ab5fSopenharmony_ci    BindScopeNode(lexicalScope.GetScope(), whileStmt);
2493af6ab5fSopenharmony_ci    CallNode(whileStmt->Body());
2503af6ab5fSopenharmony_ci}
2513af6ab5fSopenharmony_ci
2523af6ab5fSopenharmony_civoid ScopesInitPhase::VisitETSStructDeclaration(ir::ETSStructDeclaration *structDecl)
2533af6ab5fSopenharmony_ci{
2543af6ab5fSopenharmony_ci    Iterate(structDecl);
2553af6ab5fSopenharmony_ci    BindClassDefinition(structDecl->Definition());
2563af6ab5fSopenharmony_ci}
2573af6ab5fSopenharmony_ci
2583af6ab5fSopenharmony_civoid ScopesInitPhase::VisitClassDeclaration(ir::ClassDeclaration *classDecl)
2593af6ab5fSopenharmony_ci{
2603af6ab5fSopenharmony_ci    Iterate(classDecl);
2613af6ab5fSopenharmony_ci    BindClassDefinition(classDecl->Definition());
2623af6ab5fSopenharmony_ci}
2633af6ab5fSopenharmony_ci
2643af6ab5fSopenharmony_civoid ScopesInitPhase::VisitDoWhileStatement(ir::DoWhileStatement *doWhileStmt)
2653af6ab5fSopenharmony_ci{
2663af6ab5fSopenharmony_ci    auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), doWhileStmt);
2673af6ab5fSopenharmony_ci    AttachLabelToScope(doWhileStmt);
2683af6ab5fSopenharmony_ci    BindScopeNode(lexicalScope.GetScope(), doWhileStmt);
2693af6ab5fSopenharmony_ci    Iterate(doWhileStmt);
2703af6ab5fSopenharmony_ci}
2713af6ab5fSopenharmony_ci
2723af6ab5fSopenharmony_civoid ScopesInitPhase::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl)
2733af6ab5fSopenharmony_ci{
2743af6ab5fSopenharmony_ci    const auto func = funcDecl->Function();
2753af6ab5fSopenharmony_ci    if (!funcDecl->IsAnonymous()) {
2763af6ab5fSopenharmony_ci        CreateFuncDecl(func);
2773af6ab5fSopenharmony_ci    }
2783af6ab5fSopenharmony_ci    Iterate(funcDecl);
2793af6ab5fSopenharmony_ci}
2803af6ab5fSopenharmony_ci
2813af6ab5fSopenharmony_civoid ScopesInitPhase::VisitExportAllDeclaration(ir::ExportAllDeclaration *exportAllDecl)
2823af6ab5fSopenharmony_ci{
2833af6ab5fSopenharmony_ci    Iterate(exportAllDecl);
2843af6ab5fSopenharmony_ci    const auto name = exportAllDecl->Exported() != nullptr ? exportAllDecl->Exported()->Name() : "*";
2853af6ab5fSopenharmony_ci    auto *decl =
2863af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), name, exportAllDecl, exportAllDecl->Start(), name, "*");
2873af6ab5fSopenharmony_ci    VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportAllDecl, decl);
2883af6ab5fSopenharmony_ci}
2893af6ab5fSopenharmony_ci
2903af6ab5fSopenharmony_civoid ScopesInitPhase::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
2913af6ab5fSopenharmony_ci{
2923af6ab5fSopenharmony_ci    Iterate(importSpec);
2933af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(), "*",
2943af6ab5fSopenharmony_ci                                        importSpec->Local()->Name(), importSpec);
2953af6ab5fSopenharmony_ci}
2963af6ab5fSopenharmony_ci
2973af6ab5fSopenharmony_civoid ScopesInitPhase::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
2983af6ab5fSopenharmony_ci{
2993af6ab5fSopenharmony_ci    Iterate(importSpec);
3003af6ab5fSopenharmony_ci    const auto *imported = importSpec->Imported();
3013af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
3023af6ab5fSopenharmony_ci                                        imported->Name(), importSpec->Local()->Name(), importSpec);
3033af6ab5fSopenharmony_ci}
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_civoid ScopesInitPhase::VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier *importSpec)
3063af6ab5fSopenharmony_ci{
3073af6ab5fSopenharmony_ci    Iterate(importSpec);
3083af6ab5fSopenharmony_ci    const auto *local = importSpec->Local();
3093af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), local->Name(), importSpec, local->Start(), "default",
3103af6ab5fSopenharmony_ci                                        local->Name(), importSpec);
3113af6ab5fSopenharmony_ci}
3123af6ab5fSopenharmony_ci
3133af6ab5fSopenharmony_civoid ScopesInitPhase::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
3143af6ab5fSopenharmony_ci{
3153af6ab5fSopenharmony_ci    ExportDeclarationContext exportDeclCtx(VarBinder());
3163af6ab5fSopenharmony_ci    Iterate(exportDecl);
3173af6ab5fSopenharmony_ci    exportDeclCtx.BindExportDecl(exportDecl);
3183af6ab5fSopenharmony_ci}
3193af6ab5fSopenharmony_ci
3203af6ab5fSopenharmony_civoid ScopesInitPhase::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
3213af6ab5fSopenharmony_ci{
3223af6ab5fSopenharmony_ci    Iterate(arrowExpr);
3233af6ab5fSopenharmony_ci}
3243af6ab5fSopenharmony_ci
3253af6ab5fSopenharmony_civoid ScopesInitPhase::VisitDirectEvalExpression(ir::DirectEvalExpression *directCallExpr)
3263af6ab5fSopenharmony_ci{
3273af6ab5fSopenharmony_ci    VarBinder()->PropagateDirectEval();
3283af6ab5fSopenharmony_ci    Iterate(directCallExpr);
3293af6ab5fSopenharmony_ci}
3303af6ab5fSopenharmony_ci
3313af6ab5fSopenharmony_civoid ScopesInitPhase::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
3323af6ab5fSopenharmony_ci{
3333af6ab5fSopenharmony_ci    if (exportDecl->Decl() != nullptr) {
3343af6ab5fSopenharmony_ci        ExportDeclarationContext exportDeclCtx(VarBinder());
3353af6ab5fSopenharmony_ci        Iterate(exportDecl);
3363af6ab5fSopenharmony_ci        exportDeclCtx.BindExportDecl(exportDecl);
3373af6ab5fSopenharmony_ci    } else {
3383af6ab5fSopenharmony_ci        varbinder::ModuleScope::ExportDeclList exportDecls(program_->Allocator()->Adapter());
3393af6ab5fSopenharmony_ci
3403af6ab5fSopenharmony_ci        for (auto *spec : exportDecl->Specifiers()) {
3413af6ab5fSopenharmony_ci            auto *decl =
3423af6ab5fSopenharmony_ci                AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), spec->Local()->Name(), spec, exportDecl->Start(),
3433af6ab5fSopenharmony_ci                                                    spec->Exported()->Name(), spec->Local()->Name(), spec);
3443af6ab5fSopenharmony_ci            exportDecls.push_back(decl);
3453af6ab5fSopenharmony_ci        }
3463af6ab5fSopenharmony_ci        VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportDecl, std::move(exportDecls));
3473af6ab5fSopenharmony_ci    }
3483af6ab5fSopenharmony_ci}
3493af6ab5fSopenharmony_ci
3503af6ab5fSopenharmony_civoid ScopesInitPhase::VisitTSFunctionType(ir::TSFunctionType *funcType)
3513af6ab5fSopenharmony_ci{
3523af6ab5fSopenharmony_ci    auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::FunctionParamScope>(VarBinder(), funcType);
3533af6ab5fSopenharmony_ci    auto *funcParamScope = lexicalScope.GetScope();
3543af6ab5fSopenharmony_ci    BindScopeNode(funcParamScope, funcType);
3553af6ab5fSopenharmony_ci    Iterate(funcType);
3563af6ab5fSopenharmony_ci}
3573af6ab5fSopenharmony_ci
3583af6ab5fSopenharmony_civoid ScopesInitPhase::SetProgram(parser::Program *program) noexcept
3593af6ab5fSopenharmony_ci{
3603af6ab5fSopenharmony_ci    program_ = program;
3613af6ab5fSopenharmony_ci}
3623af6ab5fSopenharmony_ci
3633af6ab5fSopenharmony_civoid ScopesInitPhase::CallFuncParams(const ArenaVector<ir::Expression *> &params)
3643af6ab5fSopenharmony_ci{
3653af6ab5fSopenharmony_ci    // NOTE: extract params to separate class
3663af6ab5fSopenharmony_ci    for (auto *param : params) {
3673af6ab5fSopenharmony_ci        if (!param->IsETSParameterExpression()) {
3683af6ab5fSopenharmony_ci            VarBinder()->AddParamDecl(param);
3693af6ab5fSopenharmony_ci        }
3703af6ab5fSopenharmony_ci    }
3713af6ab5fSopenharmony_ci    CallNode(params);
3723af6ab5fSopenharmony_ci}
3733af6ab5fSopenharmony_ci
3743af6ab5fSopenharmony_civoid ScopesInitPhase::IterateNoTParams(ir::ClassDefinition *classDef)
3753af6ab5fSopenharmony_ci{
3763af6ab5fSopenharmony_ci    CallNode(classDef->Super());
3773af6ab5fSopenharmony_ci    CallNode(classDef->SuperTypeParams());
3783af6ab5fSopenharmony_ci    CallNode(classDef->Implements());
3793af6ab5fSopenharmony_ci    CallNode(classDef->Ctor());
3803af6ab5fSopenharmony_ci    CallNode(classDef->Body());
3813af6ab5fSopenharmony_ci}
3823af6ab5fSopenharmony_ci
3833af6ab5fSopenharmony_civoid ScopesInitPhase::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
3843af6ab5fSopenharmony_ci{
3853af6ab5fSopenharmony_ci    util::ErrorHandler::ThrowSyntaxError(Program(), errorMessage, pos);
3863af6ab5fSopenharmony_ci}
3873af6ab5fSopenharmony_ci
3883af6ab5fSopenharmony_civoid ScopesInitPhase::CreateFuncDecl(ir::ScriptFunction *func)
3893af6ab5fSopenharmony_ci{
3903af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::FunctionDecl>(VarBinder(), func->Id()->Name(), func, func->Id()->Start(), Allocator(),
3913af6ab5fSopenharmony_ci                                          func->Id()->Name(), func);
3923af6ab5fSopenharmony_ci}
3933af6ab5fSopenharmony_ci
3943af6ab5fSopenharmony_ciutil::StringView ScopesInitPhase::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
3953af6ab5fSopenharmony_ci{
3963af6ab5fSopenharmony_ci    return id->Name();
3973af6ab5fSopenharmony_ci}
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_civarbinder::Decl *ScopesInitPhase::BindClassName(ir::ClassDefinition *classDef)
4003af6ab5fSopenharmony_ci{
4013af6ab5fSopenharmony_ci    const auto identNode = classDef->Ident();
4023af6ab5fSopenharmony_ci    if (identNode == nullptr) {
4033af6ab5fSopenharmony_ci        return nullptr;
4043af6ab5fSopenharmony_ci    }
4053af6ab5fSopenharmony_ci
4063af6ab5fSopenharmony_ci    auto identDecl = AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), identNode->Name(), classDef, identNode->Start(),
4073af6ab5fSopenharmony_ci                                                        identNode->Name());
4083af6ab5fSopenharmony_ci    if (identDecl != nullptr) {
4093af6ab5fSopenharmony_ci        identDecl->BindNode(classDef);
4103af6ab5fSopenharmony_ci    }
4113af6ab5fSopenharmony_ci    return identDecl;
4123af6ab5fSopenharmony_ci}
4133af6ab5fSopenharmony_ci
4143af6ab5fSopenharmony_civoid ScopesInitPhase::BindFunctionScopes(varbinder::FunctionScope *scope, varbinder::FunctionParamScope *paramScope)
4153af6ab5fSopenharmony_ci{
4163af6ab5fSopenharmony_ci    scope->BindParamScope(paramScope);
4173af6ab5fSopenharmony_ci    paramScope->BindFunctionScope(scope);
4183af6ab5fSopenharmony_ci}
4193af6ab5fSopenharmony_ci
4203af6ab5fSopenharmony_civoid ScopesInitPhase::BindClassDefinition(ir::ClassDefinition *classDef)
4213af6ab5fSopenharmony_ci{
4223af6ab5fSopenharmony_ci    if (classDef->IsGlobal()) {
4233af6ab5fSopenharmony_ci        return;  // We handle it in ClassDeclaration
4243af6ab5fSopenharmony_ci    }
4253af6ab5fSopenharmony_ci    const auto locStart = classDef->Ident()->Start();
4263af6ab5fSopenharmony_ci    const auto &className = classDef->Ident()->Name();
4273af6ab5fSopenharmony_ci    if ((classDef->Modifiers() & ir::ClassDefinitionModifiers::CLASS_DECL) != 0U) {
4283af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::ClassDecl>(VarBinder(), className, classDef, locStart, className, classDef);
4293af6ab5fSopenharmony_ci    } else {
4303af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::LetDecl>(VarBinder(), className, classDef, locStart, className, classDef);
4313af6ab5fSopenharmony_ci    }
4323af6ab5fSopenharmony_ci}
4333af6ab5fSopenharmony_ci
4343af6ab5fSopenharmony_cistd::tuple<varbinder::Decl *, varbinder::Variable *> ScopesInitPhase::AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,
4353af6ab5fSopenharmony_ci                                                                                      lexer::SourcePosition startLoc,
4363af6ab5fSopenharmony_ci                                                                                      const ir::Identifier *id)
4373af6ab5fSopenharmony_ci{
4383af6ab5fSopenharmony_ci    if (auto var = id->Variable(); var != nullptr) {
4393af6ab5fSopenharmony_ci        return {var->Declaration(), var};
4403af6ab5fSopenharmony_ci    }
4413af6ab5fSopenharmony_ci    auto name = id->Name();
4423af6ab5fSopenharmony_ci    switch (flag) {
4433af6ab5fSopenharmony_ci        case ir::VariableDeclaratorFlag::LET:
4443af6ab5fSopenharmony_ci            return VarBinder()->NewVarDecl<varbinder::LetDecl>(startLoc, name);
4453af6ab5fSopenharmony_ci        case ir::VariableDeclaratorFlag::VAR:
4463af6ab5fSopenharmony_ci            return VarBinder()->NewVarDecl<varbinder::VarDecl>(startLoc, name);
4473af6ab5fSopenharmony_ci        case ir::VariableDeclaratorFlag::CONST:
4483af6ab5fSopenharmony_ci            return VarBinder()->NewVarDecl<varbinder::ConstDecl>(startLoc, name);
4493af6ab5fSopenharmony_ci        default:
4503af6ab5fSopenharmony_ci            UNREACHABLE();
4513af6ab5fSopenharmony_ci    }
4523af6ab5fSopenharmony_ci}
4533af6ab5fSopenharmony_ci
4543af6ab5fSopenharmony_civoid ScopesInitPhase::BindVarDecl([[maybe_unused]] ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
4553af6ab5fSopenharmony_ci                                  [[maybe_unused]] varbinder::Variable *var)
4563af6ab5fSopenharmony_ci{
4573af6ab5fSopenharmony_ci    decl->BindNode(init);
4583af6ab5fSopenharmony_ci}
4593af6ab5fSopenharmony_ci
4603af6ab5fSopenharmony_civoid ScopesInitPhase::AttachLabelToScope([[maybe_unused]] ir::AstNode *node) {}
4613af6ab5fSopenharmony_ci
4623af6ab5fSopenharmony_civoid ScopesInitPhase::VisitFunctionExpression(ir::FunctionExpression *funcExpr)
4633af6ab5fSopenharmony_ci{
4643af6ab5fSopenharmony_ci    Iterate(funcExpr);
4653af6ab5fSopenharmony_ci    if (!funcExpr->IsAnonymous()) {
4663af6ab5fSopenharmony_ci        auto func = funcExpr->Function();
4673af6ab5fSopenharmony_ci        auto id = funcExpr->Id();
4683af6ab5fSopenharmony_ci        auto *funcParamScope = func->Scope()->ParamScope();
4693af6ab5fSopenharmony_ci        funcParamScope->BindName(Allocator(), id->Name());
4703af6ab5fSopenharmony_ci        func->SetIdent(id->Clone(Allocator(), nullptr));
4713af6ab5fSopenharmony_ci    }
4723af6ab5fSopenharmony_ci}
4733af6ab5fSopenharmony_ci
4743af6ab5fSopenharmony_civoid ScopesInitPhase::Prepare(ScopesInitPhase::PhaseContext *ctx, parser::Program *program)
4753af6ab5fSopenharmony_ci{
4763af6ab5fSopenharmony_ci    ctx_ = ctx;
4773af6ab5fSopenharmony_ci    program_ = program;
4783af6ab5fSopenharmony_ci}
4793af6ab5fSopenharmony_ci
4803af6ab5fSopenharmony_civoid ScopesInitPhase::Finalize()
4813af6ab5fSopenharmony_ci{
4823af6ab5fSopenharmony_ci    AnalyzeExports();
4833af6ab5fSopenharmony_ci}
4843af6ab5fSopenharmony_ci
4853af6ab5fSopenharmony_civoid ScopesInitPhase::AnalyzeExports()
4863af6ab5fSopenharmony_ci{
4873af6ab5fSopenharmony_ci    if (Program()->Kind() == parser::ScriptKind::MODULE && VarBinder()->TopScope()->IsModuleScope() &&
4883af6ab5fSopenharmony_ci        !VarBinder()->TopScope()->AsModuleScope()->ExportAnalysis()) {
4893af6ab5fSopenharmony_ci        ThrowSyntaxError("Invalid exported binding", Program()->Ast()->End());
4903af6ab5fSopenharmony_ci    }
4913af6ab5fSopenharmony_ci}
4923af6ab5fSopenharmony_ci
4933af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSModuleDeclaration(ir::TSModuleDeclaration *moduleDecl)
4943af6ab5fSopenharmony_ci{
4953af6ab5fSopenharmony_ci    if (!moduleDecl->IsExternalOrAmbient()) {
4963af6ab5fSopenharmony_ci        auto name = moduleDecl->Name()->AsIdentifier()->Name();
4973af6ab5fSopenharmony_ci        auto *decl = AddOrGetDecl<varbinder::VarDecl>(VarBinder(), name, moduleDecl, moduleDecl->Name()->Start(), name);
4983af6ab5fSopenharmony_ci        decl->BindNode(moduleDecl);
4993af6ab5fSopenharmony_ci    }
5003af6ab5fSopenharmony_ci    auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), moduleDecl);
5013af6ab5fSopenharmony_ci    BindScopeNode(localCtx.GetScope(), moduleDecl);
5023af6ab5fSopenharmony_ci    Iterate(moduleDecl);
5033af6ab5fSopenharmony_ci}
5043af6ab5fSopenharmony_ci
5053af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSModuleBlock(ir::TSModuleBlock *block)
5063af6ab5fSopenharmony_ci{
5073af6ab5fSopenharmony_ci    auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), block);
5083af6ab5fSopenharmony_ci    Iterate(block);
5093af6ab5fSopenharmony_ci    BindScopeNode(localCtx.GetScope(), block);
5103af6ab5fSopenharmony_ci}
5113af6ab5fSopenharmony_ci
5123af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl)
5133af6ab5fSopenharmony_ci{
5143af6ab5fSopenharmony_ci    const auto id = typeAliasDecl->Id();
5153af6ab5fSopenharmony_ci    varbinder::TSBinding tsBinding(Allocator(), id->Name());
5163af6ab5fSopenharmony_ci    auto *decl = VarBinder()->AddTsDecl<varbinder::TypeAliasDecl>(id->Start(), tsBinding.View());
5173af6ab5fSopenharmony_ci    auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAliasDecl->TypeParams());
5183af6ab5fSopenharmony_ci    decl->BindNode(typeAliasDecl);
5193af6ab5fSopenharmony_ci    Iterate(typeAliasDecl);
5203af6ab5fSopenharmony_ci}
5213af6ab5fSopenharmony_ci
5223af6ab5fSopenharmony_ciutil::StringView ScopeInitTyped::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
5233af6ab5fSopenharmony_ci{
5243af6ab5fSopenharmony_ci    varbinder::TSBinding tsBinding(Allocator(), id->Name());
5253af6ab5fSopenharmony_ci    return tsBinding.View();
5263af6ab5fSopenharmony_ci}
5273af6ab5fSopenharmony_ci
5283af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfDecl)
5293af6ab5fSopenharmony_ci{
5303af6ab5fSopenharmony_ci    const auto &bindings = VarBinder()->GetScope()->Bindings();
5313af6ab5fSopenharmony_ci    const auto ident = interfDecl->Id();
5323af6ab5fSopenharmony_ci    const auto name = FormInterfaceOrEnumDeclarationIdBinding(ident);
5333af6ab5fSopenharmony_ci    auto res = bindings.find(name);
5343af6ab5fSopenharmony_ci
5353af6ab5fSopenharmony_ci    varbinder::InterfaceDecl *decl {};
5363af6ab5fSopenharmony_ci
5373af6ab5fSopenharmony_ci    bool alreadyExists = false;
5383af6ab5fSopenharmony_ci    if (res == bindings.end()) {
5393af6ab5fSopenharmony_ci        decl = VarBinder()->AddTsDecl<varbinder::InterfaceDecl>(ident->Start(), Allocator(), name);
5403af6ab5fSopenharmony_ci    } else if (!AllowInterfaceRedeclaration()) {
5413af6ab5fSopenharmony_ci        ThrowSyntaxError("Interface redeclaration is not allowed", interfDecl->Start());
5423af6ab5fSopenharmony_ci    } else if (!res->second->Declaration()->IsInterfaceDecl()) {
5433af6ab5fSopenharmony_ci        VarBinder()->ThrowRedeclaration(ident->Start(), ident->Name());
5443af6ab5fSopenharmony_ci    } else {
5453af6ab5fSopenharmony_ci        decl = res->second->Declaration()->AsInterfaceDecl();
5463af6ab5fSopenharmony_ci        alreadyExists = true;
5473af6ab5fSopenharmony_ci    }
5483af6ab5fSopenharmony_ci
5493af6ab5fSopenharmony_ci    CallNode(ident);
5503af6ab5fSopenharmony_ci    auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl->TypeParams());
5513af6ab5fSopenharmony_ci    CallNode(interfDecl->TypeParams());
5523af6ab5fSopenharmony_ci    CallNode(interfDecl->Extends());
5533af6ab5fSopenharmony_ci
5543af6ab5fSopenharmony_ci    auto localScope = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl);
5553af6ab5fSopenharmony_ci    auto *identDecl =
5563af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), ident->Name(), interfDecl, ident->Start(), ident->Name());
5573af6ab5fSopenharmony_ci    identDecl->BindNode(interfDecl);
5583af6ab5fSopenharmony_ci    BindScopeNode(localScope.GetScope(), interfDecl);
5593af6ab5fSopenharmony_ci
5603af6ab5fSopenharmony_ci    CallNode(interfDecl->Body());
5613af6ab5fSopenharmony_ci    if (!alreadyExists) {
5623af6ab5fSopenharmony_ci        decl->BindNode(interfDecl);
5633af6ab5fSopenharmony_ci    }
5643af6ab5fSopenharmony_ci    decl->Add(interfDecl);
5653af6ab5fSopenharmony_ci}
5663af6ab5fSopenharmony_ci
5673af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSEnumMember(ir::TSEnumMember *enumMember)
5683af6ab5fSopenharmony_ci{
5693af6ab5fSopenharmony_ci    const auto key = enumMember->Key();
5703af6ab5fSopenharmony_ci    util::StringView name;
5713af6ab5fSopenharmony_ci    if (key->IsIdentifier()) {
5723af6ab5fSopenharmony_ci        name = key->AsIdentifier()->Name();
5733af6ab5fSopenharmony_ci    } else if (key->IsStringLiteral()) {
5743af6ab5fSopenharmony_ci        name = key->AsStringLiteral()->Str();
5753af6ab5fSopenharmony_ci    } else {
5763af6ab5fSopenharmony_ci        UNREACHABLE();
5773af6ab5fSopenharmony_ci    }
5783af6ab5fSopenharmony_ci    auto *decl = AddOrGetDecl<varbinder::EnumDecl>(VarBinder(), name, enumMember, key->Start(), name);
5793af6ab5fSopenharmony_ci    decl->BindNode(enumMember);
5803af6ab5fSopenharmony_ci}
5813af6ab5fSopenharmony_ci
5823af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
5833af6ab5fSopenharmony_ci{
5843af6ab5fSopenharmony_ci    util::StringView ident = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
5853af6ab5fSopenharmony_ci    const auto &bindings = VarBinder()->GetScope()->Bindings();
5863af6ab5fSopenharmony_ci    auto res = bindings.find(ident);
5873af6ab5fSopenharmony_ci
5883af6ab5fSopenharmony_ci    varbinder::EnumLiteralDecl *decl {};
5893af6ab5fSopenharmony_ci    if (res == bindings.end()) {
5903af6ab5fSopenharmony_ci        decl = VarBinder()->AddTsDecl<varbinder::EnumLiteralDecl>(enumDecl->Start(), ident, enumDecl->IsConst());
5913af6ab5fSopenharmony_ci        varbinder::LexicalScope enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
5923af6ab5fSopenharmony_ci        decl->BindScope(enumCtx.GetScope());
5933af6ab5fSopenharmony_ci        BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), enumDecl);
5943af6ab5fSopenharmony_ci    } else if (!res->second->Declaration()->IsEnumLiteralDecl() ||
5953af6ab5fSopenharmony_ci               (enumDecl->IsConst() ^ res->second->Declaration()->AsEnumLiteralDecl()->IsConst()) != 0) {
5963af6ab5fSopenharmony_ci        auto loc = enumDecl->Key()->End();
5973af6ab5fSopenharmony_ci        loc.index++;
5983af6ab5fSopenharmony_ci        VarBinder()->ThrowRedeclaration(loc, enumDecl->Key()->Name());
5993af6ab5fSopenharmony_ci    } else {
6003af6ab5fSopenharmony_ci        decl = res->second->Declaration()->AsEnumLiteralDecl();
6013af6ab5fSopenharmony_ci
6023af6ab5fSopenharmony_ci        auto scopeCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), decl->Scope());
6033af6ab5fSopenharmony_ci    }
6043af6ab5fSopenharmony_ci    decl->BindNode(enumDecl);
6053af6ab5fSopenharmony_ci    Iterate(enumDecl);
6063af6ab5fSopenharmony_ci}
6073af6ab5fSopenharmony_ci
6083af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
6093af6ab5fSopenharmony_ci{
6103af6ab5fSopenharmony_ci    auto name = typeParam->Name()->Name();
6113af6ab5fSopenharmony_ci    auto decl = AddOrGetDecl<varbinder::TypeParameterDecl>(VarBinder(), name, typeParam, typeParam->Start(), name);
6123af6ab5fSopenharmony_ci    decl->BindNode(typeParam);
6133af6ab5fSopenharmony_ci    Iterate(typeParam);
6143af6ab5fSopenharmony_ci}
6153af6ab5fSopenharmony_ci
6163af6ab5fSopenharmony_civoid ScopeInitTyped::VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl)
6173af6ab5fSopenharmony_ci{
6183af6ab5fSopenharmony_ci    BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), paramDecl);
6193af6ab5fSopenharmony_ci    Iterate(paramDecl);
6203af6ab5fSopenharmony_ci}
6213af6ab5fSopenharmony_ci
6223af6ab5fSopenharmony_civoid ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *classDef)
6233af6ab5fSopenharmony_ci{
6243af6ab5fSopenharmony_ci    auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
6253af6ab5fSopenharmony_ci    CallNode(classDef->TypeParams());
6263af6ab5fSopenharmony_ci
6273af6ab5fSopenharmony_ci    auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
6283af6ab5fSopenharmony_ci    BindClassName(classDef);
6293af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->PrivateId(), classDef, classDef->Start(),
6303af6ab5fSopenharmony_ci                                       classDef->PrivateId());
6313af6ab5fSopenharmony_ci    BindScopeNode(classCtx.GetScope(), classDef);
6323af6ab5fSopenharmony_ci    IterateNoTParams(classDef);
6333af6ab5fSopenharmony_ci}
6343af6ab5fSopenharmony_ci
6353af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
6363af6ab5fSopenharmony_ci{
6373af6ab5fSopenharmony_ci    ExportDeclarationContext exportDeclCtx(VarBinder());
6383af6ab5fSopenharmony_ci    Iterate(exportDecl);
6393af6ab5fSopenharmony_ci}
6403af6ab5fSopenharmony_ci
6413af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
6423af6ab5fSopenharmony_ci{
6433af6ab5fSopenharmony_ci    ExportDeclarationContext exportDeclCtx(VarBinder());
6443af6ab5fSopenharmony_ci    Iterate(exportDecl);
6453af6ab5fSopenharmony_ci}
6463af6ab5fSopenharmony_ci
6473af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
6483af6ab5fSopenharmony_ci{
6493af6ab5fSopenharmony_ci    ImportDeclarationContext importCtx(VarBinder());
6503af6ab5fSopenharmony_ci    Iterate(importDeclaration);
6513af6ab5fSopenharmony_ci}
6523af6ab5fSopenharmony_ci
6533af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constrType)
6543af6ab5fSopenharmony_ci{
6553af6ab5fSopenharmony_ci    auto lexicalScope =
6563af6ab5fSopenharmony_ci        (constrType->Scope() == nullptr)
6573af6ab5fSopenharmony_ci            ? HandleFunctionSig(constrType->TypeParams(), constrType->Params(), constrType->ReturnType())
6583af6ab5fSopenharmony_ci            : constrType->Scope();
6593af6ab5fSopenharmony_ci    BindScopeNode(lexicalScope, constrType);
6603af6ab5fSopenharmony_ci}
6613af6ab5fSopenharmony_ci
6623af6ab5fSopenharmony_civoid InitScopesPhaseTs::CreateFuncDecl(ir::ScriptFunction *func)
6633af6ab5fSopenharmony_ci{
6643af6ab5fSopenharmony_ci    const auto identNode = func->Id();
6653af6ab5fSopenharmony_ci    const auto startLoc = identNode->Start();
6663af6ab5fSopenharmony_ci    const auto &bindings = VarBinder()->GetScope()->Bindings();
6673af6ab5fSopenharmony_ci    auto res = bindings.find(identNode->Name());
6683af6ab5fSopenharmony_ci    varbinder::FunctionDecl *decl {};
6693af6ab5fSopenharmony_ci
6703af6ab5fSopenharmony_ci    if (res == bindings.end()) {
6713af6ab5fSopenharmony_ci        decl = VarBinder()->AddDecl<varbinder::FunctionDecl>(startLoc, Allocator(), identNode->Name(), func);
6723af6ab5fSopenharmony_ci    } else {
6733af6ab5fSopenharmony_ci        varbinder::Decl *currentDecl = res->second->Declaration();
6743af6ab5fSopenharmony_ci
6753af6ab5fSopenharmony_ci        auto &existing = currentDecl->AsFunctionDecl()->Decls();
6763af6ab5fSopenharmony_ci        if (std::find(existing.begin(), existing.end(), func) != existing.end()) {
6773af6ab5fSopenharmony_ci            return;
6783af6ab5fSopenharmony_ci        }
6793af6ab5fSopenharmony_ci
6803af6ab5fSopenharmony_ci        if (!currentDecl->IsFunctionDecl() ||
6813af6ab5fSopenharmony_ci            !currentDecl->AsFunctionDecl()->Node()->AsScriptFunction()->IsOverload()) {
6823af6ab5fSopenharmony_ci            VarBinder()->ThrowRedeclaration(startLoc, currentDecl->Name());
6833af6ab5fSopenharmony_ci        }
6843af6ab5fSopenharmony_ci        decl = currentDecl->AsFunctionDecl();
6853af6ab5fSopenharmony_ci    }
6863af6ab5fSopenharmony_ci
6873af6ab5fSopenharmony_ci    decl->Add(func);
6883af6ab5fSopenharmony_ci}
6893af6ab5fSopenharmony_ci
6903af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constrT)
6913af6ab5fSopenharmony_ci{
6923af6ab5fSopenharmony_ci    auto funcParamScope = (constrT->Scope() == nullptr)
6933af6ab5fSopenharmony_ci                              ? HandleFunctionSig(constrT->TypeParams(), constrT->Params(), constrT->ReturnType())
6943af6ab5fSopenharmony_ci                              : constrT->Scope();
6953af6ab5fSopenharmony_ci    BindScopeNode(funcParamScope, constrT);
6963af6ab5fSopenharmony_ci}
6973af6ab5fSopenharmony_ci
6983af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr)
6993af6ab5fSopenharmony_ci{
7003af6ab5fSopenharmony_ci    auto typeParamsCtx =
7013af6ab5fSopenharmony_ci        LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), arrowFExpr->Function()->TypeParams());
7023af6ab5fSopenharmony_ci    Iterate(arrowFExpr);
7033af6ab5fSopenharmony_ci}
7043af6ab5fSopenharmony_ci
7053af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl)
7063af6ab5fSopenharmony_ci{
7073af6ab5fSopenharmony_ci    auto funcParamScope = (signDecl->Scope() == nullptr) ? HandleFunctionSig(signDecl->TypeParams(), signDecl->Params(),
7083af6ab5fSopenharmony_ci                                                                             signDecl->ReturnTypeAnnotation())
7093af6ab5fSopenharmony_ci                                                         : signDecl->Scope();
7103af6ab5fSopenharmony_ci    BindScopeNode(funcParamScope, signDecl);
7113af6ab5fSopenharmony_ci}
7123af6ab5fSopenharmony_ci
7133af6ab5fSopenharmony_civoid InitScopesPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *methodSign)
7143af6ab5fSopenharmony_ci{
7153af6ab5fSopenharmony_ci    auto funcParamScope =
7163af6ab5fSopenharmony_ci        (methodSign->Scope() == nullptr)
7173af6ab5fSopenharmony_ci            ? HandleFunctionSig(methodSign->TypeParams(), methodSign->Params(), methodSign->ReturnTypeAnnotation())
7183af6ab5fSopenharmony_ci            : methodSign->Scope();
7193af6ab5fSopenharmony_ci    BindScopeNode(funcParamScope, methodSign);
7203af6ab5fSopenharmony_ci}
7213af6ab5fSopenharmony_ci
7223af6ab5fSopenharmony_civoid InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder)
7233af6ab5fSopenharmony_ci{
7243af6ab5fSopenharmony_ci    auto program = parser::Program(varbinder->Allocator(), varbinder);
7253af6ab5fSopenharmony_ci    RunExternalNode(node, &program);
7263af6ab5fSopenharmony_ci}
7273af6ab5fSopenharmony_ci
7283af6ab5fSopenharmony_civoid InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, parser::Program *ctx)
7293af6ab5fSopenharmony_ci{
7303af6ab5fSopenharmony_ci    auto scopesPhase = InitScopesPhaseETS();
7313af6ab5fSopenharmony_ci    scopesPhase.SetProgram(ctx);
7323af6ab5fSopenharmony_ci    scopesPhase.CallNode(node);
7333af6ab5fSopenharmony_ci}
7343af6ab5fSopenharmony_ci
7353af6ab5fSopenharmony_cibool InitScopesPhaseETS::Perform(PhaseContext *ctx, parser::Program *program)
7363af6ab5fSopenharmony_ci{
7373af6ab5fSopenharmony_ci    Prepare(ctx, program);
7383af6ab5fSopenharmony_ci
7393af6ab5fSopenharmony_ci    if (program->VarBinder()->TopScope() == nullptr) {
7403af6ab5fSopenharmony_ci        program->VarBinder()->InitTopScope();
7413af6ab5fSopenharmony_ci        BindScopeNode(GetScope(), program->Ast());
7423af6ab5fSopenharmony_ci        AddGlobalToBinder(program);
7433af6ab5fSopenharmony_ci    }
7443af6ab5fSopenharmony_ci    HandleProgram(program);
7453af6ab5fSopenharmony_ci    Finalize();
7463af6ab5fSopenharmony_ci    return true;
7473af6ab5fSopenharmony_ci}
7483af6ab5fSopenharmony_ci
7493af6ab5fSopenharmony_civoid InitScopesPhaseETS::HandleProgram(parser::Program *program)
7503af6ab5fSopenharmony_ci{
7513af6ab5fSopenharmony_ci    for (auto &[_, prog_list] : program->ExternalSources()) {
7523af6ab5fSopenharmony_ci        (void)_;
7533af6ab5fSopenharmony_ci        auto savedTopScope(program->VarBinder()->TopScope());
7543af6ab5fSopenharmony_ci        auto mainProg = prog_list.front();
7553af6ab5fSopenharmony_ci        mainProg->VarBinder()->InitTopScope();
7563af6ab5fSopenharmony_ci        AddGlobalToBinder(mainProg);
7573af6ab5fSopenharmony_ci        BindScopeNode(mainProg->VarBinder()->GetScope(), mainProg->Ast());
7583af6ab5fSopenharmony_ci        auto globalClass = mainProg->GlobalClass();
7593af6ab5fSopenharmony_ci        auto globalScope = mainProg->GlobalScope();
7603af6ab5fSopenharmony_ci        for (auto &prog : prog_list) {
7613af6ab5fSopenharmony_ci            prog->SetGlobalClass(globalClass);
7623af6ab5fSopenharmony_ci            BindScopeNode(prog->VarBinder()->GetScope(), prog->Ast());
7633af6ab5fSopenharmony_ci            prog->VarBinder()->ResetTopScope(globalScope);
7643af6ab5fSopenharmony_ci            if (mainProg->Ast() != nullptr) {
7653af6ab5fSopenharmony_ci                InitScopesPhaseETS().Perform(Context(), prog);
7663af6ab5fSopenharmony_ci            }
7673af6ab5fSopenharmony_ci        }
7683af6ab5fSopenharmony_ci        program->VarBinder()->ResetTopScope(savedTopScope);
7693af6ab5fSopenharmony_ci    }
7703af6ab5fSopenharmony_ci    ASSERT(program->Ast() != nullptr);
7713af6ab5fSopenharmony_ci
7723af6ab5fSopenharmony_ci    HandleETSScript(program->Ast());
7733af6ab5fSopenharmony_ci}
7743af6ab5fSopenharmony_ci
7753af6ab5fSopenharmony_civoid InitScopesPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
7763af6ab5fSopenharmony_ci                                     varbinder::Variable *var)
7773af6ab5fSopenharmony_ci{
7783af6ab5fSopenharmony_ci    binding->SetVariable(var);
7793af6ab5fSopenharmony_ci    var->SetScope(VarBinder()->GetScope());
7803af6ab5fSopenharmony_ci    var->AddFlag(varbinder::VariableFlags::LOCAL);
7813af6ab5fSopenharmony_ci    decl->BindNode(init);
7823af6ab5fSopenharmony_ci}
7833af6ab5fSopenharmony_ci
7843af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitBlockExpression(ir::BlockExpression *blockExpr)
7853af6ab5fSopenharmony_ci{
7863af6ab5fSopenharmony_ci    auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), blockExpr);
7873af6ab5fSopenharmony_ci    if (blockExpr->Scope() == nullptr) {
7883af6ab5fSopenharmony_ci        BindScopeNode(GetScope(), blockExpr);
7893af6ab5fSopenharmony_ci    }
7903af6ab5fSopenharmony_ci    Iterate(blockExpr);
7913af6ab5fSopenharmony_ci}
7923af6ab5fSopenharmony_ci
7933af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
7943af6ab5fSopenharmony_ci{
7953af6ab5fSopenharmony_ci    const auto func = staticBlock->Function();
7963af6ab5fSopenharmony_ci
7973af6ab5fSopenharmony_ci    {
7983af6ab5fSopenharmony_ci        auto funcParamCtx = (func->Scope() == nullptr)
7993af6ab5fSopenharmony_ci                                ? varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder())
8003af6ab5fSopenharmony_ci                                : varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(
8013af6ab5fSopenharmony_ci                                      VarBinder(), func->Scope()->ParamScope());
8023af6ab5fSopenharmony_ci        auto *funcParamScope = funcParamCtx.GetScope();
8033af6ab5fSopenharmony_ci        auto funcCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), func);
8043af6ab5fSopenharmony_ci        auto *funcScope = funcCtx.GetScope();
8053af6ab5fSopenharmony_ci
8063af6ab5fSopenharmony_ci        func->Body()->AsBlockStatement()->SetScope(funcScope);
8073af6ab5fSopenharmony_ci        BindScopeNode(funcScope, func);
8083af6ab5fSopenharmony_ci        funcParamScope->BindNode(func);
8093af6ab5fSopenharmony_ci        BindFunctionScopes(funcScope, funcParamScope);
8103af6ab5fSopenharmony_ci        Iterate(func->Body()->AsBlockStatement());
8113af6ab5fSopenharmony_ci    }
8123af6ab5fSopenharmony_ci
8133af6ab5fSopenharmony_ci    auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
8143af6ab5fSopenharmony_ci        VarBinder(), VarBinder()->GetScope()->AsClassScope()->StaticMethodScope());
8153af6ab5fSopenharmony_ci
8163af6ab5fSopenharmony_ci    if (func->Id()->Variable() != nullptr) {
8173af6ab5fSopenharmony_ci        return;
8183af6ab5fSopenharmony_ci    }
8193af6ab5fSopenharmony_ci
8203af6ab5fSopenharmony_ci    auto [_, var] = VarBinder()->NewVarDecl<varbinder::FunctionDecl>(staticBlock->Start(), Allocator(),
8213af6ab5fSopenharmony_ci                                                                     func->Id()->Name(), staticBlock);
8223af6ab5fSopenharmony_ci    (void)_;
8233af6ab5fSopenharmony_ci    var->AddFlag(varbinder::VariableFlags::METHOD);
8243af6ab5fSopenharmony_ci    func->Id()->SetVariable(var);
8253af6ab5fSopenharmony_ci}
8263af6ab5fSopenharmony_ci
8273af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
8283af6ab5fSopenharmony_ci{
8293af6ab5fSopenharmony_ci    if (importSpec->Local()->Name().Empty()) {
8303af6ab5fSopenharmony_ci        return;
8313af6ab5fSopenharmony_ci    }
8323af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
8333af6ab5fSopenharmony_ci                                        importSpec->Local()->Name(), importSpec->Local()->Name(), importSpec);
8343af6ab5fSopenharmony_ci    auto var =
8353af6ab5fSopenharmony_ci        VarBinder()->GetScope()->FindLocal(importSpec->Local()->Name(), varbinder::ResolveBindingOptions::BINDINGS);
8363af6ab5fSopenharmony_ci    importSpec->Local()->SetVariable(var);
8373af6ab5fSopenharmony_ci    Iterate(importSpec);
8383af6ab5fSopenharmony_ci}
8393af6ab5fSopenharmony_ci
8403af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
8413af6ab5fSopenharmony_ci{
8423af6ab5fSopenharmony_ci    if (importSpec->Parent()->AsETSImportDeclaration()->IsPureDynamic()) {
8433af6ab5fSopenharmony_ci        auto [decl, var] =
8443af6ab5fSopenharmony_ci            VarBinder()->NewVarDecl<varbinder::LetDecl>(importSpec->Start(), importSpec->Local()->Name(), importSpec);
8453af6ab5fSopenharmony_ci        var->AddFlag(varbinder::VariableFlags::INITIALIZED);
8463af6ab5fSopenharmony_ci    }
8473af6ab5fSopenharmony_ci    Iterate(importSpec);
8483af6ab5fSopenharmony_ci}
8493af6ab5fSopenharmony_ci
8503af6ab5fSopenharmony_ci//  Auxiliary method to avoid extra nested levels and too large function size
8513af6ab5fSopenharmony_civoid AddOverload(ir::MethodDefinition *overload, varbinder::Variable *variable) noexcept
8523af6ab5fSopenharmony_ci{
8533af6ab5fSopenharmony_ci    auto *currentNode = variable->Declaration()->Node();
8543af6ab5fSopenharmony_ci    currentNode->AsMethodDefinition()->AddOverload(overload);
8553af6ab5fSopenharmony_ci    overload->Id()->SetVariable(variable);
8563af6ab5fSopenharmony_ci    overload->SetParent(currentNode);
8573af6ab5fSopenharmony_ci}
8583af6ab5fSopenharmony_ci
8593af6ab5fSopenharmony_civoid InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method)
8603af6ab5fSopenharmony_ci{
8613af6ab5fSopenharmony_ci    ASSERT(VarBinder()->GetScope()->IsClassScope());
8623af6ab5fSopenharmony_ci
8633af6ab5fSopenharmony_ci    if ((method->AsMethodDefinition()->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) != 0) {
8643af6ab5fSopenharmony_ci        return;
8653af6ab5fSopenharmony_ci    }
8663af6ab5fSopenharmony_ci
8673af6ab5fSopenharmony_ci    const auto methodName = method->Id();
8683af6ab5fSopenharmony_ci    auto *const clsScope = VarBinder()->GetScope()->AsClassScope();
8693af6ab5fSopenharmony_ci    auto options =
8703af6ab5fSopenharmony_ci        method->IsStatic()
8713af6ab5fSopenharmony_ci            ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION
8723af6ab5fSopenharmony_ci            : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION;
8733af6ab5fSopenharmony_ci    if (clsScope->FindLocal(methodName->Name(), options) != nullptr) {
8743af6ab5fSopenharmony_ci        VarBinder()->ThrowRedeclaration(methodName->Start(), methodName->Name());
8753af6ab5fSopenharmony_ci    }
8763af6ab5fSopenharmony_ci
8773af6ab5fSopenharmony_ci    varbinder::LocalScope *targetScope {};
8783af6ab5fSopenharmony_ci    if (method->IsStatic() || method->IsConstructor()) {
8793af6ab5fSopenharmony_ci        targetScope = clsScope->StaticMethodScope();
8803af6ab5fSopenharmony_ci    } else {
8813af6ab5fSopenharmony_ci        targetScope = clsScope->InstanceMethodScope();
8823af6ab5fSopenharmony_ci    }
8833af6ab5fSopenharmony_ci    auto *found = targetScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::BINDINGS);
8843af6ab5fSopenharmony_ci
8853af6ab5fSopenharmony_ci    MaybeAddOverload(method, methodName, found, clsScope, targetScope);
8863af6ab5fSopenharmony_ci}
8873af6ab5fSopenharmony_ci
8883af6ab5fSopenharmony_civoid InitScopesPhaseETS::MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName,
8893af6ab5fSopenharmony_ci                                          varbinder::Variable *found, varbinder::ClassScope *clsScope,
8903af6ab5fSopenharmony_ci                                          varbinder::LocalScope *targetScope)
8913af6ab5fSopenharmony_ci{
8923af6ab5fSopenharmony_ci    if (found == nullptr) {
8933af6ab5fSopenharmony_ci        auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), targetScope);
8943af6ab5fSopenharmony_ci
8953af6ab5fSopenharmony_ci        auto *var = methodName->Variable();
8963af6ab5fSopenharmony_ci        if (var == nullptr) {
8973af6ab5fSopenharmony_ci            var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(methodName->Start(), Allocator(),
8983af6ab5fSopenharmony_ci                                                                               methodName->Name(), method));
8993af6ab5fSopenharmony_ci            var->SetScope(clsScope);
9003af6ab5fSopenharmony_ci            var->AddFlag(varbinder::VariableFlags::METHOD);
9013af6ab5fSopenharmony_ci            methodName->SetVariable(var);
9023af6ab5fSopenharmony_ci        }
9033af6ab5fSopenharmony_ci        for (auto *overload : method->Overloads()) {
9043af6ab5fSopenharmony_ci            ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD));
9053af6ab5fSopenharmony_ci            overload->Id()->SetVariable(var);
9063af6ab5fSopenharmony_ci            overload->SetParent(var->Declaration()->Node());
9073af6ab5fSopenharmony_ci        }
9083af6ab5fSopenharmony_ci    } else {
9093af6ab5fSopenharmony_ci        if (methodName->Name().Is(compiler::Signatures::MAIN) && clsScope->Parent()->IsGlobalScope()) {
9103af6ab5fSopenharmony_ci            ThrowSyntaxError("Main overload is not enabled", methodName->Start());
9113af6ab5fSopenharmony_ci        }
9123af6ab5fSopenharmony_ci        AddOverload(method, found);
9133af6ab5fSopenharmony_ci        method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
9143af6ab5fSopenharmony_ci
9153af6ab5fSopenharmony_ci        // default params overloads
9163af6ab5fSopenharmony_ci        for (auto *overload : method->Overloads()) {
9173af6ab5fSopenharmony_ci            ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD));
9183af6ab5fSopenharmony_ci            AddOverload(overload, found);
9193af6ab5fSopenharmony_ci        }
9203af6ab5fSopenharmony_ci        method->ClearOverloads();
9213af6ab5fSopenharmony_ci    }
9223af6ab5fSopenharmony_ci}
9233af6ab5fSopenharmony_ci
9243af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport)
9253af6ab5fSopenharmony_ci{
9263af6ab5fSopenharmony_ci    if (reExport->GetETSImportDeclarations()->Language().IsDynamic()) {
9273af6ab5fSopenharmony_ci        VarBinder()->AsETSBinder()->AddDynamicImport(reExport->GetETSImportDeclarations());
9283af6ab5fSopenharmony_ci    }
9293af6ab5fSopenharmony_ci    VarBinder()->AsETSBinder()->AddReExportImport(reExport);
9303af6ab5fSopenharmony_ci}
9313af6ab5fSopenharmony_ci
9323af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr)
9333af6ab5fSopenharmony_ci{
9343af6ab5fSopenharmony_ci    auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramExpr));
9353af6ab5fSopenharmony_ci    paramExpr->Ident()->SetVariable(var);
9363af6ab5fSopenharmony_ci    var->SetScope(VarBinder()->GetScope());
9373af6ab5fSopenharmony_ci    Iterate(paramExpr);
9383af6ab5fSopenharmony_ci}
9393af6ab5fSopenharmony_ci
9403af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl)
9413af6ab5fSopenharmony_ci{
9423af6ab5fSopenharmony_ci    ImportDeclarationContext importCtx(VarBinder());
9433af6ab5fSopenharmony_ci    if (importDecl->Language().IsDynamic()) {
9443af6ab5fSopenharmony_ci        VarBinder()->AsETSBinder()->AddDynamicImport(importDecl);
9453af6ab5fSopenharmony_ci    }
9463af6ab5fSopenharmony_ci    Iterate(importDecl);
9473af6ab5fSopenharmony_ci}
9483af6ab5fSopenharmony_ci
9493af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember)
9503af6ab5fSopenharmony_ci{
9513af6ab5fSopenharmony_ci    auto ident = enumMember->Key()->AsIdentifier();
9523af6ab5fSopenharmony_ci    if (ident->Variable() != nullptr) {
9533af6ab5fSopenharmony_ci        return;
9543af6ab5fSopenharmony_ci    }
9553af6ab5fSopenharmony_ci    auto [decl, var] = VarBinder()->NewVarDecl<varbinder::LetDecl>(ident->Start(), ident->Name());
9563af6ab5fSopenharmony_ci    var->SetScope(VarBinder()->GetScope());
9573af6ab5fSopenharmony_ci    var->AddFlag(varbinder::VariableFlags::STATIC);
9583af6ab5fSopenharmony_ci    ident->SetVariable(var);
9593af6ab5fSopenharmony_ci    decl->BindNode(enumMember);
9603af6ab5fSopenharmony_ci    Iterate(enumMember);
9613af6ab5fSopenharmony_ci}
9623af6ab5fSopenharmony_ci
9633af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method)
9643af6ab5fSopenharmony_ci{
9653af6ab5fSopenharmony_ci    auto *curScope = VarBinder()->GetScope();
9663af6ab5fSopenharmony_ci    const auto methodName = method->Id();
9673af6ab5fSopenharmony_ci    auto res =
9683af6ab5fSopenharmony_ci        curScope->Find(methodName->Name(), method->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
9693af6ab5fSopenharmony_ci                                                              : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
9703af6ab5fSopenharmony_ci    if (res.variable != nullptr && !res.variable->Declaration()->IsFunctionDecl() && res.scope == curScope) {
9713af6ab5fSopenharmony_ci        VarBinder()->ThrowRedeclaration(methodName->Start(), res.name);
9723af6ab5fSopenharmony_ci    }
9733af6ab5fSopenharmony_ci    Iterate(method);
9743af6ab5fSopenharmony_ci    DeclareClassMethod(method);
9753af6ab5fSopenharmony_ci}
9763af6ab5fSopenharmony_ci
9773af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType)
9783af6ab5fSopenharmony_ci{
9793af6ab5fSopenharmony_ci    auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), funcType->TypeParams());
9803af6ab5fSopenharmony_ci
9813af6ab5fSopenharmony_ci    // Check for existing scope
9823af6ab5fSopenharmony_ci    // In some cases we can visit function again with scope that already exists
9833af6ab5fSopenharmony_ci    // Example: async lambda, we "move" original function to another place and visit it again
9843af6ab5fSopenharmony_ci    if (funcType->Scope() == nullptr) {
9853af6ab5fSopenharmony_ci        varbinder::LexicalScope<varbinder::FunctionParamScope> lexicalScope(VarBinder());
9863af6ab5fSopenharmony_ci        auto *funcParamScope = lexicalScope.GetScope();
9873af6ab5fSopenharmony_ci        BindScopeNode(funcParamScope, funcType);
9883af6ab5fSopenharmony_ci        Iterate(funcType);
9893af6ab5fSopenharmony_ci    }
9903af6ab5fSopenharmony_ci}
9913af6ab5fSopenharmony_ci
9923af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr)
9933af6ab5fSopenharmony_ci{
9943af6ab5fSopenharmony_ci    CallNode(newClassExpr->GetArguments());
9953af6ab5fSopenharmony_ci    CallNode(newClassExpr->GetTypeRef());
9963af6ab5fSopenharmony_ci    if (newClassExpr->ClassDefinition() != nullptr) {
9973af6ab5fSopenharmony_ci        const auto classDef = newClassExpr->ClassDefinition();
9983af6ab5fSopenharmony_ci        auto *parentClassScope = VarBinder()->GetScope();
9993af6ab5fSopenharmony_ci        while (!parentClassScope->IsClassScope()) {
10003af6ab5fSopenharmony_ci            ASSERT(parentClassScope->Parent());
10013af6ab5fSopenharmony_ci            parentClassScope = parentClassScope->Parent();
10023af6ab5fSopenharmony_ci        }
10033af6ab5fSopenharmony_ci        auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), newClassExpr->ClassDefinition());
10043af6ab5fSopenharmony_ci        util::UString anonymousName(util::StringView("#"), Allocator());
10053af6ab5fSopenharmony_ci        anonymousName.Append(std::to_string(parentClassScope->AsClassScope()->GetAndIncrementAnonymousClassIdx()));
10063af6ab5fSopenharmony_ci        classDef->SetInternalName(anonymousName.View());
10073af6ab5fSopenharmony_ci        classDef->Ident()->SetName(anonymousName.View());
10083af6ab5fSopenharmony_ci        CallNode(classDef);
10093af6ab5fSopenharmony_ci    }
10103af6ab5fSopenharmony_ci}
10113af6ab5fSopenharmony_ci
10123af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
10133af6ab5fSopenharmony_ci{
10143af6ab5fSopenharmony_ci    if (typeParam->Name()->Variable() != nullptr) {
10153af6ab5fSopenharmony_ci        return;
10163af6ab5fSopenharmony_ci    }
10173af6ab5fSopenharmony_ci    auto [decl, var] =
10183af6ab5fSopenharmony_ci        VarBinder()->NewVarDecl<varbinder::TypeParameterDecl>(typeParam->Name()->Start(), typeParam->Name()->Name());
10193af6ab5fSopenharmony_ci    typeParam->Name()->SetVariable(var);
10203af6ab5fSopenharmony_ci    var->SetScope(VarBinder()->GetScope());
10213af6ab5fSopenharmony_ci    var->AddFlag(varbinder::VariableFlags::TYPE_PARAMETER);
10223af6ab5fSopenharmony_ci    decl->BindNode(typeParam);
10233af6ab5fSopenharmony_ci}
10243af6ab5fSopenharmony_ci
10253af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl)
10263af6ab5fSopenharmony_ci{
10273af6ab5fSopenharmony_ci    {
10283af6ab5fSopenharmony_ci        auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfaceDecl->TypeParams());
10293af6ab5fSopenharmony_ci        CallNode(interfaceDecl->TypeParams());
10303af6ab5fSopenharmony_ci        CallNode(interfaceDecl->Extends());
10313af6ab5fSopenharmony_ci        auto localScope = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), interfaceDecl);
10323af6ab5fSopenharmony_ci        CallNode(interfaceDecl->Body());
10333af6ab5fSopenharmony_ci        BindScopeNode(localScope.GetScope(), interfaceDecl);
10343af6ab5fSopenharmony_ci    }
10353af6ab5fSopenharmony_ci    auto name = FormInterfaceOrEnumDeclarationIdBinding(interfaceDecl->Id());
10363af6ab5fSopenharmony_ci    auto *decl = AddOrGetDecl<varbinder::InterfaceDecl>(VarBinder(), name, interfaceDecl, interfaceDecl->Start(),
10373af6ab5fSopenharmony_ci                                                        Allocator(), name, interfaceDecl);
10383af6ab5fSopenharmony_ci    decl->AsInterfaceDecl()->Add(interfaceDecl);
10393af6ab5fSopenharmony_ci}
10403af6ab5fSopenharmony_ci
10413af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
10423af6ab5fSopenharmony_ci{
10433af6ab5fSopenharmony_ci    {
10443af6ab5fSopenharmony_ci        const auto enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
10453af6ab5fSopenharmony_ci        BindScopeNode(enumCtx.GetScope(), enumDecl);
10463af6ab5fSopenharmony_ci        Iterate(enumDecl);
10473af6ab5fSopenharmony_ci    }
10483af6ab5fSopenharmony_ci    auto name = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
10493af6ab5fSopenharmony_ci    auto *decl = AddOrGetDecl<varbinder::EnumLiteralDecl>(VarBinder(), name, enumDecl, enumDecl->Start(), name,
10503af6ab5fSopenharmony_ci                                                          enumDecl, enumDecl->IsConst());
10513af6ab5fSopenharmony_ci    decl->BindScope(enumDecl->Scope());
10523af6ab5fSopenharmony_ci}
10533af6ab5fSopenharmony_ci
10543af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias)
10553af6ab5fSopenharmony_ci{
10563af6ab5fSopenharmony_ci    AddOrGetDecl<varbinder::TypeAliasDecl>(VarBinder(), typeAlias->Id()->Name(), typeAlias, typeAlias->Id()->Start(),
10573af6ab5fSopenharmony_ci                                           typeAlias->Id()->Name(), typeAlias);
10583af6ab5fSopenharmony_ci    auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAlias->TypeParams());
10593af6ab5fSopenharmony_ci    Iterate(typeAlias);
10603af6ab5fSopenharmony_ci}
10613af6ab5fSopenharmony_ci
10623af6ab5fSopenharmony_civoid InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program)
10633af6ab5fSopenharmony_ci{
10643af6ab5fSopenharmony_ci    auto globalId = program->GlobalClass()->Ident();
10653af6ab5fSopenharmony_ci    if (globalId->Variable() != nullptr) {
10663af6ab5fSopenharmony_ci        return;
10673af6ab5fSopenharmony_ci    }
10683af6ab5fSopenharmony_ci
10693af6ab5fSopenharmony_ci    auto [decl2, var] = program->VarBinder()->NewVarDecl<varbinder::ClassDecl>(globalId->Start(), globalId->Name());
10703af6ab5fSopenharmony_ci
10713af6ab5fSopenharmony_ci    auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(program->VarBinder(), program->GlobalClass());
10723af6ab5fSopenharmony_ci    classCtx.GetScope()->BindNode(program->GlobalClass());
10733af6ab5fSopenharmony_ci    program->GlobalClass()->SetScope(classCtx.GetScope());
10743af6ab5fSopenharmony_ci
10753af6ab5fSopenharmony_ci    auto *classDecl = program->GlobalClass()->Parent();
10763af6ab5fSopenharmony_ci    decl2->BindNode(classDecl);
10773af6ab5fSopenharmony_ci    globalId->SetVariable(var);
10783af6ab5fSopenharmony_ci}
10793af6ab5fSopenharmony_ci
10803af6ab5fSopenharmony_civoid InitScopesPhaseETS::HandleETSScript(ir::BlockStatement *script)
10813af6ab5fSopenharmony_ci{
10823af6ab5fSopenharmony_ci    for (auto decl : script->Statements()) {
10833af6ab5fSopenharmony_ci        if (decl->IsETSImportDeclaration()) {
10843af6ab5fSopenharmony_ci            CallNode(decl);
10853af6ab5fSopenharmony_ci        } else {
10863af6ab5fSopenharmony_ci            auto classCtx =
10873af6ab5fSopenharmony_ci                varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
10883af6ab5fSopenharmony_ci            CallNode(decl);
10893af6ab5fSopenharmony_ci        }
10903af6ab5fSopenharmony_ci    }
10913af6ab5fSopenharmony_ci    auto classCtx = varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
10923af6ab5fSopenharmony_ci
10933af6ab5fSopenharmony_ci    for (auto decl : script->Statements()) {
10943af6ab5fSopenharmony_ci        AddGlobalDeclaration(decl);
10953af6ab5fSopenharmony_ci    }
10963af6ab5fSopenharmony_ci}
10973af6ab5fSopenharmony_ci
10983af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef)
10993af6ab5fSopenharmony_ci{
11003af6ab5fSopenharmony_ci    if (classDef->IsGlobal()) {
11013af6ab5fSopenharmony_ci        ParseGlobalClass(classDef);
11023af6ab5fSopenharmony_ci        return;
11033af6ab5fSopenharmony_ci    }
11043af6ab5fSopenharmony_ci    auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
11053af6ab5fSopenharmony_ci    CallNode(classDef->TypeParams());
11063af6ab5fSopenharmony_ci    auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), classDef);
11073af6ab5fSopenharmony_ci
11083af6ab5fSopenharmony_ci    IterateNoTParams(classDef);
11093af6ab5fSopenharmony_ci    FilterOverloads(classDef->Body());
11103af6ab5fSopenharmony_ci    auto *classScope = classCtx.GetScope();
11113af6ab5fSopenharmony_ci    BindScopeNode(classScope, classDef);
11123af6ab5fSopenharmony_ci}
11133af6ab5fSopenharmony_ci
11143af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody)
11153af6ab5fSopenharmony_ci{
11163af6ab5fSopenharmony_ci    Iterate(interfBody);
11173af6ab5fSopenharmony_ci    FilterInterfaceOverloads(interfBody->Body());
11183af6ab5fSopenharmony_ci}
11193af6ab5fSopenharmony_ci
11203af6ab5fSopenharmony_civoid InitScopesPhaseETS::FilterInterfaceOverloads(ArenaVector<ir::AstNode *, false> &props)
11213af6ab5fSopenharmony_ci{
11223af6ab5fSopenharmony_ci    auto condition = [](ir::AstNode *prop) {
11233af6ab5fSopenharmony_ci        if (prop->IsMethodDefinition()) {
11243af6ab5fSopenharmony_ci            const auto func = prop->AsMethodDefinition()->Function();
11253af6ab5fSopenharmony_ci            return func->IsOverload() && func->Body() != nullptr;
11263af6ab5fSopenharmony_ci        }
11273af6ab5fSopenharmony_ci        return false;
11283af6ab5fSopenharmony_ci    };
11293af6ab5fSopenharmony_ci    props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
11303af6ab5fSopenharmony_ci}
11313af6ab5fSopenharmony_ci
11323af6ab5fSopenharmony_civoid InitScopesPhaseETS::FilterOverloads(ArenaVector<ir::AstNode *, false> &props)
11333af6ab5fSopenharmony_ci{
11343af6ab5fSopenharmony_ci    auto condition = [](ir::AstNode *prop) {
11353af6ab5fSopenharmony_ci        if (prop->IsMethodDefinition()) {
11363af6ab5fSopenharmony_ci            const auto func = prop->AsMethodDefinition()->Function();
11373af6ab5fSopenharmony_ci            return func->IsOverload();
11383af6ab5fSopenharmony_ci        }
11393af6ab5fSopenharmony_ci        return false;
11403af6ab5fSopenharmony_ci    };
11413af6ab5fSopenharmony_ci    props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
11423af6ab5fSopenharmony_ci}
11433af6ab5fSopenharmony_ci
11443af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitClassProperty(ir::ClassProperty *classProp)
11453af6ab5fSopenharmony_ci{
11463af6ab5fSopenharmony_ci    auto curScope = VarBinder()->GetScope();
11473af6ab5fSopenharmony_ci    const auto name = classProp->Key()->AsIdentifier()->Name();
11483af6ab5fSopenharmony_ci    if (classProp->IsClassStaticBlock()) {
11493af6ab5fSopenharmony_ci        ASSERT(curScope->IsClassScope());
11503af6ab5fSopenharmony_ci        auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
11513af6ab5fSopenharmony_ci            VarBinder(), curScope->AsClassScope()->StaticMethodScope());
11523af6ab5fSopenharmony_ci        auto *var = classProp->Id()->Variable();
11533af6ab5fSopenharmony_ci        if (var == nullptr) {
11543af6ab5fSopenharmony_ci            var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(classProp->Start(), Allocator(),
11553af6ab5fSopenharmony_ci                                                                               classProp->Id()->Name(), classProp));
11563af6ab5fSopenharmony_ci        }
11573af6ab5fSopenharmony_ci        var->AddFlag(varbinder::VariableFlags::METHOD);
11583af6ab5fSopenharmony_ci        classProp->AsClassStaticBlock()->Function()->Id()->SetVariable(var);
11593af6ab5fSopenharmony_ci    } else if (classProp->IsConst()) {
11603af6ab5fSopenharmony_ci        ASSERT(curScope->Parent() != nullptr);
11613af6ab5fSopenharmony_ci        const auto initializer = classProp->Value();
11623af6ab5fSopenharmony_ci        if (initializer == nullptr && curScope->Parent()->IsGlobalScope() && !classProp->IsDeclare()) {
11633af6ab5fSopenharmony_ci            auto pos = classProp->End();
11643af6ab5fSopenharmony_ci            // NOTE: Just use property Name?
11653af6ab5fSopenharmony_ci            if (!classProp->TypeAnnotation()->IsETSPrimitiveType()) {
11663af6ab5fSopenharmony_ci                pos.index--;
11673af6ab5fSopenharmony_ci            }
11683af6ab5fSopenharmony_ci            ThrowSyntaxError("Missing initializer in const declaration", pos);
11693af6ab5fSopenharmony_ci        }
11703af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
11713af6ab5fSopenharmony_ci    } else if (classProp->IsReadonly()) {
11723af6ab5fSopenharmony_ci        ASSERT(curScope->Parent() != nullptr);
11733af6ab5fSopenharmony_ci        if (curScope->Parent()->IsGlobalScope() && !classProp->IsDeclare()) {
11743af6ab5fSopenharmony_ci            auto pos = classProp->End();
11753af6ab5fSopenharmony_ci            ThrowSyntaxError("Readonly field cannot be in Global scope", pos);
11763af6ab5fSopenharmony_ci        }
11773af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::ReadonlyDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
11783af6ab5fSopenharmony_ci    } else {
11793af6ab5fSopenharmony_ci        AddOrGetDecl<varbinder::LetDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
11803af6ab5fSopenharmony_ci    }
11813af6ab5fSopenharmony_ci    Iterate(classProp);
11823af6ab5fSopenharmony_ci}
11833af6ab5fSopenharmony_ci
11843af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitBreakStatement(ir::BreakStatement *stmt)
11853af6ab5fSopenharmony_ci{
11863af6ab5fSopenharmony_ci    auto label = stmt->Ident();
11873af6ab5fSopenharmony_ci    if (label != nullptr) {
11883af6ab5fSopenharmony_ci        auto scope = VarBinder()->GetScope();
11893af6ab5fSopenharmony_ci        auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
11903af6ab5fSopenharmony_ci        label->SetVariable(var);
11913af6ab5fSopenharmony_ci    }
11923af6ab5fSopenharmony_ci}
11933af6ab5fSopenharmony_ci
11943af6ab5fSopenharmony_civoid InitScopesPhaseETS::VisitContinueStatement(ir::ContinueStatement *stmt)
11953af6ab5fSopenharmony_ci{
11963af6ab5fSopenharmony_ci    auto label = stmt->Ident();
11973af6ab5fSopenharmony_ci    if (label != nullptr) {
11983af6ab5fSopenharmony_ci        auto scope = VarBinder()->GetScope();
11993af6ab5fSopenharmony_ci        auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
12003af6ab5fSopenharmony_ci        label->SetVariable(var);
12013af6ab5fSopenharmony_ci    }
12023af6ab5fSopenharmony_ci}
12033af6ab5fSopenharmony_ci
12043af6ab5fSopenharmony_civoid InitScopesPhaseETS::AttachLabelToScope(ir::AstNode *node)
12053af6ab5fSopenharmony_ci{
12063af6ab5fSopenharmony_ci    if (node->Parent() == nullptr) {
12073af6ab5fSopenharmony_ci        return;
12083af6ab5fSopenharmony_ci    }
12093af6ab5fSopenharmony_ci
12103af6ab5fSopenharmony_ci    if (!node->Parent()->IsLabelledStatement()) {
12113af6ab5fSopenharmony_ci        return;
12123af6ab5fSopenharmony_ci    }
12133af6ab5fSopenharmony_ci
12143af6ab5fSopenharmony_ci    auto stmt = node->Parent()->AsLabelledStatement();
12153af6ab5fSopenharmony_ci    auto label = stmt->Ident();
12163af6ab5fSopenharmony_ci    if (label == nullptr) {
12173af6ab5fSopenharmony_ci        return;
12183af6ab5fSopenharmony_ci    }
12193af6ab5fSopenharmony_ci
12203af6ab5fSopenharmony_ci    auto decl = AddOrGetDecl<varbinder::LabelDecl>(VarBinder(), label->Name(), stmt, label->Start(), label->Name());
12213af6ab5fSopenharmony_ci    decl->BindNode(stmt);
12223af6ab5fSopenharmony_ci
12233af6ab5fSopenharmony_ci    auto var = VarBinder()->GetScope()->FindLocal(label->Name(), varbinder::ResolveBindingOptions::BINDINGS);
12243af6ab5fSopenharmony_ci    if (var != nullptr) {
12253af6ab5fSopenharmony_ci        label->SetVariable(var);
12263af6ab5fSopenharmony_ci        var->SetScope(VarBinder()->GetScope());
12273af6ab5fSopenharmony_ci        var->AddFlag(varbinder::VariableFlags::LOCAL);
12283af6ab5fSopenharmony_ci    }
12293af6ab5fSopenharmony_ci}
12303af6ab5fSopenharmony_ci
12313af6ab5fSopenharmony_civoid InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global)
12323af6ab5fSopenharmony_ci{
12333af6ab5fSopenharmony_ci    for (auto decl : global->Body()) {
12343af6ab5fSopenharmony_ci        if (decl->IsDefaultExported()) {
12353af6ab5fSopenharmony_ci            if (VarBinder()->AsETSBinder()->DefaultExport() != nullptr) {
12363af6ab5fSopenharmony_ci                ThrowSyntaxError("Only one default export is allowed in a module", decl->Start());
12373af6ab5fSopenharmony_ci            }
12383af6ab5fSopenharmony_ci            VarBinder()->AsETSBinder()->SetDefaultExport(decl);
12393af6ab5fSopenharmony_ci        }
12403af6ab5fSopenharmony_ci        CallNode(decl);
12413af6ab5fSopenharmony_ci    }
12423af6ab5fSopenharmony_ci    FilterOverloads(global->Body());
12433af6ab5fSopenharmony_ci}
12443af6ab5fSopenharmony_ci
12453af6ab5fSopenharmony_civoid InitScopesPhaseETS::AddGlobalDeclaration(ir::AstNode *node)
12463af6ab5fSopenharmony_ci{
12473af6ab5fSopenharmony_ci    ir::Identifier *ident = nullptr;
12483af6ab5fSopenharmony_ci    bool isBuiltin = false;
12493af6ab5fSopenharmony_ci    switch (node->Type()) {
12503af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_DECLARATION: {
12513af6ab5fSopenharmony_ci            auto def = node->AsClassDeclaration()->Definition();
12523af6ab5fSopenharmony_ci            if (def->IsGlobal()) {
12533af6ab5fSopenharmony_ci                return;
12543af6ab5fSopenharmony_ci            }
12553af6ab5fSopenharmony_ci            ident = def->Ident();
12563af6ab5fSopenharmony_ci            isBuiltin = def->IsFromExternal();
12573af6ab5fSopenharmony_ci            break;
12583af6ab5fSopenharmony_ci        }
12593af6ab5fSopenharmony_ci        case ir::AstNodeType::STRUCT_DECLARATION: {
12603af6ab5fSopenharmony_ci            ident = node->AsETSStructDeclaration()->Definition()->Ident();
12613af6ab5fSopenharmony_ci            isBuiltin = node->AsETSStructDeclaration()->Definition()->IsFromExternal();
12623af6ab5fSopenharmony_ci            break;
12633af6ab5fSopenharmony_ci        }
12643af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
12653af6ab5fSopenharmony_ci            ident = node->AsTSInterfaceDeclaration()->Id();
12663af6ab5fSopenharmony_ci            isBuiltin = node->AsTSInterfaceDeclaration()->IsFromExternal();
12673af6ab5fSopenharmony_ci            break;
12683af6ab5fSopenharmony_ci        }
12693af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_ENUM_DECLARATION: {
12703af6ab5fSopenharmony_ci            ident = node->AsTSEnumDeclaration()->Key();
12713af6ab5fSopenharmony_ci            break;
12723af6ab5fSopenharmony_ci        }
12733af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: {
12743af6ab5fSopenharmony_ci            ident = node->AsTSTypeAliasDeclaration()->Id();
12753af6ab5fSopenharmony_ci            break;
12763af6ab5fSopenharmony_ci        }
12773af6ab5fSopenharmony_ci        default: {
12783af6ab5fSopenharmony_ci            break;
12793af6ab5fSopenharmony_ci        }
12803af6ab5fSopenharmony_ci    }
12813af6ab5fSopenharmony_ci    if (ident != nullptr) {
12823af6ab5fSopenharmony_ci        VarBinder()->TopScope()->InsertBinding(ident->Name(), ident->Variable());
12833af6ab5fSopenharmony_ci        if (isBuiltin) {
12843af6ab5fSopenharmony_ci            ident->Variable()->AddFlag(varbinder::VariableFlags::BUILTIN_TYPE);
12853af6ab5fSopenharmony_ci        }
12863af6ab5fSopenharmony_ci    }
12873af6ab5fSopenharmony_ci}
12883af6ab5fSopenharmony_ci
12893af6ab5fSopenharmony_civoid InitScopesPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
12903af6ab5fSopenharmony_ci{
12913af6ab5fSopenharmony_ci    Iterate(arrowExpr);
12923af6ab5fSopenharmony_ci}
12933af6ab5fSopenharmony_ci
12943af6ab5fSopenharmony_civoid InitScopesPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
12953af6ab5fSopenharmony_ci{
12963af6ab5fSopenharmony_ci    ExportDeclarationContext exportDeclCtx(VarBinder());
12973af6ab5fSopenharmony_ci    Iterate(exportDecl);
12983af6ab5fSopenharmony_ci}
12993af6ab5fSopenharmony_ci
13003af6ab5fSopenharmony_ci}  // namespace ark::es2panda::compiler
1301