• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 namespace ark::es2panda::compiler {
24 
CreateCall(checker::ETSChecker * checker,ir::ClassDefinition * const classDef,checker::ETSEnumType::Method (checker::ETSEnumType::* getMethod)()const,ir::Expression * argument)25 ir::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 
Perform(public_lib::Context * ctx,parser::Program * program)41 bool 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