mu/archive/1.vm/exception1.mu

62 lines
2.3 KiB
Forth

# Example program showing exceptions built out of delimited continuations.
# Since Mu is statically typed, we can't build an all-purpose higher-order
# function called 'try'; it wouldn't know how many arguments the function
# passed to it needs to take, what their types are, etc. Instead, until Mu
# gets macros we'll directly use the continuation primitives.
def main [
local-scope
foo false/no-exception
foo true/raise-exception
]
# example showing exception handling
def foo raise-exception?:bool [
local-scope
load-inputs
# To run an instruction of the form:
# try f ...
# write this:
# call-with-continuation-mark 999/exception-tag, f, ...
# By convention we reserve tag 999 for exceptions.
#
# 'f' above may terminate at either a regular 'return' or a 'return-with-continuation-mark'.
# We never re-call the continuation returned in the latter case;
# its existence merely signals that an exception was raised.
# So just treat it as a boolean.
# The other inputs and outputs to 'call-with-continuation-mark' depend on
# the function it is called with.
exception-raised?:bool, err:text, result:num <- call-with-continuation-mark 999/exception-tag, f, raise-exception?
{
break-if exception-raised?
$print [normal exit; result ] result 10/newline
}
{
break-unless exception-raised?
$print [error caught: ] err 10/newline
}
]
# A callee function that can raise an exception has some weird constraints at
# the moment.
#
# The caller's 'call-with-continuation-mark' instruction may return with
# either a regular 'return' or a 'return-continuation-until-mark'.
# To handle both cases, regular 'return' instructions in the callee must
# prepend an extra 0 result, in place of the continuation that may have been
# returned.
# This change to number of outputs violates our type system, so the call has
# to be dynamically typed. The callee can't have a header.
def f [
local-scope
raise-exception?:bool <- next-input
{
break-unless raise-exception?
# throw/raise: 2 results + implicit continuation (ignoring the continuation tag)
return-continuation-until-mark 999/exception-tag, [error will robinson!], 0/unused
}
# normal return: 3 results including 0 continuation placeholder at start
return 0/continuation-placeholder, null/no-error, 34/regular-result
]