aboutsummaryrefslogtreecommitdiff
path: root/std/prelude
diff options
context:
space:
mode:
authorJJ2023-12-31 01:41:19 +0000
committerJJ2023-12-31 01:41:19 +0000
commitbf580bb5580d48e6c2a59ffe094f0edc391d7690 (patch)
treef23f5123dd234a40402ea30e314a88b5b7c6a046 /std/prelude
parentb8445b011d9b2a287af0e014998c42525a7fd315 (diff)
std: initial draft of strings and lists
Diffstat (limited to 'std/prelude')
-rw-r--r--std/prelude/lists.pk109
-rw-r--r--std/prelude/strings.pk100
2 files changed, 209 insertions, 0 deletions
diff --git a/std/prelude/lists.pk b/std/prelude/lists.pk
new file mode 100644
index 0000000..410cfed
--- /dev/null
+++ b/std/prelude/lists.pk
@@ -0,0 +1,109 @@
+## std.lists: Dynamic arrays.
+## 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
+ capacity: int
+ length: int
+
+## 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 }
+
+## Gets the length of a list.
+pub func len[T](self: list[T]): uint =
+ self.length
+
+pub func empty[T](self: list[T]): bool =
+ self.length == 0
+
+## Gets the internal capacity of a list.
+func cap[T](self: list[T]): uint =
+ self.capacity
+
+## Expands the capacity of a list.
+func grow[T](self: mut list[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
+
+## 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]) =
+ ...
+
+## Removes & returns an element from the end of a list, if it exists.
+pub func pop[T](self: mut list[T]): T? =
+ if self.length == 0:
+ None
+ unsafe:
+ self.length -= 1
+ Some(self.data.raw_get[T](self.length)) # fixme
+ # unsafe { Some(ptr::read(self.ptr().add(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? =
+ ...
+
+## 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) =
+ ...
+
+## Inserts a value at a location and shifts elements of the list accordingly.
+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;
+ # }
+
+## 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:
+ 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
+ # }
+
+## Gets the last element of a list, if it exists.
+pub func last[T](self: list[T]): lent T? =
+ self.get(self.len - 1)
+
+# todo: iteration...
+# todo: destructors...
+# todo: syntax for inlining + other pragmas... as a macro, perhaps?
+# todo: slices
+
+type slice[T] = struct
+ data: ptr[T] # hrm...
+ length: uint
diff --git a/std/prelude/strings.pk b/std/prelude/strings.pk
new file mode 100644
index 0000000..c2b0518
--- /dev/null
+++ b/std/prelude/strings.pk
@@ -0,0 +1,100 @@
+## std.strings: The standard implementation of strings.
+## This module is imported by default.
+# reference: https://doc.rust-lang.org/std/string/struct.String.html
+
+use std.pointers
+
+# possible approaches: list[byte], distinct list[byte], this
+# should *really* just rely on lists, i don't want to duplicate slicing logic, but... maybe...
+type str = struct
+ data: ptr[byte]
+ length: uint
+ capacity: uint
+
+## Initialize and return an empty string.
+pub func init(): str =
+ ...
+
+## Gets the length of a string.
+pub func len(self: str): uint =
+ self.length
+
+pub func empty(self: str): bool =
+ self.length == 0
+
+## Gets the internal capacity of a string.
+func cap(self: str): uint =
+ self.capacity
+
+## Expands the capacity of a string.
+func grow(self: mut str) =
+ ...
+
+## Pushes a character to the end of a mutable string.
+pub func push(self: mut str, val: chr) = # todo: `add` alias?
+ ...
+
+## Pushes an owned string to the end of a mutable string.
+pub func push(self: mut str, val: str) =
+ ...
+
+## Removes and returns the last character of a string, if it exists.
+pub func pop(self: mut str): chr? =
+ ...
+
+## Returns the character at the provided index, if it exists.
+pub func get(self: str, i: uint): chr? =
+ ...
+
+## Sets the character at the provided index, if it exists.
+## todo: what if it does not exist?
+pub func set(self: mut str, i: uint, val: chr) =
+ ...
+
+## Inserts a character at an arbitrary position within a string.
+## Error handling: todo
+pub func insert(self: mut str, i: uint, val: chr) =
+ ...
+
+## Removes and returns a character at an arbitrary position within a string.
+## Panics on failure.
+pub func remove(self: mut str, i: uint): chr =
+ ...
+
+## Returns the *byte* at an arbitrary position within a string.
+## Explicitly distinct from `get` as this breaks safety conventions idk
+pub func get_byte(self: str): byte =
+ ...
+
+## Sets a byte at the provided index, if it exists. Do we want this?
+pub func set_byte(self: mut str, i: uint, val: byte) =
+ ...
+
+## Inserts a byte into a string. Breaks string convention. Do we want this?
+pub func insert_byte(self: mut str, i: uint, val: byte) =
+ ...
+
+## Removes a byte at a given offset from a string. Do we want this?
+pub func remove_byte(self: mut str, i: uint): byte? =
+ ...
+
+## Converts a given string to a list of bytes for iteration purposes.
+pub func bytes(self: str): list[byte] =
+ ... # many performance considerations
+
+## Converts a given string to a list of chars for iteration purposes.
+pub func chars(self: str): list[chr] # todo: useful?
+
+## The concatenation operator.
+pub func &(a: str, b: str): str =
+ ...
+
+## Syntatic sugar for sring appending.
+pub func &=(a: mut str, b: owned str) =
+ a.push(b)
+
+# todo: many things
+
+# pub func iter(self: str): StrIter
+# pub func next(self: mut StrIter)
+# pub func peek(self: mut StrIter)