feat(autogen): generate basis for instance

This commit is contained in:
maelstrom 2025-04-26 02:14:39 +02:00
parent 85e1efe5b3
commit 8049d45b43
6 changed files with 60 additions and 2 deletions

View file

@ -6,6 +6,7 @@ add_executable(autogen
src/util.cpp src/util.cpp
src/cache.cpp src/cache.cpp
src/analysis.cpp src/analysis.cpp
src/codegen.cpp
) )
set_target_properties(autogen PROPERTIES OUTPUT_NAME "autogen") set_target_properties(autogen PROPERTIES OUTPUT_NAME "autogen")

View file

@ -1,9 +1,13 @@
#include "analysis.h" #include "analysis.h"
#include "util.h" #include "util.h"
#include <clang-c/CXFile.h>
#include <clang-c/CXSourceLocation.h>
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <cstdio> #include <cstdio>
#include <optional> #include <optional>
#include <filesystem>
namespace fs = std::filesystem;
// Very simple parser // Very simple parser
// Example format: // Example format:
@ -161,14 +165,23 @@ void processField(CXCursor cur, ClassAnalysis* state) {
state->properties.push_back(anly); state->properties.push_back(anly);
} }
void processClass(CXCursor cur, AnalysisState* state, std::string className) { void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
ClassAnalysis anly; ClassAnalysis anly;
// Find base class // Find base class
std::string baseClass = findBaseClass(cur); std::string baseClass = findBaseClass(cur);
// Find header file
CXSourceLocation loc = clang_getCursorLocation(cur);
CXFile file;
unsigned line, column, off;
clang_getFileLocation(loc, &file, &line, &column, &off);
std::string headerName = x_clang_toString(clang_getFileName(file));
fs::path headerPath = fs::relative(headerName, srcRoot);
anly.name = className; anly.name = className;
anly.baseClass = baseClass; anly.baseClass = baseClass;
anly.headerPath = headerPath;
// Add misc flags and options // Add misc flags and options
auto instanceDef = findAnnotation(cur, "OB::def_inst"); auto instanceDef = findAnnotation(cur, "OB::def_inst");
@ -237,7 +250,7 @@ bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state)
if (!findInstanceAnnotation(cur)) return CXChildVisit_Continue; // Class is not "primary" declaration/is not instance, skip if (!findInstanceAnnotation(cur)) return CXChildVisit_Continue; // Class is not "primary" declaration/is not instance, skip
if (state->classes.count(className) > 0) return CXChildVisit_Continue; // Class has already been analyzed, skip... if (state->classes.count(className) > 0) return CXChildVisit_Continue; // Class has already been analyzed, skip...
processClass(cur, state, className); processClass(cur, state, className, srcRoot);
return CXChildVisit_Continue; return CXChildVisit_Continue;
}); });

View file

@ -38,6 +38,7 @@ inline PropertyFlags operator|(PropertyFlags a, PropertyFlags b) {
struct ClassAnalysis { struct ClassAnalysis {
std::string name; std::string name;
std::string baseClass; std::string baseClass;
std::string headerPath;
std::vector<PropertyAnalysis> properties; std::vector<PropertyAnalysis> properties;
ClassFlags flags = (ClassFlags)0; ClassFlags flags = (ClassFlags)0;
std::string explorerIcon; std::string explorerIcon;

27
autogen/src/codegen.cpp Normal file
View file

@ -0,0 +1,27 @@
#include "codegen.h"
#include "analysis.h"
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
std::string strFlags;
if (state.flags & ClassFlag_NotCreatable)
strFlags += " | INSTANCE_NOT_CREATABLE";
if (state.flags & ClassFlag_Service)
strFlags += " | INSTANCE_SERVICE";
if (state.flags & ClassFlag_Hidden)
strFlags += " | INSTANCE_HIDDEN";
if (!strFlags.empty()) strFlags = strFlags.substr(3); // Remove leading pipe
else strFlags = "0"; // 0 == No option
out << "#include \"" << state.headerPath << "\"\n\n";
out << "const InstanceType " << state.name << "::TYPE = {\n"
<< " .super = &" << state.baseClass << "::TYPE,\n"
<< " .className = \"" << state.name << "\",\n"
<< " .constructor = &" << state.name << "::CreateGeneric,\n"
<< " .explorerIcon = \"" << state.explorerIcon << "\",\n"
<< " .flags = " << strFlags << ",\n"
<< "};\n\n";
out << "const InstanceType* " << state.name << "::GetClass() {\n"
<< " return &TYPE;\n"
<< "};\n\n";
}

6
autogen/src/codegen.h Normal file
View file

@ -0,0 +1,6 @@
#pragma once
#include "analysis.h"
#include <fstream>
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state);

View file

@ -4,11 +4,13 @@
#include <clang-c/CXString.h> #include <clang-c/CXString.h>
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <cstdio> #include <cstdio>
#include <fstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <filesystem> #include <filesystem>
#include "analysis.h" #include "analysis.h"
#include "cache.h" #include "cache.h"
#include "codegen.h"
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -40,6 +42,14 @@ int main(int argc, char** argv) {
analyzeClasses("../core/src/objects/part.h", argv[1], &state); analyzeClasses("../core/src/objects/part.h", argv[1], &state);
printf("[AUTOGEN] Generating cpp files...\n");
for (auto& [_, clazz] : state.classes) {
fs::path outPath = fs::path(argv[3]) / ("class_" + clazz.name + ".cpp");
std::ofstream outStream(outPath);
writeCodeForClass(outStream, clazz);
outStream.close();
}
// for (auto& [_, clazz] : state.classes) { // for (auto& [_, clazz] : state.classes) {
// printf("Class: %s\n", clazz.name.c_str()); // printf("Class: %s\n", clazz.name.c_str());