aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/lists.pk
diff options
context:
space:
mode:
authorJJ2024-05-10 01:00:01 +0000
committerJJ2024-05-10 02:41:52 +0000
commit073c902a31936c2b53d89245662fb272c9670169 (patch)
treea8789ed4561dc4c3dde84489a600272cbd5f806b /std/prelude/lists.pk
parent51c8b349a77a8d8b1b34ce8e03518dad6e3cba00 (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.pk128
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...