Okay, I am quite happy with the standard library as it is now, but in the process of coming up with an interface for a test framework I realized that the error handling, as far as it can be called that, is completely unusable. While it probably would be possible to write try/catch constructs it would be entirely impossible to write a version that somehow knows how to handle errors thrown by misuse of a primary operation or the use of `error`.
In short: Currently there is no way to handle something like
0 reciprocal !
That is completely unacceptable but unfortunately I am currently a bit stumped on how to devise a better system.
A big hurdle is that all Poslin code needs to be sequentially processable, or, put another way, there is no such thing as code blocks or something which can be associated with a wrapping error handler or something.
What can be wrapped with an error handler, though, is a thread. This brings me to the first option:
This would first require a new data type `:Error`, which would have two attributes: A string (the error message) and metadata about the error (whatever those might be).
`handle-error` would be an operation which takes two threads, the body and the handler, and returns one thread, a checked thread (or something like that, I'm not sure about the terminology).
This scheme also requires a second return stack for handlers, a handler stack… Hmmm…
Now, if a checked thread is called, the handler is pushed onto the handler stack and the body called. When the checked thread is done, the top of the handler stack is dropped.
Now, every time some kind of error happens, the corresponding error object is pushed onto the current stack, the top of the handler stack is popped off and called. If that doesn't work (because the handler stack is empty) fall back to the way errors are treated right now (but still, the error object now is available for the user, as long as a REPL is available for the user, which probably shouldn't be the case for user applications).
This scheme requires two new Types (`:Error` and `:CheckedThread`) and 6 or 8 new primary operations (`new-error`, `error-message`, `error-data`, `handle-error`, `checked-thread-body`, `checked-thread-handler`; maybe `h<-` and `h->`, who knows what kind of crazy exception systems can be done with those two). `error` would become obsolete, moving to the standard library as a simpler version of `new-error` that doesn't bother with metadata.
One boon if this kind of system is that it doesn't do any kind of stack unwinding or anything like that, so you don't loose information. The downside of this approach is that, when wrapping with `handle-error` you need to anticipate every place in the wrapped thread the handled error could come from and make sure that it is handled correctly. I guess it would be possible to write a more… reasonable exception handling facility on top of this, which would be enough for me (because Poslin is all about building reasonable stuff on simple mechanisms), but, well it's just a
guess.
Also, the additional handler stack seems a little bit like overkill. But only a little bit. Also I just realized that it might be possible to discard of checked threads (and the corresponding operations) entirely and implement `handle-error` with `h<-` and `h->`.
So, any thoughts on this? An alternative idea on how to do this? Tweaks to the proposed systems?