blueloveTH před 2 roky
rodič
revize
6714a3f784
16 změnil soubory, kde provedl 110 přidání a 106 odebrání
  1. 1 1
      preprocess.py
  2. 1 1
      src/ceval.h
  3. 5 5
      src/cffi.h
  4. 2 2
      src/codeobject.h
  5. 1 1
      src/compiler.h
  6. 1 1
      src/frame.h
  7. 1 4
      src/gc.h
  8. 3 3
      src/io.h
  9. 1 1
      src/iter.h
  10. 4 4
      src/namedict.h
  11. 3 3
      src/obj.h
  12. 16 17
      src/pocketpy.h
  13. 2 2
      src/ref.h
  14. 0 0
      src/str.h
  15. 7 7
      src/tuplelist.h
  16. 62 54
      src/vm.h

+ 1 - 1
preprocess.py

@@ -20,7 +20,7 @@ def generate_python_sources():
 #include <string>
 
 namespace pkpy{
-    std::map<std::string, const char*> kPythonLibs = {
+    inline static std::map<std::string, const char*> kPythonLibs = {
 '''
     for key, value in sources.items():
         header += ' '*8 + '{"' + key + '", "' + value + '"},'

+ 1 - 1
src/ceval.h

@@ -7,7 +7,7 @@ namespace pkpy{
 
 Str _read_file_cwd(const Str& name, bool* ok);
 
-PyObject* VM::run_frame(Frame* frame){
+inline PyObject* VM::run_frame(Frame* frame){
     while(frame->has_next_bytecode()){
         const Bytecode& byte = frame->next_bytecode();
         switch (byte.op)

+ 5 - 5
src/cffi.h

@@ -152,7 +152,7 @@ struct TypeDB{
 static TypeDB _type_db;
 
 
-auto _ = [](){
+inline static auto ___x = [](){
     #define REGISTER_BASIC_TYPE(T) _type_db.register_type<T>(#T, {});
     _type_db.register_type<void>("void", {});
     REGISTER_BASIC_TYPE(char);
@@ -403,9 +403,9 @@ struct CType{
     }
 };
 
-void add_module_c(VM* vm){
+inline void add_module_c(VM* vm){
     PyObject* mod = vm->new_module("c");
-    PyObject* ptr_t = Pointer::register_class(vm, mod);
+    Pointer::register_class(vm, mod);
     Value::register_class(vm, mod);
     CType::register_class(vm, mod);
 
@@ -462,11 +462,11 @@ void add_module_c(VM* vm){
     });
 }
 
-PyObject* py_var(VM* vm, void* p){
+inline PyObject* py_var(VM* vm, void* p){
     return VAR_T(Pointer, _type_db.get<void>(), (char*)p);
 }
 
-PyObject* py_var(VM* vm, char* p){
+inline PyObject* py_var(VM* vm, char* p){
     return VAR_T(Pointer, _type_db.get<char>(), (char*)p);
 }
 

+ 2 - 2
src/codeobject.h

@@ -18,7 +18,7 @@ enum Opcode {
     #undef OPCODE
 };
 
-static const char* OP_NAMES[] = {
+inline const char* OP_NAMES[] = {
     #define OPCODE(name) #name,
     #include "opcodes.h"
     #undef OPCODE
@@ -31,7 +31,7 @@ struct Bytecode{
     uint16_t block;
 };
 
-Str pad(const Str& s, const int n){
+inline Str pad(const Str& s, const int n){
     if(s.size() >= n) return s.substr(0, n);
     return s + std::string(n - s.size(), ' ');
 }

+ 1 - 1
src/compiler.h

@@ -766,7 +766,7 @@ private:
 
     // from a import b as c, d as e
     void compile_from_import() {
-        Token tkmodule = _compile_import();
+        _compile_import();
         consume(TK("import"));
         if (match(TK("*"))) {
             if(name_scope() != NAME_GLOBAL) SyntaxError("import * can only be used in global scope");

+ 1 - 1
src/frame.h

@@ -73,7 +73,7 @@ struct Frame {
         _data.pop_back();
     }
 
-    inline void try_deref(VM*, PyObject*&);
+    void try_deref(VM*, PyObject*&);
 
     inline PyObject* pop_value(VM* vm){
         PyObject* value = pop();

+ 1 - 4
src/gc.h

@@ -6,12 +6,9 @@ namespace pkpy {
     struct ManagedHeap{
         std::vector<PyObject*> heap;
 
-        template<typename T>
-        PyObject* gcnew(Type type, T&& val){
-            PyObject* obj = new Py_<std::decay_t<T>>(type, std::forward<T>(val));
+        void _add(PyObject* obj){
             obj->gc.enabled = true;
             heap.push_back(obj);
-            return obj;
         }
 
         void sweep(){

+ 3 - 3
src/io.h

@@ -10,7 +10,7 @@
 
 namespace pkpy{
 
-Str _read_file_cwd(const Str& name, bool* ok){
+inline Str _read_file_cwd(const Str& name, bool* ok){
     std::filesystem::path path(name.c_str());
     bool exists = std::filesystem::exists(path);
     if(!exists){
@@ -78,7 +78,7 @@ struct FileIO {
     }
 };
 
-void add_module_io(VM* vm){
+inline void add_module_io(VM* vm){
     PyObject* mod = vm->new_module("io");
     PyObject* type = FileIO::register_class(vm, mod);
     vm->bind_builtin_func<2>("open", [type](VM* vm, const Args& args){
@@ -86,7 +86,7 @@ void add_module_io(VM* vm){
     });
 }
 
-void add_module_os(VM* vm){
+inline void add_module_os(VM* vm){
     PyObject* mod = vm->new_module("os");
     // Working directory is shared by all VMs!!
     vm->bind_func<0>(mod, "getcwd", [](VM* vm, const Args& args){

+ 1 - 1
src/iter.h

@@ -50,7 +50,7 @@ public:
     }
 };
 
-PyObject* Generator::next(){
+inline PyObject* Generator::next(){
     if(state == 2) return nullptr;
     vm->callstack.push(std::move(frame));
     PyObject* ret = vm->_exec();

+ 4 - 4
src/namedict.h

@@ -6,7 +6,7 @@
 
 namespace pkpy{
 
-const int kNameDictNodeSize = sizeof(StrName) + sizeof(PyObject*);
+const int kNameDictNodeSize = sizeof(StrName) + sizeof(void*);
 
 template<int __Bucket, int __BucketSize=32>
 struct DictArrayPool {
@@ -41,7 +41,7 @@ struct DictArrayPool {
 const std::vector<uint16_t> kHashSeeds = {9629, 43049, 13267, 59509, 39251, 1249, 35803, 54469, 27689, 9719, 34897, 18973, 30661, 19913, 27919, 32143, 3467, 28019, 1051, 39419, 1361, 28547, 48197, 2609, 24317, 22861, 41467, 17623, 52837, 59053, 33589, 32117};
 static DictArrayPool<32> _dict_pool;
 
-uint16_t find_next_capacity(uint16_t n){
+inline uint16_t find_next_capacity(uint16_t n){
     uint16_t x = 2;
     while(x < n) x <<= 1;
     return x;
@@ -49,7 +49,7 @@ uint16_t find_next_capacity(uint16_t n){
 
 #define _hash(key, mask, hash_seed) ( ( (key).index * (hash_seed) >> 8 ) & (mask) )
 
-uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector<StrName>& keys){
+inline uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector<StrName>& keys){
     if(keys.empty()) return kHashSeeds[0];
     std::set<uint16_t> indices;
     std::pair<uint16_t, float> best_score = {kHashSeeds[0], 0.0f};
@@ -207,7 +207,7 @@ while(!_keys[i].empty()) { \
         bool ok; uint16_t i;
         HASH_PROBE(key, ok, i);
         if(!ok) throw std::out_of_range("NameDict key not found: " + key.str());
-        _keys[i] = StrName(); value(i).reset();
+        _keys[i] = StrName(); value(i) = nullptr;
         _size--;
     }
 

+ 3 - 3
src/obj.h

@@ -147,8 +147,8 @@ const int kTpFloatIndex = 3;
 
 inline bool is_type(PyObject* obj, Type type) noexcept {
     switch(type.index){
-        case kTpIntIndex: return is_tag_01(obj);
-        case kTpFloatIndex: return is_tag_10(obj);
+        case kTpIntIndex: return is_int(obj);
+        case kTpFloatIndex: return is_float(obj);
         default: return !is_tagged(obj) && obj->type == type;
     }
 }
@@ -216,7 +216,7 @@ __T _py_cast(VM* vm, PyObject* obj) {
 }
 
 #define VAR(x) py_var(vm, x)
-#define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__))
+#define VAR_T(T, ...) vm->gcnew<T>(T::_type(vm), T(__VA_ARGS__))
 #define CAST(T, x) py_cast<T>(vm, x)
 #define _CAST(T, x) _py_cast<T>(vm, x)
 

+ 16 - 17
src/pocketpy.h

@@ -10,7 +10,7 @@
 
 namespace pkpy {
 
-CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
+inline CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
     Compiler compiler(this, source.c_str(), filename, mode);
     try{
         return compiler.compile();
@@ -42,7 +42,7 @@ CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
     });
     
 
-void init_builtins(VM* _vm) {
+inline void init_builtins(VM* _vm) {
     BIND_NUM_ARITH_OPT(__add__, +)
     BIND_NUM_ARITH_OPT(__sub__, -)
     BIND_NUM_ARITH_OPT(__mul__, *)
@@ -69,7 +69,7 @@ void init_builtins(VM* _vm) {
             vm->TypeError("super(type, obj): obj must be an instance or subtype of type");
         }
         Type base = vm->_all_types[type.index].base;
-        return vm->heap.gcnew(vm->tp_super, Super(args[1], base));
+        return vm->gcnew(vm->tp_super, Super(args[1], base));
     });
 
     _vm->bind_builtin_func<2>("isinstance", [](VM* vm, Args& args) {
@@ -88,7 +88,8 @@ void init_builtins(VM* _vm) {
         i64 lhs = CAST(i64, args[0]);
         i64 rhs = CAST(i64, args[1]);
         if(rhs == 0) vm->ZeroDivisionError();
-        return VAR(Tuple{VAR(lhs/rhs), VAR(lhs%rhs)});
+        Tuple t = Tuple{VAR(lhs/rhs), VAR(lhs%rhs)};
+        return VAR(std::move(t));
     });
 
     _vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) {
@@ -574,7 +575,7 @@ void init_builtins(VM* _vm) {
 #define __EXPORT
 #endif
 
-void add_module_time(VM* vm){
+inline void add_module_time(VM* vm){
     PyObject* mod = vm->new_module("time");
     vm->bind_func<0>(mod, "time", [](VM* vm, Args& args) {
         auto now = std::chrono::high_resolution_clock::now();
@@ -582,20 +583,17 @@ void add_module_time(VM* vm){
     });
 }
 
-void add_module_sys(VM* vm){
+inline void add_module_sys(VM* vm){
     PyObject* mod = vm->new_module("sys");
     vm->setattr(mod, "version", VAR(PK_VERSION));
-
-    vm->bind_func<1>(mod, "getrefcount", CPP_LAMBDA(VAR(args[0].use_count())));
     vm->bind_func<0>(mod, "getrecursionlimit", CPP_LAMBDA(VAR(vm->recursionlimit)));
-
     vm->bind_func<1>(mod, "setrecursionlimit", [](VM* vm, Args& args) {
         vm->recursionlimit = CAST(int, args[0]);
         return vm->None;
     });
 }
 
-void add_module_json(VM* vm){
+inline void add_module_json(VM* vm){
     PyObject* mod = vm->new_module("json");
     vm->bind_func<1>(mod, "loads", [](VM* vm, Args& args) {
         const Str& expr = CAST(Str&, args[0]);
@@ -606,7 +604,7 @@ void add_module_json(VM* vm){
     vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call(args[0], __json__)));
 }
 
-void add_module_math(VM* vm){
+inline void add_module_math(VM* vm){
     PyObject* mod = vm->new_module("math");
     vm->setattr(mod, "pi", VAR(3.1415926535897932384));
     vm->setattr(mod, "e" , VAR(2.7182818284590452354));
@@ -625,7 +623,7 @@ void add_module_math(VM* vm){
     vm->bind_func<1>(mod, "sqrt", CPP_LAMBDA(VAR(std::sqrt(vm->num_to_float(args[0])))));
 }
 
-void add_module_dis(VM* vm){
+inline void add_module_dis(VM* vm){
     PyObject* mod = vm->new_module("dis");
     vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) {
         PyObject* f = args[0];
@@ -651,7 +649,8 @@ struct ReMatch {
 
         vm->bind_method<0>(type, "span", [](VM* vm, Args& args) {
             auto& self = CAST(ReMatch&, args[0]);
-            return VAR(Tuple{VAR(self.start), VAR(self.end)});
+            Tuple t = Tuple{VAR(self.start), VAR(self.end)};
+            return VAR(std::move(t));
         });
 
         vm->bind_method<1>(type, "group", [](VM* vm, Args& args) {
@@ -663,7 +662,7 @@ struct ReMatch {
     }
 };
 
-PyObject* _regex_search(const Str& pattern, const Str& string, bool fromStart, VM* vm){
+inline PyObject* _regex_search(const Str& pattern, const Str& string, bool fromStart, VM* vm){
     std::regex re(pattern);
     std::smatch m;
     if(std::regex_search(string, m, re)){
@@ -675,7 +674,7 @@ PyObject* _regex_search(const Str& pattern, const Str& string, bool fromStart, V
     return vm->None;
 };
 
-void add_module_re(VM* vm){
+inline void add_module_re(VM* vm){
     PyObject* mod = vm->new_module("re");
     ReMatch::register_class(vm, mod);
 
@@ -749,14 +748,14 @@ struct Random{
     }
 };
 
-void add_module_random(VM* vm){
+inline void add_module_random(VM* vm){
     PyObject* mod = vm->new_module("random");
     Random::register_class(vm, mod);
     CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
     vm->_exec(code, mod);
 }
 
-void VM::post_init(){
+inline void VM::post_init(){
     init_builtins(this);
     add_module_sys(this);
     add_module_time(this);

+ 2 - 2
src/ref.h

@@ -154,10 +154,10 @@ struct TupleRef : BaseRef {
 template<typename P>
 PyObject* VM::PyRef(P&& value) {
     static_assert(std::is_base_of_v<BaseRef, std::decay_t<P>>);
-    return heap.gcnew<P>(tp_ref, std::forward<P>(value));
+    return gcnew<P>(tp_ref, std::forward<P>(value));
 }
 
-const BaseRef* VM::PyRef_AS_C(PyObject* obj)
+inline const BaseRef* VM::PyRef_AS_C(PyObject* obj)
 {
     if(!is_type(obj, tp_ref)) TypeError("expected an l-value");
     return static_cast<const BaseRef*>(obj->value());

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/str.h


+ 7 - 7
src/tuplelist.h

@@ -41,8 +41,8 @@ namespace pkpy {
 
         static pkpy::Args from_list(List&& other) noexcept {
             Args ret(other.size());
-            memcpy((void*)ret._args, (void*)other.data(), sizeof(PyObject*)*ret.size());
-            memset((void*)other.data(), 0, sizeof(PyObject*)*ret.size());
+            memcpy((void*)ret._args, (void*)other.data(), sizeof(void*)*ret.size());
+            memset((void*)other.data(), 0, sizeof(void*)*ret.size());
             other.clear();
             return ret;
         }
@@ -63,8 +63,8 @@ namespace pkpy {
 
         List move_to_list() noexcept {
             List ret(_size);
-            memcpy((void*)ret.data(), (void*)_args, sizeof(PyObject*)*_size);
-            memset((void*)_args, 0, sizeof(PyObject*)*_size);
+            memcpy((void*)ret.data(), (void*)_args, sizeof(void*)*_size);
+            memset((void*)_args, 0, sizeof(void*)*_size);
             return ret;
         }
 
@@ -75,8 +75,8 @@ namespace pkpy {
             _args[0] = self;
             if(old_size == 0) return;
 
-            memcpy((void*)(_args+1), (void*)old_args, sizeof(PyObject*)*old_size);
-            memset((void*)old_args, 0, sizeof(PyObject*)*old_size);
+            memcpy((void*)(_args+1), (void*)old_args, sizeof(void*)*old_size);
+            memset((void*)old_args, 0, sizeof(void*)*old_size);
             _pool.dealloc(old_args, old_size);
         }
 
@@ -89,5 +89,5 @@ namespace pkpy {
     }
 
     typedef Args Tuple;
-    THREAD_LOCAL SmallArrayPool<PyObject*, 10> Args::_pool;
+    inline THREAD_LOCAL SmallArrayPool<PyObject*, 10> Args::_pool;
 }   // namespace pkpy

+ 62 - 54
src/vm.h

@@ -8,22 +8,22 @@
 namespace pkpy{
 
 #define DEF_NATIVE_2(ctype, ptype)                                      \
-    template<> ctype py_cast<ctype>(VM* vm, PyObject* obj) {            \
+    template<> inline ctype py_cast<ctype>(VM* vm, PyObject* obj) {            \
         vm->check_type(obj, vm->ptype);                                 \
         return OBJ_GET(ctype, obj);                                     \
     }                                                                   \
-    template<> ctype _py_cast<ctype>(VM* vm, PyObject* obj) {           \
+    template<> inline ctype _py_cast<ctype>(VM* vm, PyObject* obj) {           \
         return OBJ_GET(ctype, obj);                                     \
     }                                                                   \
-    template<> ctype& py_cast<ctype&>(VM* vm, PyObject* obj) {          \
+    template<> inline ctype& py_cast<ctype&>(VM* vm, PyObject* obj) {          \
         vm->check_type(obj, vm->ptype);                                 \
         return OBJ_GET(ctype, obj);                                     \
     }                                                                   \
-    template<> ctype& _py_cast<ctype&>(VM* vm, PyObject* obj) {         \
+    template<> inline ctype& _py_cast<ctype&>(VM* vm, PyObject* obj) {         \
         return OBJ_GET(ctype, obj);                                     \
     }                                                                   \
-    PyObject* py_var(VM* vm, const ctype& value) { return vm->heap.gcnew(vm->ptype, value);}     \
-    PyObject* py_var(VM* vm, ctype&& value) { return vm->heap.gcnew(vm->ptype, std::move(value));}
+    inline PyObject* py_var(VM* vm, const ctype& value) { return vm->gcnew(vm->ptype, value);}     \
+    inline PyObject* py_var(VM* vm, ctype&& value) { return vm->gcnew(vm->ptype, std::move(value));}
 
 class Generator: public BaseIter {
     std::unique_ptr<Frame> frame;
@@ -134,14 +134,21 @@ public:
     }
 
     PyObject* fast_call(StrName name, Args&& args){
-        PyObject** val = find_name_in_mro(_t(args[0]).get(), name);
+        PyObject** val = find_name_in_mro(_t(args[0]), name);
         if(val != nullptr) return call(*val, std::move(args));
         AttributeError(args[0], name);
         return nullptr;
     }
 
-    inline PyObject* call(PyObject* _callable){
-        return call(_callable, no_arg(), no_arg(), false);
+    template<typename T>
+    PyObject* gcnew(Type type, T&& val){
+        PyObject* obj = new Py_<std::decay_t<T>>(type, std::forward<T>(val));
+        heap._add(obj);
+        return obj;
+    }
+
+    inline PyObject* call(PyObject* callable){
+        return call(callable, no_arg(), no_arg(), false);
     }
 
     template<typename ArgT>
@@ -193,7 +200,7 @@ public:
 
     PyObject* property(NativeFuncRaw fget){
         PyObject* p = builtins->attr("property");
-        PyObject* method = heap.gcnew(tp_native_function, NativeFunc(fget, 1, false));
+        PyObject* method = gcnew(tp_native_function, NativeFunc(fget, 1, false));
         return call(p, Args{method});
     }
 
@@ -267,7 +274,7 @@ public:
     template<typename P>
     inline PyObject* PyIter(P&& value) {
         static_assert(std::is_base_of_v<BaseIter, std::decay_t<P>>);
-        return heap.gcnew<P>(tp_iterator, std::forward<P>(value));
+        return gcnew<P>(tp_iterator, std::forward<P>(value));
     }
 
     inline BaseIter* PyIter_AS_C(PyObject* obj)
@@ -359,7 +366,7 @@ PyObject* NativeFunc::operator()(VM* vm, Args& args) const{
     return f(vm, args);
 }
 
-void CodeObject::optimize(VM* vm){
+inline void CodeObject::optimize(VM* vm){
     std::vector<StrName> keys;
     for(auto& p: names) if(p.second == NAME_LOCAL) keys.push_back(p.first);
     uint32_t base_n = (uint32_t)(keys.size() / kLocalsLoadFactor + 0.5);
@@ -411,13 +418,13 @@ DEF_NATIVE_2(Slice, tp_slice)
 DEF_NATIVE_2(Exception, tp_exception)
 DEF_NATIVE_2(StarWrapper, tp_star_wrapper)
 
-#define PY_CAST_INT(T) \
-template<> T py_cast<T>(VM* vm, PyObject* obj){ \
-    vm->check_type(obj, vm->tp_int); \
-    return (T)(obj.bits >> 2); \
-} \
-template<> T _py_cast<T>(VM* vm, PyObject* obj){ \
-    return (T)(obj.bits >> 2); \
+#define PY_CAST_INT(T)                          \
+template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
+    vm->check_type(obj, vm->tp_int);            \
+    return (T)(BITS(obj) >> 2);                 \
+}                                               \
+template<> inline T _py_cast<T>(VM* vm, PyObject* obj){    \
+    return (T)(BITS(obj) >> 2);                     \
 }
 
 PY_CAST_INT(char)
@@ -432,32 +439,32 @@ PY_CAST_INT(unsigned long)
 PY_CAST_INT(unsigned long long)
 
 
-template<> float py_cast<float>(VM* vm, PyObject* obj){
+template<> inline float py_cast<float>(VM* vm, PyObject* obj){
     vm->check_type(obj, vm->tp_float);
-    i64 bits = obj.bits;
+    i64 bits = BITS(obj);
     bits = (bits >> 2) << 2;
     return BitsCvt(bits)._float;
 }
-template<> float _py_cast<float>(VM* vm, PyObject* obj){
-    i64 bits = obj.bits;
+template<> inline float _py_cast<float>(VM* vm, PyObject* obj){
+    i64 bits = BITS(obj);
     bits = (bits >> 2) << 2;
     return BitsCvt(bits)._float;
 }
-template<> double py_cast<double>(VM* vm, PyObject* obj){
+template<> inline double py_cast<double>(VM* vm, PyObject* obj){
     vm->check_type(obj, vm->tp_float);
-    i64 bits = obj.bits;
+    i64 bits = BITS(obj);
     bits = (bits >> 2) << 2;
     return BitsCvt(bits)._float;
 }
-template<> double _py_cast<double>(VM* vm, PyObject* obj){
-    i64 bits = obj.bits;
+template<> inline double _py_cast<double>(VM* vm, PyObject* obj){
+    i64 bits = BITS(obj);
     bits = (bits >> 2) << 2;
     return BitsCvt(bits)._float;
 }
 
 
 #define PY_VAR_INT(T)                           \
-    PyObject* py_var(VM* vm, T _val){           \
+    inline PyObject* py_var(VM* vm, T _val){           \
         i64 val = static_cast<i64>(_val);       \
         if(((val << 2) >> 2) != val){           \
             vm->_error("OverflowError", std::to_string(val) + " is out of range");  \
@@ -478,7 +485,7 @@ PY_VAR_INT(unsigned long)
 PY_VAR_INT(unsigned long long)
 
 #define PY_VAR_FLOAT(T)                             \
-    PyObject* py_var(VM* vm, T _val){               \
+    inline PyObject* py_var(VM* vm, T _val){               \
         f64 val = static_cast<f64>(_val);           \
         i64 bits = BitsCvt(val)._int;                  \
         bits = (bits >> 2) << 2;                    \
@@ -489,23 +496,23 @@ PY_VAR_INT(unsigned long long)
 PY_VAR_FLOAT(float)
 PY_VAR_FLOAT(double)
 
-PyObject* py_var(VM* vm, bool val){
+inline PyObject* py_var(VM* vm, bool val){
     return val ? vm->True : vm->False;
 }
 
-template<> bool py_cast<bool>(VM* vm, PyObject* obj){
+template<> inline bool py_cast<bool>(VM* vm, PyObject* obj){
     vm->check_type(obj, vm->tp_bool);
     return obj == vm->True;
 }
-template<> bool _py_cast<bool>(VM* vm, PyObject* obj){
+template<> inline bool _py_cast<bool>(VM* vm, PyObject* obj){
     return obj == vm->True;
 }
 
-PyObject* py_var(VM* vm, const char val[]){
+inline PyObject* py_var(VM* vm, const char val[]){
     return VAR(Str(val));
 }
 
-PyObject* py_var(VM* vm, std::string val){
+inline PyObject* py_var(VM* vm, std::string val){
     return VAR(Str(std::move(val)));
 }
 
@@ -514,7 +521,7 @@ void _check_py_class(VM* vm, PyObject* obj){
     vm->check_type(obj, T::_type(vm));
 }
 
-PyObject* VM::num_negated(PyObject* obj){
+inline PyObject* VM::num_negated(PyObject* obj){
     if (is_int(obj)){
         return VAR(-CAST(i64, obj));
     }else if(is_float(obj)){
@@ -524,7 +531,7 @@ PyObject* VM::num_negated(PyObject* obj){
     return nullptr;
 }
 
-f64 VM::num_to_float(PyObject* obj){
+inline f64 VM::num_to_float(PyObject* obj){
     if(is_float(obj)){
         return CAST(f64, obj);
     } else if (is_int(obj)){
@@ -534,7 +541,7 @@ f64 VM::num_to_float(PyObject* obj){
     return 0;
 }
 
-PyObject* VM::asBool(PyObject* obj){
+inline PyObject* VM::asBool(PyObject* obj){
     if(is_type(obj, tp_bool)) return obj;
     if(obj == None) return False;
     if(is_type(obj, tp_int)) return VAR(CAST(i64, obj) != 0);
@@ -547,7 +554,7 @@ PyObject* VM::asBool(PyObject* obj){
     return True;
 }
 
-i64 VM::hash(PyObject* obj){
+inline i64 VM::hash(PyObject* obj){
     if (is_type(obj, tp_str)) return CAST(Str&, obj).hash();
     if (is_int(obj)) return CAST(i64, obj);
     if (is_type(obj, tp_tuple)) {
@@ -555,11 +562,12 @@ i64 VM::hash(PyObject* obj){
         const Tuple& items = CAST(Tuple&, obj);
         for (int i=0; i<items.size(); i++) {
             i64 y = hash(items[i]);
-            x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
+            // recommended by Github Copilot
+            x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
         }
         return x;
     }
-    if (is_type(obj, tp_type)) return obj.bits;
+    if (is_type(obj, tp_type)) return BITS(obj);
     if (is_type(obj, tp_bool)) return _CAST(bool, obj) ? 1 : 0;
     if (is_float(obj)){
         f64 val = CAST(f64, obj);
@@ -569,11 +577,11 @@ i64 VM::hash(PyObject* obj){
     return 0;
 }
 
-PyObject* VM::asRepr(PyObject* obj){
+inline PyObject* VM::asRepr(PyObject* obj){
     return call(obj, __repr__);
 }
 
-PyObject* VM::new_module(StrName name) {
+inline PyObject* VM::new_module(StrName name) {
     PyObject* obj = new Py_<DummyModule>(tp_module, DummyModule());
     obj->attr().set(__name__, VAR(name.str()));
     // we do not allow override in order to avoid memory leak
@@ -583,7 +591,7 @@ PyObject* VM::new_module(StrName name) {
     return obj;
 }
 
-Str VM::disassemble(CodeObject_ co){
+inline Str VM::disassemble(CodeObject_ co){
     std::vector<int> jumpTargets;
     for(auto byte : co->codes){
         if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_SAFE_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){
@@ -652,7 +660,7 @@ Str VM::disassemble(CodeObject_ co){
     return Str(ss.str());
 }
 
-void VM::init_builtin_types(){
+inline void VM::init_builtin_types(){
     PyObject* _tp_object = new Py_<Type>(Type(1), Type(0));
     PyObject* _tp_type = new Py_<Type>(Type(1), Type(1));
     // PyTypeObject is managed by _all_types
@@ -711,14 +719,14 @@ void VM::init_builtin_types(){
     for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash();
 }
 
-PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, bool opCall){
+inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, bool opCall){
     if(is_type(callable, tp_type)){
         PyObject** new_f = callable->attr().try_get(__new__);
         PyObject* obj;
         if(new_f != nullptr){
             obj = call(*new_f, std::move(args), kwargs, false);
         }else{
-            obj = heap.gcnew<DummyInstance>(_callable, {});
+            obj = gcnew<DummyInstance>(OBJ_GET(Type, callable), {});
             PyObject* init_f = getattr(obj, __init__, false, true);
             if (init_f != nullptr) call(init_f, std::move(args), kwargs, false);
         }
@@ -784,15 +792,15 @@ PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, bool opCal
         return _exec();
     }
 
-    PyObject* call_f = getattr(_callable, __call__, false, true);
+    PyObject* call_f = getattr(callable, __call__, false, true);
     if(call_f != nullptr){
         return call(call_f, std::move(args), kwargs, false);
     }
-    TypeError(OBJ_NAME(_t(*callable)).escape(true) + " object is not callable");
+    TypeError(OBJ_NAME(_t(callable)).escape(true) + " object is not callable");
     return None;
 }
 
-void VM::unpack_args(Args& args){
+inline void VM::unpack_args(Args& args){
     List unpacked;
     for(int i=0; i<args.size(); i++){
         if(is_type(args[i], tp_star_wrapper)){
@@ -811,7 +819,7 @@ void VM::unpack_args(Args& args){
 using Super = std::pair<PyObject*, Type>;
 
 // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
-PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err, bool class_only){
+inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err, bool class_only){
     PyObject* objtype = _t(obj);
     // handle super() proxy
     if(is_type(obj, tp_super)){
@@ -842,12 +850,12 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err, bool class_on
 }
 
 template<typename T>
-void VM::setattr(PyObject* obj, StrName name, T&& value){
+inline void VM::setattr(PyObject* obj, StrName name, T&& value){
     static_assert(std::is_same_v<std::decay_t<T>, PyObject*>);
     PyObject* objtype = _t(obj);
     // handle super() proxy
     if(is_type(obj, tp_super)){
-        Super& super = OBJ_GET(Super, *obj);
+        Super& super = OBJ_GET(Super, obj);
         obj = super.first;
         objtype = _t(super.second);
     }
@@ -881,7 +889,7 @@ void VM::bind_func(PyObject* obj, Str name, NativeFuncRaw fn) {
     obj->attr().set(name, VAR(NativeFunc(fn, ARGC, false)));
 }
 
-void VM::_error(Exception e){
+inline void VM::_error(Exception e){
     if(callstack.empty()){
         e.is_re = false;
         throw e;
@@ -890,7 +898,7 @@ void VM::_error(Exception e){
     _raise();
 }
 
-PyObject* VM::_exec(){
+inline PyObject* VM::_exec(){
     Frame* frame = top_frame();
     i64 base_id = frame->id;
     PyObject* ret = nullptr;

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů