fix(autogen): syntax errors in codegen
This commit is contained in:
parent
c578b7361c
commit
76554c8295
5 changed files with 37 additions and 12 deletions
|
@ -4,7 +4,6 @@ find_package(Clang REQUIRED)
|
||||||
add_executable(autogen
|
add_executable(autogen
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/util.cpp
|
src/util.cpp
|
||||||
src/cache.cpp
|
|
||||||
src/analysis.cpp
|
src/analysis.cpp
|
||||||
src/codegen.cpp
|
src/codegen.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -282,6 +282,9 @@ bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state)
|
||||||
CXCursorKind kind = clang_getCursorKind(cur);
|
CXCursorKind kind = clang_getCursorKind(cur);
|
||||||
if (kind != CXCursor_ClassDecl) return CXChildVisit_Continue;
|
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));
|
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
|
// 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
|
if (!findInstanceAnnotation(cur)) return CXChildVisit_Continue; // Class is not "primary" declaration/is not instance, skip
|
||||||
|
|
|
@ -17,8 +17,6 @@ std::map<std::string, std::string> MAPPED_TYPE = {
|
||||||
{ "int", "Data::Int" },
|
{ "int", "Data::Int" },
|
||||||
{ "float", "Data::Float" },
|
{ "float", "Data::Float" },
|
||||||
{ "std::string", "Data::String" },
|
{ "std::string", "Data::String" },
|
||||||
{ "std::weak_ptr<Instance>", "Data::InstanceRef" },
|
|
||||||
{ "std::weak_ptr<Part>", "Data::InstanceRef" },
|
|
||||||
{ "glm::vec3", "Vector3" },
|
{ "glm::vec3", "Vector3" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,6 +24,16 @@ std::map<std::string, std::monostate> ENUM_TYPES = {
|
||||||
{ "SurfaceType", std::monostate() }
|
{ "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) {
|
std::string castFromVariant(std::string valueStr, std::string fieldType) {
|
||||||
// Manual exception for now, enums will get their own system eventually
|
// Manual exception for now, enums will get their own system eventually
|
||||||
if (fieldType == "SurfaceType") {
|
if (fieldType == "SurfaceType") {
|
||||||
|
@ -42,6 +50,12 @@ std::string castToVariant(std::string valueStr, std::string fieldType) {
|
||||||
return "Data::Int((int)" + valueStr + ")";
|
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];
|
std::string mappedType = MAPPED_TYPE[fieldType];
|
||||||
if (!mappedType.empty()) {
|
if (!mappedType.empty()) {
|
||||||
return mappedType + "(" + valueStr + ")";
|
return mappedType + "(" + valueStr + ")";
|
||||||
|
@ -56,6 +70,8 @@ void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto& prop : state.properties) {
|
for (auto& prop : state.properties) {
|
||||||
out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {";
|
out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {";
|
||||||
|
// InstanceRef
|
||||||
|
std::string subtype = parseWeakPtr(prop.backingFieldType);
|
||||||
|
|
||||||
if (prop.flags & PropertyFlag_Readonly) {
|
if (prop.flags & PropertyFlag_Readonly) {
|
||||||
out << "\n return AssignToReadOnlyMember(GetClass()->className, name)";
|
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>();";
|
out << "\n this->" << prop.fieldName << " = this->" << prop.fieldName << ".Rotation() + value.get<Vector3>();";
|
||||||
} else if (prop.cframeMember == CFrameMember_Rotation) {
|
} else if (prop.cframeMember == CFrameMember_Rotation) {
|
||||||
out << "\n this->" << prop.fieldName << " = CFrame::FromEulerAnglesXYZ(value.get<Vector3>()) + this->" << prop.fieldName << ".Position();";
|
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 {
|
} else {
|
||||||
out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";";
|
out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";";
|
||||||
if (!prop.onUpdateCallback.empty())
|
if (!prop.onUpdateCallback.empty())
|
||||||
|
@ -106,13 +125,15 @@ void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
|
void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
|
||||||
out << "std::vector<string> " << state.name << "::InternalGetProperties() {\n";
|
out << "std::vector<std::string> " << state.name << "::InternalGetProperties() {\n";
|
||||||
out << " std::vector<string> properties = " << state.baseClass << "::InternalGetProperties();\n";
|
out << " std::vector<std::string> properties = " << state.baseClass << "::InternalGetProperties();\n";
|
||||||
|
|
||||||
for (auto& prop : state.properties) {
|
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";
|
out << "};\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +148,7 @@ void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
|
||||||
std::string type = MAPPED_TYPE[prop.backingFieldType];
|
std::string type = MAPPED_TYPE[prop.backingFieldType];
|
||||||
if (type.empty()) type = prop.backingFieldType;
|
if (type.empty()) type = prop.backingFieldType;
|
||||||
if (type == "SurfaceType") type = "Data::Int";
|
if (type == "SurfaceType") type = "Data::Int";
|
||||||
|
if (!parseWeakPtr(prop.backingFieldType).empty()) type = "Data::InstanceRef";
|
||||||
|
|
||||||
std::string strFlags;
|
std::string strFlags;
|
||||||
if (prop.flags & PropertyFlag_Readonly)
|
if (prop.flags & PropertyFlag_Readonly)
|
||||||
|
@ -174,6 +196,7 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
|
||||||
if (state.abstract) constructorStr = "nullptr";
|
if (state.abstract) constructorStr = "nullptr";
|
||||||
else constructorStr = "&" + state.name + "::Create";
|
else constructorStr = "&" + state.name + "::Create";
|
||||||
|
|
||||||
|
out << "#define __AUTOGEN_EXTRA_INCLUDES__\n";
|
||||||
out << "#include \"" << state.headerPath << "\"\n\n";
|
out << "#include \"" << state.headerPath << "\"\n\n";
|
||||||
out << "const InstanceType " << state.name << "::TYPE = {\n"
|
out << "const InstanceType " << state.name << "::TYPE = {\n"
|
||||||
<< " .super = &" << state.baseClass << "::TYPE,\n"
|
<< " .super = &" << state.baseClass << "::TYPE,\n"
|
||||||
|
@ -193,4 +216,5 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
|
||||||
writePropertySetHandler(out, state);
|
writePropertySetHandler(out, state);
|
||||||
writePropertyGetHandler(out, state);
|
writePropertyGetHandler(out, state);
|
||||||
writePropertyMetaHandler(out, state);
|
writePropertyMetaHandler(out, state);
|
||||||
|
writePropertiesList(out, state);
|
||||||
}
|
}
|
|
@ -5,11 +5,8 @@
|
||||||
#include <clang-c/Index.h>
|
#include <clang-c/Index.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include "analysis.h"
|
#include "analysis.h"
|
||||||
#include "cache.h"
|
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
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
|
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());
|
printf("[AUTOGEN] Generating file %s...\n", relpath.c_str());
|
||||||
std::ofstream outStream(outPath);
|
std::ofstream outStream(outPath);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#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 Part;
|
||||||
class Workspace;
|
class Workspace;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue