blueloveTH 1 tahun lalu
induk
melakukan
1696bb6d66

+ 2 - 3
include/pocketpy/interpreter/vm.h

@@ -50,10 +50,9 @@ typedef struct pk_VM {
     void (*_stdout)(const char*, ...);
     void (*_stderr)(const char*, ...);
 
-    // singleton objects
-    py_TValue True, False, None, NotImplemented, Ellipsis;
-
     py_TValue last_retval;
+    bool has_error;
+    
     py_TValue reg[8];  // users' registers
 
     py_TValue __curr_class;

+ 2 - 2
include/pocketpy/pocketpy.h

@@ -40,10 +40,10 @@ void py_initialize();
 void py_finalize();
 
 /// Run a simple source string. Do not change the stack.
-bool py_exec(const char*);
+bool py_exec(const char* source);
 /// Eval a simple expression.
 /// The result will be set to `py_retval()`.
-bool py_eval(const char*);
+bool py_eval(const char* source);
 
 /************* Values Creation *************/
 void py_newint(py_Ref, py_i64);

+ 0 - 5
src/common/strname.c

@@ -20,11 +20,6 @@ void py_Name__initialize() {
 #define MAGIC_METHOD(x) assert(x == py_name(#x));
 #include "pocketpy/xmacros/magics.h"
 #undef MAGIC_METHOD
-
-    // print all names
-    for(int i = 0; i < _interned.count; i++) {
-        printf("%d: %s\n", i + 1, c11__getitem(char*, &_r_interned, i));
-    }
 }
 
 void py_Name__finalize() {

+ 13 - 10
src/interpreter/ceval.c

@@ -13,7 +13,6 @@ int NameError(py_Name name) { return -1; }
 
 static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
 
-
 #define DISPATCH()                                                                                 \
     do {                                                                                           \
         frame->ip++;                                                                               \
@@ -123,13 +122,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 DISPATCH();
             /*****************************************/
             case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH();
-            case OP_LOAD_NONE: PUSH(&self->None); DISPATCH();
-            case OP_LOAD_TRUE: PUSH(&self->True); DISPATCH();
-            case OP_LOAD_FALSE: PUSH(&self->False); DISPATCH();
+            case OP_LOAD_NONE: py_newnone(SP()++); DISPATCH();
+            case OP_LOAD_TRUE: py_newbool(SP()++, true); DISPATCH();
+            case OP_LOAD_FALSE: py_newbool(SP()++, false); DISPATCH();
             /*****************************************/
             case OP_LOAD_SMALL_INT: py_newint(SP()++, (int64_t)(int16_t)byte.arg); DISPATCH();
             /*****************************************/
-            case OP_LOAD_ELLIPSIS: PUSH(&self->Ellipsis); DISPATCH();
+            case OP_LOAD_ELLIPSIS: py_newellipsis(SP()++); DISPATCH();
             case OP_LOAD_FUNCTION: {
                 // FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
                 // py_TValue obj;
@@ -512,7 +511,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 bool res = py_isidentical(SECOND(), TOP());
                 POP();
                 if(byte.arg) res = !res;
-                *TOP() = res ? self->True : self->False;
+                py_newbool(TOP(), res);
                 DISPATCH();
             }
             case OP_CONTAINS_OP: {
@@ -575,9 +574,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             case OP_SHORTCUT_IF_FALSE_OR_POP: {
                 int res = py_bool(TOP());
                 if(res < 0) goto __ERROR;
-                if(!res) {               // [b, False]
-                    STACK_SHRINK(2);     // []
-                    PUSH(&self->False);  // [False]
+                if(!res) {                      // [b, False]
+                    STACK_SHRINK(2);            // []
+                    py_newbool(SP()++, false);  // [False]
                     DISPATCH_JUMP((int16_t)byte.arg);
                 } else {
                     POP();  // [b]
@@ -606,7 +605,11 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 // }
                 /*****************************************/
             case OP_RETURN_VALUE: {
-                self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
+                if(byte.arg == BC_NOARG){
+                    self->last_retval = POPX();
+                }else{
+                    py_newnone(&self->last_retval);
+                }
                 pk_VM__pop_frame(self);
                 if(frame == base_frame) {  // [ frameBase<- ]
                     return RES_RETURN;

+ 6 - 2
src/interpreter/vm.c

@@ -68,7 +68,8 @@ void pk_VM__ctor(pk_VM* self) {
     self->_stderr = pk_default_stderr;
 
     self->last_retval = PY_NULL;
-
+    self->has_error = false;
+    
     self->__curr_class = PY_NULL;
     self->__cached_object_new = PY_NULL;
     self->__dynamic_func_decl = NULL;
@@ -148,7 +149,10 @@ void pk_VM__ctor(pk_VM* self) {
         pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t);
         py_setdict(&self->builtins, ti->name, py_tpobject(t));
     }
-    py_setdict(&self->builtins, py_name("NotImplemented"), &self->NotImplemented);
+
+    py_TValue tmp;
+    py_newnotimplemented(&tmp);
+    py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
 
     /* Do Buildin Bindings*/
     pk_VM__init_builtins(self);

+ 16 - 0
src/public/error.c

@@ -0,0 +1,16 @@
+#include "pocketpy/pocketpy.h"
+#include "pocketpy/interpreter/vm.h"
+
+void py_printexc(){
+    pk_VM* vm = pk_current_vm;
+    if(vm->has_error){
+        assert(vm->last_retval.type == tp_exception);
+    }else{
+        vm->_stdout("NoneType: None\n");
+    }
+}
+
+
+void py_formatexc(char *out){
+
+}

+ 128 - 4
src/public/vm.c

@@ -2,6 +2,7 @@
 #include "pocketpy/pocketpy.h"
 
 #include "pocketpy/common/utils.h"
+#include "pocketpy/common/sstream.h"
 #include "pocketpy/objects/object.h"
 #include "pocketpy/interpreter/vm.h"
 #include "pocketpy/compiler/compiler.h"
@@ -23,17 +24,136 @@ void py_finalize() {
     pk_MemoryPools__finalize();
 }
 
-bool py_exec(const char* source) { PK_UNREACHABLE(); }
+static void disassemble(CodeObject* co) {
+    const static char* OP_NAMES[] = {
+#define OPCODE(name) #name,
+#include "pocketpy/xmacros/opcodes.h"
+#undef OPCODE
+    };
+
+    c11_vector /*T=int*/ jumpTargets;
+    c11_vector__ctor(&jumpTargets, sizeof(int));
+    for(int i = 0; i < co->codes.count; i++) {
+        Bytecode* bc = c11__at(Bytecode, &co->codes, i);
+        if(Bytecode__is_forward_jump(bc)) {
+            int target = (int16_t)bc->arg + i;
+            c11_vector__push(int, &jumpTargets, target);
+        }
+    }
+
+    c11_sbuf ss;
+    c11_sbuf__ctor(&ss);
+
+    int prev_line = -1;
+    for(int i = 0; i < co->codes.count; i++) {
+        Bytecode byte = c11__getitem(Bytecode, &co->codes, i);
+        BytecodeEx ex = c11__getitem(BytecodeEx, &co->codes_ex, i);
+
+        char line[8];
+        if(ex.lineno == prev_line) {
+            line[0] = '\0';
+        } else {
+            snprintf(line, sizeof(line), "%d", ex.lineno);
+            if(prev_line != -1) c11_sbuf__write_char(&ss, '\n');
+            prev_line = ex.lineno;
+        }
+
+        char pointer[4] = "";
+        c11__foreach(int, &jumpTargets, it) {
+            if(*it == i) {
+                snprintf(pointer, sizeof(pointer), "->");
+                break;
+            }
+        }
+
+        char buf[64];
+        snprintf(buf, sizeof(buf), "%-8s%-3s%-3d", line, pointer, i);
+        c11_sbuf__write_cstr(&ss, buf);
+
+        snprintf(buf, sizeof(buf), " %-24s", OP_NAMES[byte.op]);
+        c11_sbuf__write_cstr(&ss, buf);
+        c11_sbuf__write_char(&ss, ex.is_virtual ? '*' : ' ');
+
+        // _opcode_argstr(this, i, byte, co);
+        do {
+            if(Bytecode__is_forward_jump(&byte)) {
+                c11_sbuf__write_int(&ss, (int16_t)byte.arg);
+                c11_sbuf__write_cstr(&ss, " (to ");
+                c11_sbuf__write_int(&ss, (int16_t)byte.arg + i);
+                c11_sbuf__write_char(&ss, ')');
+                break;
+            }
+
+            c11_sbuf__write_int(&ss, byte.arg);
+            switch(byte.op) {
+                case OP_LOAD_CONST:
+                case OP_FORMAT_STRING:
+                case OP_IMPORT_PATH: {
+                    c11_string* ud = py_touserdata(c11__at(py_TValue, &co->consts, byte.arg));
+                    c11_sbuf__write_cstr(&ss, " (");
+                    c11_sbuf__write_cstr(&ss, ud->data);
+                    c11_sbuf__write_char(&ss, ')');
+                    break;
+                }
+                case OP_LOAD_NAME:
+                case OP_LOAD_GLOBAL:
+                case OP_LOAD_NONLOCAL:
+                case OP_STORE_GLOBAL:
+                case OP_LOAD_ATTR:
+                case OP_LOAD_METHOD:
+                case OP_STORE_ATTR:
+                case OP_DELETE_ATTR:
+                case OP_BEGIN_CLASS:
+                case OP_GOTO:
+                case OP_DELETE_GLOBAL:
+                case OP_STORE_CLASS_ATTR:
+                case OP_FOR_ITER_STORE_GLOBAL: {
+                    c11_sbuf__write_cstr(&ss, " (");
+                    c11_sbuf__write_cstr(&ss, py_name2str(byte.arg));
+                    c11_sbuf__write_char(&ss, ')');
+                    break;
+                }
+                case OP_LOAD_FAST:
+                case OP_STORE_FAST:
+                case OP_DELETE_FAST:
+                case OP_FOR_ITER_STORE_FAST: {
+                    py_Name name = c11__getitem(py_Name, &co->varnames, byte.arg);
+                    c11_sbuf__write_cstr(&ss, " (");
+                    c11_sbuf__write_cstr(&ss, py_name2str(name));
+                    c11_sbuf__write_char(&ss, ')');
+                    break;
+                }
+                case OP_LOAD_FUNCTION: {
+                    const FuncDecl* decl = c11__getitem(FuncDecl*, &co->func_decls, byte.arg);
+                    c11_sbuf__write_cstr(&ss, " (");
+                    c11_sbuf__write_cstr(&ss, decl->code.name->data);
+                    c11_sbuf__write_char(&ss, ')');
+                    break;
+                }
+            }
+        } while(0);
+
+        if(i != co->codes.count - 1) c11_sbuf__write_char(&ss, '\n');
+    }
+
+    c11_string* output = c11_sbuf__submit(&ss);
+    pk_current_vm->_stdout("%s\n", output->data);
+    c11_string__delete(output);
+    c11_vector__dtor(&jumpTargets);
+}
 
-bool py_eval(const char* source) {
+static bool
+    pk_VM__exec(pk_VM* vm, const char* source, const char* filename, enum CompileMode mode) {
     CodeObject co;
-    pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false);
+    pk_SourceData_ src = pk_SourceData__rcnew(source, filename, mode, false);
     Error* err = pk_compile(src, &co);
     if(err) {
         PK_DECREF(src);
         return false;
     }
-    pk_VM* vm = pk_current_vm;
+
+    disassemble(&co);
+
     Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co);
     pk_VM__push_frame(vm, frame);
     pk_FrameResult res = pk_VM__run_top_frame(vm);
@@ -44,6 +164,10 @@ bool py_eval(const char* source) {
     PK_UNREACHABLE();
 }
 
+bool py_exec(const char* source) { return pk_VM__exec(pk_current_vm, source, "<exec>", EXEC_MODE); }
+
+bool py_eval(const char* source) { return pk_VM__exec(pk_current_vm, source, "<eval>", EVAL_MODE); }
+
 bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; }
 
 bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }