blueloveTH 1 yıl önce
ebeveyn
işleme
26815fae74

+ 3 - 0
compile_flags.txt

@@ -1,5 +1,8 @@
 -Wall
 -W*
+-xc++
+
+-std=c++17
 
 -Iinclude/
 -I3rd/cjson/include/

+ 2 - 2
include/pocketpy/common/smallmap.h

@@ -11,7 +11,7 @@ extern "C" {
 #define SMALLMAP_T__HEADER
 #define K uint16_t
 #define V int
-#define TAG n2i
+#define NAME c11_smallmap_n2i
 #include "pocketpy/xmacros/smallmap.h"
 #undef SMALLMAP_T__HEADER
 
@@ -19,7 +19,7 @@ extern "C" {
 #define SMALLMAP_T__HEADER
 #define K c11_string
 #define V uint16_t
-#define TAG s2n
+#define NAME c11_smallmap_s2n
 #define less(a, b)      (c11_string__cmp((a), (b)) <  0)
 #define equal(a, b)     (c11_string__cmp((a), (b)) == 0)
 #include "pocketpy/xmacros/smallmap.h"

+ 1 - 1
include/pocketpy/interpreter/cffi.hpp

@@ -39,7 +39,7 @@ struct VoidP {
 #define POINTER_VAR(Tp, NAME)                                       \
     inline PyVar py_var(VM* vm, Tp val) {                           \
         const static pair<StrName, StrName> P("c", NAME);           \
-        PyVar type = vm->_modules[P.first]->attr(P.second);         \
+        PyVar type = vm->_modules[P.first]->attr()[P.second];       \
         return vm->new_object<VoidP>(type->as<Type>(), val);        \
     }
 

+ 6 - 6
include/pocketpy/interpreter/vm.hpp

@@ -218,11 +218,11 @@ public:
     constexpr static Type tp_none_type = Type(kTpNoneTypeIndex), tp_not_implemented_type = Type(kTpNotImplementedTypeIndex);
     constexpr static Type tp_ellipsis = Type(26);
 
-    constexpr static PyVar True{const_sso_var(), tp_bool, 1};
-    constexpr static PyVar False{const_sso_var(), tp_bool, 0};
-    constexpr static PyVar None{const_sso_var(), tp_none_type, 0};
-    constexpr static PyVar NotImplemented{const_sso_var(), tp_not_implemented_type, 0};
-    constexpr static PyVar Ellipsis{const_sso_var(), tp_ellipsis, 0};
+    inline static PyVar True = pkpy_True;
+    inline static PyVar False = pkpy_False;
+    inline static PyVar None = pkpy_None;
+    inline static PyVar NotImplemented = pkpy_NotImplemented;
+    inline static PyVar Ellipsis = pkpy_Ellipsis;
 
     const bool enable_os;
     VM(bool enable_os = true);
@@ -242,7 +242,7 @@ public:
     List py_list(PyVar);                                // x -> list(x)
     bool py_callable(PyVar obj);                        // x -> callable(x)
     bool py_bool(PyVar obj){                            // x -> bool(x)
-        if(obj.type == tp_bool) return obj._0;
+        if(obj.type == tp_bool) return obj._bool;
         return __py_bool_non_trivial(obj);
     }
     i64 py_hash(PyVar obj);                             // x -> hash(x)

+ 77 - 0
include/pocketpy/objects/base.h

@@ -0,0 +1,77 @@
+#pragma once
+
+#include "stdint.h"
+#include "stdbool.h"
+#include "stdlib.h"
+#include "assert.h"
+#include "string.h"
+
+#include "pocketpy/common/utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int16_t pkpy_Type;
+
+typedef struct PyObject PyObject;
+
+typedef struct PyVar{
+    pkpy_Type type;
+    bool is_ptr;
+    uint8_t flags;
+    int flags_ex;
+    union {
+        int64_t _i64;
+        double _f64;
+        bool _bool;
+        PyObject* _obj;
+        void* _ptr;
+        // Vec2
+    };
+} PyVar;
+
+static_assert(sizeof(PyVar) == 16, "sizeof(PyVar) != 16");
+
+PK_INLINE bool PyVar__is_null(const PyVar* self) { return self->type == 0; }
+PK_INLINE PyObject* PyVar__get(const PyVar* self) { return self->_obj; }
+PK_INLINE int64_t PyVar__hash(const PyVar* self) { return self->flags_ex + self->_i64; }
+
+PK_INLINE bool PyVar__less(const PyVar* self, const PyVar* other){
+    return memcmp(self, other, sizeof(PyVar)) < 0;
+}
+PK_INLINE bool PyVar__equal(const PyVar* self, const PyVar* other){
+    return memcmp(self, other, sizeof(PyVar)) == 0;
+}
+
+PK_INLINE void PyVar__ctor(PyVar* self, pkpy_Type type, PyObject* obj){
+    self->type = type;
+    self->is_ptr = true;
+    self->flags = 0;
+    self->flags_ex = 0;
+    self->_obj = obj;
+}
+
+#define pkpy_Var__is_null(self) ((self)->type == 0)
+#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
+bool pkpy_Var__eq__(void *vm, PyVar a, PyVar b);
+int64_t pkpy_Var__hash__(void *vm, PyVar a);
+
+extern const pkpy_Type tp_object, tp_type;
+extern const pkpy_Type tp_int, tp_float, tp_bool, tp_str;
+extern const pkpy_Type tp_list, tp_tuple;
+extern const pkpy_Type tp_slice, tp_range, tp_module;
+extern const pkpy_Type tp_function, tp_native_func, tp_bound_method;
+extern const pkpy_Type tp_super, tp_exception, tp_bytes, tp_mappingproxy;
+extern const pkpy_Type tp_dict, tp_property, tp_star_wrapper;
+extern const pkpy_Type tp_staticmethod, tp_classmethod;
+extern const pkpy_Type tp_none_type, tp_not_implemented_type;
+extern const pkpy_Type tp_ellipsis;
+
+extern const PyVar pkpy_True, pkpy_False, pkpy_None;
+extern const PyVar pkpy_NotImplemented, pkpy_Ellipsis;
+extern const PyVar pkpy_NULL;
+
+#ifdef __cplusplus
+}
+#endif

+ 31 - 30
include/pocketpy/objects/base.hpp

@@ -2,6 +2,7 @@
 
 #include "pocketpy/common/types.hpp"
 #include "pocketpy/common/traits.hpp"
+#include "pocketpy/objects/base.h"
 
 #include <cstdint>
 #include <cassert>
@@ -11,29 +12,15 @@
 namespace pkpy {
 
 struct Type {
-    int16_t index;
-
+    pkpy_Type index;
     constexpr Type() : index(0) {}
-
-    explicit constexpr Type(int index) : index(index) {}
-
+    constexpr Type(pkpy_Type index) : index(index) {}
     bool operator== (Type other) const { return this->index == other.index; }
-
     bool operator!= (Type other) const { return this->index != other.index; }
-
-    constexpr operator int () const { return index; }
+    constexpr operator pkpy_Type () const { return index; }
 };
 
-struct const_sso_var {};
-
-struct PyVar final {
-    Type type;
-    bool is_ptr;
-    uint8_t flags;
-    // 12 bytes SSO
-    int _0;
-    i64 _1;
-
+struct PyVar final: ::PyVar {
     // uninitialized
     PyVar() = default;
 
@@ -41,20 +28,29 @@ struct PyVar final {
     PyVar(PyObject* p);
 
     /* We must initialize all members to allow == operator to work correctly */
-    // constexpr initialized
-    constexpr PyVar(const const_sso_var&, Type type, int value) :
-        type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
-
     // zero initialized
-    constexpr PyVar(std::nullptr_t) : type(0), is_ptr(false), flags(0), _0(0), _1(0) {}
+    PyVar(std::nullptr_t){
+        set_null();
+    }
 
     // PyObject* initialized (is_sso = false)
-    PyVar(Type type, PyObject* p) : type(type), is_ptr(true), flags(0), _0(0), _1(reinterpret_cast<i64>(p)) {}
+    PyVar(Type type, PyObject* p){
+        this->type = type;
+        this->is_ptr = true;
+        this->flags = 0;
+        this->flags_ex = 0;
+        this->_obj = (::PyObject*)p;
+    }
 
     // SSO initialized (is_sso = true)
     template <typename T>
-    PyVar(Type type, T value) : type(type), is_ptr(false), flags(0), _0(0), _1(0) {
+    PyVar(Type type, T value){
         static_assert(sizeof(T) <= 12, "SSO size exceeded");
+        this->type = type;
+        this->is_ptr = false;
+        this->flags = 0;
+        this->flags_ex = 0;
+        this->_i64 = 0;
         as<T>() = value;
     }
 
@@ -62,9 +58,9 @@ struct PyVar final {
     T& as() {
         static_assert(!std::is_reference_v<T>);
         if constexpr(sizeof(T) <= 8) {
-            return reinterpret_cast<T&>(_1);
+            return reinterpret_cast<T&>(_i64);
         } else {
-            return reinterpret_cast<T&>(_0);
+            return reinterpret_cast<T&>(flags_ex);
         }
     }
 
@@ -89,21 +85,26 @@ struct PyVar final {
 
     PyObject* get() const {
         assert(is_ptr);
-        return reinterpret_cast<PyObject*>(_1);
+        return (PyObject*)_obj;
     }
 
     PyObject* operator->() const {
         assert(is_ptr);
-        return reinterpret_cast<PyObject*>(_1);
+        return (PyObject*)_obj;
     }
 
-    i64 hash() const { return _0 + _1; }
+    i64 hash() const { return PyVar__hash(this); }
 
     template <typename T>
     obj_get_t<T> obj_get();
 
     // std::less<> for map-like containers
     bool operator< (const PyVar& other) const { return memcmp(this, &other, sizeof(PyVar)) < 0; }
+
+    // implicit convert from ::PyVar
+    PyVar(const ::PyVar& var) {
+        memcpy(this, &var, sizeof(var));
+    }
 };
 
 static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);

+ 7 - 8
include/pocketpy/objects/builtins.hpp

@@ -82,13 +82,13 @@ const inline int16_t kTpNotImplementedTypeIndex = 25;
 
 inline bool is_tagged(PyVar p) noexcept { return !p.is_ptr; }
 
-inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; }
+inline bool is_float(PyVar p) noexcept { return p.type == kTpFloatIndex; }
 
-inline bool is_int(PyVar p) noexcept { return p.type.index == kTpIntIndex; }
+inline bool is_int(PyVar p) noexcept { return p.type == kTpIntIndex; }
 
-inline bool is_none(PyVar p) noexcept { return p.type.index == kTpNoneTypeIndex; }
+inline bool is_none(PyVar p) noexcept { return p.type == kTpNoneTypeIndex; }
 
-inline bool is_not_implemented(PyVar p) noexcept { return p.type.index == kTpNotImplementedTypeIndex; }
+inline bool is_not_implemented(PyVar p) noexcept { return p.type == kTpNotImplementedTypeIndex; }
 
 inline bool is_type(PyVar obj, Type type) {
     assert(obj != nullptr);
@@ -121,7 +121,7 @@ obj_get_t<T> PyVar::obj_get() {
         return as<T>();
     } else {
         assert(is_ptr);
-        void* v = ((PyObject*)_1)->_value_ptr();
+        void* v = PyObject__value_ptr(_obj);
         return *reinterpret_cast<T*>(v);
     }
 }
@@ -139,9 +139,8 @@ obj_get_t<T> PyVar::obj_get() {
 #define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast<T>(vm, x) : (default_value)
 
 /*****************************************************************/
-
 #define PY_NULL nullptr
-extern PyVar const PY_OP_CALL;
-extern const PyVar PY_OP_YIELD;
+extern PyVar PY_OP_CALL;
+extern PyVar PY_OP_YIELD;
 
 }  // namespace pkpy

+ 6 - 6
include/pocketpy/objects/dict.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include <stdbool.h>
-#include "pocketpy/objects/pyvar.h"
+#include "pocketpy/objects/base.h"
 #include "pocketpy/common/vector.h"
 
 #ifdef __cplusplus
@@ -49,7 +49,7 @@ pkpy_Dict pkpy_Dict__copy(const pkpy_Dict* self);
  * @param val value to set
  * @return `true` if the key is newly added, `false` if the key already exists
  */
-bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val);
+bool pkpy_Dict__set(pkpy_Dict* self, void* vm, PyVar key, PyVar val);
 
 /**
  * @brief Check if a key exists in the `pkpy_Dict`
@@ -58,7 +58,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val);
  * @param key key to check
  * @return `true` if the key exists, `false` otherwise
  */
-bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key);
+bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, PyVar key);
 
 /**
  * @brief Remove a key from the `pkpy_Dict`
@@ -67,7 +67,7 @@ bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key);
  * @param key key to remove
  * @return `true` if the key was found and removed, `false` if the key doesn't exist
  */
-bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key);
+bool pkpy_Dict__del(pkpy_Dict* self, void* vm, PyVar key);
 
 /**
  * @brief Try to get a value from the `pkpy_Dict`
@@ -76,7 +76,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key);
  * @param key key to get
  * @return the value associated with the key, `NULL` if the key doesn't exist
  */
-const pkpy_Var* pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, pkpy_Var key);
+const PyVar* pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, PyVar key);
 
 /**
  * @brief Update the `pkpy_Dict` with another one
@@ -106,7 +106,7 @@ pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict* self);
  * @param value value will be filled with the current value, can be `NULL` if not needed
  * @return `true` if the iteration is still valid, `false` otherwise
  */
-bool pkpy_DictIter__next(pkpy_DictIter* self, pkpy_Var* key, pkpy_Var* value);
+bool pkpy_DictIter__next(pkpy_DictIter* self, PyVar* key, PyVar* value);
 
 #ifdef __cplusplus
 }

+ 7 - 7
include/pocketpy/objects/dict.hpp

@@ -28,21 +28,21 @@ struct Dict : private pkpy_Dict {
     int size() const { return count; }
 
     void set(VM* vm, PyVar key, PyVar val) {
-        pkpy_Dict__set(this, vm, *(pkpy_Var*)(&key), *(pkpy_Var*)(&val));
+        pkpy_Dict__set(this, vm, *(::PyVar*)(&key), *(::PyVar*)(&val));
     }
 
     PyVar try_get(VM* vm, PyVar key) const {
-        auto res = pkpy_Dict__try_get(this, vm, *(pkpy_Var*)(&key));
+        auto res = pkpy_Dict__try_get(this, vm, *(::PyVar*)(&key));
         if (!res) return nullptr;
         return *(const PyVar*)(res);
     }
 
     bool contains(VM* vm, PyVar key) const {
-        return pkpy_Dict__contains(this, vm, *(pkpy_Var*)(&key));
+        return pkpy_Dict__contains(this, vm, *(::PyVar*)(&key));
     }
 
     bool del(VM* vm, PyVar key) {
-        return pkpy_Dict__del(this, vm, *(pkpy_Var*)(&key));
+        return pkpy_Dict__del(this, vm, *(::PyVar*)(&key));
     }
 
     void update(VM* vm, const Dict& other) {
@@ -53,7 +53,7 @@ struct Dict : private pkpy_Dict {
     void apply(__Func f) const {
         pkpy_DictIter it = iter();
         PyVar key, val;
-        while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
+        while(pkpy_DictIter__next(&it, (::PyVar*)(&key), (::PyVar*)(&val))) {
             f(key, val);
         }
     }
@@ -63,7 +63,7 @@ struct Dict : private pkpy_Dict {
         pkpy_DictIter it = iter();
         PyVar key, val;
         int i = 0;
-        while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
+        while(pkpy_DictIter__next(&it, (::PyVar*)(&key), (::PyVar*)(&val))) {
             res[i++] = key;
         }
         return res;
@@ -74,7 +74,7 @@ struct Dict : private pkpy_Dict {
         pkpy_DictIter it = iter();
         PyVar key, val;
         int i = 0;
-        while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
+        while(pkpy_DictIter__next(&it, (::PyVar*)(&key), (::PyVar*)(&val))) {
             res[i++] = val;
         }
         return res;

+ 3 - 6
include/pocketpy/objects/namedict.h

@@ -2,23 +2,20 @@
 
 #include "pocketpy/common/vector.h"
 #include "pocketpy/common/str.h"
+#include "pocketpy/objects/base.h"
 #include <stdint.h>
 
-#include "pocketpy/objects/pyvar.h"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #define SMALLMAP_T__HEADER
 #define K uint16_t
-#define V pkpy_Var
-#define TAG n2v
+#define V PyVar
+#define NAME pkpy_NameDict
 #include "pocketpy/xmacros/smallmap.h"
 #undef SMALLMAP_T__HEADER
 
-typedef c11_smallmap_n2v pkpy_NameDict;
-
 #ifdef __cplusplus
 }
 #endif

+ 16 - 13
include/pocketpy/objects/namedict.hpp

@@ -6,6 +6,8 @@
 #include "pocketpy/objects/object.hpp"
 #include "pocketpy/objects/namedict.h"
 
+#include <string_view>
+
 namespace pkpy {
 
 struct NameDict: pkpy_NameDict {
@@ -14,11 +16,11 @@ struct NameDict: pkpy_NameDict {
     using Item = pair<StrName, PyVar>;
 
     NameDict() {
-        c11_smallmap_n2v__ctor(this);
+        pkpy_NameDict__ctor(this);
     }
 
     ~NameDict() {
-        c11_smallmap_n2v__dtor(this);
+        pkpy_NameDict__dtor(this);
     }
 
     uint16_t size() const {
@@ -26,18 +28,19 @@ struct NameDict: pkpy_NameDict {
     }
 
     void set(StrName key, PyVar val){
-        pkpy_Var* p = (pkpy_Var*)&val;
-        c11_smallmap_n2v__set(this, key.index, *p);
+        PyVar* p = (PyVar*)&val;
+        pkpy_NameDict__set(this, key.index, *p);
     }
 
     PyVar try_get(StrName key) const{
         PyVar* p = try_get_2(key);
-        return p ? *p : nullptr;
+        if(p) return *p;
+        return nullptr;
     }
 
     PyVar* try_get_2(StrName key) const{
-        pkpy_Var* p = c11_smallmap_n2v__try_get(this, key.index);
-        return p ? (PyVar*)p : nullptr;
+        PyVar* p = (PyVar*)pkpy_NameDict__try_get(this, key.index);
+        return p;
     }
 
     PyVar try_get_likely_found(StrName key) const{
@@ -49,11 +52,11 @@ struct NameDict: pkpy_NameDict {
     }
 
     bool del(StrName key){
-        return c11_smallmap_n2v__del(this, key.index);
+        return pkpy_NameDict__del(this, key.index);
     }
 
     bool contains(StrName key) const{
-        return c11_smallmap_n2v__contains(this, key.index);
+        return pkpy_NameDict__contains(this, key.index);
     }
 
     PyVar operator[] (StrName key) const{
@@ -65,13 +68,13 @@ struct NameDict: pkpy_NameDict {
     }
 
     void clear(){
-        c11_smallmap_n2v__clear(this);
+        pkpy_NameDict__clear(this);
     }
 
     array<StrName> keys() const{
         array<StrName> retval((int)size());
         for(int i=0; i<size(); i++){
-            auto it = c11__at(c11_smallmap_entry_n2v, this, i);
+            auto it = c11__at(pkpy_NameDict_KV, this, i);
             retval[i] = StrName(it->key);
         }
         return retval;
@@ -80,7 +83,7 @@ struct NameDict: pkpy_NameDict {
     array<Item> items() const{
         array<Item> retval((int)size());
         for(int i=0; i<size(); i++){
-            auto it = c11__at(c11_smallmap_entry_n2v, this, i);
+            auto it = c11__at(pkpy_NameDict_KV, this, i);
             PyVar* p = (PyVar*)&it->value;
             retval[i] = Item(StrName(it->key), *p);
         }
@@ -89,7 +92,7 @@ struct NameDict: pkpy_NameDict {
 
     void apply(void (*f)(StrName, PyVar, void*), void* data){
         for(int i=0; i<size(); i++){
-            auto it = c11__at(c11_smallmap_entry_n2v, this, i);
+            auto it = c11__at(pkpy_NameDict_KV, this, i);
             PyVar* p = (PyVar*)&it->value;
             f(StrName(it->key), *p, data);
         }

+ 41 - 0
include/pocketpy/objects/object.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include "pocketpy/objects/namedict.h"
+#include "pocketpy/objects/base.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PyObject{
+    pkpy_Type type;         // we have a duplicated type here for convenience
+    bool gc_is_large;
+    bool gc_marked;
+    pkpy_NameDict* _attr;   // gc will delete this on destruction
+} PyObject;
+
+static_assert(sizeof(PyObject) <= 16, "!(sizeof(PyObject) <= 16)");
+
+#define PyObject__value_ptr(self)   ((char*)self + 16)
+#define PyObject__as(T, self)       (T*)(PyObject__value_ptr(self))
+
+PK_INLINE void PyObject__ctor(PyObject* self, pkpy_Type type, bool gc_is_large){
+    self->type = type;
+    self->gc_is_large = gc_is_large;
+    self->gc_marked = false;
+    self->_attr = NULL;
+}
+
+PK_INLINE PyVar PyVar__fromobj(PyObject* self){
+    PyVar var;
+    var.type = self->type;
+    var.is_ptr = true;
+    var.flags = 0;
+    var.flags_ex = 0;
+    var._obj = self;
+    return var;
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 13 - 13
include/pocketpy/objects/object.hpp

@@ -3,35 +3,35 @@
 #include "pocketpy/common/str.hpp"
 #include "pocketpy/common/config.h"
 #include "pocketpy/objects/base.hpp"
+#include "pocketpy/objects/object.h"
 
 namespace pkpy {
 
 struct NameDict;
 
-struct PyObject final {
-    Type type;        // we have a duplicated type here for convenience
-    bool gc_is_large;
-    bool gc_marked;
-    NameDict* _attr;  // gc will delete this on destruction
-
+struct PyObject final: ::PyObject {
     bool is_attr_valid() const noexcept { return _attr != nullptr; }
 
     void* _value_ptr() noexcept { return (char*)this + 16; }
 
+    NameDict& attr() const{
+        return *(NameDict*)_attr;
+    }
+
+    PyVar attr(StrName name) const;
+
     template <typename T>
     T& as() noexcept {
         static_assert(std::is_same_v<T, std::decay_t<T>>);
         return *reinterpret_cast<T*>(_value_ptr());
     }
 
-    NameDict& attr() {
-        assert(is_attr_valid());
-        return *_attr;
+    PyObject(Type type, bool gc_is_large){
+        this->type = type;
+        this->gc_is_large = gc_is_large;
+        this->gc_marked = false;
+        this->_attr = nullptr;
     }
-
-    PyObject(Type type, bool gc_is_large) : type(type), gc_is_large(gc_is_large), gc_marked(false), _attr(nullptr) {}
-
-    PyVar attr(StrName name) const;
 };
 
 static_assert(sizeof(PyObject) <= 16);

+ 0 - 51
include/pocketpy/objects/pyvar.h

@@ -1,51 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief A python value in pocketpy.
- */
-typedef struct {
-    int type;
-    int _0;
-    int64_t _1;
-} pkpy_Var;
-
-/**
- * @brief Check if the pkpy_Var is null.
- * @param self The variable to check.
- * @return True if the variable is null, false otherwise.
- */
-#define pkpy_Var__is_null(self) ((self)->type == 0)
-
-/**
- * @brief Set the variable to null.
- * @param self The variable to set.
- */
-#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
-
-/**
- * @brief Check if two pkpy_Vars are equal, respects to __eq__ method.
- * @param vm The virtual machine.
- * @param a The first pkpy_Var.
- * @param b The second pkpy_Var.
- * @return True if the pkpy_Vars are equal, false otherwise.
- */
-bool pkpy_Var__eq__(void *vm, pkpy_Var a, pkpy_Var b);
-
-/**
- * @brief Get the hash of the pkpy_Var, respects to __hash__ method.
- * @param vm The virtual machine.
- * @param a The pkpy_Var to hash.
- * @return The hash of the pkpy_Var.
- */
-int64_t pkpy_Var__hash__(void *vm, pkpy_Var a);
-
-#ifdef __cplusplus
-}
-#endif

+ 5 - 4
include/pocketpy/pocketpy_c.h

@@ -1,15 +1,15 @@
 #ifndef POCKETPY_C_H
 #define POCKETPY_C_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <stdbool.h>
 #include <stdint.h>
 
 #include "pocketpy/common/export.h"
 
+#ifdef __cplusplus
+extern "C" {
+    namespace pkpy{
+#endif
     typedef struct pkpy_vm_handle pkpy_vm;
     typedef int (*pkpy_CFunction)(pkpy_vm*);
     typedef void (*pkpy_COutputHandler)(const char*, int);
@@ -101,6 +101,7 @@ extern "C" {
     PK_EXPORT void pkpy_delete_repl(void* repl);
 #ifdef __cplusplus
 }
+}
 #endif
 
 #endif

+ 24 - 26
include/pocketpy/xmacros/smallmap.h

@@ -6,7 +6,7 @@
     /* Input */
     #define K int
     #define V float
-    #define TAG int_float
+    #define NAME c11_smallmap_i2f
 #endif
 
 /* Optional Input */
@@ -23,9 +23,8 @@
 #define CONCAT(A, B)            CONCAT_(A, B)
 #define CONCAT_(A, B)           A##B
 
-#define KV CONCAT(c11_smallmap_entry_, TAG)
-#define SMALLMAP CONCAT(c11_smallmap_, TAG)
-#define SMALLMAP_METHOD(name) CONCAT(SMALLMAP, CONCAT(__, name))
+#define KV CONCAT(NAME, _KV)
+#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
 
 #ifdef SMALLMAP_T__HEADER
 /* Declaration */
@@ -34,32 +33,32 @@ typedef struct {
     V value;
 } KV;
 
-typedef c11_vector SMALLMAP;
+typedef c11_vector NAME;
 
-void SMALLMAP_METHOD(ctor)(SMALLMAP* self);
-void SMALLMAP_METHOD(dtor)(SMALLMAP* self);
-void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value);
-V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key);
-V SMALLMAP_METHOD(get)(const SMALLMAP* self, K key, V default_value);
-bool SMALLMAP_METHOD(contains)(const SMALLMAP* self, K key);
-bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key);
-void SMALLMAP_METHOD(clear)(SMALLMAP* self);
+void METHOD(ctor)(NAME* self);
+void METHOD(dtor)(NAME* self);
+void METHOD(set)(NAME* self, K key, V value);
+V* METHOD(try_get)(const NAME* self, K key);
+V METHOD(get)(const NAME* self, K key, V default_value);
+bool METHOD(contains)(const NAME* self, K key);
+bool METHOD(del)(NAME* self, K key);
+void METHOD(clear)(NAME* self);
 
 #endif
 
 #ifdef SMALLMAP_T__SOURCE
 /* Implementation */
 
-void SMALLMAP_METHOD(ctor)(SMALLMAP* self) {
+void METHOD(ctor)(NAME* self) {
     c11_vector__ctor(self, sizeof(KV));
     c11_vector__reserve(self, 4);
 }
 
-void SMALLMAP_METHOD(dtor)(SMALLMAP* self) {
+void METHOD(dtor)(NAME* self) {
     c11_vector__dtor(self);
 }
 
-void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value) {
+void METHOD(set)(NAME* self, K key, V value) {
     int index;
     c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
     KV* it = c11__at(KV, self, index);
@@ -71,7 +70,7 @@ void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value) {
     }
 }
 
-V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key) {
+V* METHOD(try_get)(const NAME* self, K key) {
     // use `bsearch` which is faster than `lower_bound`
     int low = 0;
     int high = self->count - 1;
@@ -89,16 +88,16 @@ V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key) {
     return NULL;
 }
 
-V SMALLMAP_METHOD(get)(const SMALLMAP* self, K key, V default_value) {
-    V* p = SMALLMAP_METHOD(try_get)(self, key);
+V METHOD(get)(const NAME* self, K key, V default_value) {
+    V* p = METHOD(try_get)(self, key);
     return p ? *p : default_value;
 }
 
-bool SMALLMAP_METHOD(contains)(const SMALLMAP* self, K key) {
-    return SMALLMAP_METHOD(try_get)(self, key) != NULL;
+bool METHOD(contains)(const NAME* self, K key) {
+    return METHOD(try_get)(self, key) != NULL;
 }
 
-bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key) {
+bool METHOD(del)(NAME* self, K key) {
     int index;
     c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
     KV* it = c11__at(KV, self, index);
@@ -109,7 +108,7 @@ bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key) {
     return false;
 }
 
-void SMALLMAP_METHOD(clear)(SMALLMAP* self) {
+void METHOD(clear)(NAME* self) {
     c11_vector__clear(self);
 }
 
@@ -117,14 +116,13 @@ void SMALLMAP_METHOD(clear)(SMALLMAP* self) {
 
 /* Undefine all macros */
 #undef KV
-#undef SMALLMAP
-#undef SMALLMAP_METHOD
+#undef METHOD
 #undef CONCAT
 #undef CONCAT_
 
 #undef K
 #undef V
-#undef TAG
+#undef NAME
 #undef less
 #undef partial_less
 #undef equal

+ 2 - 2
src/common/smallmap.c

@@ -3,7 +3,7 @@
 #define SMALLMAP_T__SOURCE
 #define K uint16_t
 #define V int
-#define TAG n2i
+#define NAME c11_smallmap_n2i
 #include "pocketpy/xmacros/smallmap.h"
 #undef SMALLMAP_T__SOURCE
 
@@ -11,7 +11,7 @@
 #define SMALLMAP_T__SOURCE
 #define K c11_string
 #define V uint16_t
-#define TAG s2n
+#define NAME c11_smallmap_s2n
 #define less(a, b)      (c11_string__cmp((a), (b)) <  0)
 #define equal(a, b)     (c11_string__cmp((a), (b)) == 0)
 #include "pocketpy/xmacros/smallmap.h"

+ 1 - 1
src/compiler/lexer.cpp

@@ -637,7 +637,7 @@ Error* Lexer::precompile(Str* out) noexcept{
     ss << "=" << (int)token_indices.count << '\n';  // L3: raw string count
     uint16_t index = 0;
     for(int i=0; i<token_indices.count; i++){
-        c11_smallmap_entry_s2n* kv = c11__at(c11_smallmap_entry_s2n, &token_indices, i);
+        auto kv = c11__at(c11_smallmap_s2n_KV, &token_indices, i);
         ss << kv->key << '\n';  // L4: raw strings
         kv->value = index++;
     }

+ 2 - 2
src/interpreter/ceval.cpp

@@ -475,7 +475,7 @@ PyVar VM::__run_top_frame() {
                         DISPATCH()
                     case OP_BUILD_SET: {
                         PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
-                        _0 = call(builtins->attr(pk_id_set), _0);
+                        _0 = call(builtins->attr()[pk_id_set], _0);
                         STACK_SHRINK(byte.arg);
                         PUSH(_0);
                     }
@@ -526,7 +526,7 @@ PyVar VM::__run_top_frame() {
                         __unpack_as_list(STACK_VIEW(byte.arg), list);
                         STACK_SHRINK(byte.arg);
                         PyVar _0 = VAR(std::move(list));
-                        _0 = call(builtins->attr(pk_id_set), _0);
+                        _0 = call(builtins->attr()[pk_id_set], _0);
                         PUSH(_0);
                     }
                         DISPATCH()

+ 1 - 1
src/interpreter/cffi.cpp

@@ -267,7 +267,7 @@ void add_module_c(VM* vm) {
 
 #undef BIND_PRIMITIVE
 
-    PyObject* char_p_t = mod->attr("char_p").get();
+    PyObject* char_p_t = mod->attr()["char_p"].get();
     vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args) {
         obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
         const char* target = (const char*)voidp.ptr;

+ 1 - 1
src/interpreter/frame.cpp

@@ -11,7 +11,7 @@ PyVar* FastLocals::try_get_name(StrName name) {
 NameDict* FastLocals::to_namedict() {
     NameDict* dict = new NameDict();
     for(int i=0; i<co->varnames_inv.count; i++){
-        auto entry = c11__getitem(c11_smallmap_entry_n2i, &co->varnames_inv, i);
+        auto entry = c11__getitem(c11_smallmap_n2i_KV, &co->varnames_inv, i);
         PyVar value = a[entry.value];
         if(value) dict->set(StrName(entry.key), value);
     }

+ 1 - 1
src/interpreter/iter.cpp

@@ -118,7 +118,7 @@ void DictItemsIter::_register(VM* vm, PyObject* mod, PyObject* type) {
     vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned {
         DictItemsIter& self = _CAST(DictItemsIter&, _0);
         PyVar key, val;
-        if (pkpy_DictIter__next(&self.it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
+        if (pkpy_DictIter__next(&self.it, (PyVar*)(&key), (PyVar*)(&val))) {
             vm->s_data.push(key);
             vm->s_data.push(val);
             return 2;

+ 21 - 24
src/interpreter/vm.cpp

@@ -254,7 +254,7 @@ PyVar VM::py_op(std::string_view name) {
     PyVar func;
     auto it = __cached_op_funcs.try_get(name);
     if(it == nullptr) {
-        func = py_import("operator")->attr(StrName::get(name));
+        func = py_import("operator")->attr()[StrName::get(name)];
         __cached_op_funcs.insert(name, func);
     } else {
         func = *it;
@@ -283,11 +283,11 @@ PyVar VM::py_next(PyVar obj) {
 
 bool VM::py_callable(PyVar obj) {
     Type cls = vm->_tp(obj);
-    switch(cls.index) {
-        case VM::tp_function.index: return true;
-        case VM::tp_native_func.index: return true;
-        case VM::tp_bound_method.index: return true;
-        case VM::tp_type.index: return true;
+    switch(cls) {
+        case VM::tp_function: return true;
+        case VM::tp_native_func: return true;
+        case VM::tp_bound_method: return true;
+        case VM::tp_type: return true;
     }
     return vm->find_name_in_mro(cls, __call__) != nullptr;
 }
@@ -538,7 +538,7 @@ i64 VM::py_hash(PyVar obj) {
         has_custom_eq = true;
     else {
         f = get_unbound_method(obj, __eq__, &self, false);
-        has_custom_eq = f != _t(tp_object)->attr(__eq__);
+        has_custom_eq = f != _t(tp_object)->attr()[__eq__];
     }
     if(has_custom_eq) {
         TypeError(_S("unhashable type: ", ti->name.escape()));
@@ -1228,11 +1228,11 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err) {
     if(cls_var != nullptr) {
         // bound method is non-data descriptor
         if(!is_tagged(*cls_var)) {
-            switch(cls_var->type.index) {
-                case tp_function.index: return VAR(BoundMethod(obj, *cls_var));
-                case tp_native_func.index: return VAR(BoundMethod(obj, *cls_var));
-                case tp_staticmethod.index: return PK_OBJ_GET(StaticMethod, *cls_var).func;
-                case tp_classmethod.index: return VAR(BoundMethod(_t(objtype), PK_OBJ_GET(ClassMethod, *cls_var).func));
+            switch(cls_var->type) {
+                case tp_function: return VAR(BoundMethod(obj, *cls_var));
+                case tp_native_func: return VAR(BoundMethod(obj, *cls_var));
+                case tp_staticmethod: return PK_OBJ_GET(StaticMethod, *cls_var).func;
+                case tp_classmethod: return VAR(BoundMethod(_t(objtype), PK_OBJ_GET(ClassMethod, *cls_var).func));
             }
         }
         return *cls_var;
@@ -1291,11 +1291,11 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er
 
     if(cls_var != nullptr) {
         if(!is_tagged(*cls_var)) {
-            switch(cls_var->type.index) {
-                case tp_function.index: *self = obj; break;
-                case tp_native_func.index: *self = obj; break;
-                case tp_staticmethod.index: self->set_null(); return PK_OBJ_GET(StaticMethod, *cls_var).func;
-                case tp_classmethod.index: *self = _t(objtype); return PK_OBJ_GET(ClassMethod, *cls_var).func;
+            switch(cls_var->type) {
+                case tp_function: *self = obj; break;
+                case tp_native_func: *self = obj; break;
+                case tp_staticmethod: self->set_null(); return PK_OBJ_GET(StaticMethod, *cls_var).func;
+                case tp_classmethod: *self = _t(objtype); return PK_OBJ_GET(ClassMethod, *cls_var).func;
             }
         }
         return *cls_var;
@@ -1395,9 +1395,9 @@ PyObject* VM::bind_property(PyObject* obj, const char* name, NativeFuncC fget, N
     return prop;
 }
 
-void VM::__builtin_error(StrName type) { _error(call(builtins->attr(type))); }
+void VM::__builtin_error(StrName type) { _error(call(builtins->attr()[type])); }
 
-void VM::__builtin_error(StrName type, PyVar arg) { _error(call(builtins->attr(type), arg)); }
+void VM::__builtin_error(StrName type, PyVar arg) { _error(call(builtins->attr()[type], arg)); }
 
 void VM::__builtin_error(StrName type, const Str& msg) { __builtin_error(type, VAR(msg)); }
 
@@ -1796,11 +1796,8 @@ void VM::__breakpoint() {
 #endif
 }
 
-/**************************************************************************/
-
-PyVar PyObject::attr(StrName name) const {
-    assert(is_attr_valid());
-    return (*_attr)[name];
+PyVar PyObject::attr(StrName name) const{
+    return attr()[name];
 }
 
 /**************************************************************************/

+ 5 - 5
src/modules/array2d.cpp

@@ -149,11 +149,11 @@ struct Array2d {
                 HANDLE_SLICE();
 
                 bool is_basic_type = false;
-                switch(vm->_tp(_2).index) {
-                    case VM::tp_int.index: is_basic_type = true; break;
-                    case VM::tp_float.index: is_basic_type = true; break;
-                    case VM::tp_str.index: is_basic_type = true; break;
-                    case VM::tp_bool.index: is_basic_type = true; break;
+                switch(vm->_tp(_2)) {
+                    case VM::tp_int: is_basic_type = true; break;
+                    case VM::tp_float: is_basic_type = true; break;
+                    case VM::tp_str: is_basic_type = true; break;
+                    case VM::tp_bool: is_basic_type = true; break;
                     default: is_basic_type = is_none(_2);
                 }
 

+ 1 - 1
src/modules/csv.cpp

@@ -65,7 +65,7 @@ void add_module_csv(VM* vm) {
     });
 
     vm->bind(mod, "DictReader(csvfile: list[str]) -> list[dict]", [](VM* vm, ArgsView args) {
-        PyVar csv_reader = vm->_modules["csv"]->attr("reader");
+        PyVar csv_reader = vm->_modules["csv"]->attr()["reader"];
         PyVar ret_obj = vm->call(csv_reader, args[0]);
         const List& ret = CAST(List&, ret_obj);
         if(ret.size() == 0) { vm->ValueError("empty csvfile"); }

+ 2 - 2
src/modules/dataclasses.cpp

@@ -72,8 +72,8 @@ static void patch__eq__(VM* vm, Type cls) {
         const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
         const auto& fields = cls_info->annotated_fields;
         for(StrName field: fields) {
-            PyVar lhs = _0->attr(field);
-            PyVar rhs = _1->attr(field);
+            PyVar lhs = _0->attr()[field];
+            PyVar rhs = _1->attr()[field];
             if(vm->py_ne(lhs, rhs)) return vm->False;
         }
         return vm->True;

+ 20 - 0
src/objects/base.c

@@ -0,0 +1,20 @@
+#include "pocketpy/objects/base.h"
+
+/* predefined vars */
+const pkpy_Type tp_object = 1, tp_type = 2;
+const pkpy_Type tp_int = 3, tp_float = 4, tp_bool = 5, tp_str = 6;
+const pkpy_Type tp_list = 7, tp_tuple = 8;
+const pkpy_Type tp_slice = 9, tp_range = 10, tp_module = 11;
+const pkpy_Type tp_function = 12, tp_native_func = 13, tp_bound_method = 14;
+const pkpy_Type tp_super = 15, tp_exception = 16, tp_bytes = 17, tp_mappingproxy = 18;
+const pkpy_Type tp_dict = 19, tp_property = 20, tp_star_wrapper = 21;
+const pkpy_Type tp_staticmethod = 22, tp_classmethod = 23;
+const pkpy_Type tp_none_type = 24, tp_not_implemented_type = 25;
+const pkpy_Type tp_ellipsis = 26;
+
+const PyVar pkpy_True = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=true};
+const PyVar pkpy_False = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=false};
+const PyVar pkpy_None = {.type=tp_none_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
+const PyVar pkpy_NotImplemented = {.type=tp_not_implemented_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
+const PyVar pkpy_Ellipsis = {.type=tp_ellipsis, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
+const PyVar pkpy_NULL = {.type=0, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};

+ 2 - 2
src/objects/builtins.cpp

@@ -1,6 +1,6 @@
 #include "pocketpy/objects/builtins.hpp"
 
 namespace pkpy {
-const PyVar PY_OP_CALL(Type(), new PyObject(Type(), true));
-const PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true));
+PyVar PY_OP_CALL(Type(), new PyObject(Type(), true));
+PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true));
 }  // namespace pkpy

+ 9 - 9
src/objects/dict.c

@@ -10,8 +10,8 @@
 #define PK_DICT_COMPACT_MODE 1
 
 struct pkpy_DictEntry {
-    pkpy_Var key;
-    pkpy_Var val;
+    PyVar key;
+    PyVar val;
 };
 
 inline extern int pkpy_Dict__idx_size(const pkpy_Dict* self) {
@@ -73,7 +73,7 @@ static void pkpy_Dict__htset(pkpy_Dict* self, int h, int v) {
 #endif
 }
 
-static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, pkpy_Var key, int hash) {
+static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, PyVar key, int hash) {
     const int null = pkpy_Dict__idx_null(self);
     const int mask = self->_htcap - 1;
     for(int h = hash & mask;; h = DICT_HASH_NEXT(h) & mask) {
@@ -86,7 +86,7 @@ static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, pkpy_Var key, int
     PK_UNREACHABLE();
 }
 
-static int pkpy_Dict__probe1(const pkpy_Dict* self, void* vm, pkpy_Var key, int hash) {
+static int pkpy_Dict__probe1(const pkpy_Dict* self, void* vm, PyVar key, int hash) {
     const int null = pkpy_Dict__idx_null(self);
     const int mask = self->_htcap - 1;
     for(int h = hash & mask;; h = DICT_HASH_NEXT(h) & mask) {
@@ -116,7 +116,7 @@ static void pkpy_Dict__extendht(pkpy_Dict* self, void* vm) {
     }
 }
 
-bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
+bool pkpy_Dict__set(pkpy_Dict* self, void* vm, PyVar key, PyVar val) {
     int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
     int h = pkpy_Dict__probe1(self, vm, key, hash);
 
@@ -151,7 +151,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
     return false;
 }
 
-bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key) {
+bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, PyVar key) {
     int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
     int h = pkpy_Dict__probe1(self, vm, key, hash);
 
@@ -191,7 +191,7 @@ static bool pkpy_Dict__refactor(pkpy_Dict* self, void* vm) {
     return true;
 }
 
-bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
+bool pkpy_Dict__del(pkpy_Dict* self, void* vm, PyVar key) {
     int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
     int h = pkpy_Dict__probe1(self, vm, key, hash);
     int idx = pkpy_Dict__htget(self, h), null = pkpy_Dict__idx_null(self);
@@ -204,7 +204,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
     return true;
 }
 
-const pkpy_Var *pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, pkpy_Var key) {
+const PyVar *pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, PyVar key) {
     int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
     int h = pkpy_Dict__probe1(self, vm, key, hash);
     
@@ -245,7 +245,7 @@ pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict *self) {
     };
 }
 
-bool pkpy_DictIter__next(pkpy_DictIter *self, pkpy_Var *key, pkpy_Var *val) {
+bool pkpy_DictIter__next(pkpy_DictIter *self, PyVar *key, PyVar *val) {
     if(self->_index >= self->_dict->_entries.count) return false;
     
     struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_dict->_entries, self->_index);

+ 2 - 2
src/objects/namedict.c

@@ -2,7 +2,7 @@
 
 #define SMALLMAP_T__SOURCE
 #define K uint16_t
-#define V pkpy_Var
-#define TAG n2v
+#define V PyVar
+#define NAME pkpy_NameDict
 #include "pocketpy/xmacros/smallmap.h"
 #undef SMALLMAP_T__SOURCE

+ 5 - 6
src/objects/pyvar.cpp

@@ -1,17 +1,16 @@
-#include "pocketpy/objects/base.hpp"
-#include "pocketpy/objects/pyvar.h"
+#include "pocketpy/objects/base.h"
 #include "pocketpy/interpreter/vm.hpp"
 
 extern "C" {
 
-bool pkpy_Var__eq__(void* vm_, pkpy_Var a, pkpy_Var b) {
+bool pkpy_Var__eq__(void* vm_, PyVar a, PyVar b) {
     auto vm = (pkpy::VM*)(vm_);
-    return vm->py_eq(*(pkpy::PyVar*)(&a), *(pkpy::PyVar*)(&b));
+    return vm->py_eq(*(PyVar*)(&a), *(PyVar*)(&b));
 }
 
-int64_t pkpy_Var__hash__(void* vm_, pkpy_Var a) {
+int64_t pkpy_Var__hash__(void* vm_, PyVar a) {
     auto vm = (pkpy::VM*)(vm_);
-    return vm->py_hash(*(pkpy::PyVar*)(&a));
+    return vm->py_hash(*(PyVar*)(&a));
 }
 
 }

+ 1 - 1
src/pocketpy.cpp

@@ -1495,7 +1495,7 @@ void __init_builtins(VM* _vm) {
         if(self.size() != other.size()) return vm->False;
         pkpy_DictIter it = self.iter();
         PyVar key, val;
-        while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
+        while(pkpy_DictIter__next(&it, (PyVar*)(&key), (PyVar*)(&val))) {
             PyVar other_val = other.try_get(vm, key);
             if(other_val == nullptr) return vm->False;
             if(!vm->py_eq(val, other_val)) return vm->False;

+ 3 - 1
src/pocketpy_c.cpp

@@ -5,7 +5,7 @@
 
 #include <iostream>
 
-using namespace pkpy;
+namespace pkpy{
 
 #define PK_ASSERT_N_EXTRA_ELEMENTS(n)                                                                                  \
     int __ex_count = count_extra_elements(vm, n);                                                                      \
@@ -567,3 +567,5 @@ bool pkpy_repl_input(void* r, const char* line) { return ((REPL*)r)->input(line)
 void pkpy_delete_repl(void* repl) { delete (REPL*)repl; }
 
 #endif  // PK_NO_EXPORT_C_API
+
+}  // namespace pkpy

+ 2 - 0
src2/main.cpp

@@ -34,6 +34,8 @@ std::string pkpy_platform_getline(bool* eof) {
 
 #else
 
+using namespace pkpy;
+
 std::string pkpy_platform_getline(bool* eof) {
     std::string output;
     if(!std::getline(std::cin, output)) {