This work but code is brittle and dirty
This commit is contained in:
parent
ce6f67422f
commit
dd259ef5bb
1 changed files with 104 additions and 10 deletions
|
@ -1,14 +1,22 @@
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include "wrenpp/vm.hpp"
|
#include "wrenpp/vm.hpp"
|
||||||
|
#include "wrenpp/vm_fun.hpp"
|
||||||
#include "wrenpp/def_configuration.hpp"
|
#include "wrenpp/def_configuration.hpp"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string_view>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#define CURR_MODULE_NAME WRENPP_NAME
|
#define CURR_MODULE_NAME "py" WRENPP_NAME
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct VMObject;
|
struct VMObject;
|
||||||
int vm_init (VMObject* self, PyObject*, PyObject*);
|
int vm_init (VMObject* self, PyObject*, PyObject*);
|
||||||
|
PyObject* vm_new (PyTypeObject* type, PyObject*, PyObject*);
|
||||||
|
void vm_dealloc (VMObject* self);
|
||||||
|
PyObject* vm_interpret (VMObject* self, PyObject* args);
|
||||||
|
PyObject* vm_call (VMObject* self, PyObject* args);
|
||||||
|
|
||||||
class VMConfig : public wren::DefConfiguration {
|
class VMConfig : public wren::DefConfiguration {
|
||||||
public:
|
public:
|
||||||
|
@ -40,31 +48,117 @@ struct VMObject {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
wren::VM vm;
|
wren::VM vm;
|
||||||
};
|
};
|
||||||
|
//PyMemberDef VMProperties[] = {
|
||||||
|
// {nullptr}
|
||||||
|
//};
|
||||||
|
PyMethodDef VMMethods[] = {
|
||||||
|
{
|
||||||
|
"interpret",
|
||||||
|
reinterpret_cast<PyCFunction>(vm_interpret),
|
||||||
|
METH_VARARGS,
|
||||||
|
"Interpret a string script"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
reinterpret_cast<PyCFunction>(vm_call),
|
||||||
|
METH_VARARGS,
|
||||||
|
"Call a method from a previously parsed script"
|
||||||
|
},
|
||||||
|
{nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
PyTypeObject VMType = {
|
PyTypeObject VMType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
.tp_name = CURR_MODULE_NAME ".VM",
|
.tp_name = CURR_MODULE_NAME ".VM",
|
||||||
.tp_basicsize = sizeof(VMObject),
|
.tp_basicsize = sizeof(VMObject),
|
||||||
.tp_itemsize = 0,
|
.tp_itemsize = 0,
|
||||||
|
.tp_dealloc = reinterpret_cast<destructor>(vm_dealloc),
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = "Wrenpp VM",
|
.tp_doc = "Wrenpp VM",
|
||||||
|
.tp_methods = VMMethods,
|
||||||
|
.tp_members = nullptr, //VMProperties,
|
||||||
.tp_init = reinterpret_cast<initproc>(vm_init),
|
.tp_init = reinterpret_cast<initproc>(vm_init),
|
||||||
.tp_new = PyType_GenericNew,
|
.tp_new = vm_new,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PyObject* vm_new (PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/) {
|
||||||
|
VMObject* const self = reinterpret_cast<VMObject*>(type->tp_alloc(type, 0));
|
||||||
|
if (self) {
|
||||||
|
try {
|
||||||
|
VMConfig config;
|
||||||
|
new(&self->vm) wren::VM(&config, nullptr);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
Py_DECREF(self);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reinterpret_cast<PyObject*>(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_dealloc (VMObject* self) {
|
||||||
|
self->vm.~VM();
|
||||||
|
}
|
||||||
|
|
||||||
int vm_init (VMObject* self, PyObject* /*args*/, PyObject* /*kwds*/) {
|
int vm_init (VMObject* self, PyObject* /*args*/, PyObject* /*kwds*/) {
|
||||||
try {
|
VMConfig config;
|
||||||
VMConfig config;
|
self->vm.reset(&config);
|
||||||
new(&self->vm) wren::VM(&config, nullptr);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject* vm_interpret (VMObject* self, PyObject* args) {
|
||||||
|
const char* module_name;
|
||||||
|
const char* script;
|
||||||
|
if (!PyArg_ParseTuple(args, "ss", &module_name, &script))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
self->vm.interpret(module_name, script);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* vm_call (VMObject* self, PyObject* args) {
|
||||||
|
const Py_ssize_t argc = PyTuple_Size(args);
|
||||||
|
std::vector<PyObject*> objects;
|
||||||
|
objects.reserve(argc);
|
||||||
|
|
||||||
|
self->vm.ensure_slots(static_cast<std::size_t>(argc) + 1);
|
||||||
|
variable(self->vm, wren::ModuleAndName{"main", "the_user"}, 0);
|
||||||
|
|
||||||
|
std::string func_sig;
|
||||||
|
{
|
||||||
|
Py_ssize_t sz;
|
||||||
|
PyObject* const obj = PyTuple_GetItem(args, 0);
|
||||||
|
const char* const buf = PyUnicode_AsUTF8AndSize(obj, &sz);
|
||||||
|
func_sig.reserve(sz + 3);
|
||||||
|
func_sig.append(buf, sz);
|
||||||
|
func_sig.append(1, '(');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Py_ssize_t z = 1; z < argc; ++z) {
|
||||||
|
PyObject* const obj = PyTuple_GetItem(args, z);
|
||||||
|
if (not obj)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const std::string_view type_name(Py_TYPE(obj)->tp_name);
|
||||||
|
//std::cout << "vm_call, parameter " << z+1 << " has type \"" << type_name << "\"\n";
|
||||||
|
if (type_name == "str") {
|
||||||
|
const char* const buf = PyUnicode_AsUTF8(obj);
|
||||||
|
self->vm.set_slot_string(static_cast<std::size_t>(z), buf);
|
||||||
|
}
|
||||||
|
func_sig += "_,";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func_sig.back() == ',')
|
||||||
|
func_sig.resize(func_sig.size() - 1);
|
||||||
|
func_sig += ")";
|
||||||
|
auto handle = self->vm.make_call_handle(func_sig.c_str());
|
||||||
|
self->vm.call(handle);
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
PyMODINIT_FUNC PyInit_wrenpp(void) {
|
PyMODINIT_FUNC PyInit_pywrenpp(void) {
|
||||||
if (PyType_Ready(&VMType) < 0)
|
if (PyType_Ready(&VMType) < 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
PyObject* const m = PyModule_Create(&WrenppModule);
|
PyObject* const m = PyModule_Create(&WrenppModule);
|
||||||
|
|
Loading…
Reference in a new issue