aboutsummaryrefslogtreecommitdiff
path: root/std/default
diff options
context:
space:
mode:
authorJJ2023-10-23 02:34:17 +0000
committerJJ2023-10-23 02:34:17 +0000
commitd5f89ba0e2fd0458f4e51e13233069583d5a89ac (patch)
tree658019acfbd5cec5c5944accb95d0fde618da050 /std/default
parent2d5d47c89d5b9df3535029f04cf1205e47276451 (diff)
std: broad updates; add ast, iterators, format, tests, logs
Diffstat (limited to 'std/default')
-rw-r--r--std/default/format.pk51
-rw-r--r--std/default/iterators.pk38
-rw-r--r--std/default/options.pk18
-rw-r--r--std/default/results.pk22
4 files changed, 111 insertions, 18 deletions
diff --git a/std/default/format.pk b/std/default/format.pk
new file mode 100644
index 0000000..c7d7ab8
--- /dev/null
+++ b/std/default/format.pk
@@ -0,0 +1,51 @@
+## std/format: Niceties around printing and debugging.
+## This module is imported by default.
+
+## The Display interface. Any type implementing `str` is printable.
+## Any type that is Display must also implement Debug.
+pub type Display = interface
+ str(Self): str
+ dbg(Self): str
+
+## The Debug interface. Broadly implemented for every type with magic,
+## types can (and should) override the generic implementations.
+pub type Debug = interface
+ dbg(Self): str
+
+## Prints all of its arguments to the command line.
+pub func print(params: varargs[Display]) =
+ stdout.write(params.map(x => x.str).join(" "), "\n")
+
+## Prints all of its arguments to the command line, in Debug form.
+pub func dbg(params: varargs[Debug]) =
+ stdout.write(params.map(x => x.dbg).join(" "), "\n")
+
+## A dummy implementation of the Display interface for strings.
+pub func str(self: str): str = self
+## An implementation of the Debug interface for strings.
+pub func dbg(self: str): str = "\"" & self & "\""
+
+## An implementation of the Debug interface for all structs.
+## Uses the special `struct` typeclass.
+pub func dbg(self: struct): str =
+ "{" & self.fields.map(field => field.id & field.value.dbg) & "}"
+
+## An implementation of the Debug interface for all tuples.
+## Uses the special `tuple` typeclass.
+pub func dbg(self: tuple): str =
+ result &= "("
+ for i, field in self.fields.enumerate():
+ result &= field.id.map(id => id & " = ").get_or("")
+ if i != self.fields.len:
+ result &= ", "
+ result &= ")"
+
+## An implementation of the Debug interface for all arrays and lists.
+pub func dbg(self: Iter[Debug]): str =
+ "[" & self.map(x => x.str).join(", ") & "]"
+
+## The fmt macro. Builds a formatted string from its arguments.
+pub macro fmt(formatted: static[str], args: varargs[Display]) =
+ # if not formatted of String:
+ # macro_error("fmt must take a static string parameter!")
+ ...
diff --git a/std/default/iterators.pk b/std/default/iterators.pk
new file mode 100644
index 0000000..f97c61a
--- /dev/null
+++ b/std/default/iterators.pk
@@ -0,0 +1,38 @@
+## std/iterators: The Iter interface and associated functions.
+## This module is imported by default.
+
+## The Iter interface. Any type implementing `next()` is iterable.
+pub type Iter[T] = interface
+ next(mut Self): Option[T]
+
+# todo: useful functions for an iterator
+# https://doc.rust-lang.org/std/iter/trait.Iterator.html#provided-methods
+
+pub func advance_by[T](self: Iter[T], n: uint): Result[T, ...] =
+ for i in 0 .. n:
+ if self.next().is_none():
+ return Error(...)
+ Okay
+
+pub func get[T](self: Iter[T], at: uint): Option[T]
+ self.advance_by(at-1).ok?
+ self.next()
+
+# todo: implement iter[T](self: ...): Iter[T] funcs
+# todo: efficient functional methods
+
+## The Peek interface. Any type implementing Iter, `peek`, and `peek_nth` is peekable.
+pub type Peek[T] = interface
+ next(mut Self): Option[T]
+ peek(mut Self): Option[T]
+ peek_nth(mut Self, n: uint): Option[T]
+
+# todo: implement peek[T](self: Iter[T]): Peek[T]
+# todo: implement Peekable struct
+# https://github.com/LukeMathWalker/multipeek/blob/main/src/lib.rs
+
+## We don't want a Countable. It's not terribly useful.
+# pub type Countable[T] = interface
+# next(mut Self): Option[T]
+# len(Self): uint
+# get(Self, uint): Option[T]
diff --git a/std/default/options.pk b/std/default/options.pk
index f1bcac4..3aaea49 100644
--- a/std/default/options.pk
+++ b/std/default/options.pk
@@ -1,4 +1,4 @@
-## std/options
+## std/options: Optional types.
## This module is imported by default.
import std/format
@@ -47,20 +47,20 @@ pub func flatten[T](self: Option[Option[T]]): Option[T] = # todo: better name?
None
## Returns the inner value or a default.
-pub func or[T](self: Option[T], default: T): T =
+pub func get_or[T](self: Option[T], default: T): T =
if self of Some(x): x
else: default
## Directly accesses the inner value. Throws an exception if None.
-pub yeet func get[T](self: Option[T]): T =
+pub yeet func `!`[T](self: Option[T]): T =
if self of Some(x): x
else: raise Exception # todo: syntax??
-# todo: direct access, alias to get
-macro `!`[T](self: Option[T]): T
-# todo: indirect access, ??? do we propagate? is this useful? probably not
-macro `?`[T](self: Option[T]): T
-# todo: field access? useful? assignment?
-macro `.?`[T](self: Option[T])
+## Indirect access. Propagates None.
+pub macro `?`[T](self: Option[T]) =
+ quote:
+ match self
+ of Some(x): x
+ of None: return None
## Overloads the == operation for use on Options.
pub func `==`[T](a, b: Option[T]): bool =
diff --git a/std/default/results.pk b/std/default/results.pk
index 2ac47d0..187ece9 100644
--- a/std/default/results.pk
+++ b/std/default/results.pk
@@ -1,4 +1,4 @@
-## std/results
+## std/results: Result types.
## This module is imported by default.
import std/[options, format]
@@ -7,9 +7,11 @@ pub type Result[T, E] = union
Okay: T
Error: E
+# todo: determine the difference between interfaces and types
+# ErrorInterface? Errorable? Err?
pub type Error = interface
- func str(self: Self)
- func dbg(self: Self)
+ str(Self): str
+ dbg(Self): str
pub type Result[T] = Result[T, ref Error]
@@ -79,11 +81,11 @@ pub func transpose[T, E](self: Option[Result[T, E]], error: E): Result[Option[T]
Error(error)
## Returns the inner value or a default.
-pub func or[T, E](self: Result[T, E], default: T): T =
+pub func get_or[T, E](self: Result[T, E], default: T): T =
if self of Okay(x): x
else: default
## Directly accesses the inner value. Throws an exception if Error(e).
-pub yeet func get[T, E](self: Result[T, E]): T =
+pub yeet func `!`[T, E](self: Result[T, E]): T =
match self
of Okay(x): x
of Error(e): raise Exception(e) # todo: syntax??
@@ -92,10 +94,12 @@ pub yeet func get_err[T, E](self: Result[T, E]): E =
of Error(e): e
of Okay(x): raise Exception(x) # todo: syntax??
-# todo: direct access, alias to get
-macro `!`[T, E](self: Result[T, E]): T
-# todo: indirect access, propagates Err
-macro `?`[T, E](self: Result[T]): T
+## Indirect access. Propagates Error.
+macro `?`[T, E](self: Result[T, E]) =
+ quote:
+ match self
+ of Okay(x): x
+ of Error(e): return Error(e)
## Overloads the == operation for use on Results.
pub func `==`[T, E, F](a: Result[T, E], b: Result[T, F]): bool =