diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index b7eca496..26f82dab 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -12,6 +12,8 @@ #include "pocketpy/interpreter/line_profiler.h" #include +#include + // TODO: // 1. __eq__ and __ne__ fallbacks // 2. un-cleared exception detection @@ -51,6 +53,7 @@ typedef struct VM { py_Callbacks callbacks; py_Capabilities capabilities; + atomic_bool is_interrupted; py_TValue last_retval; py_TValue unhandled_exc; diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 51146271..71310d13 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -124,6 +124,11 @@ __NEXT_STEP: } #endif + if(atomic_exchange(&self->is_interrupted, false)) { + py_exception(tp_KeyboardInterrupt, ""); + goto __ERROR; + } + #ifndef NDEBUG pk_print_stack(self, frame, byte); #endif diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index c8fb7ace..12558f13 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -94,6 +94,7 @@ void VM__ctor(VM* self) { self->callbacks.getchr = pk_default_getchr; memset(&self->capabilities, 0, sizeof(py_Capabilities)); + atomic_store(&self->is_interrupted, false); self->last_retval = *py_NIL(); self->unhandled_exc = *py_NIL(); diff --git a/src/public/GlobalSetup.c b/src/public/GlobalSetup.c index a7bd33e8..566708c7 100644 --- a/src/public/GlobalSetup.c +++ b/src/public/GlobalSetup.c @@ -112,6 +112,8 @@ py_Callbacks* py_callbacks() { return &pk_current_vm->callbacks; } py_Capabilities* py_capabilities() { return &pk_current_vm->capabilities; } +void py_interrupt() { atomic_store(&pk_current_vm->is_interrupted, true); } + py_AppCallbacks* py_appcallbacks() { static py_AppCallbacks _callbacks = {0}; return &_callbacks;