blueloveTH 1 an în urmă
părinte
comite
15fd2ef8a0

+ 5 - 1
build_g.sh

@@ -5,8 +5,12 @@ python prebuild.py
 SRC=$(find src/ -name "*.c")
 
 FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
+
 SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
-# SANITIZE_FLAGS=""
+
+if [ "$(uname)" == "Darwin" ]; then
+    SANITIZE_FLAGS="-fsanitize=address,undefined"
+fi
 
 echo "Compiling C files..."
 clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main

+ 0 - 2
include/pocketpy/common/strname.h

@@ -10,8 +10,6 @@ extern "C" {
 
 typedef uint16_t StrName;
 
-#define py_name(name) pk_StrName__map(name)
-
 uint16_t pk_StrName__map(const char*);
 uint16_t pk_StrName__map2(c11_string);
 const char* pk_StrName__rmap(uint16_t index);

+ 26 - 29
include/pocketpy/interpreter/vm.h

@@ -8,61 +8,54 @@
 extern "C" {
 #endif
 
-typedef struct pk_TypeInfo{
+typedef struct pk_TypeInfo {
     py_Name name;
     py_Type base;
 
-    py_TValue self;      // the type object itself
-    py_TValue module;    // the module where the type is defined
+    py_TValue self;
+    py_TValue module;  // the module where the type is defined
     bool subclass_enabled;
 
     void (*dtor)(void*);
     void (*gc_mark)(void*);
 
-    c11_vector/*T=StrName*/ annotated_fields;
+    c11_vector /*T=StrName*/ annotated_fields;
 
-    py_CFunction on_end_subclass;   // backdoor for enum module
+    py_CFunction on_end_subclass;  // backdoor for enum module
 
-    /* Magic Caches */
+    /* Magic Slots */
     py_TValue magic[64];
-    // // unary operators
-    // py_CFunction m__repr__, m__str__, m__hash__, m__len__;
-    // py_CFunction m__iter__, m__next__, m__neg__, m__invert__;
-    // // binary operators
-    // py_CFunction m__eq__, m__lt__, m__le__, m__gt__, m__ge__, m__contains__;
-    // py_CFunction m__add__, m__sub__, m__mul__, m__truediv__, m__floordiv__;
-    // py_CFunction m__mod__, m__pow__, m__matmul__;
-    // py_CFunction m__lshift__, m__rshift__, m__and__, m__xor__, m__or__;
-    // // indexer
-    // py_CFunction m__getitem__, m__setitem__, m__delitem__;
-    // // attribute access (internal use only)
-    // py_CFunction m__getattr__, m__setattr__, m__delattr__;
 } pk_TypeInfo;
 
-void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled);
+void pk_TypeInfo__ctor(pk_TypeInfo* self,
+                       py_Name name,
+                       py_Type index,
+                       py_Type base,
+                       const py_TValue* module,
+                       bool subclass_enabled);
 void pk_TypeInfo__dtor(pk_TypeInfo* self);
 
 typedef struct pk_VM {
     Frame* top_frame;
-    
+
     pk_NameDict modules;
-    c11_vector/*T=pk_TypeInfo*/ types;
+    c11_vector /*T=pk_TypeInfo*/ types;
 
-    py_TValue StopIteration;    // a special Exception class
-    py_TValue builtins;         // builtins module
-    py_TValue main;             // __main__ module
+    py_TValue StopIteration;  // a special Exception class
+    py_TValue builtins;       // builtins module
+    py_TValue main;           // __main__ module
 
     void (*_ceval_on_step)(Frame*, Bytecode);
     unsigned char* (*_import_file)(const char*);
     void (*_stdout)(const char*, ...);
     void (*_stderr)(const char*, ...);
-    
+
     // singleton objects
     py_TValue True, False, None, NotImplemented, Ellipsis;
 
     py_Error* last_error;
     py_TValue last_retval;
-    py_TValue reg[8];   // users' registers
+    py_TValue reg[8];  // users' registers
 
     py_TValue __curr_class;
     py_TValue __cached_object_new;
@@ -70,7 +63,7 @@ typedef struct pk_VM {
     py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
 
     pk_ManagedHeap heap;
-    ValueStack stack;   // put `stack` at the end for better cache locality
+    ValueStack stack;  // put `stack` at the end for better cache locality
 } pk_VM;
 
 void pk_VM__ctor(pk_VM* self);
@@ -81,7 +74,7 @@ void pk_VM__pop_frame(pk_VM* self);
 
 void pk_VM__init_builtins(pk_VM* self);
 
-typedef enum pk_FrameResult{
+typedef enum pk_FrameResult {
     RES_RETURN,
     RES_CALL,
     RES_YIELD,
@@ -90,7 +83,11 @@ typedef enum pk_FrameResult{
 
 pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
 
-py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled);
+py_Type pk_VM__new_type(pk_VM* self,
+                        const char* name,
+                        py_Type base,
+                        const py_TValue* module,
+                        bool subclass_enabled);
 
 // type registration
 py_Type pk_list__register();

+ 4 - 14
include/pocketpy/objects/base.h

@@ -24,9 +24,9 @@ typedef struct py_TValue {
     union {
         int64_t _i64;
         double _f64;
-        PyObject* _obj;
-        void* _ptr;
+        bool _bool;
         py_CFunction _cfunc;
+        PyObject* _obj;
         // Vec2
     };
 } py_TValue;
@@ -46,20 +46,10 @@ const static py_Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21};
 const static py_Type tp_staticmethod = {22}, tp_classmethod = {23};
 const static py_Type tp_none_type = {24}, tp_not_implemented_type = {25};
 const static py_Type tp_ellipsis = {26};
-const static py_Type tp_op_call = {27}, tp_op_yield = {28};
-const static py_Type tp_syntax_error = {29}, tp_stop_iteration = {30};
+const static py_Type tp_syntax_error = {27}, tp_stop_iteration = {28};
 
-extern py_TValue PY_NULL, PY_OP_CALL, PY_OP_YIELD;
+extern py_TValue PY_NULL;
 
 #ifdef __cplusplus
 }
 #endif
-
-/*
-SSO types:
-1. int64_t
-2. double
-3. bool (dummy)
-4. tuple (extra + void*)
-5. string (extra + void* or buf)
-*/

+ 17 - 11
include/pocketpy/pocketpy.h

@@ -36,7 +36,7 @@ void py_finalize();
 /// Run a simple source string. Do not change the stack.
 bool py_exec(const char*);
 /// Eval a simple expression.
-/// The result will be set to `vm->last_retval`.
+/// The result will be set to `py_retval()`.
 bool py_eval(const char*);
 
 /************* Values Creation *************/
@@ -45,10 +45,11 @@ void py_newfloat(py_Ref, double);
 void py_newbool(py_Ref, bool);
 void py_newstr(py_Ref, const char*);
 void py_newstrn(py_Ref, const char*, int);
-void py_newStr_(py_Ref, py_Str);
 // void py_newfstr(py_Ref, const char*, ...);
 void py_newbytes(py_Ref, const unsigned char*, int);
 void py_newnone(py_Ref);
+void py_newnotimplemented(py_Ref out);
+void py_newellipsis(py_Ref out);
 void py_newnull(py_Ref);
 
 /// Create a tuple with n UNINITIALIZED elements.
@@ -60,6 +61,10 @@ void py_newlist(py_Ref);
 /// You should initialize all elements before using it.
 void py_newlistn(py_Ref, int n);
 
+py_Name py_name(const char*);
+const char* py_name2str(py_Name);
+bool py_ismagicname(py_Name);
+
 // opaque types
 void py_newdict(py_Ref);
 void py_newset(py_Ref);
@@ -76,8 +81,6 @@ void py_newfunction2(py_Ref out,
 // old style argc-based function
 void py_newnativefunc(py_Ref out, py_CFunction);
 
-void py_newnotimplemented(py_Ref out);
-
 /// Create a new object.
 /// @param out output reference.
 /// @param type type of the object.
@@ -89,6 +92,7 @@ int64_t py_toint(const py_Ref);
 double py_tofloat(const py_Ref);
 bool py_castfloat(const py_Ref, double* out);
 bool py_tobool(const py_Ref);
+py_Type py_totype(const py_Ref);
 const char* py_tostr(const py_Ref);
 const char* py_tostrn(const py_Ref, int* size);
 
@@ -104,8 +108,10 @@ bool py_isinstance(const py_Ref obj, py_Type type);
 bool py_issubclass(py_Type derived, py_Type base);
 
 /************* References *************/
+#define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
+
 #define TypeError(x) false
-#define py_arg(i) (py_Ref)((char*)argv + ((i) << 4))
+#define py_arg(i) py_offset(argv, i)
 #define py_checkargc(n)                                                                            \
     if(argc != n) return TypeError()
 
@@ -164,7 +170,7 @@ bool py_delitem(py_Ref self, const py_Ref key);
 
 /// Perform a binary operation on the stack.
 /// It assumes `lhs` and `rhs` are already pushed to the stack.
-/// The result will be set to `vm->last_retval`.
+/// The result will be set to `py_retval()`.
 bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop);
 
 #define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
@@ -237,21 +243,21 @@ bool py_isidentical(const py_Ref, const py_Ref);
 
 /// A stack operation that calls a function.
 /// It assumes `argc + kwargc` arguments are already pushed to the stack.
-/// The result will be set to `vm->last_retval`.
+/// The result will be set to `py_retval()`.
 /// The stack size will be reduced by `argc + kwargc`.
 bool pk_vectorcall(int argc, int kwargc, bool op_call);
 /// Call a function.
 /// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
-/// The result will be set to `vm->last_retval`.
+/// The result will be set to `py_retval()`.
 /// The stack remains unchanged after the operation.
 bool py_call(py_Ref f, int argc, py_Ref argv);
 /// Call a non-magic method.
 /// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`.
-/// The result will be set to `vm->last_retval`.
+/// The result will be set to `py_retval()`.
 /// The stack remains unchanged after the operation.
 bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv);
 /// Call a magic method.
-/// The result will be set to `vm->last_retval`.
+/// The result will be set to `py_retval()`.
 /// The stack remains unchanged after the operation.
 bool py_callmagic(py_Name name, int argc, py_Ref argv);
 
@@ -259,7 +265,7 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv);
 #define py_str(self) py_callmagic(__str__, 1, self)
 
 /// The return value of the most recent vectorcall.
-py_Ref py_lastretval();
+py_Ref py_retval();
 
 #define py_isnull(self) ((self)->type == 0)
 

+ 13 - 0
src/common/strname.c

@@ -2,6 +2,7 @@
 #include "pocketpy/common/smallmap.h"
 #include "pocketpy/common/utils.h"
 #include "pocketpy/common/vector.h"
+#include "pocketpy/pocketpy.h"
 
 #include <stdio.h>
 
@@ -80,6 +81,18 @@ c11_string pk_StrName__rmap2(uint16_t index) {
     return (c11_string){p, strlen(p)};
 }
 
+py_Name py_name(const char* name) {
+    return pk_StrName__map(name);
+}
+
+const char* py_name2str(py_Name name) {
+    return pk_StrName__rmap(name);
+}
+
+bool py_ismagicname(py_Name name){
+    return name <= __missing__;
+}
+
 ///////////////////////////////////
 #define MAGIC_METHOD(x) uint16_t x;
 #include "pocketpy/xmacros/magics.h"

+ 3 - 0
src/interpreter/ceval.c

@@ -13,6 +13,9 @@ int NameError(py_Name name) { return -1; }
 
 static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
 
+// private
+void py_newStr_(py_Ref, py_Str);
+
 #define DISPATCH()                                                                                 \
     do {                                                                                           \
         frame->ip++;                                                                               \

+ 23 - 23
src/interpreter/py_number.c

@@ -45,13 +45,13 @@
         if(py_isint(&argv[1])) {                                                                   \
             int64_t lhs = py_toint(&argv[0]);                                                      \
             int64_t rhs = py_toint(&argv[1]);                                                      \
-            rint(py_lastretval(), lhs op rhs);                                                     \
+            rint(py_retval(), lhs op rhs);                                                     \
         } else if(py_isfloat(&argv[1])) {                                                          \
             int64_t lhs = py_toint(&argv[0]);                                                      \
             double rhs = py_tofloat(&argv[1]);                                                     \
-            rfloat(py_lastretval(), lhs op rhs);                                                   \
+            rfloat(py_retval(), lhs op rhs);                                                   \
         } else {                                                                                   \
-            py_newnotimplemented(py_lastretval());                                                 \
+            py_newnotimplemented(py_retval());                                                 \
         }                                                                                          \
         return true;                                                                               \
     }                                                                                              \
@@ -60,9 +60,9 @@
         double lhs = py_tofloat(&argv[0]);                                                         \
         double rhs;                                                                                \
         if(py_castfloat(&argv[1], &rhs)) {                                                         \
-            rfloat(py_lastretval(), lhs op rhs);                                                   \
+            rfloat(py_retval(), lhs op rhs);                                                   \
         } else {                                                                                   \
-            py_newnotimplemented(py_lastretval());                                                 \
+            py_newnotimplemented(py_retval());                                                 \
         }                                                                                          \
         return true;                                                                               \
     }
@@ -83,14 +83,14 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
 static bool _py_int__neg__(int argc, py_Ref argv) {
     py_checkargc(1);
     int64_t val = py_toint(&argv[0]);
-    py_newint(py_lastretval(), -val);
+    py_newint(py_retval(), -val);
     return true;
 }
 
 static bool _py_float__neg__(int argc, py_Ref argv) {
     py_checkargc(1);
     double val = py_tofloat(&argv[0]);
-    py_newfloat(py_lastretval(), -val);
+    py_newfloat(py_retval(), -val);
     return true;
 }
 
@@ -99,9 +99,9 @@ static bool _py_int__truediv__(int argc, py_Ref argv) {
     int64_t lhs = py_toint(&argv[0]);
     double rhs;
     if(py_castfloat(&argv[1], &rhs)) {
-        py_newfloat(py_lastretval(), lhs / rhs);
+        py_newfloat(py_retval(), lhs / rhs);
     } else {
-        py_newnotimplemented(py_lastretval());
+        py_newnotimplemented(py_retval());
     }
     return true;
 }
@@ -111,9 +111,9 @@ static bool _py_float__truediv__(int argc, py_Ref argv) {
     double lhs = py_tofloat(&argv[0]);
     double rhs;
     if(py_castfloat(&argv[1], &rhs)) {
-        py_newfloat(py_lastretval(), lhs / rhs);
+        py_newfloat(py_retval(), lhs / rhs);
     } else {
-        py_newnotimplemented(py_lastretval());
+        py_newnotimplemented(py_retval());
     }
     return true;
 }
@@ -129,7 +129,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
             if(lhs == 0) {
                 return ZeroDivisionError("0.0 cannot be raised to a negative power");
             } else {
-                py_newfloat(py_lastretval(), pow(lhs, rhs));
+                py_newfloat(py_retval(), pow(lhs, rhs));
             }
         } else {
             int64_t ret = 1;
@@ -138,15 +138,15 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
                 lhs *= lhs;
                 rhs >>= 1;
             }
-            py_newint(py_lastretval(), ret);
+            py_newint(py_retval(), ret);
         }
     } else {
         double lhs, rhs;
         py_castfloat(&argv[0], &lhs);
         if(py_castfloat(&argv[1], &rhs)) {
-            py_newfloat(py_lastretval(), pow(lhs, rhs));
+            py_newfloat(py_retval(), pow(lhs, rhs));
         } else {
-            py_newnotimplemented(py_lastretval());
+            py_newnotimplemented(py_retval());
         }
     }
     return true;
@@ -158,9 +158,9 @@ static bool _py_int__floordiv__(int argc, py_Ref argv) {
     if(py_isint(&argv[1])) {
         int64_t rhs = py_toint(&argv[1]);
         if(rhs == 0) return -1;
-        py_newint(py_lastretval(), lhs / rhs);
+        py_newint(py_retval(), lhs / rhs);
     } else {
-        py_newnotimplemented(py_lastretval());
+        py_newnotimplemented(py_retval());
     }
     return true;
 }
@@ -171,9 +171,9 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
     if(py_isint(&argv[1])) {
         int64_t rhs = py_toint(&argv[1]);
         if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
-        py_newint(py_lastretval(), lhs % rhs);
+        py_newint(py_retval(), lhs % rhs);
     } else {
-        py_newnotimplemented(py_lastretval());
+        py_newnotimplemented(py_retval());
     }
     return true;
 }
@@ -181,7 +181,7 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
 static bool _py_int__invert__(int argc, py_Ref argv) {
     py_checkargc(1);
     int64_t val = py_toint(&argv[0]);
-    py_newint(py_lastretval(), ~val);
+    py_newint(py_retval(), ~val);
     return true;
 }
 
@@ -194,7 +194,7 @@ static bool _py_int__bit_length(int argc, py_Ref argv) {
         x >>= 1;
         bits++;
     }
-    py_newint(py_lastretval(), bits);
+    py_newint(py_retval(), bits);
     return true;
 }
 
@@ -204,9 +204,9 @@ static bool _py_int__bit_length(int argc, py_Ref argv) {
         int64_t lhs = py_toint(&argv[0]);                                                          \
         if(py_isint(&argv[1])) {                                                                   \
             int64_t rhs = py_toint(&argv[1]);                                                      \
-            py_newint(py_lastretval(), lhs op rhs);                                                \
+            py_newint(py_retval(), lhs op rhs);                                                \
         } else {                                                                                   \
-            py_newnotimplemented(py_lastretval());                                                 \
+            py_newnotimplemented(py_retval());                                                 \
         }                                                                                          \
         return true;                                                                               \
     }

+ 15 - 42
src/interpreter/vm.c

@@ -1,8 +1,11 @@
 #include "pocketpy/interpreter/vm.h"
 #include "pocketpy/common/memorypool.h"
 #include "pocketpy/common/sstream.h"
+#include "pocketpy/objects/base.h"
 #include "pocketpy/pocketpy.h"
 
+#include <stdarg.h>
+
 static unsigned char* pk_default_import_file(const char* path) { return NULL; }
 
 static void pk_default_stdout(const char* fmt, ...) {
@@ -23,8 +26,8 @@ static void pk_default_stderr(const char* fmt, ...) {
 
 void pk_TypeInfo__ctor(pk_TypeInfo* self,
                        py_Name name,
+                       py_Type index,
                        py_Type base,
-                       PyObject* obj,
                        const py_TValue* module,
                        bool subclass_enabled) {
     memset(self, 0, sizeof(pk_TypeInfo));
@@ -32,7 +35,11 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
     self->name = name;
     self->base = base;
 
-    self->self = PyVar__fromobj(obj);
+    // create type object with __dict__
+    pk_ManagedHeap* heap = &pk_current_vm->heap;
+    PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
+    self->self = PyVar__fromobj(typeobj);
+
     self->module = module ? *module : PY_NULL;
     self->subclass_enabled = subclass_enabled;
 
@@ -66,37 +73,9 @@ void pk_VM__ctor(pk_VM* self) {
     pk_ManagedHeap__ctor(&self->heap, self);
     ValueStack__ctor(&self->stack);
 
-    self->True = (py_TValue){
-        .type = tp_bool,
-        .is_ptr = true,
-        .extra = 1,
-        ._obj = pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
-    };
-    self->False = (py_TValue){
-        .type = tp_bool,
-        .is_ptr = true,
-        .extra = 0,
-        ._obj = pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
-    };
-    self->None = (py_TValue){
-        .type = tp_none_type,
-        .is_ptr = true,
-        ._obj = pk_ManagedHeap__gcnew(&self->heap, tp_none_type, 0, 0),
-    };
-    self->NotImplemented = (py_TValue){
-        .type = tp_not_implemented_type,
-        .is_ptr = true,
-        ._obj = pk_ManagedHeap__gcnew(&self->heap, tp_not_implemented_type, 0, 0),
-    };
-    self->Ellipsis = (py_TValue){
-        .type = tp_ellipsis,
-        .is_ptr = true,
-        ._obj = pk_ManagedHeap__gcnew(&self->heap, tp_ellipsis, 0, 0),
-    };
-
     /* Init Builtin Types */
     // 0: unused
-    pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, NULL, NULL, false);
+    pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, 0, NULL, false);
 #define validate(t, expr)                                                                          \
     if(t != (expr)) abort()
 
@@ -136,14 +115,11 @@ void pk_VM__ctor(pk_VM* self) {
              pk_VM__new_type(self, "NotImplementedType", tp_object, NULL, false));
     validate(tp_ellipsis, pk_VM__new_type(self, "ellipsis", tp_object, NULL, false));
 
-    validate(tp_op_call, pk_VM__new_type(self, "__op_call", tp_object, NULL, false));
-    validate(tp_op_yield, pk_VM__new_type(self, "__op_yield", tp_object, NULL, false));
-
     validate(tp_syntax_error, pk_VM__new_type(self, "SyntaxError", tp_exception, NULL, false));
     validate(tp_stop_iteration, pk_VM__new_type(self, "StopIteration", tp_exception, NULL, false));
 #undef validate
 
-    self->StopIteration = c11__at(pk_TypeInfo, &self->types, tp_stop_iteration)->self;
+    self->StopIteration = *py_tpobject(tp_stop_iteration);
     self->builtins = *py_newmodule("builtins", NULL);
 
     /* Setup Public Builtin Types */
@@ -167,7 +143,7 @@ void pk_VM__ctor(pk_VM* self) {
     for(int i = 0; i < PK_ARRAY_COUNT(public_types); i++) {
         py_Type t = public_types[i];
         pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t);
-        py_setdict(&self->builtins, ti->name, &ti->self);
+        py_setdict(&self->builtins, ti->name, py_tpobject(t));
     }
     py_setdict(&self->builtins, py_name("NotImplemented"), &self->NotImplemented);
 
@@ -207,13 +183,10 @@ py_Type pk_VM__new_type(pk_VM* self,
                         py_Type base,
                         const py_TValue* module,
                         bool subclass_enabled) {
-    py_Type type = self->types.count;
+    py_Type index = self->types.count;
     pk_TypeInfo* ti = c11_vector__emplace(&self->types);
-    PyObject* typeobj = pk_ManagedHeap__gcnew(&self->heap, tp_type, -1, sizeof(py_Type));
-    py_Type* value = PyObject__value(typeobj);
-    *value = type;
-    pk_TypeInfo__ctor(ti, py_name(name), base, typeobj, module, subclass_enabled);
-    return type;
+    pk_TypeInfo__ctor(ti, py_name(name), index, base, module, subclass_enabled);
+    return index;
 }
 
 /****************************************/

+ 0 - 2
src/objects/base.c

@@ -1,6 +1,4 @@
 #include "pocketpy/objects/base.h"
 
 py_TValue PY_NULL = {.type=0, .is_ptr=false, .extra=0, ._i64=0};
-py_TValue PY_OP_CALL = {.type=27, .is_ptr=false, .extra=0, ._i64=0};
-py_TValue PY_OP_YIELD = {.type=28, .is_ptr=false, .extra=0, ._i64=0};
 

+ 7 - 1
src/public/cast.c

@@ -29,7 +29,13 @@ bool py_castfloat(const py_Ref self, double* out){
 
 bool py_tobool(const py_Ref self){
     assert(self->type == tp_bool);
-    return self->extra;
+    return self->_bool;
+}
+
+py_Type py_totype(const py_Ref self){
+    assert(self->type == tp_type);
+    py_Type* ud = py_touserdata(self);
+    return *ud;
 }
 
 const char* py_tostr(const py_Ref self){

+ 14 - 3
src/public/py_ops.c

@@ -1,9 +1,20 @@
 #include "pocketpy/interpreter/vm.h"
+#include "pocketpy/objects/base.h"
 #include "pocketpy/pocketpy.h"
 
 bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
-    if(lhs->is_ptr && rhs->is_ptr) { return lhs->_obj == rhs->_obj; }
-    return false;
+    if(lhs->type != rhs->type) return false;
+    switch(lhs->type){
+        case tp_int: return lhs->_i64 == rhs->_i64;
+        case tp_float: return lhs->_f64 == rhs->_f64;
+        case tp_bool: return lhs->_bool == rhs->_bool;
+        case tp_nativefunc: return lhs->_cfunc == rhs->_cfunc;
+        case tp_none_type: return true;
+        case tp_not_implemented_type: return true;
+        case tp_ellipsis: return true;
+        // fallback to pointer comparison
+        default: return lhs->is_ptr && rhs->is_ptr && lhs->_obj == rhs->_obj;
+    }    
 }
 
 int py_bool(const py_Ref val) { return 1; }
@@ -26,7 +37,7 @@ bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
     int py_##name(const py_Ref lhs, const py_Ref rhs) {                                            \
         bool ok = py_binaryop(lhs, rhs, op, rop);                                                  \
         if(!ok) return -1;                                                                         \
-        return py_tobool(py_lastretval());                                                         \
+        return py_tobool(py_retval());                                                         \
     }
 
 COMPARE_OP_IMPL(eq, __eq__, __eq__)

+ 9 - 0
src/public/stack_ops.c

@@ -10,11 +10,20 @@ py_Ref py_reg(int i){
 
 py_Ref py_getdict(const py_Ref self, py_Name name){
     assert(self && self->is_ptr);
+    if(self->type == tp_type && py_ismagicname(name)){
+        py_Type* ud = py_touserdata(self);
+        py_Ref slot = py_tpmagic(*ud, name);
+        return py_isnull(slot) ? NULL : slot;
+    }
     return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
 }
 
 void py_setdict(py_Ref self, py_Name name, const py_Ref val){
     assert(self && self->is_ptr);
+    if(self->type == tp_type && py_ismagicname(name)){
+        py_Type* ud = py_touserdata(self);
+        *py_tpmagic(*ud, name) = *val;
+    }
     pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
 }
 

+ 21 - 14
src/public/values.c

@@ -17,10 +17,29 @@ void py_newfloat(py_Ref out, double val) {
 }
 
 void py_newbool(py_Ref out, bool val) {
-    pk_VM* vm = pk_current_vm;
-    *out = val ? vm->True : vm->False;
+    out->type = tp_bool;
+    out->is_ptr = false;
+    out->_bool = val;
+}
+
+void py_newnone(py_Ref out) {
+    out->type = tp_none_type;
+    out->is_ptr = false;
+}
+
+void py_newnotimplemented(py_Ref out) {
+    out->type = tp_not_implemented_type;
+    out->is_ptr = false;
+}
+
+void py_newellipsis(py_Ref out) {
+    out->type = tp_ellipsis;
+    out->is_ptr = false;
 }
 
+
+void py_newnull(py_Ref out) { out->type = 0; }
+
 void py_newstr(py_Ref out, const char* data) {
     pk_ManagedHeap* heap = &pk_current_vm->heap;
     PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, sizeof(py_Str));
@@ -61,13 +80,6 @@ void py_newbytes(py_Ref out, const unsigned char* data, int size) {
     out->_obj = obj;
 }
 
-void py_newnone(py_Ref out) {
-    pk_VM* vm = pk_current_vm;
-    *out = vm->None;
-}
-
-void py_newnull(py_Ref out) { out->type = 0; }
-
 void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {
     py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL);
 }
@@ -101,11 +113,6 @@ void py_bindnativefunc(py_Ref obj, const char *name, py_CFunction f){
     py_setdict(obj, py_name(name), &tmp);
 }
 
-void py_newnotimplemented(py_Ref out) {
-    pk_VM* vm = pk_current_vm;
-    *out = vm->NotImplemented;
-}
-
 void py_newslice(py_Ref out, const py_Ref start, const py_Ref stop, const py_Ref step) {
     py_newobject(out, tp_slice, 3, 0);
     py_setslot(out, 0, start);

+ 4 - 3
src/public/vm.c

@@ -50,7 +50,7 @@ bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1
 
 bool pk_vectorcall(int argc, int kwargc, bool op_call) { return -1; }
 
-py_Ref py_lastretval() { return &pk_current_vm->last_retval; }
+py_Ref py_retval() { return &pk_current_vm->last_retval; }
 
 bool py_getunboundmethod(const py_Ref self,
                          py_Name name,
@@ -66,7 +66,7 @@ pk_TypeInfo* pk_tpinfo(const py_Ref self) {
 }
 
 py_Ref py_tpfindmagic(py_Type t, py_Name name) {
-    assert(name < 64);
+    assert(py_ismagicname(name));
     pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
     do {
         py_Ref f = &types[t].magic[name];
@@ -77,7 +77,7 @@ py_Ref py_tpfindmagic(py_Type t, py_Name name) {
 }
 
 py_Ref py_tpmagic(py_Type type, py_Name name) {
-    assert(name < 64);
+    assert(py_ismagicname(name));
     pk_VM* vm = pk_current_vm;
     return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name];
 }
@@ -89,6 +89,7 @@ py_Ref py_tpobject(py_Type type) {
 
 bool py_callmagic(py_Name name, int argc, py_Ref argv) {
     assert(argc >= 1);
+    assert(py_ismagicname(name));
     py_Ref tmp = py_tpfindmagic(argv->type, name);
     if(!tmp) return TypeError(name);
     if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv); }

+ 2 - 2
src2/main.c

@@ -30,7 +30,7 @@ int main(int argc, char** argv) {
 
     if(py_eval(source)) {
         // handle the result
-        bool _L0 = py_tobool(py_lastretval());
+        bool _L0 = py_tobool(py_retval());
         printf("%d\n", _L0);
     }
 
@@ -42,7 +42,7 @@ int main(int argc, char** argv) {
 
     bool ok = py_binaryadd(r0, r1);
     assert(ok);
-    double res = py_tofloat(py_lastretval());
+    double res = py_tofloat(py_retval());
     printf("%f\n", res);
 
     py_finalize();