blueloveTH 3 лет назад
Родитель
Сommit
22b0d46c73
6 измененных файлов с 50 добавлено и 34 удалено
  1. 1 2
      src/compiler.h
  2. 38 22
      src/memory.h
  3. 1 1
      src/obj.h
  4. 6 6
      src/parser.h
  5. 2 1
      src/pocketpy.h
  6. 2 2
      src/vm.h

+ 1 - 2
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;

+ 38 - 22
src/memory.h

@@ -2,6 +2,8 @@
 
 #include "common.h"
 
+struct PyObject;
+
 namespace pkpy{
     template<typename T>
     struct SpAllocator {
@@ -21,22 +23,38 @@ namespace pkpy{
         int* counter;
 
         inline T* _t() const {
-            if(is_tagged()) UNREACHABLE();
+            if constexpr(std::is_same_v<T, PyObject>){
+                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<T>::dealloc(counter); } }
+
+        inline void _inc_counter() const {
+            if constexpr(std::is_same_v<T, PyObject>){
+                if(is_tagged()) return;
+            }
+            if(counter) ++(*counter);
+        }
+
+        inline void _dec_counter() const {
+            if constexpr(std::is_same_v<T, PyObject>){
+                if(is_tagged()) return;
+            }
+            if(counter && --(*counter) == 0){
+                SpAllocator<T>::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 <typename __VAL>
-        inline __VAL cast() const { return reinterpret_cast<__VAL>(counter); }
+        inline __VAL cast() const {
+            static_assert(std::is_same_v<T, PyObject>, "T must be PyObject");
+            return reinterpret_cast<__VAL>(counter);
+        }
 
-        inline bool is_tagged() const { return (cast<std::uintptr_t>() & 0b11) != 0b00; }
-        inline bool is_tag_00() const { return (cast<std::uintptr_t>() & 0b11) == 0b00; }
-        inline bool is_tag_01() const { return (cast<std::uintptr_t>() & 0b11) == 0b01; }
-        inline bool is_tag_10() const { return (cast<std::uintptr_t>() & 0b11) == 0b10; }
-        inline bool is_tag_11() const { return (cast<std::uintptr_t>() & 0b11) == 0b11; }
+        inline bool is_tagged() const { return (cast<i64>() & 0b11) != 0b00; }
+        inline bool is_tag_00() const { return (cast<i64>() & 0b11) == 0b00; }
+        inline bool is_tag_01() const { return (cast<i64>() & 0b11) == 0b01; }
+        inline bool is_tag_10() const { return (cast<i64>() & 0b11) == 0b10; }
+        inline bool is_tag_11() const { return (cast<i64>() & 0b11) == 0b11; }
     };
 
     template <typename T, typename U, typename... Args>
     shared_ptr<T> make_shared(Args&&... args) {
         static_assert(std::is_base_of_v<T, U>, "U must be derived from T");
         static_assert(std::has_virtual_destructor_v<T>, "T must have virtual destructor");
+        static_assert(!std::is_same_v<T, PyObject> || (!std::is_same_v<U, i64> && !std::is_same_v<U, f64>));
         int* p = SpAllocator<T>::template alloc<U>(); *p = 1;
         new(p+1) U(std::forward<Args>(args)...);
         return shared_ptr<T>(p);
@@ -109,4 +122,7 @@ namespace pkpy{
         new(p+1) T(std::forward<Args>(args)...);
         return shared_ptr<T>(p);
     }
-};
+};
+
+static_assert(sizeof(i64) == sizeof(pkpy::shared_ptr<PyObject>));
+static_assert(sizeof(f64) == sizeof(pkpy::shared_ptr<PyObject>));

+ 1 - 1
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;
     }
 }
 

+ 6 - 6
src/parser.h

@@ -48,14 +48,14 @@ const emhash8::HashMap<std::string_view, TokenIndex> 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";

+ 2 - 1
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);
     });

+ 2 - 2
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<i64>();
-        return __8B(_int)._float;
+        return __8B(_int & 0b00)._float;
     }
 
     DEF_NATIVE(List, pkpy::List, tp_list)