fix(autogen): syntax errors in codegen

This commit is contained in:
maelstrom 2025-04-26 14:44:02 +02:00
parent c578b7361c
commit 76554c8295
5 changed files with 37 additions and 12 deletions

View file

@ -4,7 +4,6 @@ find_package(Clang REQUIRED)
add_executable(autogen
src/main.cpp
src/util.cpp
src/cache.cpp
src/analysis.cpp
src/codegen.cpp
)

View file

@ -282,6 +282,9 @@ bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state)
CXCursorKind kind = clang_getCursorKind(cur);
if (kind != CXCursor_ClassDecl) return CXChildVisit_Continue;
CXSourceLocation loc = clang_getCursorLocation(cur);
if (!clang_Location_isFromMainFile(loc)) return CXChildVisit_Continue; // This class is not from this header. Skip
std::string className = x_clang_toString(clang_getCursorDisplayName(cur));
// Forward-decls can slip through the cracks, this prevents that, but also allows us to filter non-instance classes in the src/objects directory
if (!findInstanceAnnotation(cur)) return CXChildVisit_Continue; // Class is not "primary" declaration/is not instance, skip

View file

@ -17,8 +17,6 @@ std::map<std::string, std::string> MAPPED_TYPE = {
{ "int", "Data::Int" },
{ "float", "Data::Float" },
{ "std::string", "Data::String" },
{ "std::weak_ptr<Instance>", "Data::InstanceRef" },
{ "std::weak_ptr<Part>", "Data::InstanceRef" },
{ "glm::vec3", "Vector3" },
};
@ -26,6 +24,16 @@ std::map<std::string, std::monostate> ENUM_TYPES = {
{ "SurfaceType", std::monostate() }
};
std::string parseWeakPtr(std::string weakPtrType) {
if (!weakPtrType.starts_with("std::weak_ptr")) return "";
int pos0 = weakPtrType.find("<");
int pos1 = weakPtrType.find(">");
std::string subtype = weakPtrType.substr(pos0+1, pos1-pos0-1);
return subtype;
}
std::string castFromVariant(std::string valueStr, std::string fieldType) {
// Manual exception for now, enums will get their own system eventually
if (fieldType == "SurfaceType") {
@ -42,6 +50,12 @@ std::string castToVariant(std::string valueStr, std::string fieldType) {
return "Data::Int((int)" + valueStr + ")";
}
// InstanceRef
std::string subtype = parseWeakPtr(fieldType);
if (!subtype.empty()) {
return "Data::Variant(" + valueStr + ".expired() ? Data::InstanceRef() : Data::InstanceRef(std::dynamic_pointer_cast<Instance>(" + valueStr + ".lock())))";
}
std::string mappedType = MAPPED_TYPE[fieldType];
if (!mappedType.empty()) {
return mappedType + "(" + valueStr + ")";
@ -56,6 +70,8 @@ void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
bool first = true;
for (auto& prop : state.properties) {
out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {";
// InstanceRef
std::string subtype = parseWeakPtr(prop.backingFieldType);
if (prop.flags & PropertyFlag_Readonly) {
out << "\n return AssignToReadOnlyMember(GetClass()->className, name)";
@ -63,6 +79,9 @@ void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
out << "\n this->" << prop.fieldName << " = this->" << prop.fieldName << ".Rotation() + value.get<Vector3>();";
} else if (prop.cframeMember == CFrameMember_Rotation) {
out << "\n this->" << prop.fieldName << " = CFrame::FromEulerAnglesXYZ(value.get<Vector3>()) + this->" << prop.fieldName << ".Position();";
} else if (!subtype.empty()) {
out << "\n std::weak_ptr<Instance> ref = value.get<Data::InstanceRef>();"
<< "\n this->" << prop.fieldName << " = ref.expired() ? std::weak_ptr<" << subtype << ">() : std::dynamic_pointer_cast<" << subtype << ">(ref.lock());";
} else {
out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";";
if (!prop.onUpdateCallback.empty())
@ -106,13 +125,15 @@ void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
}
void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
out << "std::vector<string> " << state.name << "::InternalGetProperties() {\n";
out << " std::vector<string> properties = " << state.baseClass << "::InternalGetProperties();\n";
out << "std::vector<std::string> " << state.name << "::InternalGetProperties() {\n";
out << " std::vector<std::string> properties = " << state.baseClass << "::InternalGetProperties();\n";
for (auto& prop : state.properties) {
out << " properties.push_back(\"" << prop.name << "\")l\n";
out << " properties.push_back(\"" << prop.name << "\");\n";
}
out << " return properties;\n";
out << "};\n\n";
}
@ -127,6 +148,7 @@ void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
std::string type = MAPPED_TYPE[prop.backingFieldType];
if (type.empty()) type = prop.backingFieldType;
if (type == "SurfaceType") type = "Data::Int";
if (!parseWeakPtr(prop.backingFieldType).empty()) type = "Data::InstanceRef";
std::string strFlags;
if (prop.flags & PropertyFlag_Readonly)
@ -174,6 +196,7 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
if (state.abstract) constructorStr = "nullptr";
else constructorStr = "&" + state.name + "::Create";
out << "#define __AUTOGEN_EXTRA_INCLUDES__\n";
out << "#include \"" << state.headerPath << "\"\n\n";
out << "const InstanceType " << state.name << "::TYPE = {\n"
<< " .super = &" << state.baseClass << "::TYPE,\n"
@ -193,4 +216,5 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
writePropertySetHandler(out, state);
writePropertyGetHandler(out, state);
writePropertyMetaHandler(out, state);
writePropertiesList(out, state);
}

View file

@ -5,11 +5,8 @@
#include <clang-c/Index.h>
#include <cstdio>
#include <fstream>
#include <string>
#include <vector>
#include <filesystem>
#include "analysis.h"
#include "cache.h"
#include "codegen.h"
namespace fs = std::filesystem;
@ -32,9 +29,6 @@ int main(int argc, char** argv) {
fs::create_directories(outPath.parent_path()); // Make sure generated dir exists before we try writing to it
if (state.classes.empty())
return 0;
printf("[AUTOGEN] Generating file %s...\n", relpath.c_str());
std::ofstream outStream(outPath);

View file

@ -5,6 +5,11 @@
#include <memory>
#include <optional>
//this is necessary ebcause we use std::weak_ptr<Part> without including it in this file
#ifdef __AUTOGEN_EXTRA_INCLUDES__
#include "../part.h"
#endif
class Part;
class Workspace;