···11-#include "pocketpy.h"
22-#include "pocketpy_c.h"
33-44-using namespace pkpy;
55-66-#define PKPY_STACK_SIZE 32
77-88-#define SAFEGUARD_OPEN try { \
99-1010-#define SAFEGUARD_CLOSE \
1111- } catch(std::exception& e) { \
1212- std::cerr << "ERROR: a std::exception " \
1313- << "this probably means pocketpy itself has a bug!\n" \
1414- << e.what() << "\n"; \
1515- exit(2); \
1616- } catch(...) { \
1717- std::cerr << "ERROR: a unknown exception was thrown from " << __func__ \
1818- << "\nthis probably means pocketpy itself has a bug!\n"; \
1919- exit(2); \
2020- }
2121-2222-2323-#define ERRHANDLER_OPEN SAFEGUARD_OPEN \
2424- try { \
2525- if (vm->c_data->size() > 0 && vm->c_data->top() == nullptr) \
2626- return false; \
2727-2828-#define ERRHANDLER_CLOSE \
2929- } catch( Exception e ) { \
3030- vm->c_data->push(py_var(vm, e)); \
3131- vm->c_data->push(NULL); \
3232- return false; \
3333- } \
3434- SAFEGUARD_CLOSE \
3535-3636-3737-3838-class CVM : public VM {
3939- public :
4040-4141- ValueStackImpl<PKPY_STACK_SIZE>* c_data;
4242- CVM(bool enable_os=true) : VM(enable_os) {
4343- c_data = new ValueStackImpl<PKPY_STACK_SIZE>();
4444- }
4545-4646- ~CVM() {
4747- c_data->clear();
4848- delete c_data;
4949- }
5050-};
5151-5252-5353-//for now I will unpack a tuple automatically, we may not want to handle
5454-//it this way, not sure
5555-//it is more lua like, but maybe not python like
5656-static void unpack_return(CVM* vm, PyObject* ret) {
5757- if (is_type(ret, vm->tp_tuple)) {
5858- Tuple& t = py_cast<Tuple&>(vm, ret);
5959- for (int i = 0; i < t.size(); i++)
6060- vm->c_data->push(t[i]);
6161- } else if (ret == vm->None) {
6262- //do nothing here
6363- //having to pop the stack after every call that returns none is annoying
6464- //lua does not do this
6565- //
6666- //so for now we will not push none on the stack when it is the sole thing returned
6767- //if this becomes a problem we can change it
6868- //
6969- //you can still check if it returned none by comparing stack size before
7070- //and after if you have to
7171- } else
7272- vm->c_data->push(ret);
7373-7474-}
7575-7676-7777-bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) {
7878- CVM* vm = (CVM*) vm_handle;
7979- SAFEGUARD_OPEN
8080-8181- if (vm->c_data->size() == 0 || vm->c_data->top() != nullptr)
8282- return false;
8383-8484- vm->c_data->pop();
8585- Exception& e = py_cast<Exception&>(vm, vm->c_data->top());
8686- if (message != nullptr)
8787- *message = e.summary().c_str_dup();
8888- else
8989- std::cerr << "ERROR: " << e.summary() << "\n";
9090-9191- vm->c_data->clear();
9292- vm->callstack.clear();
9393- vm->s_data.clear();
9494- return true;
9595-9696- SAFEGUARD_CLOSE
9797-}
9898-9999-void gc_marker_ex(CVM* vm) {
100100- for(PyObject* obj: *vm->c_data) if(obj!=nullptr) OBJ_MARK(obj);
101101-}
102102-103103-104104-static void noop_output_handler(VM* vm, const Str& str) {
105105- (void) vm;
106106- (void) str;
107107-}
108108-109109-pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os) {
110110-111111- CVM* vm = new CVM(enable_os);
112112- vm->c_data = new ValueStackImpl<PKPY_STACK_SIZE>();
113113- vm->_gc_marker_ex = (void (*)(VM*)) gc_marker_ex;
114114-115115- if (!use_stdio) {
116116- vm->_stdout = noop_output_handler;
117117- vm->_stderr = noop_output_handler;
118118- }
119119-120120- return (pkpy_vm*) vm;
121121-}
122122-123123-bool pkpy_vm_run(pkpy_vm* vm_handle, const char* source) {
124124- CVM* vm = (CVM*) vm_handle;
125125- ERRHANDLER_OPEN
126126-127127- CodeObject_ code = vm->compile(source, "<c-bound>", EXEC_MODE);
128128- PyObject* result = vm->_exec(code, vm->_main);
129129-130130- //unpack_return(w, result);
131131- //NOTE: it seems like vm->_exec should return whatever the last command it
132132- //ran returned but instead it seems to pretty much always return None
133133- //so I guess uncomment this line if that every changes
134134-135135- return true;
136136- ERRHANDLER_CLOSE
137137-}
138138-139139-void pkpy_vm_destroy(pkpy_vm* vm_handle) {
140140- CVM* vm = (CVM*) vm_handle;
141141- delete vm;
142142-}
143143-144144-static void propagate_if_errored(CVM* vm, ValueStackImpl<PKPY_STACK_SIZE>* stored_stack) {
145145- try {
146146- if (vm->c_data->size() == 0 || vm->c_data->top() != nullptr)
147147- return;
148148-149149- vm->c_data->pop();
150150- Exception& e = py_cast<Exception&>(vm, vm->c_data->top());
151151- vm->c_data->pop();
152152-153153- vm->c_data = stored_stack;
154154-155155- throw e;
156156- } catch(Exception& e) {
157157- throw;
158158- } catch(...) {
159159- std::cerr << "ERROR: a non pocketpy exeception was thrown "
160160- << "this probably means pocketpy itself has a bug!\n";
161161- exit(2);
162162- }
163163-}
164164-165165-PyObject* c_function_wrapper(VM* vm, ArgsView args) {
166166- LuaStyleFuncC f = py_cast<NativeFunc&>(vm, args[-2])._lua_f;
167167- CVM* cvm = (CVM*) vm;
168168-169169- //setup c stack
170170- ValueStackImpl<PKPY_STACK_SIZE> local_stack;
171171-172172- for (int i = 0; i < args.size(); i++)
173173- local_stack.push(args[i]);
174174-175175- ValueStackImpl<PKPY_STACK_SIZE>* stored_stack = cvm->c_data;
176176- cvm->c_data = &local_stack;
177177-178178- int retc = f(cvm);
179179-180180- propagate_if_errored(cvm, stored_stack);
181181- cvm->c_data = stored_stack;
182182-183183- PyObject* ret = cvm->None;
184184-185185- if (retc == 1)
186186- ret = local_stack.top();
187187- else if (retc > 1) {
188188- Tuple t(retc);
189189-190190- for (int i = 0; i < retc; i++) {
191191- int stack_index = (local_stack.size() - retc) + i;
192192- t[i] = local_stack.begin()[stack_index];
193193- }
194194-195195- ret = py_var(cvm, t);
196196- }
197197-198198- return ret;
199199-}
200200-201201-bool pkpy_push_function(pkpy_vm* vm_handle, pkpy_function f) {
202202- CVM* vm = (CVM*) vm_handle;
203203- ERRHANDLER_OPEN
204204-205205- //TODO right now we just treat all c bound functions a varargs functions
206206- //do we want to change that?
207207- NativeFunc nf = NativeFunc(c_function_wrapper, -1, 0);
208208- nf._lua_f = (LuaStyleFuncC) f;
209209-210210- vm->c_data->push(py_var(vm, nf));
211211-212212- return true;
213213- ERRHANDLER_CLOSE
214214-}
215215-216216-bool pkpy_push_int(pkpy_vm* vm_handle, int value) {
217217- CVM* vm = (CVM*) vm_handle;
218218- ERRHANDLER_OPEN
219219-220220- vm->c_data->push(py_var(vm, value));
221221-222222- return true;
223223- ERRHANDLER_CLOSE
224224-}
225225-226226-bool pkpy_push_float(pkpy_vm* vm_handle, double value) {
227227- CVM* vm = (CVM*) vm_handle;
228228- ERRHANDLER_OPEN
229229- vm->c_data->push(py_var(vm, value));
230230-231231- return true;
232232- ERRHANDLER_CLOSE
233233-}
234234-235235-bool pkpy_push_bool(pkpy_vm* vm_handle, bool value) {
236236- CVM* vm = (CVM*) vm_handle;
237237- ERRHANDLER_OPEN
238238- vm->c_data->push(py_var(vm, value));
239239-240240- return true;
241241- ERRHANDLER_CLOSE
242242-}
243243-244244-bool pkpy_push_string(pkpy_vm* vm_handle, const char* value) {
245245- CVM* vm = (CVM*) vm_handle;
246246- ERRHANDLER_OPEN
247247- vm->c_data->push(py_var(vm, value));
248248-249249- return true;
250250- ERRHANDLER_CLOSE
251251-}
252252-253253-bool pkpy_push_stringn(pkpy_vm* vm_handle, const char* value, int length) {
254254- CVM* vm = (CVM*) vm_handle;
255255- ERRHANDLER_OPEN
256256-257257- Str s = Str(value, length);
258258- vm->c_data->push(py_var(vm, s));
259259-260260- return true;
261261- ERRHANDLER_CLOSE
262262-}
263263-264264-bool pkpy_push_voidp(pkpy_vm* vm_handle, void* value) {
265265- CVM* vm = (CVM*) vm_handle;
266266- ERRHANDLER_OPEN
267267- vm->c_data->push(py_var(vm, value));
268268-269269- return true;
270270- ERRHANDLER_CLOSE
271271-}
272272-273273-bool pkpy_push_none(pkpy_vm* vm_handle) {
274274- CVM* vm = (CVM*) vm_handle;
275275- ERRHANDLER_OPEN
276276- vm->c_data->push(vm->None);
277277-278278- return true;
279279- ERRHANDLER_CLOSE
280280-}
281281-282282-283283-284284-bool pkpy_set_global(pkpy_vm* vm_handle, const char* name) {
285285- CVM* vm = (CVM*) vm_handle;
286286- ERRHANDLER_OPEN
287287-288288- vm->_main->attr().set(name, vm->c_data->top());
289289-290290- vm->c_data->pop();
291291-292292- return true;
293293- ERRHANDLER_CLOSE
294294-}
295295-296296-//get global will also get bulitins
297297-bool pkpy_get_global(pkpy_vm* vm_handle, const char* name) {
298298- CVM* vm = (CVM*) vm_handle;
299299- ERRHANDLER_OPEN
300300-301301- PyObject* o = vm->_main->attr().try_get(name);
302302- if (o == nullptr) {
303303- o = vm->builtins->attr().try_get(name);
304304- if (o == nullptr)
305305- throw Exception("NameError", "could not find requested global");
306306- }
307307-308308- vm->c_data->push(o);
309309-310310- return true;
311311- ERRHANDLER_CLOSE
312312-}
313313-314314-315315-bool pkpy_call(pkpy_vm* vm_handle, int argc) {
316316- CVM* vm = (CVM*) vm_handle;
317317- ERRHANDLER_OPEN
318318-319319- int callable_index = vm->c_data->size() - argc - 1;
320320-321321- PyObject* callable = vm->c_data->begin()[callable_index];
322322-323323- vm->s_data.push(callable);
324324- vm->s_data.push(PY_NULL);
325325-326326- for (int i = 0; i < argc; i++)
327327- vm->s_data.push(vm->c_data->begin()[callable_index + i + 1]);
328328-329329- PyObject* o = vm->vectorcall(argc);
330330-331331- vm->c_data->shrink(argc + 1);
332332-333333- unpack_return(vm, o);
334334-335335- return true;
336336- ERRHANDLER_CLOSE
337337-}
338338-339339-bool pkpy_call_method(pkpy_vm* vm_handle, const char* name, int argc) {
340340- CVM* vm = (CVM*) vm_handle;
341341- ERRHANDLER_OPEN
342342-343343- int self_index = vm->c_data->size() - argc - 1;
344344- PyObject* self = vm->c_data->begin()[self_index];
345345-346346- PyObject* callable = vm->get_unbound_method(self, name, &self);
347347-348348- vm->s_data.push(callable);
349349- vm->s_data.push(self);
350350-351351- for (int i = 0; i < argc; i++)
352352- vm->s_data.push(vm->c_data->begin()[self_index + i + 1]);
353353-354354- PyObject* o = vm->vectorcall(argc);
355355-356356- vm->c_data->shrink(argc + 1);
357357-358358- unpack_return(vm, o);
359359-360360- return true;
361361- ERRHANDLER_CLOSE
362362-}
363363-364364-365365-366366-static int lua_to_cstack_index(int index, int size) {
367367- if (index < 0)
368368- index = size + index;
369369- return index;
370370-}
371371-372372-bool pkpy_to_int(pkpy_vm* vm_handle, int index, int* ret) {
373373- CVM* vm = (CVM*) vm_handle;
374374- ERRHANDLER_OPEN
375375-376376- index = lua_to_cstack_index(index, vm->c_data->size());
377377-378378- PyObject* o = vm->c_data->begin()[index];
379379-380380- if (!is_type(o, vm->tp_int))
381381- throw Exception("TypeError", "pkpy_to_int on non int object");
382382-383383- if (ret != nullptr)
384384- *ret = py_cast<int>(vm, o);
385385-386386- return true;
387387- ERRHANDLER_CLOSE
388388-}
389389-390390-bool pkpy_to_float(pkpy_vm* vm_handle, int index, double* ret) {
391391- CVM* vm = (CVM*) vm_handle;
392392- ERRHANDLER_OPEN
393393-394394- index = lua_to_cstack_index(index, vm->c_data->size());
395395-396396- PyObject* o = vm->c_data->begin()[index];
397397-398398- if (!is_type(o, vm->tp_float))
399399- throw Exception("TypeError", "pkpy_to_float on non float object");
400400-401401- if (ret != nullptr)
402402- *ret = py_cast<double>(vm, o);
403403-404404- return true;
405405- ERRHANDLER_CLOSE
406406-}
407407-408408-bool pkpy_to_bool(pkpy_vm* vm_handle, int index, bool* ret) {
409409- CVM* vm = (CVM*) vm_handle;
410410- ERRHANDLER_OPEN
411411-412412- index = lua_to_cstack_index(index, vm->c_data->size());
413413-414414- PyObject* o = vm->c_data->begin()[index];
415415- if (!is_type(o, vm->tp_bool))
416416- throw Exception("TypeError", "pkpy_to_bool on non bool object");
417417-418418- if (ret != nullptr)
419419- *ret = py_cast<bool>(vm, o);
420420-421421- return true;
422422- ERRHANDLER_CLOSE
423423-}
424424-425425-bool pkpy_to_voidp(pkpy_vm* vm_handle, int index, void** ret) {
426426- CVM* vm = (CVM*) vm_handle;
427427- ERRHANDLER_OPEN
428428-429429- index = lua_to_cstack_index(index, vm->c_data->size());
430430-431431- PyObject* o = vm->c_data->begin()[index];
432432- if (!is_type(o, VoidP::_type(vm)))
433433- throw Exception("TypeError", "pkpy_to_voidp on non void* object");
434434-435435- if (ret != nullptr)
436436- *ret = py_cast<void*>(vm, o);
437437-438438- return true;
439439- ERRHANDLER_CLOSE
440440-}
441441-442442-bool pkpy_to_string(pkpy_vm* vm_handle, int index, char** ret) {
443443- CVM* vm = (CVM*) vm_handle;
444444- ERRHANDLER_OPEN
445445-446446- index = lua_to_cstack_index(index, vm->c_data->size());
447447-448448- PyObject* o = vm->c_data->begin()[index];
449449- if (!is_type(o, vm->tp_str))
450450- throw Exception("TypeError", "pkpy_to_string on non string object");
451451-452452- if (ret != nullptr) {
453453- Str& s = py_cast<Str&>(vm, o);
454454- *ret = s.c_str_dup();
455455- }
456456-457457- return true;
458458- ERRHANDLER_CLOSE
459459-}
460460-461461-bool pkpy_to_stringn(pkpy_vm* vm_handle, int index, const char** ret, int* size) {
462462- CVM* vm = (CVM*) vm_handle;
463463- ERRHANDLER_OPEN
464464-465465- index = lua_to_cstack_index(index, vm->c_data->size());
466466-467467- PyObject* o = vm->c_data->begin()[index];
468468- if (ret != nullptr) {
469469- std::string_view sv = py_cast<Str&>(vm, o).sv();
470470- *ret = sv.data();
471471- *size = sv.size();
472472- }
473473-474474- return true;
475475- ERRHANDLER_CLOSE
476476-}
477477-478478-479479-bool pkpy_is_int(pkpy_vm* vm_handle, int index) {
480480- CVM* vm = (CVM*) vm_handle;
481481- index = lua_to_cstack_index(index, vm->c_data->size());
482482- PyObject* o = vm->c_data->begin()[index];
483483-484484- return is_type(o, vm->tp_int);
485485-}
486486-bool pkpy_is_float(pkpy_vm* vm_handle, int index) {
487487- CVM* vm = (CVM*) vm_handle;
488488- index = lua_to_cstack_index(index, vm->c_data->size());
489489- PyObject* o = vm->c_data->begin()[index];
490490-491491- return is_type(o, vm->tp_float);
492492-}
493493-bool pkpy_is_bool(pkpy_vm* vm_handle, int index) {
494494- CVM* vm = (CVM*) vm_handle;
495495- index = lua_to_cstack_index(index, vm->c_data->size());
496496- PyObject* o = vm->c_data->begin()[index];
497497-498498- return is_type(o, vm->tp_bool);
499499-}
500500-bool pkpy_is_string(pkpy_vm* vm_handle, int index) {
501501- CVM* vm = (CVM*) vm_handle;
502502- index = lua_to_cstack_index(index, vm->c_data->size());
503503- PyObject* o = vm->c_data->begin()[index];
504504-505505- return is_type(o, vm->tp_str);
506506-}
507507-bool pkpy_is_voidp(pkpy_vm* vm_handle, int index) {
508508- CVM* vm = (CVM*) vm_handle;
509509- index = lua_to_cstack_index(index, vm->c_data->size());
510510- PyObject* o = vm->c_data->begin()[index];
511511-512512- return is_type(o, VoidP::_type(vm));
513513-}
514514-515515-bool pkpy_is_none(pkpy_vm* vm_handle, int index) {
516516- CVM* vm = (CVM*) vm_handle;
517517- index = lua_to_cstack_index(index, vm->c_data->size());
518518- PyObject* o = vm->c_data->begin()[index];
519519-520520- return o == vm->None;
521521-}
522522-523523-bool pkpy_check_global(pkpy_vm* vm_handle, const char* name) {
524524- CVM* vm = (CVM*) vm_handle;
525525- SAFEGUARD_OPEN
526526- PyObject* o = vm->_main->attr().try_get(name);
527527- if (o == nullptr) {
528528- o = vm->builtins->attr().try_get(name);
529529- if (o == nullptr)
530530- return false;
531531- }
532532- return true;
533533-534534- SAFEGUARD_CLOSE
535535-}
536536-537537-bool pkpy_check_error(pkpy_vm* vm_handle) {
538538- CVM* vm = (CVM*) vm_handle;
539539- SAFEGUARD_OPEN
540540- if (vm->c_data->size() > 0 && vm->c_data->top() == nullptr)
541541- return true;
542542- return false;
543543- SAFEGUARD_CLOSE
544544-}
545545-546546-547547-bool pkpy_check_stack(pkpy_vm* vm_handle, int free) {
548548- CVM* vm = (CVM*) vm_handle;
549549- return free + vm->c_data->size() <= PKPY_STACK_SIZE;
550550-}
551551-552552-int pkpy_stack_size(pkpy_vm* vm_handle) {
553553- CVM* vm = (CVM*) vm_handle;
554554- return vm->c_data->size();
555555-}
556556-557557-bool pkpy_pop(pkpy_vm* vm_handle, int n) {
558558- CVM* vm = (CVM*) vm_handle;
559559- vm->c_data->shrink(n);
560560- return true;
561561-}
562562-563563-564564-bool pkpy_push(pkpy_vm* vm_handle, int index) {
565565- CVM* vm = (CVM*) vm_handle;
566566- index = lua_to_cstack_index(index, vm->c_data->size());
567567- vm->c_data->push(vm->c_data->begin()[index]);
568568- return true;
569569-}
570570-571571-572572-bool pkpy_error(pkpy_vm* vm_handle, const char* message) {
573573- CVM* vm = (CVM*) vm_handle;
574574- ERRHANDLER_OPEN
575575- throw Exception("CBindingError", message);
576576- ERRHANDLER_CLOSE
577577-}
578578-
-115
vendor/pocketpy/pocketpy_c.h
···11-#ifndef POCKETPY_C_H
22-#define POCKETPY_C_H
33-44-#ifdef __cplusplus
55-extern "C" {
66-#endif
77-88-#include <stdbool.h>
99-#include <stdint.h>
1010-1111-typedef struct pkpy_vm_handle pkpy_vm;
1212-1313-//we we take a lot of inspiration from the lua api for these bindings
1414-//the key difference being most methods return a bool,
1515-//true if it succeeded false if it did not
1616-1717-//if a method returns false call the pkpy_clear_error method to check the error and clear it
1818-//if pkpy_clear_error returns false it means that no error was set, and it takes no action
1919-//if pkpy_clear_error returns true it means there was an error and it was cleared,
2020-//it will provide a string summary of the error in the message parameter (if it is not NULL)
2121-//if null is passed in as message, and it will just print the message to stderr
2222-bool pkpy_clear_error(pkpy_vm*, char** message);
2323-//NOTE you are responsible for freeing message
2424-2525-//this will cause the vm to enter an error state and report the given message
2626-//when queried
2727-//note that at the moment this is more like a panic than throwing an error
2828-//the user will not be able to catch it with python code
2929-bool pkpy_error(pkpy_vm*, const char* message);
3030-3131-3232-pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os);
3333-bool pkpy_vm_run(pkpy_vm*, const char* source);
3434-void pkpy_vm_destroy(pkpy_vm*);
3535-3636-typedef int (*pkpy_function)(pkpy_vm*);
3737-3838-bool pkpy_pop(pkpy_vm*, int n);
3939-4040-//push the item at index onto the top of the stack (as well as leaving it where
4141-//it is on the stack)
4242-bool pkpy_push(pkpy_vm*, int index);
4343-4444-bool pkpy_push_function(pkpy_vm*, pkpy_function);
4545-bool pkpy_push_int(pkpy_vm*, int);
4646-bool pkpy_push_float(pkpy_vm*, double);
4747-bool pkpy_push_bool(pkpy_vm*, bool);
4848-bool pkpy_push_string(pkpy_vm*, const char*);
4949-bool pkpy_push_stringn(pkpy_vm*, const char*, int length);
5050-bool pkpy_push_voidp(pkpy_vm*, void*);
5151-bool pkpy_push_none(pkpy_vm*);
5252-5353-bool pkpy_set_global(pkpy_vm*, const char* name);
5454-bool pkpy_get_global(pkpy_vm*, const char* name);
5555-5656-//first push callable you want to call
5757-//then push the arguments to send
5858-//argc is the number of arguments that was pushed (not counting the callable)
5959-bool pkpy_call(pkpy_vm*, int argc);
6060-6161-//first push the object the method belongs to (self)
6262-//then push the the argments
6363-//argc is the number of arguments that was pushed (not counting the callable or self)
6464-//name is the name of the method to call on the object
6565-bool pkpy_call_method(pkpy_vm*, const char* name, int argc);
6666-6767-6868-//we will break with the lua api here
6969-//lua uses 1 as the index to the first pushed element for all of these functions
7070-//but we will start counting at zero to match python
7171-//we will allow negative numbers to count backwards from the top
7272-bool pkpy_to_int(pkpy_vm*, int index, int* ret);
7373-bool pkpy_to_float(pkpy_vm*, int index, double* ret);
7474-bool pkpy_to_bool(pkpy_vm*, int index, bool* ret);
7575-bool pkpy_to_voidp(pkpy_vm*, int index, void** ret);
7676-7777-//this method provides a strong reference, you are responsible for freeing the
7878-//string when you are done with it
7979-bool pkpy_to_string(pkpy_vm*, int index, char** ret);
8080-8181-//this method provides a weak reference, it is only valid until the
8282-//next api call
8383-//it is not null terminated
8484-bool pkpy_to_stringn(pkpy_vm*, int index, const char** ret, int* size);
8585-8686-8787-//these do not follow the same error semantics as above, their return values
8888-//just say whether the check succeeded or not, or else return the value asked for
8989-9090-bool pkpy_is_int(pkpy_vm*, int index);
9191-bool pkpy_is_float(pkpy_vm*, int index);
9292-bool pkpy_is_bool(pkpy_vm*, int index);
9393-bool pkpy_is_string(pkpy_vm*, int index);
9494-bool pkpy_is_voidp(pkpy_vm*, int index);
9595-bool pkpy_is_none(pkpy_vm*, int index);
9696-9797-9898-//will return true if global exists
9999-bool pkpy_check_global(pkpy_vm*, const char* name);
100100-101101-//will return true if the vm is currently in an error state
102102-bool pkpy_check_error(pkpy_vm*);
103103-104104-//will return true if at least free empty slots remain on the stack
105105-bool pkpy_check_stack(pkpy_vm*, int free);
106106-107107-//returns the number of elements on the stack
108108-int pkpy_stack_size(pkpy_vm*);
109109-110110-111111-#ifdef __cplusplus
112112-}
113113-#endif
114114-115115-#endif