diff options
author | JJ | 2024-05-10 01:00:01 +0000 |
---|---|---|
committer | JJ | 2024-05-10 02:41:52 +0000 |
commit | 073c902a31936c2b53d89245662fb272c9670169 (patch) | |
tree | a8789ed4561dc4c3dde84489a600272cbd5f806b /std/prelude/lists.pk | |
parent | 51c8b349a77a8d8b1b34ce8e03518dad6e3cba00 (diff) |
std: sweeping changes.
- replace interfaces with classes
- replace : with then and do
- solidify memory management as rust-style ownership
- replace unsafe blocks with safe/unsafe attributes
- add magic and copy attributes
- switch Coerce impl from from to to
Diffstat (limited to 'std/prelude/lists.pk')
-rw-r--r-- | std/prelude/lists.pk | 128 |
1 files changed, 68 insertions, 60 deletions
diff --git a/std/prelude/lists.pk b/std/prelude/lists.pk index 1e8dee5..57de91b 100644 --- a/std/prelude/lists.pk +++ b/std/prelude/lists.pk @@ -2,105 +2,113 @@ ## This module is imported by default. # reference: https://doc.rust-lang.org/nomicon/vec/vec.html -use std.pointers - -## The list type. -type list[T] = struct - data: unique[T] # hrm +## The fundamental list type. Heap-allocated. +## Equivalent to Vec<T> in other languages. +@[unsafe] # unsafe on a struct tells us raw field access breaks invariants. +pub type list[T] = struct + data: ptr T capacity: int length: int +## A transparent, common alias for a list of bytes. +pub type bytes = list[byte] + ## Initialize and return an empty list with inner type T. -pub func init[T](): list[T] = - ... # malloc? idk - let (data, ) - { data: , capacity: 0, length: 0 } +pub func init[T]: list[T] = + { data = nil, capacity = 0, length = 0 } # fixme: nil!!!!! ## Gets the length of a list. -pub func len[T](self: list[T]): uint = +@[inline] # idk what to do with attributes +pub func len[T](self: lent list[T]): uint = self.length -pub func empty[T](self: list[T]): bool = +pub func empty[T](self: lent list[T]): bool = self.length == 0 ## Gets the internal capacity of a list. -func cap[T](self: list[T]): uint = +func cap[T](self: lent list[T]): uint = self.capacity ## Expands the capacity of a list. +@[safe] func grow[T](self: mut list[T]) = - ... + self.capacity = max(self.length + 1, self.capacity * 2) + self.data = self.data.realloc(self.capacity * sizeof(T)) ## Pushes a new element to the end of a list. -pub func push[T](self: mut list[T], val: owned T) = - if self.length == self.capacity: - self.grow() - unsafe: # todo: do we want unsafe blocks, as they are in rust? - self.data.raw_set(self.length, val) # fixme - # unsafe { ptr::write(self.ptr().add(self.length), val); } - self.length += 1 +@[safe] +pub func push[T](self: mut list[T], val: T) = + if self.capacity == self.length then self.grow() + self.data.set(val, offset = self.length) + self.length += 1 ## Takes ownership of and pushes all the values of a list into another list. -pub func push[T](self: mut list[T], val: owned list[T]) = - ... +pub func push[T](self: mut list[T], values: list[T]) = + for val in values do + self.push(val) ## Removes & returns an element from the end of a list, if it exists. +@[safe] pub func pop[T](self: mut list[T]): T? = - if self.length == 0: + if self.length == 0 then None - unsafe: + else self.length -= 1 - Some(self.data.raw_get[T](self.length)) # fixme - # unsafe { Some(ptr::read(self.ptr().add(self.length))) } + Some(self.data.get(offset = self.length)) ## Returns a reference to an element of a list, if in range. -pub func get[T](self: list[T], i: uint): lent T? = - ... +@[safe] +pub func get[T](self: lent list[T], i: uint): lent T? = + if i > self.length then + None + else # fixme: interior mutability + Some(lent self.data.get(offset = i)) +## Returns a mutable reference to an element of a list, if in range. +@[safe] +pub func get[T](self: mut list[T], i: uint): mut T? = + if i > self.length then + None + else # fixme: interior mutability + Some(mut self.data.get(offset = i)) -## Sets the element of a list to a value. todo: when is `val` owned? -## todo: how do we deal with having the wrong offset? -pub func set[T](self: mut list[T], i: uint, val: owned T) = - ... +## Sets the element of a list to a value. +@[safe] +pub func set[T](self: mut list[T], i: uint, val: T) = + assert i <= self.length, "index out of bounds" + Okay(self.data.set(offset = i, val)) ## Inserts a value at a location and shifts elements of the list accordingly. +@[safe] pub func insert[T](self: mut list[T], i: uint, val: T) = assert i <= self.length, "index out of bounds" - if self.cap == self.len: - self.grow() - ... - # unsafe { - # ptr::copy( - # self.ptr().add(index), - # self.ptr().add(index + 1), - # self.len - index, - # ); - # ptr::write(self.ptr().add(index), elem); - # self.len += 1; - # } + if self.capacity == self.length then self.grow() + self.data.offset(i).copy(self.data.offset(i + 1), self.length - i) + self.data.set(i, val) + self.length += 1 +## Inserts a list of values at a location and shifts elements of the list accordingly. +pub func insert[T](self: mut list[T], i: uint, vals: list[T]) = + for val in vals.rev: # inserting backwards avoids counting + self.insert(val, i) ## Removes a value at a location and shifts elements of the list accordingly. -pub func remove[T](self: mut list[T], i: uint): T = - assert index < self.length, "index out of bounds" - unsafe: +@[safe] +pub func remove[T](self: mut list[T], i: uint): T? = + if index < self.length then None + else self.length -= 1 - result = ... - # unsafe { - # self.len -= 1; - # let result = ptr::read(self.ptr().add(index)); - # ptr::copy( - # self.ptr().add(index + 1), - # self.ptr().add(index), - # self.len - index, - # ); - # result - # } + let res = self.data.get(i) + self.data.offset(i + 1).copy(self.data.offset(i), self.length - i) + res ## Gets the last element of a list, if it exists. -pub func last[T](self: list[T]): lent T? = +pub func last[T](self: lent list[T]): lent T? = + self.get(self.len - 1) +## Gets the last element of a list mutably, if it exists. +pub func last[T](self: mut list[T]): mut T? = self.get(self.len - 1) # todo: many questions. owned? how does it not free? -pub func iter[T](self: owned list[T]): ListIter[T] = +pub func iter[T](self: list[T]): ListIter[T] = ... # todo: iteration... |