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#ifndef ES2PANDA_COMPILER_ENUM_PRE_CHECK_LOWERING_H
17#define ES2PANDA_COMPILER_ENUM_PRE_CHECK_LOWERING_H
18
19#include "compiler/lowering/phase.h"
20#include "checker/types/ets/etsEnumType.h"
21
22namespace ark::es2panda::compiler {
23
24class EnumLoweringPhase : public Phase {
25public:
26    EnumLoweringPhase() noexcept = default;
27    std::string_view Name() const override
28    {
29        return "EnumLoweringPhase";
30    }
31    bool Perform(public_lib::Context *ctx, parser::Program *program) override;
32    static util::UString GetEnumClassName(checker::ETSChecker *checker, const ir::TSEnumDeclaration *const enumDecl);
33    checker::ETSChecker *Checker()
34    {
35        return checker_;
36    }
37
38    varbinder::ETSBinder *Varbinder()
39    {
40        return varbinder_;
41    }
42
43private:
44    struct FunctionInfo {
45        varbinder::FunctionParamScope *paramScope;
46        ArenaVector<ir::Expression *> &&params;
47        ArenaVector<ir::Statement *> &&body;
48        ir::TypeNode *returnTypeAnnotation;
49        const ir::TSEnumDeclaration *enumDecl;
50        ir::ModifierFlags flags;
51    };
52
53    [[nodiscard]] ir::ScriptFunction *MakeFunction(FunctionInfo &&functionInfo);
54    ir::ClassDefinition *CreateClass(ir::TSEnumDeclaration *const enumDecl);
55    ir::ClassProperty *CreateOrdinalField(ir::ClassDefinition *const enumClass);
56    void CreateCCtorForEnumClass(ir::ClassDefinition *const enumClass);
57    void CreateCtorForEnumClass(ir::ClassDefinition *const enumClass);
58
59    void CreateEnumIntClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl);
60    void CreateEnumStringClassFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl);
61    static void AppendParentNames(util::UString &qualifiedName, const ir::AstNode *const node);
62    template <typename ElementMaker>
63    [[nodiscard]] ir::Identifier *MakeArray(const ir::TSEnumDeclaration *const enumDecl, ir::ClassDefinition *enumClass,
64                                            const util::StringView &name, ir::TypeNode *const typeAnnotation,
65                                            ElementMaker &&elementMaker);
66
67    ir::Identifier *CreateEnumNamesArray(const ir::TSEnumDeclaration *const enumDecl, ir::ClassDefinition *enumClass);
68    ir::Identifier *CreateEnumValuesArray(const ir::TSEnumDeclaration *const enumDecl, ir::ClassDefinition *enumClass);
69    ir::Identifier *CreateEnumStringValuesArray(const ir::TSEnumDeclaration *const enumDecl,
70                                                ir::ClassDefinition *enumClass);
71    ir::Identifier *CreateEnumItemsArray(const ir::TSEnumDeclaration *const enumDecl, ir::ClassDefinition *enumClass);
72    ir::Identifier *CreateBoxedEnumItemsArray(const ir::TSEnumDeclaration *const enumDecl,
73                                              ir::ClassDefinition *enumClass);
74
75    void CreateEnumFromIntMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
76                                 ir::Identifier *const arrayIdent, const util::StringView &methodName,
77                                 const util::StringView &returnTypeName);
78    void CreateEnumToStringMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
79                                  ir::Identifier *const stringValuesArrayIdent);
80    void CreateEnumValueOfMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
81                                 ir::Identifier *const valuesArrayIdent);
82    void CreateEnumGetNameMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
83                                 ir::Identifier *const namesArrayIdent);
84    void CreateEnumGetValueOfMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
85                                    ir::Identifier *const namesArrayIdent);
86    void CreateEnumValuesMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
87                                ir::Identifier *const itemsArrayIdent);
88    void CreateUnboxingMethod(ir::TSEnumDeclaration const *const enumDecl, ir::ClassDefinition *const enumClass,
89                              ir::Identifier *const itemsArrayIdent);
90
91    ArenaAllocator *Allocator();
92
93private:
94    checker::ETSChecker *checker_ {nullptr};
95    parser::Program *program_ {nullptr};
96    varbinder::ETSBinder *varbinder_ {nullptr};
97};
98
99}  // namespace ark::es2panda::compiler
100
101#endif  // ES2PANDA_COMPILER_ENUM_PRE_CHECK_LOWERING_H
102