Start working on a c++ interface.

This commit is contained in:
King_DuckZ 2020-04-25 20:45:59 +02:00
commit 3142e4c4ce
11 changed files with 382 additions and 19 deletions

116
src/wren/vm.cpp Normal file
View file

@ -0,0 +1,116 @@
#include "vm.hpp"
#include "configuration.hpp"
#include <wren.hpp>
#include <cassert>
#include <stdexcept>
namespace wren {
namespace {
[[gnu::const]]
ErrorType to_error_type (WrenErrorType wet) {
switch (wet) {
case WREN_ERROR_COMPILE: return ErrorType::Compile;
case WREN_ERROR_RUNTIME: return ErrorType::Runtime;
case WREN_ERROR_STACK_TRACE: return ErrorType::StackTrace;
default: return ErrorType::Runtime;
};
}
void write_fn (WrenVM* wvm, const char* text) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->write_fn and cb->config_obj and cb->vm);
cb->write_fn(*cb->config_obj, cb->vm, text);
}
void error_fn (WrenVM* wvm, WrenErrorType type, const char* module, int line, const char* message) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->error_fn and cb->config_obj and cb->vm);
cb->error_fn(*cb->config_obj, cb->vm, to_error_type(type), module, line, message);
}
const char* resolve_module_fn (WrenVM* wvm, const char* importer, const char* name) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->resolve_module_fn and cb->config_obj and cb->vm);
return cb->resolve_module_fn(*cb->config_obj, cb->vm, importer, name);
}
char* load_module_fn (WrenVM* wvm, const char* name) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->load_module_fn and cb->config_obj and cb->vm);
return cb->load_module_fn(*cb->config_obj, cb->vm, name);
}
} //unnamed namespace
VM::VM (Configuration* conf, const detail::Callbacks& cb) :
m_callbacks(cb),
m_vm(nullptr)
{
WrenConfiguration wconf;
wrenInitConfiguration(&wconf);
wconf.userData = static_cast<void*>(&m_callbacks);
wconf.initialHeapSize = conf->initial_heap_size();
wconf.minHeapSize = conf->min_heap_size();
wconf.heapGrowthPercent = conf->heap_growth_percent();
if (cb.write_fn)
wconf.writeFn = &write_fn;
if (cb.error_fn)
wconf.errorFn = &error_fn;
if (cb.reallocate_fn)
wconf.reallocateFn = cb.reallocate_fn;
if (cb.resolve_module_fn)
wconf.resolveModuleFn = &resolve_module_fn;
if (cb.load_module_fn)
wconf.loadModuleFn = &load_module_fn;
m_vm = wrenNewVM(&wconf);
if (not m_vm)
throw std::runtime_error("Failed to initialize Wren VM");
}
VM::VM (VM&& other) :
m_vm(nullptr)
{
std::swap(m_vm, other.m_vm);
m_callbacks = other.m_callbacks;
wrenSetUserData(m_vm, &m_callbacks);
}
VM::~VM() noexcept {
if (m_vm)
wrenFreeVM(m_vm);
#if !defined(NDEBUG)
m_vm = nullptr;
#endif
}
void VM::interpret (const char* module_name, const char* script) {
using std::string;
using std::runtime_error;
const WrenInterpretResult res = wrenInterpret(m_vm, 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);
case WREN_RESULT_SUCCESS:
break;
}
}
void VM::interpret (const std::string& module_name, const std::string& script) {
return interpret(module_name.c_str(), script.c_str());
}
} //namespace wren