import "./core.zc" import "./iter.zc" struct Vec { data: T*; len: usize; cap: usize; } struct VecIter { data: T*; count: usize; idx: usize; } struct VecIterResult { ptr: T*; } impl VecIterResult { fn is_none(self) -> bool { return self.ptr == 0; } fn unwrap(self) -> T* { if (self.ptr == 0) { !"Panic: unwrap called on null VecIterResult"; exit(1); } return self.ptr; } } struct VecIterRef { data: T*; count: usize; idx: usize; } impl VecIter { fn next(self) -> Option { if (self.idx < self.count) { let item = self.data[self.idx]; self.idx = self.idx + 1; return Option::Some(item); } return Option::None(); } fn iterator(self) -> VecIter { return *self; } } impl VecIterRef { fn next(self) -> VecIterResult { if (self.idx < self.count) { let item = &self.data[self.idx]; self.idx = self.idx + 1; return VecIterResult { ptr: item }; } return VecIterResult { ptr: 0 }; } fn iterator(self) -> VecIterRef { return *self; } } impl Vec { fn new() -> Vec { return Vec { data: 0, len: 0, cap: 0 }; } fn with_capacity(cap: usize) -> Vec { if (cap == 0) { return Vec { data: 0, len: 0, cap: 0 }; } return Vec { data: (T*)malloc(cap * sizeof(T)), len: 0, cap: cap }; } fn grow(self) { if (self.cap == 0) { self.cap = 8; } else { self.cap = self.cap * 2; } self.data = (T*)realloc(self.data, self.cap * sizeof(T)); } fn grow_to_fit(self, new_len: usize) { if self.cap >= new_len { return; } if (self.cap == 0) { self.cap = 8; } while self.cap < new_len { self.cap = self.cap * 2; } self.data = (T*)realloc(self.data, self.cap * sizeof(T)); } fn iterator(self) -> VecIter { return VecIter { data: self.data, count: self.len, idx: 0 }; } fn iter_ref(self) -> VecIterRef { return VecIterRef { data: self.data, count: self.len, idx: 0 }; } fn push(self, item: T) { if (self.len >= self.cap) { self.grow(); } self.data[self.len] = item; self.len = self.len + 1; } fn insert(self, idx: usize, item: T) { if (idx > self.len) { !"Panic: Insert index out of bounds"; exit(1); } if (self.len >= self.cap) { self.grow(); } // Shift elements right if (idx < self.len) { memmove(self.data + idx + 1, self.data + idx, (self.len - idx) * sizeof(T)); } self.data[idx] = item; self.len = self.len + 1; } fn pop(self) -> T { if (self.len == 0) { !"Panic: pop called on empty Vec"; exit(1); } self.len = self.len - 1; return self.data[self.len]; } fn pop_opt(self) -> Option { if (self.len == 0) { return Option::None(); } self.len = self.len - 1; return Option::Some(self.data[self.len]); } fn remove(self, idx: usize) -> T { if (idx >= self.len) { !"Panic: Remove index out of bounds"; exit(1); } let item = self.data[idx]; // Shift elements left if (idx < self.len - 1) { memmove(self.data + idx, self.data + idx + 1, (self.len - idx - 1) * sizeof(T)); } self.len = self.len - 1; return item; } fn append(self, other: Vec) { let new_len = self.len + other.len; self.grow_to_fit(new_len); memcpy(self.data + self.len, other.data, other.len * sizeof(T)); self.len = new_len; } fn get(self, idx: usize) -> T { if (idx >= self.len) { !"Panic: Index out of bounds"; exit(1); } return self.data[idx]; } fn get_ref(self, idx: usize) -> T* { if (idx >= self.len) { !"Panic: Index out of bounds"; exit(1); } return &self.data[idx]; } fn last(self) -> T { if (self.len == 0) { !"Panic: last called on empty Vec"; exit(1); } return self.data[self.len - 1]; } fn length(self) -> usize { return self.len; } fn contains(self, item: T) -> bool { let i: usize = 0; while i < self.len { if memcmp(&self.data[i], &item, sizeof(T)) == 0 { return true; } i++; } return false; } fn is_empty(self) -> bool { return self.len == 0; } fn clear(self) { self.len = 0; } fn free(self) { if (self.data) free(self.data); self.data = 0; self.len = 0; self.cap = 0; } fn first(self) -> T { if (self.len == 0) { !"Panic: first called on empty Vec"; exit(1); } return self.data[0]; } fn set(self, idx: usize, item: T) { if (idx >= self.len) { !"Panic: set index out of bounds"; exit(1); } self.data[idx] = item; } fn reverse(self) { let i: usize = 0; let j = self.len - 1; while i < j { let tmp = self.data[i]; self.data[i] = self.data[j]; self.data[j] = tmp; i++; j--; } } fn eq(self, other: Vec) -> bool { if self.len != other.len { return false; } let i: usize = 0; while i < self.len { if memcmp(&self.data[i], &other.data[i], sizeof(T)) != 0 { return false; } i = i + 1; } return true; } // Prevent Drop from freeing memory (simulates move) fn forget(self) { self.data = 0; self.len = 0; self.cap = 0; } fn clone(self) -> Vec { if (self.len == 0) { return Vec { data: 0, len: 0, cap: 0 }; } let new_data = (T*)malloc(self.len * sizeof(T)); let i: usize = 0; while i < self.len { new_data[i] = self.data[i]; i = i + 1; } return Vec { data: new_data, len: self.len, cap: self.len // Set capacity to exact length }; // No local Vec variable means no Drop is called here. } } impl Drop for Vec { fn drop(self) { self.free(); } }