mirror of
https://github.com/geode-sdk/geode.git
synced 2025-02-17 00:30:26 -05:00
update broma
This commit is contained in:
parent
26893f1b80
commit
0a584327ff
8 changed files with 33 additions and 232 deletions
|
@ -4,7 +4,7 @@ project(Codegen LANGUAGES C CXX)
|
||||||
include(../cmake/CPM.cmake)
|
include(../cmake/CPM.cmake)
|
||||||
|
|
||||||
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
||||||
CPMAddPackage("gh:geode-sdk/Broma#b1adda0")
|
CPMAddPackage("gh:geode-sdk/Broma#a9c1d2e")
|
||||||
|
|
||||||
file(GLOB SOURCES
|
file(GLOB SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
#include "TypeOpt.hpp"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
namespace format_strings {
|
namespace format_strings {
|
||||||
|
@ -76,9 +75,6 @@ Result<tulip::hook::HandlerMetadata> geode::modifier::handlerMetadataForAddress(
|
||||||
|
|
||||||
std::string generateAddressHeader(Root& root) {
|
std::string generateAddressHeader(Root& root) {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
|
||||||
TypeBank bank;
|
|
||||||
bank.loadFrom(root);
|
|
||||||
output += format_strings::address_begin;
|
output += format_strings::address_begin;
|
||||||
|
|
||||||
for (auto& c : root.classes) {
|
for (auto& c : root.classes) {
|
||||||
|
@ -92,14 +88,12 @@ std::string generateAddressHeader(Root& root) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codegen::getStatus(field) == BindStatus::Binded) {
|
if (codegen::getStatus(field) == BindStatus::Binded) {
|
||||||
auto const ids = bank.getIDs(fn->beginning, c.name);
|
|
||||||
|
|
||||||
address_str = fmt::format(
|
address_str = fmt::format(
|
||||||
"addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))",
|
"addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))",
|
||||||
str_if("Non", !fn->beginning.is_virtual),
|
str_if("Non", !fn->prototype.is_virtual),
|
||||||
codegen::getParameterTypes(fn->beginning),
|
codegen::getParameterTypes(fn->prototype),
|
||||||
field.parent,
|
field.parent,
|
||||||
fn->beginning.name
|
fn->prototype.name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (codegen::getStatus(field) == BindStatus::NeedsBinding) {
|
else if (codegen::getStatus(field) == BindStatus::NeedsBinding) {
|
||||||
|
|
|
@ -187,7 +187,7 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
||||||
|
|
||||||
bool unimplementedField = false;
|
bool unimplementedField = false;
|
||||||
for (auto field : cls.fields) {
|
for (auto field : cls.fields) {
|
||||||
FunctionBegin* fb;
|
MemberFunctionProto* fb;
|
||||||
char const* used_format = format_strings::function_definition;
|
char const* used_format = format_strings::function_definition;
|
||||||
|
|
||||||
std::string addressDocs;
|
std::string addressDocs;
|
||||||
|
@ -212,11 +212,11 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else if (auto fn = field.get_as<OutOfLineField>()) {
|
} else if (auto fn = field.get_as<OutOfLineField>()) {
|
||||||
fb = &fn->beginning;
|
fb = &fn->prototype;
|
||||||
addressDocs = " * @note[short] Out of line\n";
|
addressDocs = " * @note[short] Out of line\n";
|
||||||
|
|
||||||
} else if (auto fn = field.get_as<FunctionBindField>()) {
|
} else if (auto fn = field.get_as<FunctionBindField>()) {
|
||||||
fb = &fn->beginning;
|
fb = &fn->prototype;
|
||||||
|
|
||||||
if (!codegen::platformNumber(fn->binds)) {
|
if (!codegen::platformNumber(fn->binds)) {
|
||||||
used_format = format_strings::error_definition;
|
used_format = format_strings::error_definition;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
#include "TypeOpt.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -58,9 +57,6 @@ namespace geode::modifier {{
|
||||||
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
|
||||||
TypeBank bank;
|
|
||||||
bank.loadFrom(root);
|
|
||||||
|
|
||||||
for (auto c : root.classes) {
|
for (auto c : root.classes) {
|
||||||
if (c.name == "cocos2d") continue;
|
if (c.name == "cocos2d") continue;
|
||||||
|
|
||||||
|
@ -108,7 +104,6 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single
|
||||||
for (auto& f : c.fields) {
|
for (auto& f : c.fields) {
|
||||||
if (codegen::getStatus(f) != BindStatus::Unbindable) {
|
if (codegen::getStatus(f) != BindStatus::Unbindable) {
|
||||||
auto begin = f.get_fn();
|
auto begin = f.get_fn();
|
||||||
auto func = TypeBank::makeFunc(*begin, c.name);
|
|
||||||
|
|
||||||
std::string format_string;
|
std::string format_string;
|
||||||
|
|
||||||
|
@ -127,11 +122,10 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single
|
||||||
single_output += fmt::format(
|
single_output += fmt::format(
|
||||||
format_string,
|
format_string,
|
||||||
fmt::arg("addr_index", f.field_id),
|
fmt::arg("addr_index", f.field_id),
|
||||||
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
|
|
||||||
fmt::arg("class_name", c.name),
|
fmt::arg("class_name", c.name),
|
||||||
fmt::arg("function_name", begin->name),
|
fmt::arg("function_name", begin->name),
|
||||||
fmt::arg("function_convention", codegen::getModifyConventionName(f)),
|
fmt::arg("function_convention", codegen::getModifyConventionName(f)),
|
||||||
fmt::arg("parameter_types", fmt::join(func.parameter_types, ", "))
|
fmt::arg("parameter_types", codegen::getParameterTypes(*begin))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ using std::istreambuf_iterator;
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace broma;
|
||||||
|
|
||||||
std::string generateAddressHeader(Root& root);
|
std::string generateAddressHeader(Root& root);
|
||||||
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder);
|
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder);
|
||||||
std::string generateWrapperHeader(Root& root);
|
std::string generateWrapperHeader(Root& root);
|
||||||
|
@ -84,15 +86,15 @@ namespace codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BindStatus getStatusWithPlatform(Platform p, Field const& field) {
|
inline BindStatus getStatusWithPlatform(Platform p, Field const& field) {
|
||||||
FunctionBegin const* fb;
|
MemberFunctionProto const* fb;
|
||||||
|
|
||||||
if (auto fn = field.get_as<FunctionBindField>()) {
|
if (auto fn = field.get_as<FunctionBindField>()) {
|
||||||
if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding;
|
if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding;
|
||||||
|
|
||||||
fb = &fn->beginning;
|
fb = &fn->prototype;
|
||||||
}
|
}
|
||||||
else if (auto fn = field.get_as<OutOfLineField>()) {
|
else if (auto fn = field.get_as<OutOfLineField>()) {
|
||||||
fb = &fn->beginning;
|
fb = &fn->prototype;
|
||||||
}
|
}
|
||||||
else return BindStatus::Unbindable;
|
else return BindStatus::Unbindable;
|
||||||
|
|
||||||
|
@ -122,7 +124,7 @@ namespace codegen {
|
||||||
return getStatusWithPlatform(codegen::platform, field);
|
return getStatusWithPlatform(codegen::platform, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string getParameters(FunctionBegin const& f) { // int p0, float p1
|
inline std::string getParameters(FunctionProto const& f) { // int p0, float p1
|
||||||
std::vector<std::string> parameters;
|
std::vector<std::string> parameters;
|
||||||
|
|
||||||
for (auto& [t, n] : f.args) {
|
for (auto& [t, n] : f.args) {
|
||||||
|
@ -132,7 +134,7 @@ namespace codegen {
|
||||||
return fmt::format("{}", fmt::join(parameters, ", "));
|
return fmt::format("{}", fmt::join(parameters, ", "));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string getParameterTypes(FunctionBegin const& f) { // int, float
|
inline std::string getParameterTypes(FunctionProto const& f) { // int, float
|
||||||
std::vector<std::string> parameters;
|
std::vector<std::string> parameters;
|
||||||
|
|
||||||
for (auto& [t, n] : f.args) {
|
for (auto& [t, n] : f.args) {
|
||||||
|
@ -142,7 +144,7 @@ namespace codegen {
|
||||||
return fmt::format("{}", fmt::join(parameters, ", "));
|
return fmt::format("{}", fmt::join(parameters, ", "));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string getParameterNames(FunctionBegin const& f) { // p0, p1
|
inline std::string getParameterNames(FunctionProto const& f) { // p0, p1
|
||||||
std::vector<std::string> parameters;
|
std::vector<std::string> parameters;
|
||||||
|
|
||||||
for (auto& [t, n] : f.args) {
|
for (auto& [t, n] : f.args) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
#include "TypeOpt.hpp"
|
|
||||||
|
|
||||||
namespace { namespace format_strings {
|
namespace { namespace format_strings {
|
||||||
char const* source_start = R"CAC(
|
char const* source_start = R"CAC(
|
||||||
|
@ -118,9 +117,6 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
|
||||||
std::string generateBindingSource(Root& root) {
|
std::string generateBindingSource(Root& root) {
|
||||||
std::string output(format_strings::source_start);
|
std::string output(format_strings::source_start);
|
||||||
|
|
||||||
TypeBank bank;
|
|
||||||
bank.loadFrom(root);
|
|
||||||
|
|
||||||
for (auto& c : root.classes) {
|
for (auto& c : root.classes) {
|
||||||
|
|
||||||
for (auto& f : c.fields) {
|
for (auto& f : c.fields) {
|
||||||
|
@ -138,25 +134,25 @@ std::string generateBindingSource(Root& root) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fn->beginning.type) {
|
switch (fn->prototype.type) {
|
||||||
case FunctionType::Ctor:
|
case FunctionType::Ctor:
|
||||||
case FunctionType::Dtor:
|
case FunctionType::Dtor:
|
||||||
output += fmt::format(format_strings::ool_structor_function_definition,
|
output += fmt::format(format_strings::ool_structor_function_definition,
|
||||||
fmt::arg("function_name", fn->beginning.name),
|
fmt::arg("function_name", fn->prototype.name),
|
||||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
fmt::arg("const", str_if(" const ", fn->prototype.is_const)),
|
||||||
fmt::arg("class_name", c.name),
|
fmt::arg("class_name", c.name),
|
||||||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
fmt::arg("parameters", codegen::getParameters(fn->prototype)),
|
||||||
fmt::arg("definition", fn->inner)
|
fmt::arg("definition", fn->inner)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
output += fmt::format(format_strings::ool_function_definition,
|
output += fmt::format(format_strings::ool_function_definition,
|
||||||
fmt::arg("function_name", fn->beginning.name),
|
fmt::arg("function_name", fn->prototype.name),
|
||||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
fmt::arg("const", str_if(" const ", fn->prototype.is_const)),
|
||||||
fmt::arg("class_name", c.name),
|
fmt::arg("class_name", c.name),
|
||||||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
fmt::arg("parameters", codegen::getParameters(fn->prototype)),
|
||||||
fmt::arg("definition", fn->inner),
|
fmt::arg("definition", fn->inner),
|
||||||
fmt::arg("return", fn->beginning.ret.name)
|
fmt::arg("return", fn->prototype.ret.name)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +168,7 @@ std::string generateBindingSource(Root& root) {
|
||||||
|
|
||||||
char const* used_declare_format;
|
char const* used_declare_format;
|
||||||
|
|
||||||
switch (fn->beginning.type) {
|
switch (fn->prototype.type) {
|
||||||
case FunctionType::Normal:
|
case FunctionType::Normal:
|
||||||
used_declare_format = format_strings::declare_member;
|
used_declare_format = format_strings::declare_member;
|
||||||
break;
|
break;
|
||||||
|
@ -184,27 +180,22 @@ std::string generateBindingSource(Root& root) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn->beginning.is_static)
|
if (fn->prototype.is_static)
|
||||||
used_declare_format = format_strings::declare_static;
|
used_declare_format = format_strings::declare_static;
|
||||||
if (fn->beginning.is_virtual && fn->beginning.type != FunctionType::Dtor)
|
if (fn->prototype.is_virtual && fn->prototype.type != FunctionType::Dtor)
|
||||||
used_declare_format = format_strings::declare_virtual;
|
used_declare_format = format_strings::declare_virtual;
|
||||||
|
|
||||||
auto ids = bank.getIDs(fn->beginning, c.name);
|
|
||||||
|
|
||||||
output += fmt::format(used_declare_format,
|
output += fmt::format(used_declare_format,
|
||||||
fmt::arg("class_name", c.name),
|
fmt::arg("class_name", c.name),
|
||||||
fmt::arg("unqualified_class_name", codegen::getUnqualifiedClassName(c.name)),
|
fmt::arg("unqualified_class_name", codegen::getUnqualifiedClassName(c.name)),
|
||||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
fmt::arg("const", str_if(" const ", fn->prototype.is_const)),
|
||||||
fmt::arg("convention", codegen::getModifyConventionName(f)),
|
fmt::arg("convention", codegen::getModifyConventionName(f)),
|
||||||
fmt::arg("function_name", fn->beginning.name),
|
fmt::arg("function_name", fn->prototype.name),
|
||||||
fmt::arg("meta_index", ids.meta),
|
|
||||||
fmt::arg("member_index", ids.member),
|
|
||||||
fmt::arg("ret_index", ids.ret),
|
|
||||||
fmt::arg("addr_index", f.field_id),
|
fmt::arg("addr_index", f.field_id),
|
||||||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
fmt::arg("parameters", codegen::getParameters(fn->prototype)),
|
||||||
fmt::arg("parameter_types", codegen::getParameterTypes(fn->beginning)),
|
fmt::arg("parameter_types", codegen::getParameterTypes(fn->prototype)),
|
||||||
fmt::arg("arguments", codegen::getParameterNames(fn->beginning)),
|
fmt::arg("arguments", codegen::getParameterNames(fn->prototype)),
|
||||||
fmt::arg("parameter_comma", str_if(", ", !fn->beginning.args.empty()))
|
fmt::arg("parameter_comma", str_if(", ", !fn->prototype.args.empty()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
#include "Shared.hpp"
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
enum class FuncType : int {
|
|
||||||
Structor,
|
|
||||||
Static,
|
|
||||||
Member
|
|
||||||
};
|
|
||||||
struct Func {
|
|
||||||
std::string return_type;
|
|
||||||
bool is_const;
|
|
||||||
std::string class_name;
|
|
||||||
std::vector<std::string> parameter_types;
|
|
||||||
FuncType type;
|
|
||||||
|
|
||||||
std::string toStr() const {
|
|
||||||
return fmt::format("{}{}{}{}{}",
|
|
||||||
return_type,
|
|
||||||
class_name,
|
|
||||||
fmt::join(parameter_types, ","),
|
|
||||||
is_const ? " const " : "",
|
|
||||||
static_cast<int>(type)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(Func const& f) const {
|
|
||||||
return toStr() < f.toStr();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(Func const& f) const {
|
|
||||||
return (
|
|
||||||
return_type == f.return_type &&
|
|
||||||
is_const == f.is_const &&
|
|
||||||
class_name == f.class_name &&
|
|
||||||
parameter_types == f.parameter_types &&
|
|
||||||
type == f.type
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ids {
|
|
||||||
int ret = -1;
|
|
||||||
int func = -1;
|
|
||||||
int pure = -1;
|
|
||||||
int meta = -1;
|
|
||||||
int member = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TypeBank {
|
|
||||||
std::vector<Func> m_stuff;
|
|
||||||
public:
|
|
||||||
static std::string getReturn(FunctionBegin const& fn, std::string const& parent) {
|
|
||||||
if (fn.type != FunctionType::Normal)
|
|
||||||
return "void";
|
|
||||||
|
|
||||||
if (fn.ret.name == "auto") {
|
|
||||||
std::vector<std::string> declvals;
|
|
||||||
|
|
||||||
for (auto& [t, n] : fn.args) {
|
|
||||||
declvals.push_back(fmt::format("std::declval<{}>()", t.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt::format(
|
|
||||||
fn.is_static ? "decltype({}::{}({}))" : "decltype(std::declval<{}>().{}({}))",
|
|
||||||
parent,
|
|
||||||
fn.name,
|
|
||||||
fmt::join(declvals, ", ")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn.ret.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Func makeFunc(FunctionBegin const& fn, std::string const& parent) {
|
|
||||||
Func f;
|
|
||||||
f.return_type = TypeBank::getReturn(fn, parent);
|
|
||||||
f.is_const = fn.is_const;
|
|
||||||
f.class_name = parent;
|
|
||||||
|
|
||||||
for (auto& arg : fn.args) {
|
|
||||||
f.parameter_types.push_back(arg.first.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fn.is_static)
|
|
||||||
f.type = FuncType::Static;
|
|
||||||
else if (fn.type != FunctionType::Normal)
|
|
||||||
f.type = FuncType::Structor;
|
|
||||||
else
|
|
||||||
f.type = FuncType::Member;
|
|
||||||
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadFrom(Root& root) {
|
|
||||||
for (auto& c : root.classes) {
|
|
||||||
for (auto& f : c.fields) {
|
|
||||||
if (codegen::getStatus(f) == BindStatus::Unbindable)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
m_stuff.push_back(TypeBank::makeFunc(*f.get_fn(), c.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(m_stuff.begin(), m_stuff.end());
|
|
||||||
m_stuff.erase(std::unique(m_stuff.begin(), m_stuff.end()), m_stuff.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Func> const& typeList() { return m_stuff; }
|
|
||||||
|
|
||||||
Ids getIDs(FunctionBegin const& fn, std::string const& parent) {
|
|
||||||
Ids out;
|
|
||||||
Func in_f = TypeBank::makeFunc(fn, parent);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto f : m_stuff) {
|
|
||||||
if (out.ret == -1 && f.return_type == in_f.return_type) {
|
|
||||||
out.ret = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.func == -1) {
|
|
||||||
if (in_f.type == FuncType::Member) {
|
|
||||||
if (f == in_f) out.func = i;
|
|
||||||
} else if (in_f.type == FuncType::Structor) {
|
|
||||||
if (
|
|
||||||
f.return_type == in_f.return_type &&
|
|
||||||
f.class_name == in_f.class_name &&
|
|
||||||
f.is_const == in_f.is_const &&
|
|
||||||
f.parameter_types == in_f.parameter_types
|
|
||||||
) out.func = i;
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
f.return_type == in_f.return_type &&
|
|
||||||
f.parameter_types == in_f.parameter_types &&
|
|
||||||
f.type == in_f.type
|
|
||||||
) out.func = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.meta == -1 || out.member == -1) {
|
|
||||||
Func assume_member = f;
|
|
||||||
assume_member.type = FuncType::Member;
|
|
||||||
|
|
||||||
if (in_f == assume_member) {
|
|
||||||
out.meta = i;
|
|
||||||
} else if (out.func != -1) {
|
|
||||||
out.meta = out.func;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.pure == -1 && f.return_type == in_f.return_type && f.parameter_types == in_f.parameter_types) {
|
|
||||||
out.pure = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.ret != -1 && out.func != -1 && out.pure != -1)
|
|
||||||
break;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.member = out.func;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPure(FunctionBegin const& fn, std::string const& parent) {
|
|
||||||
Func in_f = TypeBank::makeFunc(fn, parent);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto f : m_stuff) {
|
|
||||||
if (f.return_type == in_f.return_type && f.parameter_types == in_f.parameter_types) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in a new issue