import memhub import string class list[T]: """Heap-allocated dynamic list container backed by memhub.MemManager polymorphic allocator. Usage: pool: memhub.MemManager = memhub.MemBuddy(arena, arena_size) nums: list[int] = list[int](pool) nums.append(42) x: int = nums.get(0) For pointer types (e.g. AST*), pass elem_size=8 to avoid object slicing: lst: list[AST*] = list[AST*](pool, 8) """ __data__: rawptr __count__: sizet __capacity__: sizet __pool__: memhub.MemManager* __elem_size__: sizet __iter_index__: sizet def __new__(self, pool: memhub.MemManager*, elem_size: sizet = 0): ret = pool.alloc(48) return ret def __init__(self, pool: memhub.MemManager*, elem_size: sizet = 0): self.__pool__ = pool self.__count__ = 0 self.__capacity__ = 8 if elem_size == 0: self.__elem_size__ = T.__sizeof__() else: self.__elem_size__ = elem_size self.__data__ = memhub.MemAllocTagged(pool, self.__capacity__ * self.__elem_size__, memhub.DETSITE_LIST_43) self.__iter_index__ = 0 def __len__(self) -> sizet: return self.__count__ def append(self, item: T): if self.__count__ >= self.__capacity__: new_cap: sizet = self.__capacity__ * 2 new_data: rawptr = self.__pool__.alloc(new_cap * self.__elem_size__) if new_data == None: return string.memcpy(new_data, self.__data__, self.__count__ * self.__elem_size__) self.__data__ = new_data self.__capacity__ = new_cap # Element address: `T*(self.__data__ + i * elem_size)`. rawptr is i8* and `+` scales by 1 byte, byte-identical to the old uint64(ptr)+n form (no integer round-trip). # The stride is explicit via __elem_size__; do not use indexing (`__data__[i]` scales by sizeof(T)) since list[int](pool, 8) / list[str](pool, 64) rely on the explicit byte stride. Same form below (get/set/__getitem__/__setitem__/pop/__next__). elem_ptr: T* = T*(self.__data__ + self.__count__ * self.__elem_size__) *elem_ptr = item self.__count__ += 1 def get(self, index: sizet) -> T: elem_ptr: T* = T*(self.__data__ + index * self.__elem_size__) return *elem_ptr def __getitem__(self, index: sizet) -> T: elem_ptr: T* = T*(self.__data__ + index * self.__elem_size__) return *elem_ptr def set(self, index: sizet, value: T): elem_ptr: T* = T*(self.__data__ + index * self.__elem_size__) *elem_ptr = value def __setitem__(self, index: sizet, value: T): elem_ptr: T* = T*(self.__data__ + index * self.__elem_size__) *elem_ptr = value def pop(self) -> T: self.__count__ -= 1 elem_ptr: T* = T*(self.__data__ + self.__count__ * self.__elem_size__) return *elem_ptr def clear(self): self.__count__ = 0 def __iter__(self) -> list[T]*: self.__iter_index__ = 0 return self def __next__(self) -> T: if self.__iter_index__ >= self.__count__: raise StopIteration idx: sizet = self.__iter_index__ self.__iter_index__ = idx + 1 elem_ptr: T* = T*(self.__data__ + idx * self.__elem_size__) return *elem_ptr