blueloveTH 1 tahun lalu
induk
melakukan
455aa576e5

+ 4 - 0
include/pocketpy/interpreter/frame.h

@@ -71,6 +71,10 @@ PK_INLINE py_TValue* Frame__f_globals_try_get(Frame* self, py_Name name){
     return pk_NameDict__try_get(Frame__f_globals(self), name);
 }
 
+PK_INLINE py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name){
+    return FastLocals__try_get_by_name(self->locals, self->locals_co, name);
+}
+
 py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name);
 
 int Frame__prepare_jump_exception_handler(Frame* self, ValueStack*);

+ 17 - 7
include/pocketpy/pocketpy.h

@@ -12,7 +12,7 @@ typedef py_TValue* py_Ref;
 typedef struct py_Str py_Str;
 typedef int (*py_CFunction)(int argc, py_Ref argv);
 
-typedef struct py_Error{
+typedef struct py_Error {
     py_Type type;
 } py_Error;
 
@@ -30,8 +30,8 @@ void py_finalize();
 
 /// Run a simple source string. Do not change the stack.
 int py_exec(const char*);
-/// Eval a simple expression. If succeed, the result will be pushed onto the stack.
-int py_eval(const char*);
+/// Eval a simple expression.
+int py_eval(const char*, py_Ref out);
 
 /************* Values Creation *************/
 void py_newint(py_Ref, int64_t);
@@ -49,10 +49,20 @@ void py_newtuple(py_Ref, int);
 
 // new style decl-based function
 void py_newfunction(py_Ref out, py_CFunction, const char* sig);
-void py_newfunction2(py_Ref out, py_CFunction, const char* sig, BindType bt, const char* docstring, const py_Ref upvalue);
+void py_newfunction2(py_Ref out,
+                     py_CFunction,
+                     const char* sig,
+                     BindType bt,
+                     const char* docstring,
+                     const py_Ref upvalue);
 // old style argc-based function
 void py_newnativefunc(py_Ref out, py_CFunction, int argc);
-void py_newnativefunc2(py_Ref out, py_CFunction, int argc, BindType bt, const char* docstring, const py_Ref upvalue);
+void py_newnativefunc2(py_Ref out,
+                       py_CFunction,
+                       int argc,
+                       BindType bt,
+                       const char* docstring,
+                       const py_Ref upvalue);
 
 /// Create a new object.
 /// @param out output reference.
@@ -146,8 +156,8 @@ int py_eq(const py_Ref, const py_Ref);
 int py_le(const py_Ref, const py_Ref);
 int py_hash(const py_Ref, int64_t* out);
 
-int py_str(const py_Ref);
-int py_repr(const py_Ref);
+int py_str(const py_Ref, py_Ref out);
+int py_repr(const py_Ref, py_Ref out);
 
 int py_vectorcall(int argc, int kwargc);
 int py_call(py_Ref f, ...);

+ 90 - 9
src/interpreter/ceval.c

@@ -4,6 +4,10 @@
 #include "pocketpy/objects/codeobject.h"
 #include "pocketpy/pocketpy.h"
 
+int UnboundLocalError(py_Name name) { return -1; }
+
+int NameError(py_Name name) { return -1; }
+
 #define DISPATCH()                                                                                 \
     do {                                                                                           \
         frame->ip++;                                                                               \
@@ -83,7 +87,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
             case OP_PRINT_EXPR:
                 if(TOP().type != tp_none_type) {
-                    int err = py_repr(&TOP());
+                    int err = py_repr(&TOP(), NULL);
                     if(err) goto __ERROR;
                     self->_stdout("%s\n", py_tostr(&TOP()));
                     POP();
@@ -91,15 +95,14 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 POP();
                 DISPATCH();
             /*****************************************/
-            case OP_LOAD_CONST: PUSH(c11__getitem(py_TValue, &frame->co->consts, byte.arg)); DISPATCH();
+            case OP_LOAD_CONST:
+                PUSH(c11__getitem(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_SMALL_INT:
-                py_newint(SP(), (int64_t)(int16_t)byte.arg);
-                SP()++;
-                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_FUNCTION: {
@@ -119,10 +122,88 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 // PUSH(obj);DISPATCH();
             }
             case OP_LOAD_NULL:
-                py_newnull(SP());
-                SP()++;
+                py_newnull(SP()++);
                 DISPATCH();
-            /*****************************************/
+                /*****************************************/
+            case OP_LOAD_FAST: {
+                PUSH(frame->locals[byte.arg]);
+                if(py_isnull(&TOP())) {
+                    py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
+                    UnboundLocalError(name);
+                    goto __ERROR;
+                }
+                DISPATCH();
+            }
+            case OP_LOAD_NAME: {
+                py_Name name = byte.arg;
+                py_Ref tmp = Frame__f_locals_try_get(frame, name);
+                if(tmp != NULL) {
+                    if(py_isnull(tmp)) {
+                        UnboundLocalError(name);
+                        goto __ERROR;
+                    }
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                tmp = Frame__f_closure_try_get(frame, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                tmp = Frame__f_globals_try_get(frame, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                tmp = py_getdict(&self->builtins, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                NameError(name);
+                goto __ERROR;
+            }
+            case OP_LOAD_NONLOCAL: {
+                py_Name name = byte.arg;
+                py_Ref tmp = Frame__f_closure_try_get(frame, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                tmp = Frame__f_globals_try_get(frame, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                tmp = py_getdict(&self->builtins, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                NameError(name);
+                goto __ERROR;
+            }
+            case OP_LOAD_GLOBAL: {
+                py_Name name = byte.arg;
+                py_Ref tmp = Frame__f_globals_try_get(frame, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                tmp = py_getdict(&self->builtins, name);
+                if(tmp != NULL) {
+                    PUSH(*tmp);
+                    DISPATCH();
+                }
+                NameError(name);
+                goto __ERROR;
+            }
+            case OP_LOAD_ATTR: {
+                int err = py_getattr(&TOP(), byte.arg, &TOP());
+                if(err) goto __ERROR;
+                DISPATCH();
+            }
+
             default: PK_UNREACHABLE();
         }
 

+ 8 - 4
src/public/py_ops.c

@@ -7,10 +7,14 @@ int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; }
 
 int py_hash(const py_Ref val, int64_t* out) { return 0; }
 
-int py_str(const py_Ref val) { return 0; }
+int py_str(const py_Ref val, py_Ref out) { return 0; }
 
-int py_repr(const py_Ref val) {
+int py_repr(const py_Ref val, py_Ref out) {
     const pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, val->type);
-    if(ti->m__repr__) return ti->m__repr__(1, val);
-    return py_callmethod(val, __repr__);
+    int err;
+    if(ti->m__repr__) err = ti->m__repr__(1, val);
+    err = py_callmethod(val, __repr__);
+    if(err) return err;
+    if(out) *out = *--pk_current_vm->stack.sp;
+    return 0;
 }

+ 5 - 2
src/public/vm.c

@@ -25,7 +25,7 @@ void py_finalize() {
 
 int py_exec(const char* source) { PK_UNREACHABLE(); }
 
-int py_eval(const char* source) {
+int py_eval(const char* source, py_Ref out) {
     CodeObject co;
     pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false);
     Error* err = pk_compile(src, &co);
@@ -40,6 +40,9 @@ int py_eval(const char* source) {
     CodeObject__dtor(&co);
     PK_DECREF(src);
     if(res == RES_ERROR) return vm->last_error->type;
-    if(res == RES_RETURN) return 0;
+    if(res == RES_RETURN){
+        if(out) *out = *--vm->stack.sp;
+        return 0;
+    }
     PK_UNREACHABLE();
 }

+ 1 - 1
src2/main.c

@@ -27,7 +27,7 @@ int main(int argc, char** argv) {
     py_initialize();
     const char* source = "[1, 'a']";
 
-    if(py_eval(source)){
+    if(py_eval(source, NULL)){
         py_Error* err = py_getlasterror();
         py_Error__print(err);
     }else{