unit std.list; // A growable sequence. The buffer is owned, so a List owns its elements and // releasing it releases them (SPEC 5 R1) -- which is also why there is no // `drop` here: letting go of a List lets go of its buffer on its own. Growth // doubles, which keeps the total copying proportional to the number of // pushes. pub struct List(T) { items: ^[]mut T, len: usize, pub fn with_capacity(n: usize) -> !Self { let room: ^[]mut T = try mem.alloc_slice(T, n); return Self{ items: room, len: 0 }; } pub fn count(self: &Self) -> usize { return self.len; } pub fn at(self: &Self, i: usize) -> T { return self.items.^[i]; } pub fn set(self: &mut Self, i: usize, v: T) -> void { self.items.^[i] = v; } pub fn push(self: &mut Self, v: T) -> !void { if self.len == self.items.^.n { try self.grow(); } self.items.^[self.len] = v; self.len = self.len + 1; return; } /// Take the last one off. Nothing to take is `null`, not a trap. pub fn pop(self: &mut Self) -> ?T { if self.len == 0 { return null; } self.len = self.len - 1; return self.items.^[self.len]; } /// Move one out and leave `replacement` where it was (SPEC 5 R7). This is /// how a `T` that owns something leaves the list without the list ending /// up with a hole in it. pub fn take(self: &mut Self, i: usize, replacement: T) -> T { return mem.replace(&mut self.items.^[i], replacement); } /// Exchange two elements. pub fn swap(self: &mut Self, i: usize, j: usize) -> void { if i == j { return; } let first: T = self.items.^[i]; let second: T = mem.replace(&mut self.items.^[j], first); self.items.^[i] = second; return; } /// The elements as a slice, so `for x in xs.slice()` walks them. R8(a): /// derived from `self`, so the borrow belongs to the caller. pub fn slice(self: &Self) -> []T { return self.items.^[0..self.len]; } pub fn slice_mut(self: &mut Self) -> []mut T { return self.items.^[0..self.len]; } /// Forget the elements and keep the buffer. pub fn clear(self: &mut Self) -> void { self.len = 0; return; } /// Move to a buffer twice the size. Kept apart from `push` because the /// borrow that hands over the old buffer must not be live while the old /// buffer is still being read (SPEC 5 R6). fn grow(self: &mut Self) -> !void { var room: usize = self.items.^.n * 2; if room == 0 { room = 4; } let bigger: ^[]mut T = try mem.alloc_slice(T, room); var i: usize = 0; while i < self.len { bigger.^[i] = self.items.^[i]; i = i + 1; } let old: ^[]mut T = mem.replace(&mut self.items, bigger); mem.destroy(old); return; } }