aboutsummaryrefslogtreecommitdiff
path: root/docs/ERRORS.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/ERRORS.md')
-rw-r--r--docs/ERRORS.md83
1 files changed, 74 insertions, 9 deletions
diff --git a/docs/ERRORS.md b/docs/ERRORS.md
index 4a4b206..a6e7a6a 100644
--- a/docs/ERRORS.md
+++ b/docs/ERRORS.md
@@ -1,24 +1,89 @@
# Error Handling
-Error handling should perhaps be abstracted into a more general effects system.
-But if not, then this document lays out some potential ideas.
+Puck's error handling is shamelessly stolen from Swift.
+It uses a combination of Option/Result types and try/catch/finally statements, and leans somewhat on Puck's metaprogramming capabilities.
----
+```puck
+func get_debug[T](): T =
+ let value: Option[T] = self.unsafe_get(413)
+ try:
+ let value = value!
+ catch Exception(e)
+
+
+try:
+ ..
+catch:
+ ..
+finally:
+ print "No such errors"
+```
+
+There are several ways to handle errors in Puck. If the error is encoded in the type, one can:
+1. `match` on the error
+2. compactly match on the error with `if ... of`
+3. propagate the error with `?`
+4. throw the error with `!`
+
+If an error is thrown, one must explicitly handle (or disregard) it with a `try/catch` block.
+This method of error handling may feel more familiar to Java programmers.
+
+## Errors as monads
+
+Puck provides [`Option[T]`](std/default/options.pk) and a [`Result[T, E]`](std/default/results.pk) types, imported by default. These are `union` types and so must be pattern matched upon to be useful: but the standard library provides [a bevy of helper functions](std/default/results.pk).
+Two in particular are of note. The `?` operator unwraps a Result or propagates its error up a function call (and may only be used in type-appropriate contexts). The `!` operator unwraps an Option or Result directly or throws an exception in the case of None or Error.
```puck
+pub macro `?`[T, E](self: Result[T, E]) =
+ quote:
+ match `self`
+ of Okay(x): x
+ of Error(e): return Error(e)
```
-Puck provides [`Option[T]`](std/default/options.pk) and a [`Result[T, E]`](std/default/results.pk) types, imported by default. These are `union` types and so must be pattern matched upon to be useful: but the standard library provides a bevy of helper functions.
+```puck
+pub func `!`[T](self: Option[T]): T =
+ match self
+ of Some(x): x
+ of None: raise EmptyValue
-Two in particular are of note. The `?` operator unwraps a Result or propagates its error up a function call. The `!` operator unwraps an Option or Result directly or throws an exception in the case of None or Error.
+pub func `!`[T, E](self: Result[T, E]): T =
+ of Okay(x): x
+ of Error(e): raise e
+```
+
+The utility of the provided helpers in [`std.options`](std/default/options.pk) and [`std.results`](std/default/results.pk) should not be understated. While encoding errors into the type system may appear restrictive at first glance, some syntactic sugar goes a long way in writing compact and idiomatic code. Java programmers in particular are urged to give type-first errors a try, before falling back on unwraps and `try`/`catch`.
+
+A notable helpful type is the aliasing of `Result[T]` to `Result[T, ref Err]`, for when the particular error does not matter. This breaks `try`/`catch` exhaustion (as `ref Err` denotes a reference to *any* Error), but is particularly useful when used in conjunction with the propagation operator.
+
+## Errors as catchable exceptions
+
+Errors raised by `raise`/`throw` (or subsequently the `!` operator) must be explicitly caught and handled via a `try`/`catch`/`finally` statement.
+If an exception is not handled within a function body, the function must be explicitly marked as a throwing function via the `yeet` prefix (name to be determined). The compiler will statically determine which exceptions in particular are thrown from any given function, and enforce them to be explicitly handled or explicitly ignored.
+
+Errors are types. An error thrown from an unwrapped `Result[T, E]` is of type `E`. `catch` statements, then, may pattern match upon possible errors, behaving similarly to `of` branches.
```puck
+try:
+ ...
+catch "Error":
+ ...
+finally:
+ ...
```
-Errors raised by the `!` operator must be explicitly caught and handled via a `try/catch/finally` statement.
+This creates a distinction between two types of error handling, working in sync: functional error handling with [Option](https://en.wikipedia.org/wiki/Option_type) and [Result](https://en.wikipedia.org/wiki/Result_type) types, and object-oriented error handling with [catchable exceptions](https://en.wikipedia.org/wiki/Exception_handling). These styles may be swapped between with minimal syntax overhead. Libraries, however, should universally use `Option`/`Result`, as this provides the best support for both styles.
+
+<!-- [nullable types](https://en.wikipedia.org/wiki/Nullable_type)?? -->
+
+## Unrecoverable exceptions
-If an exception is not handled within a function body, the function must be explicitly marked as a throwing function via the `yeet` prefix (final name to be determined). The compiler will statically determine which exceptions in particular are thrown from any given function.
+There exist errors from which a program can not reasonably recover. These are the following:
+- `Assertation Failure`: a call to an `assert` function has returned false at runtime.
+- `Out of Memory`: the executable is out of memory.
+- `Stack Overflow`: the executable has overflowed the stack.
+- any others?
-This creates a distinction between two types of error handling, working in sync: functional error handling with [Option](https://en.wikipedia.org/wiki/Option_type) and [Result](https://en.wikipedia.org/wiki/Result_type) types, and object-oriented error handling with [nullable types](https://en.wikipedia.org/wiki/Nullable_type) and [exceptions](https://en.wikipedia.org/wiki/Exception_handling). These styles may be swapped between with minimal syntax overhead. Libraries, however, should universally use Options and Results, as this provides best for both usages.
+They are not recoverable, but the user should be aware of them as possible failure conditions.
-References: [std/options](std/default/options.pk), [std/results](std/default/results.pk), [Error Handling in Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling) (shamelessly stolen)
+References: [Error Handling in Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling)