blueloveTH 1 год назад
Родитель
Сommit
94b25f5d1e

+ 1 - 0
include/pocketpy/interpreter/vm.h

@@ -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

+ 2 - 0
include/pocketpy/pocketpy.h

@@ -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.

+ 1 - 1
src/common/sstream.c

@@ -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';

+ 6 - 0
src/interpreter/ceval.c

@@ -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();
             /*****************************************/

+ 1 - 1
src/interpreter/vm.c

@@ -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));
     

+ 2 - 0
src/public/internal.c

@@ -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"));

+ 14 - 0
src2/main.c

@@ -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);