13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 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 "genericBridgesLowering.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
193af6ab5fSopenharmony_ci#include "compiler/lowering/scopesInit/scopesInitPhase.h"
203af6ab5fSopenharmony_ci#include "compiler/lowering/util.h"
213af6ab5fSopenharmony_ci
223af6ab5fSopenharmony_cinamespace ark::es2panda::compiler {
233af6ab5fSopenharmony_ci
243af6ab5fSopenharmony_cistd::string GenericBridgesPhase::CreateMethodDefinitionString(ir::ClassDefinition const *classDefinition,
253af6ab5fSopenharmony_ci                                                              checker::Signature const *baseSignature,
263af6ab5fSopenharmony_ci                                                              ir::ScriptFunction const *derivedFunction,
273af6ab5fSopenharmony_ci                                                              std::vector<ir::AstNode *> &typeNodes) const noexcept
283af6ab5fSopenharmony_ci{
293af6ab5fSopenharmony_ci    constexpr std::size_t SOURCE_CODE_LENGTH = 128U;
303af6ab5fSopenharmony_ci
313af6ab5fSopenharmony_ci    auto *checker = context_->checker->AsETSChecker();
323af6ab5fSopenharmony_ci
333af6ab5fSopenharmony_ci    std::string str1 {};
343af6ab5fSopenharmony_ci    str1.reserve(2U * SOURCE_CODE_LENGTH);
353af6ab5fSopenharmony_ci
363af6ab5fSopenharmony_ci    std::string str2 {};
373af6ab5fSopenharmony_ci    str2.reserve(SOURCE_CODE_LENGTH);
383af6ab5fSopenharmony_ci
393af6ab5fSopenharmony_ci    auto const &functionName = derivedFunction->Id()->Name().Mutf8();
403af6ab5fSopenharmony_ci    str1 = functionName + '(';
413af6ab5fSopenharmony_ci
423af6ab5fSopenharmony_ci    str2 += ")." + functionName + '(';
433af6ab5fSopenharmony_ci
443af6ab5fSopenharmony_ci    auto const &baseParameters = baseSignature->Params();
453af6ab5fSopenharmony_ci    auto const &derivedParameters = derivedFunction->Signature()->Params();
463af6ab5fSopenharmony_ci    auto const parameterNumber = baseParameters.size();
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_ci    for (std::size_t i = 0U; i < parameterNumber; ++i) {
493af6ab5fSopenharmony_ci        if (i != 0U) {
503af6ab5fSopenharmony_ci            str1 += ", ";
513af6ab5fSopenharmony_ci            str2 += ", ";
523af6ab5fSopenharmony_ci        }
533af6ab5fSopenharmony_ci
543af6ab5fSopenharmony_ci        auto const *const derivedParameter = derivedParameters[i];
553af6ab5fSopenharmony_ci        auto const &parameterName = derivedParameter->Name().Utf8();
563af6ab5fSopenharmony_ci        str1 += parameterName;
573af6ab5fSopenharmony_ci        typeNodes.emplace_back(checker->AllocNode<ir::OpaqueTypeNode>(baseParameters[i]->TsType()));
583af6ab5fSopenharmony_ci        str1 += ": @@T" + std::to_string(typeNodes.size());
593af6ab5fSopenharmony_ci
603af6ab5fSopenharmony_ci        str2 += parameterName;
613af6ab5fSopenharmony_ci        typeNodes.emplace_back(checker->AllocNode<ir::OpaqueTypeNode>(derivedParameter->TsType()));
623af6ab5fSopenharmony_ci        str2 += " as @@T" + std::to_string(typeNodes.size());
633af6ab5fSopenharmony_ci    }
643af6ab5fSopenharmony_ci
653af6ab5fSopenharmony_ci    typeNodes.emplace_back(checker->AllocNode<ir::OpaqueTypeNode>(
663af6ab5fSopenharmony_ci        const_cast<checker::Type *>(derivedFunction->Signature()->ReturnType())));
673af6ab5fSopenharmony_ci    str1 += "): @@T" + std::to_string(typeNodes.size()) + ' ';
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    typeNodes.emplace_back(
703af6ab5fSopenharmony_ci        checker->AllocNode<ir::OpaqueTypeNode>(const_cast<checker::Type *>(classDefinition->TsType())));
713af6ab5fSopenharmony_ci    str2 = "{ return (this as @@T" + std::to_string(typeNodes.size()) + str2 + "); }";
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci    str1 += str2;
743af6ab5fSopenharmony_ci    return str1;
753af6ab5fSopenharmony_ci}
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_civoid GenericBridgesPhase::AddGenericBridge(ir::ClassDefinition const *const classDefinition,
783af6ab5fSopenharmony_ci                                           ir::MethodDefinition *const methodDefinition,
793af6ab5fSopenharmony_ci                                           checker::Signature const *baseSignature,
803af6ab5fSopenharmony_ci                                           ir::ScriptFunction const *const derivedFunction) const
813af6ab5fSopenharmony_ci{
823af6ab5fSopenharmony_ci    auto *parser = context_->parser->AsETSParser();
833af6ab5fSopenharmony_ci    std::vector<ir::AstNode *> typeNodes {};
843af6ab5fSopenharmony_ci    typeNodes.reserve(2U * baseSignature->Params().size() + 2U);
853af6ab5fSopenharmony_ci
863af6ab5fSopenharmony_ci    auto const sourceCode = CreateMethodDefinitionString(classDefinition, baseSignature, derivedFunction, typeNodes);
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    auto *const bridgeMethod =
893af6ab5fSopenharmony_ci        parser->CreateFormattedClassMethodDefinition(sourceCode, typeNodes)->AsMethodDefinition();
903af6ab5fSopenharmony_ci    bridgeMethod->AddModifier(methodDefinition->Modifiers());
913af6ab5fSopenharmony_ci    bridgeMethod->AddAstNodeFlags(methodDefinition->GetAstNodeFlags());
923af6ab5fSopenharmony_ci    bridgeMethod->SetParent(const_cast<ir::ClassDefinition *>(classDefinition));
933af6ab5fSopenharmony_ci
943af6ab5fSopenharmony_ci    auto *varBinder = context_->checker->VarBinder()->AsETSBinder();
953af6ab5fSopenharmony_ci    auto *scope = NearestScope(methodDefinition);
963af6ab5fSopenharmony_ci    auto scopeGuard = varbinder::LexicalScope<varbinder::Scope>::Enter(varBinder, scope);
973af6ab5fSopenharmony_ci    InitScopesPhaseETS::RunExternalNode(bridgeMethod, varBinder);
983af6ab5fSopenharmony_ci
993af6ab5fSopenharmony_ci    varbinder::BoundContext boundCtx {varBinder->GetRecordTable(), const_cast<ir::ClassDefinition *>(classDefinition),
1003af6ab5fSopenharmony_ci                                      true};
1013af6ab5fSopenharmony_ci    varBinder->AsETSBinder()->ResolveReferencesForScopeWithContext(bridgeMethod, scope);
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_ci    auto *checker = context_->checker->AsETSChecker();
1043af6ab5fSopenharmony_ci    auto const checkerCtx =
1053af6ab5fSopenharmony_ci        checker::SavedCheckerContext(checker,
1063af6ab5fSopenharmony_ci                                     checker::CheckerStatus::IN_CLASS | checker::CheckerStatus::IGNORE_VISIBILITY |
1073af6ab5fSopenharmony_ci                                         checker::CheckerStatus::IN_BRIDGE_TEST,
1083af6ab5fSopenharmony_ci                                     classDefinition->TsType()->AsETSObjectType());
1093af6ab5fSopenharmony_ci    auto scopeCtx = checker::ScopeContext(checker, scope);
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci    //  Note: we need to create and set function/method type here because the general method `BuildMethodSignature(...)`
1123af6ab5fSopenharmony_ci    //  is not suitable for this case. Moreover, we have to save and restore proper type for `methodDefinition` because
1133af6ab5fSopenharmony_ci    //  call to `BuildFunctionSignature(...)` breaks it!
1143af6ab5fSopenharmony_ci    auto *methodType = methodDefinition->Id()->Variable()->TsType()->AsETSFunctionType();
1153af6ab5fSopenharmony_ci
1163af6ab5fSopenharmony_ci    checker->BuildFunctionSignature(bridgeMethod->Function());
1173af6ab5fSopenharmony_ci    auto *const bridgeMethodType = checker->BuildNamedFunctionType(bridgeMethod->Function());
1183af6ab5fSopenharmony_ci    checker->CheckIdenticalOverloads(methodType, bridgeMethodType, bridgeMethod);
1193af6ab5fSopenharmony_ci    bridgeMethod->SetTsType(bridgeMethodType);
1203af6ab5fSopenharmony_ci    methodType->AddCallSignature(bridgeMethod->Function()->Signature());
1213af6ab5fSopenharmony_ci    methodDefinition->Id()->Variable()->SetTsType(methodType);
1223af6ab5fSopenharmony_ci
1233af6ab5fSopenharmony_ci    bridgeMethod->Check(checker);
1243af6ab5fSopenharmony_ci}
1253af6ab5fSopenharmony_ci
1263af6ab5fSopenharmony_civoid GenericBridgesPhase::ProcessScriptFunction(ir::ClassDefinition const *const classDefinition,
1273af6ab5fSopenharmony_ci                                                ir::ScriptFunction *const baseFunction,
1283af6ab5fSopenharmony_ci                                                ir::MethodDefinition *const derivedMethod,
1293af6ab5fSopenharmony_ci                                                Substitutions const &substitutions) const
1303af6ab5fSopenharmony_ci{
1313af6ab5fSopenharmony_ci    auto *const checker = context_->checker->AsETSChecker();
1323af6ab5fSopenharmony_ci    auto *const relation = checker->Relation();
1333af6ab5fSopenharmony_ci
1343af6ab5fSopenharmony_ci    auto const overrides = [checker, relation, classDefinition](checker::Signature const *source,
1353af6ab5fSopenharmony_ci                                                                checker::Signature const *target) -> bool {
1363af6ab5fSopenharmony_ci        checker::SavedCheckerContext const checkerCtx(
1373af6ab5fSopenharmony_ci            checker, checker->Context().Status() | checker::CheckerStatus::IN_BRIDGE_TEST,
1383af6ab5fSopenharmony_ci            classDefinition->TsType()->AsETSObjectType());
1393af6ab5fSopenharmony_ci        checker::SavedTypeRelationFlagsContext const savedFlags(relation, checker::TypeRelationFlag::BRIDGE_CHECK);
1403af6ab5fSopenharmony_ci        return relation->IsCompatibleTo(const_cast<checker::Signature *>(source),
1413af6ab5fSopenharmony_ci                                        const_cast<checker::Signature *>(target));
1423af6ab5fSopenharmony_ci    };
1433af6ab5fSopenharmony_ci
1443af6ab5fSopenharmony_ci    //  We are not interested in functions that either don't have type parameters at all
1453af6ab5fSopenharmony_ci    //  or have type parameters that are not modified in the derived class
1463af6ab5fSopenharmony_ci    auto const *baseSignature1 = baseFunction->Signature()->Substitute(relation, substitutions.baseConstraints);
1473af6ab5fSopenharmony_ci    if (baseSignature1 == baseFunction->Signature()) {
1483af6ab5fSopenharmony_ci        return;
1493af6ab5fSopenharmony_ci    }
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_ci    auto *baseSignature2 = baseFunction->Signature()->Substitute(relation, substitutions.derivedSubstitutions);
1523af6ab5fSopenharmony_ci    if (baseSignature2 == baseFunction->Signature()) {
1533af6ab5fSopenharmony_ci        return;
1543af6ab5fSopenharmony_ci    }
1553af6ab5fSopenharmony_ci    baseSignature2 = baseSignature2->Substitute(relation, substitutions.derivedConstraints);
1563af6ab5fSopenharmony_ci
1573af6ab5fSopenharmony_ci    ir::ScriptFunction const *derivedFunction = nullptr;
1583af6ab5fSopenharmony_ci    checker::ETSFunctionType const *methodType = derivedMethod->Id()->Variable()->TsType()->AsETSFunctionType();
1593af6ab5fSopenharmony_ci    for (auto *signature : methodType->CallSignatures()) {
1603af6ab5fSopenharmony_ci        signature = signature->Substitute(relation, substitutions.derivedConstraints);
1613af6ab5fSopenharmony_ci        if (overrides(baseSignature1, signature) || checker->HasSameAssemblySignature(baseSignature1, signature)) {
1623af6ab5fSopenharmony_ci            //  NOTE: we already have custom-implemented method with the required bridge signature.
1633af6ab5fSopenharmony_ci            //  Probably sometimes we will issue warning notification here...
1643af6ab5fSopenharmony_ci            return;
1653af6ab5fSopenharmony_ci        }
1663af6ab5fSopenharmony_ci
1673af6ab5fSopenharmony_ci        if (derivedFunction == nullptr && overrides(signature, baseSignature2)) {
1683af6ab5fSopenharmony_ci            //  NOTE: we don't care the possible case of mapping several derived function to the same bridge signature.
1693af6ab5fSopenharmony_ci            //  Probably sometimes we will process it correctly or issue warning notification here...
1703af6ab5fSopenharmony_ci            derivedFunction = signature->Function();
1713af6ab5fSopenharmony_ci        }
1723af6ab5fSopenharmony_ci    }
1733af6ab5fSopenharmony_ci
1743af6ab5fSopenharmony_ci    if (derivedFunction != nullptr) {
1753af6ab5fSopenharmony_ci        AddGenericBridge(classDefinition, derivedMethod, baseSignature1, derivedFunction);
1763af6ab5fSopenharmony_ci    }
1773af6ab5fSopenharmony_ci}
1783af6ab5fSopenharmony_ci
1793af6ab5fSopenharmony_civoid GenericBridgesPhase::MaybeAddGenericBridges(ir::ClassDefinition const *const classDefinition,
1803af6ab5fSopenharmony_ci                                                 ir::MethodDefinition *const baseMethod,
1813af6ab5fSopenharmony_ci                                                 ir::MethodDefinition *const derivedMethod,
1823af6ab5fSopenharmony_ci                                                 Substitutions const &substitutions) const
1833af6ab5fSopenharmony_ci{
1843af6ab5fSopenharmony_ci    ProcessScriptFunction(classDefinition, baseMethod->Function(), derivedMethod, substitutions);
1853af6ab5fSopenharmony_ci    for (auto *const overload : baseMethod->Overloads()) {
1863af6ab5fSopenharmony_ci        ProcessScriptFunction(classDefinition, overload->Function(), derivedMethod, substitutions);
1873af6ab5fSopenharmony_ci    }
1883af6ab5fSopenharmony_ci}
1893af6ab5fSopenharmony_ci
1903af6ab5fSopenharmony_civoid GenericBridgesPhase::CreateGenericBridges(ir::ClassDefinition const *const classDefinition,
1913af6ab5fSopenharmony_ci                                               Substitutions &substitutions) const
1923af6ab5fSopenharmony_ci{
1933af6ab5fSopenharmony_ci    auto const &classBody = classDefinition->Body();
1943af6ab5fSopenharmony_ci    auto const *const superDefinition =
1953af6ab5fSopenharmony_ci        classDefinition->Super()->TsType()->AsETSObjectType()->GetDeclNode()->AsClassDefinition();
1963af6ab5fSopenharmony_ci
1973af6ab5fSopenharmony_ci    //  Collect type parameters defaults/constraints in the derived class
1983af6ab5fSopenharmony_ci    auto *checker = context_->checker->AsETSChecker();
1993af6ab5fSopenharmony_ci    substitutions.derivedConstraints = checker->NewSubstitution();
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci    auto const *const classType = classDefinition->TsType()->AsETSObjectType();
2023af6ab5fSopenharmony_ci    auto const &typeParameters = classType->GetConstOriginalBaseType()->AsETSObjectType()->TypeArguments();
2033af6ab5fSopenharmony_ci    for (auto *const parameter : typeParameters) {
2043af6ab5fSopenharmony_ci        auto *const typeParameter = parameter->AsETSTypeParameter();
2053af6ab5fSopenharmony_ci        checker->EmplaceSubstituted(substitutions.derivedConstraints, typeParameter,
2063af6ab5fSopenharmony_ci                                    typeParameter->GetConstraintType());
2073af6ab5fSopenharmony_ci    }
2083af6ab5fSopenharmony_ci
2093af6ab5fSopenharmony_ci    for (auto *item : superDefinition->Body()) {
2103af6ab5fSopenharmony_ci        if (item->IsMethodDefinition()) {
2113af6ab5fSopenharmony_ci            // Skip `static`, `final`, `abstract` and special methods...
2123af6ab5fSopenharmony_ci            auto *const method = item->AsMethodDefinition();
2133af6ab5fSopenharmony_ci            if (method->Kind() != ir::MethodDefinitionKind::METHOD || method->IsStatic() || method->IsFinal() ||
2143af6ab5fSopenharmony_ci                method->Id()->Name().Utf8().find("lambda$invoke$") != std::string_view::npos) {
2153af6ab5fSopenharmony_ci                continue;
2163af6ab5fSopenharmony_ci            }
2173af6ab5fSopenharmony_ci
2183af6ab5fSopenharmony_ci            //  Check if the derived class has any possible overrides of this method
2193af6ab5fSopenharmony_ci            auto it = std::find_if(
2203af6ab5fSopenharmony_ci                classBody.cbegin(), classBody.end(), [&name = method->Id()->Name()](ir::AstNode const *node) -> bool {
2213af6ab5fSopenharmony_ci                    return node->IsMethodDefinition() && node->AsMethodDefinition()->Id()->Name() == name;
2223af6ab5fSopenharmony_ci                });
2233af6ab5fSopenharmony_ci            if (it != classBody.cend()) {
2243af6ab5fSopenharmony_ci                MaybeAddGenericBridges(classDefinition, method, (*it)->AsMethodDefinition(), substitutions);
2253af6ab5fSopenharmony_ci            }
2263af6ab5fSopenharmony_ci        }
2273af6ab5fSopenharmony_ci    }
2283af6ab5fSopenharmony_ci}
2293af6ab5fSopenharmony_ci
2303af6ab5fSopenharmony_ciir::ClassDefinition *GenericBridgesPhase::ProcessClassDefinition(ir::ClassDefinition *const classDefinition) const
2313af6ab5fSopenharmony_ci{
2323af6ab5fSopenharmony_ci    if (classDefinition->Super() == nullptr || classDefinition->Super()->TsType() == nullptr) {
2333af6ab5fSopenharmony_ci        return classDefinition;
2343af6ab5fSopenharmony_ci    }
2353af6ab5fSopenharmony_ci
2363af6ab5fSopenharmony_ci    //  First we need to check if the base class is a generic class.
2373af6ab5fSopenharmony_ci    auto const *const superType = classDefinition->Super()->TsType()->AsETSObjectType();
2383af6ab5fSopenharmony_ci
2393af6ab5fSopenharmony_ci    auto const &typeParameters = superType->GetConstOriginalBaseType()->AsETSObjectType()->TypeArguments();
2403af6ab5fSopenharmony_ci    if (typeParameters.empty()) {
2413af6ab5fSopenharmony_ci        return classDefinition;
2423af6ab5fSopenharmony_ci    }
2433af6ab5fSopenharmony_ci
2443af6ab5fSopenharmony_ci    auto const &typeArguments = superType->TypeArguments();
2453af6ab5fSopenharmony_ci    auto const parameterNumber = typeParameters.size();
2463af6ab5fSopenharmony_ci    ASSERT(parameterNumber == typeArguments.size());
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_ci    auto *checker = context_->checker->AsETSChecker();
2493af6ab5fSopenharmony_ci    Substitutions substitutions {};
2503af6ab5fSopenharmony_ci    substitutions.derivedSubstitutions = checker->NewSubstitution();
2513af6ab5fSopenharmony_ci    substitutions.baseConstraints = checker->NewSubstitution();
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_ci    //  Then we need to check if the class derived from base generic class has either explicit class type substitutions
2543af6ab5fSopenharmony_ci    //  or the type parameters with narrowing constraints.
2553af6ab5fSopenharmony_ci    for (std::size_t i = 0U; i < parameterNumber; ++i) {
2563af6ab5fSopenharmony_ci        auto *const typeParameter = typeParameters[i]->AsETSTypeParameter();
2573af6ab5fSopenharmony_ci        checker::Type *const typeArgument = typeArguments[i];
2583af6ab5fSopenharmony_ci
2593af6ab5fSopenharmony_ci        //  Collect type parameters defaults/constraints in the base class
2603af6ab5fSopenharmony_ci        //  and type argument substitutions in the derived class
2613af6ab5fSopenharmony_ci        checker->EmplaceSubstituted(substitutions.derivedSubstitutions, typeParameter, typeArgument);
2623af6ab5fSopenharmony_ci        if (auto *const defaultType = typeParameter->GetDefaultType(); defaultType != nullptr) {
2633af6ab5fSopenharmony_ci            checker->EmplaceSubstituted(substitutions.baseConstraints, typeParameter, defaultType);
2643af6ab5fSopenharmony_ci        } else {
2653af6ab5fSopenharmony_ci            checker->EmplaceSubstituted(substitutions.baseConstraints, typeParameter,
2663af6ab5fSopenharmony_ci                                        typeParameter->GetConstraintType());
2673af6ab5fSopenharmony_ci        }
2683af6ab5fSopenharmony_ci    }
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_ci    // If it has, then probably the generic bridges should be created.
2713af6ab5fSopenharmony_ci    if (!substitutions.derivedSubstitutions->empty()) {
2723af6ab5fSopenharmony_ci        CreateGenericBridges(classDefinition, substitutions);
2733af6ab5fSopenharmony_ci    }
2743af6ab5fSopenharmony_ci
2753af6ab5fSopenharmony_ci    return classDefinition;
2763af6ab5fSopenharmony_ci}
2773af6ab5fSopenharmony_ci
2783af6ab5fSopenharmony_cibool GenericBridgesPhase::Perform(public_lib::Context *ctx, parser::Program *program)
2793af6ab5fSopenharmony_ci{
2803af6ab5fSopenharmony_ci    if (context_ == nullptr) {
2813af6ab5fSopenharmony_ci        context_ = ctx;
2823af6ab5fSopenharmony_ci    }
2833af6ab5fSopenharmony_ci
2843af6ab5fSopenharmony_ci    if (ctx->config->options->CompilerOptions().compilationMode == CompilationMode::GEN_STD_LIB) {
2853af6ab5fSopenharmony_ci        for (auto &[_, ext_programs] : program->ExternalSources()) {
2863af6ab5fSopenharmony_ci            (void)_;
2873af6ab5fSopenharmony_ci            for (auto *extProg : ext_programs) {
2883af6ab5fSopenharmony_ci                Perform(ctx, extProg);
2893af6ab5fSopenharmony_ci            }
2903af6ab5fSopenharmony_ci        }
2913af6ab5fSopenharmony_ci    }
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci    program->Ast()->TransformChildrenRecursively(
2943af6ab5fSopenharmony_ci        [this](ir::AstNode *ast) -> ir::AstNode * {
2953af6ab5fSopenharmony_ci            if (ast->IsClassDefinition()) {
2963af6ab5fSopenharmony_ci                return ProcessClassDefinition(ast->AsClassDefinition());
2973af6ab5fSopenharmony_ci            }
2983af6ab5fSopenharmony_ci            return ast;
2993af6ab5fSopenharmony_ci        },
3003af6ab5fSopenharmony_ci        Name());
3013af6ab5fSopenharmony_ci
3023af6ab5fSopenharmony_ci    return true;
3033af6ab5fSopenharmony_ci}
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_ci}  // namespace ark::es2panda::compiler
306