diff --git a/include/wrenpp/detail/construct_foreign_class.hpp b/include/wrenpp/detail/construct_foreign_class.hpp index 616d5e6..9d64754 100644 --- a/include/wrenpp/detail/construct_foreign_class.hpp +++ b/include/wrenpp/detail/construct_foreign_class.hpp @@ -19,9 +19,13 @@ #include "wrenpp/vm.hpp" #include "seters_getters.hpp" +#if defined(WRENPP_WITH_NAME_GUESSING) +# include "guess_class_name.hpp" +#endif #include #include #include +#include namespace wren { namespace detail { @@ -34,12 +38,17 @@ namespace wren { new(memory) T{get(vm, Indices + 1)...}; } + struct ConstructResult { + std::uint16_t parameter_count; + bool success; + }; + template struct ForeignClassHelper; template class Pack, typename... PackArgs, typename... Args> struct ForeignClassHelper, Args...> { - static bool construct (VM& vm, int cardinality, void* memory) { + static ConstructResult construct (VM& vm, int cardinality, void* memory) { using std::make_integer_sequence; //search by number of parameters. @@ -48,7 +57,7 @@ namespace wren { constexpr int pack_size = static_cast(sizeof...(PackArgs)); if (pack_size == cardinality) { construct_single(make_integer_sequence{}, vm, memory); - return true; + return ConstructResult{pack_size, true}; } else { return ForeignClassHelper::construct(vm, cardinality, memory); @@ -58,12 +67,12 @@ namespace wren { template struct ForeignClassHelper { - static bool construct (VM& vm, int cardinality, void* memory) { + static ConstructResult construct (VM& vm, int cardinality, void* memory) { using std::make_integer_sequence; if (1 == cardinality) { construct_single(make_integer_sequence{}, vm, memory); - return true; + return ConstructResult{1, true}; } else { return ForeignClassHelper::construct(vm, cardinality, memory); @@ -83,29 +92,19 @@ namespace wren { template struct ForeignClassHelper { - static bool construct (VM& vm, int cardinality, void* memory) { + static ConstructResult construct (VM& vm, int cardinality, void* memory) { using std::make_integer_sequence; - assert(cardinality == 0); - construct_single(make_integer_sequence{}, vm, memory); - return true; + if (cardinality == 0) { + construct_single(make_integer_sequence{}, vm, memory); + return ConstructResult{0, true}; + } + else { + return ConstructResult{static_cast(cardinality), false}; + } } }; - template - inline void find_params_and_construct_foreign_class ( - std::integer_sequence seq, - VM& vm, - void* memory - ) { - if constexpr (sizeof...(Args) == 0) { - construct_single(seq, vm, memory); - } - else { - ForeignClassHelper::construct(vm, vm.slot_count() - 1, memory); - } - } - template struct AssertIfDuplicateValues { static_assert(sizeof...(Values) == 0, "Code bug?"); @@ -134,11 +133,17 @@ namespace wren { ret.allocate = [](VM& vm) { void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T)); - detail::find_params_and_construct_foreign_class( - std::make_integer_sequence{}, - vm, - mem - ); + const auto result = detail::ForeignClassHelper::construct(vm, vm.slot_count() - 1, mem); + if (not result.success) { + set(vm, 1, std::string{"No registered c++ constructor "} + +#if defined(WRENPP_WITH_NAME_GUESSING) + "for class " + guess_class_name() + " " + +#endif + "takes " + std::to_string(result.parameter_count) + + " parameter" + (result.parameter_count == 1 ? "" : "s") + ); + vm.abort_fiber(1); + } }; ret.finalize = [](void* mem) { const auto cale = static_cast(mem); diff --git a/include/wrenpp/vm.hpp b/include/wrenpp/vm.hpp index 72a9968..dcd5f45 100644 --- a/include/wrenpp/vm.hpp +++ b/include/wrenpp/vm.hpp @@ -103,6 +103,8 @@ namespace wren { bool has_module (const char* module) const noexcept; bool has_variable (const char* module, const char* name) const noexcept; + void abort_fiber(int slot_num); + std::size_t dynafunc_byte_size() const; void reset (Configuration* conf); diff --git a/src/vm.cpp b/src/vm.cpp index dff58c8..a599d61 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -280,6 +280,10 @@ namespace wren { return wrenHasVariable(m_local->wvm, module, name); } + void VM::abort_fiber(int slot_num) { + wrenAbortFiber(m_local->wvm, slot_num); + } + std::size_t VM::dynafunc_byte_size() const { return m_local->dynafunc.total_memory(); }