pocketpy/c_bindings/pocketpy_c.cpp
2023-04-30 11:30:45 -06:00

181 lines
3.8 KiB
C++

#include "pocketpy.h"
#include "pocketpy_c.h"
using namespace pkpy;
#define ERRHANDLER_OPEN try { \
try { \
if (vm->c_data.top() == nullptr) \
return false; \
#define ERRHANDLER_CLOSE \
} catch( Exception e ) { \
vm->c_data.clear(); \
vm->c_data.push(VAR(e.summary())); \
vm->c_data.push(NULL); \
return false; \
} \
} catch(...) { \
std::cerr << "ERROR: a non pocketpy exeception was thrown " \
<< "this probably means pocketpy itself has a bug!\n"; \
exit(2); \
}
bool pkpy_clear_error(pkpy_vm vm_handle, const char** message) {
VM* vm = (VM*) vm_handle;
try {
if (vm->c_data.top() != nullptr)
return false;
vm->c_data.pop();
Str wrapped_message = CAST(Str&, vm->c_data.top());
if (message != nullptr)
*message = wrapped_message.c_str_dup();
else
std::cerr << "ERROR: " << wrapped_message << "\n";
vm->c_data.pop();
//at this point the stack is clear
return true;
} catch(...) {
std::cerr << "ERROR: a non pocketpy exeception was thrown "
<< "this probably means pocketpy itself has a bug!\n";
exit(2);
}
}
pkpy_vm pkpy_vm_create(bool use_stdio, bool enable_os) {
VM* vm = new VM(use_stdio, enable_os);
return (pkpy_vm) vm;
}
bool pkpy_vm_exec(pkpy_vm vm_handle, const char* source) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
vm->exec(source, "main.py", EXEC_MODE);
return true;
ERRHANDLER_CLOSE
}
void pkpy_vm_destroy(pkpy_vm vm_handle) {
VM* vm = (VM*) vm_handle;
delete vm;
}
bool pkpy_push_function(pkpy_vm vm_handle, pkpy_function f) {
return true;
}
bool pkpy_push_int(pkpy_vm vm_handle, int value) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
vm->c_data.push(VAR(value));
return true;
ERRHANDLER_CLOSE
}
bool pkpy_push_float(pkpy_vm vm_handle, double value) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
vm->c_data.push(VAR(value));
return true;
ERRHANDLER_CLOSE
}
bool pkpy_set_global(pkpy_vm vm_handle, const char* name) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
vm->_main->attr().set(name, vm->c_data.top());
vm->c_data.pop();
return true;
ERRHANDLER_CLOSE
}
bool pkpy_get_global(pkpy_vm vm_handle, const char* name) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
PyObject* o = vm->_main->attr().try_get(name);
vm->c_data.push(o);
return true;
ERRHANDLER_CLOSE
}
static void call_wrapper(VM* vm, int argc, bool method_call) {
int callable_index = vm->c_data.size() - argc - 1;
PyObject* callable = vm->c_data.get(callable_index);
vm->s_data.push(callable);
if (method_call)
vm->s_data.push(vm->c_data.get(callable_index - 1));
else
vm->s_data.push(PY_NULL);
for (int i = 0; i < argc; i++)
vm->s_data.push(vm->c_data.get(callable_index + i + 1));
PyObject* o = vm->vectorcall(argc);
vm->c_data.shrink(argc + 1 + (int) method_call);
//TODO unpack tuple?
vm->c_data.push(o);
}
bool pkpy_call(pkpy_vm vm_handle, int argc) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
call_wrapper(vm, argc, false);
return true;
ERRHANDLER_CLOSE
}
bool pkpy_call_method(pkpy_vm vm_handle, int argc) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
call_wrapper(vm, argc, true);
return true;
ERRHANDLER_CLOSE
}
static int lua_to_cstack_index(int index, int size) {
if (index < 0)
index = size + index;
return index;
}
bool pkpy_to_int(pkpy_vm vm_handle, int index, int* ret) {
VM* vm = (VM*) vm_handle;
ERRHANDLER_OPEN
index = lua_to_cstack_index(index, vm->c_data.size());
PyObject* o = vm->c_data.get(index);
if (ret != nullptr)
*ret = py_cast<int>(vm, o);
return true;
ERRHANDLER_CLOSE
}