implement new Modify sytnax

This commit is contained in:
altalk23 2022-11-09 20:11:50 +03:00 committed by alk
parent 32196f3545
commit e349dc9b74
5 changed files with 107 additions and 122 deletions
codegen/src
loader/include/Geode

View file

@ -1,25 +1,27 @@
#include "Shared.hpp"
#include "TypeOpt.hpp"
#include <iostream>
#include <set>
namespace { namespace format_strings {
char const* wrap_start = R"GEN(
namespace {
namespace format_strings {
char const* wrap_start = R"GEN(
namespace wrap {
)GEN";
char const* wrap_declare_identifier = R"GEN(
char const* wrap_declare_identifier = R"GEN(
#ifndef GEODE_WRAP_{function_name}
#define GEODE_WRAP_{function_name}
GEODE_WRAPPER_FOR_IDENTIFIER({function_name})
#endif
)GEN";
char const* wrap_end = R"GEN(
char const* wrap_end = R"GEN(
}
)GEN";
// requires: class_name
char const* modify_start = R"GEN(#pragma once
// requires: class_name
char const* modify_start = R"GEN(#pragma once
#include <Geode/modify/Modify.hpp>
#include <Geode/modify/Field.hpp>
#include <Geode/modify/InternalMacros.hpp>
@ -28,99 +30,88 @@ using namespace geode::modifier;
namespace geode::modifier {{
{wrap}
template<class Derived>
struct Modify<Derived, {class_name}> : ModifyBase<Modify<Derived, {class_name}>> {{
using ModifyBase<Modify<Derived, {class_name}>>::ModifyBase;
struct ModifyDerive<Derived, {class_name}> : ModifyBase<ModifyDerive<Derived, {class_name}>> {{
using ModifyBase<ModifyDerive<Derived, {class_name}>>::ModifyBase;
using Base = {class_name};
static void apply() {{
using namespace geode::core::meta;
)GEN";
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
char const* apply_function = R"GEN(
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
char const* apply_function = R"GEN(
GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {pure_index}, {function_convention}, {class_name}, {function_name}))GEN";
char const* modify_end = R"GEN(
char const* modify_end = R"GEN(
}
};
}
)GEN";
char const* modify_include = R"GEN(#include "modify/{file_name}"
char const* modify_include = R"GEN(#include "modify/{file_name}"
)GEN";
}}
}
}
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
std::string output;
std::string output;
TypeBank bank;
bank.loadFrom(root);
TypeBank bank;
bank.loadFrom(root);
for (auto c : root.classes) {
if (c.name == "cocos2d")
continue;
for (auto c : root.classes) {
if (c.name == "cocos2d") continue;
std::string filename = (codegen::getUnqualifiedClassName(c.name) + ".hpp");
output += fmt::format(format_strings::modify_include,
fmt::arg("file_name", filename)
);
std::string filename = (codegen::getUnqualifiedClassName(c.name) + ".hpp");
output += fmt::format(format_strings::modify_include, fmt::arg("file_name", filename));
std::string single_output;
std::string wrap;
std::string single_output;
std::string wrap;
// wrap
wrap += format_strings::wrap_start;
std::set<std::string> used;
for (auto& f : c.fields) {
if (auto fn = f.get_fn()) {
if (fn->type == FunctionType::Normal && !used.count(fn->name)) {
used.insert(fn->name);
wrap += fmt::format(format_strings::wrap_declare_identifier,
fmt::arg("function_name", fn->name)
);
}
}
}
wrap += format_strings::wrap_end;
// wrap
wrap += format_strings::wrap_start;
std::set<std::string> used;
for (auto& f : c.fields) {
if (auto fn = f.get_fn()) {
if (fn->type == FunctionType::Normal && !used.count(fn->name)) {
used.insert(fn->name);
wrap += fmt::format(
format_strings::wrap_declare_identifier, fmt::arg("function_name", fn->name)
);
}
}
}
wrap += format_strings::wrap_end;
single_output += fmt::format(format_strings::modify_start,
fmt::arg("class_name", c.name),
fmt::arg("wrap", wrap)
);
single_output += fmt::format(
format_strings::modify_start, fmt::arg("class_name", c.name), fmt::arg("wrap", wrap)
);
// modify
for (auto& f : c.fields) {
if (codegen::getStatus(f) != BindStatus::Unbindable) {
auto begin = f.get_fn();
// modify
for (auto& f : c.fields) {
if (codegen::getStatus(f) != BindStatus::Unbindable) {
auto begin = f.get_fn();
std::string function_name;
std::string function_name;
switch (begin->type) {
case FunctionType::Normal:
function_name = begin->name;
break;
case FunctionType::Ctor:
function_name = "constructor";
break;
case FunctionType::Dtor:
function_name = "destructor";
break;
}
switch (begin->type) {
case FunctionType::Normal: function_name = begin->name; break;
case FunctionType::Ctor: function_name = "constructor"; break;
case FunctionType::Dtor: function_name = "destructor"; break;
}
single_output += fmt::format(format_strings::apply_function,
fmt::arg("addr_index", f.field_id),
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
fmt::arg("class_name", c.name),
fmt::arg("function_name", function_name),
fmt::arg("function_convention", codegen::getConvention(f))
);
}
}
single_output += fmt::format(
format_strings::apply_function, fmt::arg("addr_index", f.field_id),
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
fmt::arg("class_name", c.name), fmt::arg("function_name", function_name),
fmt::arg("function_convention", codegen::getConvention(f))
);
}
}
single_output += format_strings::modify_end;
single_output += format_strings::modify_end;
writeFile(singleFolder / filename, single_output);
}
writeFile(singleFolder / filename, single_output);
}
return output;
return output;
}

View file

@ -31,7 +31,7 @@ namespace geode {
class VersionInfo;
namespace modifier {
template <class, class, class>
template <class, class>
class FieldIntermediate;
}
}
@ -87,7 +87,7 @@ namespace geode {
size_t getFieldIndexForClass(size_t hash);
template <class, class, class>
template <class, class>
friend class modifier::FieldIntermediate;
void updateResourcePaths();

View file

@ -42,7 +42,7 @@ namespace geode::modifier {
}
};
template <class Base, class Intermediate, class Parent>
template <class Parent, class Base>
class FieldIntermediate {
// Padding used for guaranteeing any member of parents
// will be in between sizeof(Intermediate) and sizeof(Parent)
@ -54,22 +54,22 @@ namespace geode::modifier {
auto parent = new (parentContainer.data()) Parent();
parent->Intermediate::~Intermediate();
parent->Base::~Base();
std::memcpy(
offsetField, std::launder(&parentContainer[sizeof(Intermediate)]),
sizeof(Parent) - sizeof(Intermediate)
offsetField, std::launder(&parentContainer[sizeof(Base)]),
sizeof(Parent) - sizeof(Base)
);
}
static void fieldDestructor(void* offsetField) {
std::array<std::byte, sizeof(Parent)> parentContainer;
auto parent = new (parentContainer.data()) Intermediate();
auto parent = new (parentContainer.data()) Base();
std::memcpy(
std::launder(&parentContainer[sizeof(Intermediate)]), offsetField,
sizeof(Parent) - sizeof(Intermediate)
std::launder(&parentContainer[sizeof(Base)]), offsetField,
sizeof(Parent) - sizeof(Base)
);
static_cast<Parent*>(parent)->Parent::~Parent();
@ -87,15 +87,14 @@ namespace geode::modifier {
auto offsetField = container->getField(index);
if (!offsetField) {
offsetField = container->setField(
index, sizeof(Parent) - sizeof(Intermediate),
&FieldIntermediate::fieldDestructor
index, sizeof(Parent) - sizeof(Base), &FieldIntermediate::fieldDestructor
);
FieldIntermediate::fieldConstructor(offsetField);
}
return reinterpret_cast<Parent*>(
reinterpret_cast<std::byte*>(offsetField) - sizeof(Intermediate)
reinterpret_cast<std::byte*>(offsetField) - sizeof(Base)
);
}
};

View file

@ -8,15 +8,9 @@
* struct hook0 {};
* namespace {
* struct hook0Parent {};
* Modify<hook0<hook0Parent>, MenuLayer> hook0Apply;
* struct GEODE_HIDDEN hook0Intermediate: public MenuLayer {
* geode::modifier::FieldIntermediate<MenuLayer,
* hook0<hook0Intermediate>, hook0<hook0Parent>
* > m_fields;
* };
* }
* template<>
* struct GEODE_HIDDEN hook0<hook0Parent>: hook0Intermediate {
* struct GEODE_HIDDEN hook0<hook0Parent> : Modify<hook0<hook0Parent>, MenuLayer> {
* // code stuff idk
* };
*
@ -24,33 +18,19 @@
* I am bad at this stuff
*/
#define GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived) \
derived##Dummy; \
template <class> \
struct derived {}; \
namespace { \
struct derived##Parent {}; \
Modify<derived<derived##Parent>, base> derived##Apply; \
struct GEODE_HIDDEN derived##Intermediate : base { \
mutable geode::modifier::FieldIntermediate< \
base, derived##Intermediate, derived<derived##Parent>> \
m_fields; \
}; \
} \
template <> \
struct GEODE_HIDDEN derived<derived##Parent> : derived##Intermediate
#define GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived) \
derived##Dummy; \
template <class> \
struct derived {}; \
namespace { \
struct derived##Parent {}; \
} \
template <> \
struct GEODE_HIDDEN derived<derived##Parent> : geode::Modify<derived<derived##Parent>, base>
#define GEODE_MODIFY_DECLARE(base, derived) \
derived##Dummy; \
struct derived; \
namespace { \
Modify<derived, base> derived##Apply; \
struct GEODE_HIDDEN derived##Intermediate : base { \
mutable geode::modifier::FieldIntermediate<base, derived##Intermediate, derived> \
m_fields; \
}; \
} \
struct GEODE_HIDDEN derived : derived##Intermediate
#define GEODE_MODIFY_DECLARE(base, derived) \
derived##Dummy; \
struct GEODE_HIDDEN derived : geode::Modify<derived, base>
#define GEODE_MODIFY_REDIRECT4(base, derived) GEODE_MODIFY_DECLARE(base, derived)
#define GEODE_MODIFY_REDIRECT3(base, derived) GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived)

View file

@ -1,6 +1,7 @@
#pragma once
#include "../meta/meta.hpp"
#include "Addresses.hpp"
#include "Field.hpp"
#include "Types.hpp"
#include "Wrapper.hpp"
@ -21,7 +22,7 @@
namespace geode::modifier {
template <class Derived, class Base>
class Modify;
class ModifyDerive;
template <class Derived>
class ModifyBase {
@ -33,15 +34,29 @@ namespace geode::modifier {
});
}
template <class, class>
friend class Modify;
friend class ModifyDerive;
// explicit Modify(Property property) idea
};
template <class Derived, class Base>
class Modify {
class ModifyDerive {
public:
Modify() {
ModifyDerive() {
static_assert(core::meta::always_false<Derived>, "Custom Modify not implemented.");
}
};
}
namespace geode {
template <class Derived, class Base>
class Modify : public Base {
private:
static inline modifier::ModifyDerive<Derived, Base> s_apply;
// because for some reason we need it
static inline auto s_applyRef = &Modify::s_apply;
public:
modifier::FieldIntermediate<Derived, Base> m_fields;
};
}