1/* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "enumPostCheckLowering.h" 17#include "checker/types/ets/etsEnumType.h" 18#include "checker/ETSchecker.h" 19#include "checker/types/type.h" 20#include "varbinder/ETSBinder.h" 21#include "varbinder/variable.h" 22 23namespace ark::es2panda::compiler { 24 25ir::CallExpression *EnumPostCheckLoweringPhase::CreateCall( 26 checker::ETSChecker *checker, ir::ClassDefinition *const classDef, 27 checker::ETSEnumType::Method (checker::ETSEnumType::*getMethod)() const, ir::Expression *argument) 28{ 29 auto *classId = checker->AllocNode<ir::Identifier>(classDef->Ident()->Name(), checker->Allocator()); 30 auto *methodId = checker->AllocNode<ir::Identifier>( 31 (argument->TsType()->AsETSEnumType()->*getMethod)().memberProxyType->Name(), checker->Allocator()); 32 methodId->SetReference(); 33 auto *callee = checker->AllocNode<ir::MemberExpression>(classId, methodId, 34 ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); 35 36 ArenaVector<ir::Expression *> callArguments(checker->Allocator()->Adapter()); 37 callArguments.push_back(argument); 38 return checker->AllocNode<ir::CallExpression>(callee, std::move(callArguments), nullptr, false); 39} 40 41bool EnumPostCheckLoweringPhase::Perform(public_lib::Context *ctx, parser::Program *program) 42{ 43 if (program->Extension() != ScriptExtension::ETS) { 44 return true; 45 } 46 47 for (auto &[_, extPrograms] : program->ExternalSources()) { 48 (void)_; 49 for (auto *extProg : extPrograms) { 50 Perform(ctx, extProg); 51 } 52 } 53 program->Ast()->TransformChildrenRecursivelyPostorder( 54 // clang-format off 55 [this, ctx](ir::AstNode *const node) -> ir::AstNode* { 56 if (node->HasAstNodeFlags(ir::AstNodeFlags::RECHECK)) { 57 if (node->IsExpression()) { 58 node->AsExpression()->SetTsType(nullptr); // force recheck 59 } 60 node->Check(ctx->checker->AsETSChecker()); 61 node->RemoveAstNodeFlags(ir::AstNodeFlags::RECHECK); 62 } 63 if (node->HasAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF)) { 64 ASSERT(node->IsExpression()); 65 auto expr = node->AsExpression(); 66 auto parent = expr->Parent(); 67 parent->AddAstNodeFlags(ir::AstNodeFlags::RECHECK); 68 ASSERT((node->AsExpression()->TsType()->IsETSEnumType())); 69 auto *enumIf = expr->TsType()->AsETSEnumType(); 70 auto *callExpr = CreateCall(ctx->checker->AsETSChecker(), enumIf->GetDecl()->BoxedClass(), 71 &checker::ETSEnumType::ValueOfMethod, expr); 72 callExpr->SetParent(parent); 73 callExpr->Check(ctx->checker->AsETSChecker()); 74 node->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); 75 return callExpr; 76 } 77 if (node->HasAstNodeFlags(ir::AstNodeFlags::GENERATE_GET_NAME)) { 78 ASSERT(node->IsMemberExpression()); 79 auto memberExpr = node->AsMemberExpression(); 80 81 auto *enumIf = memberExpr->Object()->TsType()->AsETSEnumType(); 82 auto *callExpr = CreateCall(ctx->checker->AsETSChecker(), enumIf->GetDecl()->BoxedClass(), 83 &checker::ETSEnumType::GetNameMethod, memberExpr->Property()); 84 85 callExpr->SetParent(node->Parent()); 86 callExpr->Check(ctx->checker->AsETSChecker()); 87 node->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_GET_NAME); 88 return callExpr; 89 } 90 return node; 91 }, 92 // clang-format on 93 Name()); 94 return true; 95} 96 97} // namespace ark::es2panda::compiler 98