1/*
2 * Copyright (c) 2023 - 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 PANDA_GLOBALCLASSHANDLER_H
17#define PANDA_GLOBALCLASSHANDLER_H
18
19#include "parser/program/program.h"
20#include "public/public.h"
21#include "ir/astNode.h"
22
23namespace ark::es2panda::compiler {
24
25class GlobalClassHandler {
26public:
27    using ModuleDependencies = ArenaUnorderedSet<parser::Program *>;
28
29    struct GlobalStmts {
30        parser::Program *program;
31        ArenaVector<ir::Statement *> statements;
32    };
33    explicit GlobalClassHandler(parser::ETSParser *parser, ArenaAllocator *allocator)
34        : parser_(parser), allocator_(allocator) {};
35
36    /**
37     * Each "Module" has it's own global class, which contains all top level statements across "module"
38     * Result - creation of global class and _$init$_ method
39     * @param programs - vector of files in module
40     */
41    void SetupGlobalClass(const ArenaVector<parser::Program *> &programs, const ModuleDependencies *moduleDependencies);
42
43private:
44    /**
45     * Move top level statements to _$init$_ and
46     * @param program program of module
47     * @param init_statements statements which should be executed
48     */
49    void SetupGlobalMethods(parser::Program *program, ArenaVector<ir::Statement *> &&statements,
50                            bool mainExists = false, bool topLevelStatementsExist = false);
51
52    ir::ClassDeclaration *CreateGlobalClass();
53    ir::ClassStaticBlock *CreateStaticBlock(ir::ClassDefinition *classDef);
54    ir::MethodDefinition *CreateGlobalMethod(const std::string_view name, ArenaVector<ir::Statement *> &&statements);
55    void AddInitCallFromStaticBlock(ir::ClassDefinition *globalClass, ir::MethodDefinition *initMethod);
56
57    ArenaVector<ir::Statement *> FormInitMethodStatements(parser::Program *program,
58                                                          const ModuleDependencies *moduleDependencies,
59                                                          ArenaVector<GlobalStmts> &&initStatements);
60
61    void FormDependentInitTriggers(ArenaVector<ir::Statement *> &statements,
62                                   const ModuleDependencies *moduleDependencies);
63
64    /**
65     *
66     * @param program leave only declarations here
67     * @param class_def add new properties such as methods and fields
68     * @param addInitializer $init$ should contain global variable initializers
69     * @return Statements, which should be executed before the start
70     */
71    ArenaVector<ir::Statement *> CollectProgramGlobalStatements(parser::Program *program, ir::ClassDefinition *classDef,
72                                                                bool addInitializer);
73
74    ir::Identifier *RefIdent(const util::StringView &name);
75    util::UString ReplaceSpecialCharacters(util::UString *word) const;
76
77    parser::ETSParser *const parser_;
78    ArenaAllocator *const allocator_;
79};
80}  // namespace ark::es2panda::compiler
81
82#endif  // PANDA_GLOBALCLASSHANDLER_H
83