PkmnLibTools/src/Tools/ScriptHeadersExporter.cpp

247 lines
9.3 KiB
C++

#include "ScriptHeadersExporter.hpp"
#include <PkmnLib/ScriptResolving/AngelScript/AngelScriptResolver.hpp>
#include <filesystem>
static bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if (start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
static void PrintObjectTypeDef(asITypeInfo* type, const std::filesystem::path& dir) {
auto name = std::string(type->GetName());
if (name == "string" || name == "array")
return;
std::fstream fs;
fs.open((dir / name).concat(".astypedef"), std::fstream::out);
if ((type->GetFlags() & asOBJ_VALUE) != 0 && (type->GetFlags() & asOBJ_ASHANDLE) == 0) {
fs << "valuetype";
} else {
fs << "type";
}
fs << " " << type->GetName();
if ((type->GetFlags() & asOBJ_TEMPLATE) != 0) {
fs << "<";
for (asUINT i = 0; i < type->GetSubTypeCount(); ++i) {
if (i != 0) {
fs << ", ";
}
fs << type->GetSubType(i)->GetName();
}
fs << ">";
}
fs << " {" << std::endl;
auto behaviourCount = type->GetBehaviourCount();
for (asUINT j = 0; j < behaviourCount; j++) {
if (name == "ref")
break;
if (name == "dictionaryValue")
break;
asEBehaviours behaviourType;
auto behaviour = type->GetBehaviourByIndex(j, &behaviourType);
if (behaviourType > 4) {
continue;
}
auto decl = std::string(behaviour->GetDeclaration(false, false, true));
if (behaviourType == asBEHAVE_CONSTRUCT || behaviourType == asBEHAVE_FACTORY) {
replace(decl, type->GetName(), "void f");
}
if (behaviourType == asBEHAVE_DESTRUCT) {
replace(decl, std::string("~") + type->GetName(), "void f");
}
if (behaviourType == asBEHAVE_LIST_CONSTRUCT || behaviourType == asBEHAVE_LIST_FACTORY) {
replace(decl, "$list", "f");
}
fs << " behave " << behaviourType << " " << decl << ";" << std::endl;
}
auto propertyCount = type->GetMethodCount();
for (asUINT j = 0; j < propertyCount; j++) {
auto method = type->GetMethodByIndex(j);
if (method->IsProperty()) {
auto name = std::string(method->GetName());
auto decl = std::string(method->GetDeclaration(false, true, false));
auto realName = name.substr(4);
if (method->GetParamCount() > 0 && !name.starts_with("set_")) {
fs << " " << decl << " property;" << std::endl;
} else if (name.starts_with("get_")) {
replace(decl, name, realName);
replace(decl, "() const", " { get const; ");
replace(decl, "()", " { get; ");
fs << " " << decl;
auto setMethod = type->GetMethodByName(("set_" + realName).c_str());
if (setMethod != nullptr) {
auto setDecl = std::string(setMethod->GetDeclaration(false, true, false));
if (setDecl.find("const") != std::string::npos) {
fs << "set const; ";
} else {
fs << "set; ";
}
}
fs << "};" << std::endl;
} else if (name.starts_with("set")) {
auto getMethod = type->GetMethodByName(("get_" + realName).c_str());
if (getMethod != nullptr) {
continue;
}
replace(decl, name, realName);
replace(decl, "() const", " { set const; }");
replace(decl, "()", " { set; }");
fs << "\t" << decl << ";" << std::endl;
}
} else {
auto name = std::string(method->GetName());
auto decl = std::string(method->GetDeclaration(false, true, true));
replace(decl, "&in", " &in");
replace(decl, "&out", " &out");
replace(decl, "ref", "ref@");
fs << " " << decl << ";" << std::endl;
}
}
fs << "}" << std::endl;
fs.close();
}
static void PrintScriptObject(asITypeInfo* type, const std::filesystem::path& dir) {
auto name = std::string(type->GetName());
if (name == "string" || name == "array" || name == "ref")
return;
std::fstream fs;
fs.open((dir / name).concat(".as"), std::fstream::out);
auto isAbstract = (type->GetFlags() & asEObjTypeFlags::asOBJ_ABSTRACT) != 0;
fs << "shared ";
if (isAbstract)
fs << "abstract class ";
else
fs << "interface ";
fs << type->GetName() << " {" << std::endl;
auto propertyCount = type->GetMethodCount();
for (asUINT j = 0; j < propertyCount; j++) {
auto method = type->GetMethodByIndex(j);
if (method->IsProperty()) {
auto name = std::string(method->GetName());
auto decl = std::string(method->GetDeclaration(false, true, false));
auto realName = name.substr(4);
if (name.starts_with("get_")) {
replace(decl, name, realName);
replace(decl, "() const", " get const; ");
replace(decl, "()", " get; ");
fs << "\t"
<< "{" << decl;
auto setMethod = type->GetMethodByName(("set_" + realName).c_str());
if (setMethod != nullptr) {
auto setDecl = replace(decl, name, realName);
replace(decl, "() const", " set const; ");
replace(decl, "()", " set; ");
fs << setDecl;
}
fs << "}" << std::endl;
} else if (name.starts_with("set")) {
auto getMethod = type->GetMethodByName(("get_" + realName).c_str());
if (getMethod != nullptr) {
continue;
}
replace(decl, name, realName);
replace(decl, "() const", " set const; ");
replace(decl, "()", " set; ");
fs << "\t"
<< "{" << decl << "}" << std::endl;
}
} else {
auto name = std::string(method->GetName());
if (name == "opAssign")
continue;
if (name == "GetOwner") {
fs << "\tref@ __owner;" << std::endl << std::endl;
}
auto decl = std::string(method->GetDeclaration(false, true, true));
replace(decl, "&in", " &in");
replace(decl, "&out", " &out");
replace(decl, "ref", "ref@");
fs << "\t" << decl;
if (isAbstract) {
if (method->GetReturnTypeId() == 0) {
fs << "{};" << std::endl;
} else {
if (name == "GetOwner") {
fs << "{ return __owner; };" << std::endl;
} else if (method->GetReturnTypeId() == asTYPEID_BOOL) {
fs << "{ return false; };" << std::endl;
} else {
fs << "{ return 0; };" << std::endl;
}
}
} else
fs << ";" << std::endl;
}
}
fs << "}" << std::endl;
fs.close();
}
void ScriptHeadersExporter::Export(const std::string& outPath) {
auto resolver = new AngelScriptResolver();
resolver->Initialize(nullptr);
resolver->FinalizeModule();
auto module = resolver->GetMainModule();
auto engine = module->GetEngine();
auto typesCount = engine->GetObjectTypeCount();
std::filesystem::path dir(outPath);
for (asUINT i = 0; i < typesCount; i++) {
auto type = engine->GetObjectTypeByIndex(i);
if ((type->GetTypeId() & asTYPEID_SCRIPTOBJECT) != 0) {
PrintScriptObject(type, dir);
} else {
PrintObjectTypeDef(type, dir);
}
}
auto moduleTypesCount = module->GetObjectTypeCount();
for (asUINT i = 0; i < moduleTypesCount; i++) {
auto type = module->GetObjectTypeByIndex(i);
if ((type->GetTypeId() & asTYPEID_SCRIPTOBJECT) != 0) {
PrintScriptObject(type, dir);
} else {
PrintObjectTypeDef(type, dir);
}
}
auto enumCount = engine->GetEnumCount();
for (asUINT i = 0; i < enumCount; i++) {
auto en = engine->GetEnumByIndex(i);
auto name = en->GetName();
std::fstream fs;
fs.open((dir / name).concat(".astypedef"), std::fstream::out);
fs << "enum " << en->GetName() << " {" << std::endl;
auto valueCount = en->GetEnumValueCount();
for (asUINT j = 0; j < valueCount; j++) {
int val;
auto name = en->GetEnumValueByIndex(j, &val);
fs << "\t" << name << " = " << val << "," << std::endl;
}
fs << "}" << std::endl;
fs.close();
}
auto globalFuncs = engine->GetGlobalFunctionCount();
if (globalFuncs > 0) {
std::fstream fs;
fs.open((dir / "globals").concat(".astypedef"), std::fstream::out);
for (asUINT i = 0; i < globalFuncs; ++i) {
auto func = engine->GetGlobalFunctionByIndex(i);
fs << "func " << func->GetDeclaration(false, false, true) << ";" << std::endl;
}
}
}