#include "wrenpp/vm_fun.hpp" #include "wrenpp/def_configuration.hpp" #include #include #include #include #include namespace { const constexpr char g_script[] = "" R"script(class Maths { foreign static mul(a,b) foreign static div(a,b) foreign static sum(a,b) foreign static sub(a,b) } var my_mul = Maths.mul(Maths.mul(2, 2), Maths.mul(3, 2)) - 4 System.print("my_mul = %(my_mul) (expected: 20)") var my_sum = Maths.sum(Maths.sum(3, 4), Maths.sum(5, -1)) + 8 System.print("my_sum = %(my_sum) (expected: 19)") var my_sub = Maths.sub(Maths.sub(8, 5), Maths.sub(20, 19)) + 1 System.print("my_sub = %(my_sub) (expected: 3)") )script"; const constexpr char g_script_2[] = "" R"script(class Maths { foreign static mul(a,b) foreign static div(a,b) foreign static sum(a,b) foreign static sub(a,b) } var my_mul_2 = Maths.mul(Maths.mul(2, 2), Maths.mul(3, 2)) - 4 System.print("my_mul_2 = %(my_mul_2) (expected: 20)") var my_sum_2 = Maths.sum(Maths.sum(3, 4), Maths.sum(5, -1)) + 8 System.print("my_sum_2 = %(my_sum_2) (expected: 19)") var my_sub_2 = Maths.sub(Maths.sub(8, 5), Maths.sub(20, 19)) + 1 System.print("my_sub_2 = %(my_sub_2) (expected: 3)") )script"; class MyConfig : public wren::DefConfiguration { typedef std::map MethodMap; public: wren::foreign_method_t foreign_method_fn( wren::VM* vm, const char* module_ptr, const char* class_name_ptr, bool is_static, const char* signature_ptr ) { auto key = to_map_key(module_ptr, class_name_ptr, signature_ptr); auto it_found = m_foreign_methods.find(key); if (m_foreign_methods.end() != it_found) return it_found->second; else return nullptr; } void register_foreign_method ( std::string_view module_name, std::string_view class_name, std::string_view func_name, wren::foreign_method_t fn ) { m_foreign_methods[to_map_key(module_name, class_name, func_name)] = fn; } private: static std::string to_map_key( std::string_view module_name, std::string_view class_name, std::string_view func_name ) { std::string key; key.reserve(module_name.size() + class_name.size() + func_name.size() + 4); key.append(module_name); key += "::"; key.append(class_name); key += "::"; key.append(func_name); return key; } MethodMap m_foreign_methods; }; template void do_op(wren::VM& vm) { using wren::get; set(vm, 0, Op()(get(vm, 1), get(vm, 2))); } } //unnamed namespace int main() { MyConfig config; config.register_foreign_method("main", "Maths", "sum(_,_)", &do_op>); config.register_foreign_method("main", "Maths", "sub(_,_)", &do_op>); config.register_foreign_method("main", "Maths", "mul(_,_)", &do_op>); config.register_foreign_method("main", "Maths", "div(_,_)", &do_op>); wren::VM vm(&config, nullptr); vm.interpret("main", g_script); wren::variable_ensure_slot(vm, {"main", "my_mul"}, 0); std::cout << "Dynafunc mem usage: " << vm.dynafunc_byte_size() << " bytes\n"; vm.reset(&config); std::cout << "Dynafunc mem usage after reset: " << vm.dynafunc_byte_size() << " bytes\n"; vm.interpret("main", g_script_2); { auto [var] = wren::variables(vm, wren::ModuleAndName{"main", "my_mul_2"}); std::cout << "main::my_mul2 == " << var << " (expected: 20)\n"; } std::cout << "Dynafunc mem usage: " << vm.dynafunc_byte_size() << " bytes\n"; return 0; }