add py_interrupt

This commit is contained in:
blueloveTH 2024-12-30 13:51:10 +08:00
parent f1ae24a9c1
commit 94b25f5d1e
7 changed files with 27 additions and 2 deletions

View File

@ -28,6 +28,7 @@ typedef struct VM {
py_TValue last_retval;
py_TValue curr_exception;
bool is_signal_interrupted;
bool is_curr_exc_handled; // handled by try-except block but not cleared yet
py_TValue reg[8]; // users' registers

View File

@ -87,6 +87,8 @@ PK_API void py_resetvm();
PK_API void* py_getvmctx();
/// Set the current VM context. This is used for user-defined data.
PK_API void py_setvmctx(void* ctx);
/// Interrupt the current VM and raise a `KeyboardInterrupt` exception.
PK_API void py_interrupt();
/// Set `sys.argv`. Used for storing command-line arguments.
PK_API void py_sys_setargv(int argc, char** argv);
/// Setup the callbacks for the current VM.

View File

@ -253,7 +253,7 @@ int py_replinput(char* buf, int max_size) {
while(true) {
char c = getchar();
if(c == EOF) break;
if(c == EOF) return -1;
if(c == '\n') {
char last = '\0';

View File

@ -92,6 +92,12 @@ FrameResult VM__run_top_frame(VM* self) {
pk_print_stack(self, frame, byte);
#endif
if(self->is_signal_interrupted){
self->is_signal_interrupted = false;
py_exception(tp_KeyboardInterrupt, "");
goto __ERROR;
}
switch((Opcode)byte.op) {
case OP_NO_OP: DISPATCH();
/*****************************************/

View File

@ -69,6 +69,7 @@ void VM__ctor(VM* self) {
self->last_retval = *py_NIL();
self->curr_exception = *py_NIL();
self->is_signal_interrupted = false;
self->is_curr_exc_handled = false;
self->ctx = NULL;
@ -147,7 +148,6 @@ void VM__ctor(VM* self) {
INJECT_BUILTIN_EXC(SystemExit, tp_BaseException);
INJECT_BUILTIN_EXC(KeyboardInterrupt, tp_BaseException);
// INJECT_BUILTIN_EXC(StopIteration, tp_Exception);
validate(tp_StopIteration, pk_StopIteration__register());
py_setdict(&self->builtins, py_name("StopIteration"), py_tpobject(tp_StopIteration));

View File

@ -90,6 +90,8 @@ void* py_getvmctx() { return pk_current_vm->ctx; }
void py_setvmctx(void* ctx) { pk_current_vm->ctx = ctx; }
void py_interrupt() { pk_current_vm->is_signal_interrupted = true; }
void py_sys_setargv(int argc, char** argv) {
py_GlobalRef sys = py_getmodule("sys");
py_Ref argv_list = py_getdict(sys, py_name("argv"));

View File

@ -8,6 +8,14 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
// set ctrl+c handler
#include <signal.h>
#include <unistd.h>
static void sigint_handler(int sig) { py_interrupt(); }
#endif
char* read_file(const char* path) {
@ -31,6 +39,8 @@ int main(int argc, char** argv) {
#if _WIN32
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
#else
signal(SIGINT, sigint_handler);
#endif
if(argc > 2) {
@ -53,6 +63,10 @@ int main(int argc, char** argv) {
while(true) {
int size = py_replinput(buf, sizeof(buf));
if(size == -1) { // Ctrl-D (i.e. EOF)
printf("\n");
break;
}
assert(size < sizeof(buf));
if(size >= 0) {
py_StackRef p0 = py_peek(0);