diff --git a/src/compiler.h b/src/compiler.h index 73bbb5ad..e20ad5c5 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -189,8 +189,7 @@ private: void _lex_token() { parser->prev = parser->curr; parser->curr = parser->next_token(); - - //Str _info = parser->curr.info(); std::cout << _info << '[' << parser->current_line << ']' << std::endl; + //std::cout << parser->curr.info() << std::endl; while (parser->peekchar() != '\0') { parser->token_start = parser->curr_char; diff --git a/src/memory.h b/src/memory.h index ed295d6b..8f807b79 100644 --- a/src/memory.h +++ b/src/memory.h @@ -2,6 +2,8 @@ #include "common.h" +struct PyObject; + namespace pkpy{ template struct SpAllocator { @@ -21,22 +23,38 @@ namespace pkpy{ int* counter; inline T* _t() const { - if(is_tagged()) UNREACHABLE(); + if constexpr(std::is_same_v){ + if(is_tagged()) UNREACHABLE(); + } return (T*)(counter + 1); } - inline void _inc_counter() const { if(counter) ++(*counter); } - inline void _dec_counter() const { if(counter && --(*counter) == 0){ SpAllocator::dealloc(counter); } } + + inline void _inc_counter() const { + if constexpr(std::is_same_v){ + if(is_tagged()) return; + } + if(counter) ++(*counter); + } + + inline void _dec_counter() const { + if constexpr(std::is_same_v){ + if(is_tagged()) return; + } + if(counter && --(*counter) == 0){ + SpAllocator::dealloc(counter); + } + } public: shared_ptr() : counter(nullptr) {} shared_ptr(int* counter) : counter(counter) {} shared_ptr(const shared_ptr& other) : counter(other.counter) { - if(!is_tagged()) _inc_counter(); + _inc_counter(); } shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) { other.counter = nullptr; } - ~shared_ptr() { if(!is_tagged()) _dec_counter(); } + ~shared_ptr() { _dec_counter(); } bool operator==(const shared_ptr& other) const { return counter == other.counter; } bool operator!=(const shared_ptr& other) const { return counter != other.counter; } @@ -48,10 +66,6 @@ namespace pkpy{ bool operator!=(std::nullptr_t) const { return counter != nullptr; } shared_ptr& operator=(const shared_ptr& other) { - if(is_tagged()) { - counter = other.counter; - return *this; - } _dec_counter(); counter = other.counter; _inc_counter(); @@ -59,11 +73,6 @@ namespace pkpy{ } shared_ptr& operator=(shared_ptr&& other) noexcept { - if(is_tagged()) { - counter = other.counter; - other.counter = nullptr; - return *this; - } _dec_counter(); counter = other.counter; other.counter = nullptr; @@ -80,24 +89,28 @@ namespace pkpy{ } void reset(){ - if(!is_tagged()) _dec_counter(); + _dec_counter(); counter = nullptr; } template - inline __VAL cast() const { return reinterpret_cast<__VAL>(counter); } + inline __VAL cast() const { + static_assert(std::is_same_v, "T must be PyObject"); + return reinterpret_cast<__VAL>(counter); + } - inline bool is_tagged() const { return (cast() & 0b11) != 0b00; } - inline bool is_tag_00() const { return (cast() & 0b11) == 0b00; } - inline bool is_tag_01() const { return (cast() & 0b11) == 0b01; } - inline bool is_tag_10() const { return (cast() & 0b11) == 0b10; } - inline bool is_tag_11() const { return (cast() & 0b11) == 0b11; } + inline bool is_tagged() const { return (cast() & 0b11) != 0b00; } + inline bool is_tag_00() const { return (cast() & 0b11) == 0b00; } + inline bool is_tag_01() const { return (cast() & 0b11) == 0b01; } + inline bool is_tag_10() const { return (cast() & 0b11) == 0b10; } + inline bool is_tag_11() const { return (cast() & 0b11) == 0b11; } }; template shared_ptr make_shared(Args&&... args) { static_assert(std::is_base_of_v, "U must be derived from T"); static_assert(std::has_virtual_destructor_v, "T must have virtual destructor"); + static_assert(!std::is_same_v || (!std::is_same_v && !std::is_same_v)); int* p = SpAllocator::template alloc(); *p = 1; new(p+1) U(std::forward(args)...); return shared_ptr(p); @@ -109,4 +122,7 @@ namespace pkpy{ new(p+1) T(std::forward(args)...); return shared_ptr(p); } -}; \ No newline at end of file +}; + +static_assert(sizeof(i64) == sizeof(pkpy::shared_ptr)); +static_assert(sizeof(f64) == sizeof(pkpy::shared_ptr)); \ No newline at end of file diff --git a/src/obj.h b/src/obj.h index b8b8c8bd..c3f5cb27 100644 --- a/src/obj.h +++ b/src/obj.h @@ -116,7 +116,7 @@ inline bool is_type(const PyVar& obj, Type type) noexcept { switch(type.index){ case kTpIntIndex: return obj.is_tag_01(); case kTpFloatIndex: return obj.is_tag_10(); - default: return obj->type == type; + default: return !obj.is_tagged() && obj->type == type; } } diff --git a/src/parser.h b/src/parser.h index d16d8ba7..48baf435 100644 --- a/src/parser.h +++ b/src/parser.h @@ -48,14 +48,14 @@ const emhash8::HashMap kTokenKwMap = [](){ struct Token{ TokenIndex type; - const char* start; //< Begining of the token in the source. - int length; //< Number of chars of the token. - int line; //< Line number of the token (1 based). - PyVar value; //< Literal value of the token. + const char* start; + int length; + int line; + PyVar value; - const Str str() const { return Str(start, length);} + Str str() const { return Str(start, length);} - const Str info() const { + Str info() const { StrStream ss; Str raw = str(); if (raw == Str("\n")) raw = "\\n"; diff --git a/src/pocketpy.h b/src/pocketpy.h index eb5b74ea..c69bbf2b 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -132,8 +132,9 @@ void init_builtins(VM* _vm) { _vm->bind_method<0>("object", "__repr__", [](VM* vm, pkpy::Args& args) { PyVar self = args[0]; + std::uintptr_t addr = self.is_tagged() ? 0 : (uintptr_t)self.get(); StrStream ss; - ss << std::hex << (uintptr_t)self.get(); + ss << std::hex << addr; Str s = "<" + OBJ_NAME(vm->_t(self)) + " object at 0x" + ss.str() + ">"; return vm->PyStr(s); }); diff --git a/src/vm.h b/src/vm.h index 363a7fa5..bcdfa366 100644 --- a/src/vm.h +++ b/src/vm.h @@ -221,7 +221,7 @@ public: *_stderr << e.summary() << '\n'; } catch (const std::exception& e) { - *_stderr << "A std::exception occurred! It may be a bug, please report it!!\n"; + *_stderr << "An std::exception occurred! It could be a bug.\n"; *_stderr << e.what() << '\n'; } callstack = {}; @@ -576,7 +576,7 @@ public: inline f64 PyFloat_AS_C(const PyVar& obj){ check_type(obj, tp_float); i64 _int = obj.cast(); - return __8B(_int)._float; + return __8B(_int & 0b00)._float; } DEF_NATIVE(List, pkpy::List, tp_list)