* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PANDA_GLOBALCLASSHANDLER_H
#define PANDA_GLOBALCLASSHANDLER_H
#include "compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h"
#include "ir/ets/etsReExportDeclaration.h"
#include "parser/program/program.h"
#include "public/public.h"
#include "ir/astNode.h"
namespace ark::es2panda::compiler {
inline void EjectNamespacesFromStatementsVector(ArenaVector<ir::Statement *> *stmts, ArenaVector<ir::ETSModule *> *dst)
{
auto end = std::remove_if(stmts->begin(), stmts->end(), [dst](ir::AstNode *node) {
if (node->IsETSModule()) {
ES2PANDA_ASSERT(node->AsETSModule()->IsNamespace());
dst->emplace_back(node->AsETSModule());
return true;
}
return false;
});
stmts->erase(end, stmts->end());
}
class GlobalClassHandler {
public:
struct GlobalStmts {
parser::Program *program;
ArenaVector<ir::Statement *> statements;
};
explicit GlobalClassHandler(public_lib::Context *context)
: context_(context),
parser_(context->parser->AsETSParser()),
allocator_(context->Allocator()),
packageInitializerBlockCount_(context->Allocator()->Adapter()) {};
static void MergeNamespace(ArenaVector<ir::ETSModule *> &namespaces, public_lib::Context *ctx);
* Each "Module" has it's own global class, which contains all top level statements across "module"
* Result - creation of global class and _$init$_ method
* @param programs - vector of files in module
*/
void SetupGlobalClass(parser::Program *programs);
void CheckPackageMultiInitializerBlock(util::StringView packageName,
const ArenaVector<ArenaVector<ir::Statement *>> &initializerBlocks);
void SetGlobalProgram(parser::Program *program)
{
globalProgram_ = program;
}
private:
* Move top level statements to _$init$_ and
* @param program program of module
* @param init_statements statements which should be executed
*/
void SetupGlobalMethods(ArenaVector<ir::Statement *> &&statements);
void AddStaticBlockToClass(ir::ClassDefinition *classDef);
void SetupClassStaticBlocksInModule(ir::ETSModule *module);
void CollectProgramGlobalClasses(ArenaVector<ir::ETSModule *> &namespaces);
ir::ClassDeclaration *TransformNamespace(ir::ETSModule *ns);
ir::ClassDeclaration *CreateTransformedClass(ir::ETSModule *ns);
template <class Node>
void CollectExportedClasses(parser::Program *program, ir::ClassDefinition *classDef,
const ArenaVector<Node *> &statements);
void CollectReExportedClasses(parser::Program *program, ir::ClassDefinition *classDef,
const ir::ETSReExportDeclaration *reExport);
void CollectNamespaceExportedClasses(parser::Program *program, ir::ClassDefinition *classDef);
void SetupGlobalMethods(ArenaVector<ir::Statement *> &&initStatements, ir::ClassDefinition *globalClass,
bool isDeclare);
void SetupInitializerBlock(ArenaVector<ArenaVector<ir::Statement *>> &&initializerBlock,
ir::ClassDefinition *globalClass);
void MaybeAddMainFunction();
void SetupInitializationMethodIfNeeded(ir::ClassDefinition *classDef);
ArenaVector<ir::Statement *> TransformNamespaces(ArenaVector<ir::ETSModule *> &namespaces);
ir::ClassDeclaration *CreateGlobalClass();
ir::ClassStaticBlock *CreateStaticBlock(ir::ClassDefinition *classDef);
ir::MethodDefinition *CreateGlobalMethod(std::string_view name, ArenaVector<ir::Statement *> &&statements,
bool needTypeAnno = false);
void AddInitStatementsToStaticBlock(ir::ClassDefinition *globalClass,
ArenaVector<ir::Statement *> &&initStatements);
void AddInitCallToStaticBlock(ir::ClassDefinition *globalClass, ir::MethodDefinition *initMethod);
void AddInitializerBlockToStaticBlock(ir::ClassDefinition *globalClass,
ArenaVector<ir::Statement *> &&initializerBlocks);
ArenaVector<ArenaVector<ir::Statement *>> FormInitStaticBlockMethodStatements(
ArenaVector<GlobalStmts> &&initStatements);
void TransformBrokenNamespace(ir::AstNode *node);
ArenaVector<ir::Statement *> FormInitMethodStatements(ArenaVector<GlobalStmts> &&initStatements);
GlobalDeclTransformer::ResultT CollectProgramGlobalStatements(ir::ClassDefinition *classDef,
ir::BlockStatement *stmt, bool isPackageFraction);
ir::Identifier *RefIdent(const util::StringView &name);
public_lib::Context *context_;
parser::ETSParser *const parser_;
ArenaAllocator *const allocator_;
parser::Program *globalProgram_ {nullptr};
ArenaUnorderedSet<util::StringView> packageInitializerBlockCount_;
};
}
#endif