Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
feat: symcall
Browse files Browse the repository at this point in the history
  • Loading branch information
killcerr committed Feb 12, 2024
1 parent 8c047ca commit b290e33
Show file tree
Hide file tree
Showing 5 changed files with 342 additions and 3 deletions.
151 changes: 151 additions & 0 deletions src/native_helper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include "logger.h"

#include <cstdint>
#include <dyncall/dyncall.h>
#include <magic_enum.hpp>
#include <variant>
#include <vector>

FILE_LOGGER();


namespace native_helper {
enum class ArgType : unsigned char { n = -1, v, ui8, ui16, ui32, ui64, i8, i16, i32, i64, f, d, p, b, c };
template <ArgType type>
constexpr auto cast_to_int = [] {
using enum ArgType;
#define RT_IF(T, I) \
if constexpr (type == T) return I
RT_IF(v, 0);
RT_IF(ui8, 1);
RT_IF(ui16, 2);
RT_IF(ui32, 3);
RT_IF(ui64, 4);
RT_IF(i8, 5);
RT_IF(i16, 6);
RT_IF(i32, 7);
RT_IF(i64, 8);
RT_IF(f, 9);
RT_IF(d, 10);
RT_IF(p, 11);
RT_IF(b, 12);
RT_IF(c, 13);
#undef RT_IF
}();

using TypeVariant = std::variant<
std::monostate,
uint8_t,
uint16_t,
uint32_t,
uint64_t,
int8_t,
int16_t,
int32_t,
int64_t,
float,
double,
void*,
bool,
char>;

TypeVariant call(ArgType ret, const std::vector<ArgType>& args, const std::vector<TypeVariant>& vals, void* fp) {
auto vm = dcNewCallVM(1024);
using enum ArgType;
// logger.info("call:{}", __LINE__);
for (int i = 0; i < std::min(args.size(), vals.size()); i++) {
switch (args[i]) {
case ui8:
dcArgChar(vm, std::get<cast_to_int<ui8>>(vals[i]));
break;
case i8:
dcArgChar(vm, std::get<cast_to_int<i8>>(vals[i]));
break;
case ui16:
dcArgShort(vm, std::get<cast_to_int<ui16>>(vals[i]));
break;
case i16:
dcArgShort(vm, std::get<cast_to_int<ui16>>(vals[i]));
break;
case ui32:
dcArgInt(vm, std::get<cast_to_int<ui32>>(vals[i]));
break;
case i32:
dcArgInt(vm, std::get<cast_to_int<i32>>(vals[i]));
break;
case ui64:
dcArgLongLong(vm, std::get<cast_to_int<ui64>>(vals[i]));
break;
case i64:
dcArgLongLong(vm, std::get<cast_to_int<i64>>(vals[i]));
break;
case f:
dcArgFloat(vm, std::get<cast_to_int<f>>(vals[i]));
break;
case d:
dcArgDouble(vm, std::get<cast_to_int<d>>(vals[i]));
break;
case p:
dcArgPointer(vm, std::get<cast_to_int<p>>(vals[i]));
break;
case b:
dcArgBool(vm, std::get<cast_to_int<b>>(vals[i]));
break;
case c:
dcArgChar(vm, std::get<cast_to_int<c>>(vals[i]));
break;
default:
std::unreachable();
}
}
// logger.info("call:{}", __LINE__);
TypeVariant res{};
switch (ret) {
case v:
dcCallVoid(vm, fp);
break;
case ui8:
res.emplace<cast_to_int<ui8>>(dcCallChar(vm, fp));
break;
case i8:
res.emplace<cast_to_int<i8>>(dcCallChar(vm, fp));
break;
case ui16:
res.emplace<cast_to_int<ui16>>(dcCallShort(vm, fp));
break;
case i16:
res.emplace<cast_to_int<i16>>(dcCallShort(vm, fp));
break;
case ui32:
res.emplace<cast_to_int<ui32>>(dcCallInt(vm, fp));
break;
case i32:
res.emplace<cast_to_int<i32>>(dcCallInt(vm, fp));
break;
case ui64:
res.emplace<cast_to_int<ui64>>(dcCallLongLong(vm, fp));
break;
case i64:
res.emplace<cast_to_int<i64>>(dcCallLongLong(vm, fp));
break;
case f:
res.emplace<cast_to_int<f>>(dcCallFloat(vm, fp));
break;
case d:
res.emplace<cast_to_int<d>>(dcCallDouble(vm, fp));
break;
case p:
res.emplace<cast_to_int<p>>(dcCallPointer(vm, fp));
break;
case b:
res.emplace<cast_to_int<b>>(dcCallBool(vm, fp));
break;
case c:
res.emplace<cast_to_int<c>>(dcCallChar(vm, fp));
break;
default:
std::unreachable();
}
return res;
}
} // namespace native_helper
68 changes: 68 additions & 0 deletions src/native_helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#pragma once
#include <cstdint>
#include <string_view>
#include <variant>
#include <vector>


namespace native_helper {
using TypeVariant = std::variant<
std::monostate,
uint8_t,
uint16_t,
uint32_t,
uint64_t,
int8_t,
int16_t,
int32_t,
int64_t,
float,
double,
void*,
bool,
char>;
enum class ArgType : unsigned char { n = -1, v, ui8, ui16, ui32, ui64, i8, i16, i32, i64, f, d, p, b, c };
ArgType form_string(const auto& str) {
using enum ArgType;
using namespace std::string_view_literals;
#define RT_IF(T) \
if (str == #T##sv) return T;
RT_IF(v);
RT_IF(ui8);
RT_IF(ui16);
RT_IF(ui32);
RT_IF(ui64);
RT_IF(i8);
RT_IF(i16);
RT_IF(i32);
RT_IF(i64);
RT_IF(f);
RT_IF(d);
RT_IF(b);
RT_IF(c);
#undef RT_IF
return n;
}
template <ArgType type>
constexpr auto cast_to_int = [] {
using enum ArgType;
#define RT_IF(T, I) \
if constexpr (type == T) return I
RT_IF(v, 0);
RT_IF(ui8, 1);
RT_IF(ui16, 2);
RT_IF(ui32, 3);
RT_IF(ui64, 4);
RT_IF(i8, 5);
RT_IF(i16, 6);
RT_IF(i32, 7);
RT_IF(i64, 8);
RT_IF(f, 9);
RT_IF(d, 10);
RT_IF(p, 11);
RT_IF(b, 12);
RT_IF(c, 13);
#undef RT_IF
}();
TypeVariant call(ArgType ret, const std::vector<ArgType>& args, const std::vector<TypeVariant>& vals, void* fp);
} // namespace native_helper
120 changes: 120 additions & 0 deletions src/pocketpy_engine_imp.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "loader_info.hpp"
#include "logger.h"
#include "native_helper.h"
#include "pocketpy.h"
#include "pocketpy_plugin_loader.hpp"
#include "pocketpy_type_binds.h"
Expand Down Expand Up @@ -329,6 +330,125 @@ void setupHelperModule(VM* vm) {
nbtSetter_context.val = v;
return VAR(nbtSetter());
});
vm->bind(helperModule, "call(symbol:str,ret:str,*args)", [](VM* vm, ArgsView args) {
std::vector<::native_helper::ArgType> argtypes;
std::vector<::native_helper::TypeVariant> argvals;
Tuple _args = _CAST(Tuple, args[2]);
for (auto arg : _args) {
Tuple tv = _CAST(Tuple, arg);
if (tv.size() != 2) {
vm->RuntimeError("arg size must be 2");
return VAR(NoReturn{});
} else {
auto type = ::native_helper::form_string(_CAST(Str&, tv[0]).sv());
using enum ::native_helper::ArgType;
using namespace native_helper;
::native_helper::TypeVariant va;
/*logger.info("call_bind:{}", __LINE__);*/
switch (type) {
#define CASE(N) \
case ui##N: \
/*logger.info("call_bind:{}", __LINE__);*/ \
va.emplace<cast_to_int<ui##N>>(_CAST(uint##N##_t, tv[1])); \
break; \
case i##N: \
/*logger.info("call_bind:{}", __LINE__);*/ \
va.emplace<cast_to_int<ui##N>>(_CAST(uint##N##_t, tv[1])); \
break
case ui8:
va.emplace<cast_to_int<ui8>>(_py_cast<uint8_t>(vm, tv[1]));
break;
case i8:
va.emplace<cast_to_int<i8>>(_py_cast<char>(vm, tv[1]));
break;
CASE(16);
CASE(32);
CASE(64);
#undef CASE
case f:
// logger.info("call_bind:{}", __LINE__);
va.emplace<cast_to_int<f>>(_CAST(float, tv[1]));
break;
case d:
// logger.info("call_bind:{}", __LINE__);
va.emplace<cast_to_int<d>>(_CAST(double, tv[1]));
break;
case b:
// logger.info("call_bind:{}", __LINE__);
va.emplace<cast_to_int<b>>(_CAST(bool, tv[1]));
break;
case c:
// logger.info("call_bind:{}", __LINE__);
va.emplace<cast_to_int<c>>(_CAST(char, tv[1]));
break;
default:
logger.info("call_bind:{}", __LINE__);
break;
}
logger.info("call_bind:{}", __LINE__);
argtypes.push_back(type);
argvals.push_back(va);
}
}
auto res = ::native_helper::call(
::native_helper::form_string(_CAST(Str&, args[1]).sv()),
argtypes,
argvals,
ll::memory::resolveSymbol(_CAST(Str&, args[0]).sv(), false)
);
using enum ::native_helper::ArgType;
using namespace ::native_helper;
switch (::native_helper::form_string(_CAST(Str&, args[1]).sv())) {
case v:
return VAR(NoReturn{});
break;
#define RT(N) return VAR(std::get<::native_helper::cast_to_int<N>>(res))
case ui8:
RT(ui8);
break;
case i8:
RT(i8);
break;
case ui16:
RT(ui16);
break;
case i16:
RT(i16);
break;
case ui32:
RT(ui32);
break;
case i32:
RT(i32);
break;
case ui64:
RT(ui64);
break;
case i64:
RT(i64);
break;
case f:
RT(f);
break;
case d:
RT(d);
break;
case p:
RT(p);
break;
case b:
RT(b);
break;
case c:
RT(c);
break;
default:
vm->RuntimeError("unknown type");
return VAR(NoReturn{});
break;
}
#undef RT
});
}
struct {
::std::string current_import_path;
Expand Down
4 changes: 2 additions & 2 deletions src/pocketpy_plugin_loader_imp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ bool ::pocketpy_plugin_loader::pocketpy_plugin_manager::disable(std::string_view
std::shared_ptr<ll::plugin::Plugin> pocketpy_plugin_loader::pocketpy_plugin_manager::get(std::string_view name) {
// return ::pocketpy_plugin_loader::engine::disable(name);
auto manager = ::pocketpy_plugin_loader::pocketpy_plugin_manager::Impl::data();
return manager->getPlugin(name);
}
return manager->getPlugin(name); //
}
2 changes: 1 addition & 1 deletion src/type_wappers/Actor_wapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,4 @@ struct ActorWapper {
}
PY_CLASS(ActorWapper, TypeWappers, ActorWapper)
};
} // namespace type_wappers
} // namespace type_wappers

0 comments on commit b290e33

Please sign in to comment.