diff --git a/src/main.cpp b/src/main.cpp index 7f3a57d..8985950 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,9 +9,15 @@ namespace { R"(class Math { construct new() {} foreign add(a, b) + + static sum_params(a,b) { + return a + b + } } System.print("I am running in a VM!") var myvar = Math.new() +var name = "some_test" +var number = 123 myvar.add(5, 6) System.print("Script done") )"; @@ -19,11 +25,19 @@ System.print("Script done") } //unnamed namespace int main() { + typedef wren::ModuleAndName MN; + using wren::variables; + std::cout << "hello world\n"; wren::DefConfiguration config; wren::VM vm(&config); vm.interpret("my_module", g_script); std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + auto vars = variables(vm, MN{"my_module", "name"}, MN{"my_module","number"}); + std::cout << "name = \"" << std::get<0>(vars) << "\", number = " << std::get<1>(vars) << '\n'; + const int sum = wren::call(vm, {"my_module", "Math"}, vm.make_call_handle("sum_params(_,_)"), MN{"my_module", "number"}, 90); + std::cout << "wren method returned " << sum << " (expected " << std::get<1>(vars) + 90 << ")\n"; + return 0; } diff --git a/src/wren/vm.cpp b/src/wren/vm.cpp index 900e836..f1af1a3 100644 --- a/src/wren/vm.cpp +++ b/src/wren/vm.cpp @@ -68,6 +68,21 @@ namespace wren { retval.finalize = funcs.finalize; return retval; } + + void throw_if_err (WrenInterpretResult res, const char* module_name) { + using std::runtime_error; + using std::string; + + switch (res) { + case WREN_RESULT_COMPILE_ERROR: + throw runtime_error(string("Compilation of ") + module_name + " has failed"); + case WREN_RESULT_RUNTIME_ERROR: + throw runtime_error(string("A runtime error occurred in ") + module_name); + + case WREN_RESULT_SUCCESS: + break; + } + } } //unnamed namespace struct VM::LocalData { @@ -138,15 +153,12 @@ namespace wren { using std::runtime_error; const WrenInterpretResult res = wrenInterpret(m_local->wvm, module_name, script); - switch (res) { - case WREN_RESULT_COMPILE_ERROR: - throw runtime_error(string("Compilation of ") + module_name + " has failed"); - case WREN_RESULT_RUNTIME_ERROR: - throw runtime_error(string("A runtime error occurred in ") + module_name); + throw_if_err(res, module_name); + } - case WREN_RESULT_SUCCESS: - break; - } + void VM::call (const Handle& method) { + const WrenInterpretResult res = wrenCall(m_local->wvm, method); + throw_if_err(res, "[wrenCall()]"); } void VM::release_handle (Handle& handle) noexcept { diff --git a/src/wren/vm.hpp b/src/wren/vm.hpp index 63aecde..a50213b 100644 --- a/src/wren/vm.hpp +++ b/src/wren/vm.hpp @@ -52,7 +52,7 @@ namespace wren { ~VM() noexcept; void interpret (const char* module_name, const char* script); - void call (Handle& method); + void call (const Handle& method); void release_handle (Handle& handle) noexcept; void ensure_slots(int num_slots); int slot_count(); @@ -66,7 +66,7 @@ namespace wren { void set_slot_string (int slot_num, const char* value); void set_slot_double (int slot_num, double value); void set_slot_bool (int slot_num, bool value); - void set_slot_null (int slot_num); + void set_slot_null (int slot_num); void set_slot_bytes (int slot_num, const char* bytes, std::size_t length); //slot getters diff --git a/src/wren/vm_fun.cpp b/src/wren/vm_fun.cpp index 9ef347e..f6e2f05 100644 --- a/src/wren/vm_fun.cpp +++ b/src/wren/vm_fun.cpp @@ -8,6 +8,10 @@ namespace wren { vm.set_slot_bytes(slot_num, beg, std::distance(beg, end)); } + void set (VM& vm, int slot_num, const Handle& handle) { + vm.set_slot_handle(handle, slot_num); + } + std::string_view slot_string_view (VM& vm, int slot_num) { assert(SlotType::String == vm.slot_type(slot_num)); auto ptr = vm.slot_bytes(slot_num); diff --git a/src/wren/vm_fun.hpp b/src/wren/vm_fun.hpp index 5e64cca..1b5a30f 100644 --- a/src/wren/vm_fun.hpp +++ b/src/wren/vm_fun.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace wren { typedef std::tuple ModuleAndName; @@ -24,11 +25,24 @@ namespace wren { template #endif std::tuple variables(VM& vm, Params&&... modules_names); + + template + R call (VM& vm, const Handle& object, const Handle& method, const Args&... args); + + template + R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args); + void interpret (VM& vm, const std::string& module_name, const std::string& script); + void set (VM& vm, int slot_num, const char* value); + void set (VM& vm, int slot_num, double value); + void set (VM& vm, int slot_num, bool value); + void set (VM& vm, int slot_num, std::nullptr_t); + void set (VM& vm, int slot_num, const char* bytes, std::size_t length); void set (VM& vm, int slot_num, const std::string& value); void set (VM& vm, int slot_num, std::string_view value); void set (VM& vm, int slot_num, const std::vector& value); void set (VM& vm, int slot_num, const char* beg, const char* end); + void set (VM& vm, int slot_num, int value); std::string_view slot_string_view (VM& vm, int slot_num); template T get (VM& vm, int slot_num); void variable(VM& vm, const ModuleAndName& mod_and_name, int slot); @@ -52,11 +66,32 @@ namespace wren { static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output"); static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count"); - vm.ensure_slots(sizeof...(Outs)); + vm.ensure_slots(sizeof...(Params)); (variable(vm, modules_names, Indices), ...); return std::tuple(get(vm, Indices)...); } } + + template + inline void set_single_for_call (VM& vm, int slot, const T& value) { + set(vm, slot, value); + } + + template <> + inline void set_single_for_call (VM& vm, int slot_num, const Handle& handle) { + vm.set_slot_handle(handle, slot_num); + } + + template <> + inline void set_single_for_call (VM& vm, int slot_num, const ModuleAndName& name) { + variable(vm, name, slot_num); + } + + template + inline void set_for_call (std::integer_sequence, VM& vm, const Args&... args) { + vm.ensure_slots(sizeof...(Args)); + (set_single_for_call(vm, Indices + 1, args), ...); + } } //namespace detail #if __cpp_concepts >= 201907 @@ -72,6 +107,26 @@ namespace wren { return vm.interpret(module_name.c_str(), script.c_str()); } + inline void set (VM& vm, int slot_num, const char* value) { + vm.set_slot_string(slot_num, value); + } + + inline void set (VM& vm, int slot_num, double value) { + vm.set_slot_double(slot_num, value); + } + + inline void set (VM& vm, int slot_num, bool value) { + vm.set_slot_bool(slot_num, value); + } + + inline void set (VM& vm, int slot_num, std::nullptr_t) { + vm.set_slot_null(slot_num); + } + + inline void set (VM& vm, int slot_num, const char* bytes, std::size_t length) { + vm.set_slot_bytes(slot_num, bytes, length); + } + inline void set (VM& vm, int slot_num, const std::string& value) { vm.set_slot_string(slot_num, value.c_str()); } @@ -83,4 +138,25 @@ namespace wren { inline void set (VM& vm, int slot_num, const std::vector& value) { vm.set_slot_bytes(slot_num, value.data(), value.size()); } + + inline void set (VM& vm, int slot_num, int value) { + vm.set_slot_double(slot_num, static_cast(value)); + } + + template + inline R call (VM& vm, const Handle& object, const Handle& method, const Args&... args) { + detail::set_for_call(std::make_integer_sequence(), vm, args...); + vm.call(method); + if constexpr (not std::is_same::value) { + return get(vm, 0); + } + } + + template + inline R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args) { + vm.ensure_slots(sizeof...(args) + 1); + variable(vm, object, 0); + Handle obj_handle = vm.slot_handle(0); + return call(vm, obj_handle, method, args...); + } } //namespace wren