# Mu - exception2.mu

     1 # Example program showing exceptions built out of delimited continuations.
     2 # Slightly less klunky than exception1.mu.
     3
     4 # Since Mu is statically typed, we can't build an all-purpose higher-order
     5 # function called 'try'; it wouldn't know how many arguments the function
     6 # passed to it needs to take, what their types are, etc. Instead, until Mu
     7 # gets macros we'll directly use the continuation primitives.
     8
     9 exclusive-container error-or:_elem [
    10   error:text
    11   value:_elem
    12 ]
    13
    14 def main [
    15   local-scope
    16   foo false/no-exception
    17   foo true/raise-exception
    18 ]
    19
    20 # example showing exception handling
    21 def foo raise-exception?:bool [
    22   local-scope
    23   load-inputs
    24   # To run an instruction of the form:
    25   #   try f ...
    26   # write this:
    27   #   call-with-continuation-mark 999/exception-tag, f, ...
    28   # By convention we reserve tag 999 for exceptions.
    29   #
    30   # The other inputs and outputs to 'call-with-continuation-mark' depend on
    31   # the function it is called with.
    32   _, result:error-or:num <- call-with-continuation-mark 999/exception-tag, f, raise-exception?
    33   {
    34     val:num, normal-exit?:bool <- maybe-convert result, value:variant
    35     break-unless normal-exit?
    36     $print [normal exit; result ] val 10/newline
    37   }
    38   {
    39     err:text, error-exit?:bool <- maybe-convert result, error:variant
    40     break-unless error-exit?
    41     $print [error caught: ] err 10/newline
    42   }
    43 ]
    44
    45 # Callee function that we catch exceptions in must always return using a
    46 # continuation.
    47 def f raise-exception?:bool -> result:error-or:num [
    48   local-scope
    49   load-inputs
    50   {
    51     break-unless raise-exception?
    52     # throw/raise
    53     result <- merge 0/error, [error will robinson!]
    54     return-continuation-until-mark 999/exception-tag, result
    55   }
    56   # 'normal' return; still uses the continuation mark
    57   result <- merge 1/value, 34
    58   return-continuation-until-mark 999/exception-tag, result
    59   # dead code just to avoid errors
    60   result <- merge 1/value, 0
    61   return result
    62 ]