mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-22 02:45:49 -04:00
implement new Modify sytnax
This commit is contained in:
parent
32196f3545
commit
e349dc9b74
5 changed files with 107 additions and 122 deletions
codegen/src
loader/include/Geode
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue