1 # Example program showing exceptions built out of delimited continuations. 2 3 # Since Mu is statically typed, we can't build an all-purpose higher-order 4 # function called 'try'; it wouldn't know how many arguments the function 5 # passed to it needs to take, what their types are, etc. Instead, until Mu 6 # gets macros we'll directly use the continuation primitives. 7 8 def main [ 9 local-scope 10 foo 0/no-exception 11 foo 1/raise-exception 12 ] 13 14 # example showing exception handling 15 def foo raise-exception?:bool [ 16 local-scope 17 load-inputs 18 # To run an instruction of the form: 19 # try f ... 20 # write this: 21 # call-with-continuation-mark 999/exception-tag, f, ... 22 # By convention we reserve tag 999 for exceptions. 23 # 24 # 'f' above may terminate at either a regular 'return' or a 'return-with-continuation-mark'. 25 # We never re-call the continuation returned in the latter case; 26 # its existence merely signals that an exception was raised. 27 # So just treat it as a boolean. 28 # The other inputs and outputs to 'call-with-continuation-mark' depend on 29 # the function it is called with. 30 exception-raised?:bool, err:text, result:num <- call-with-continuation-mark 999/exception-tag, f, raise-exception? 31 { 32 break-if exception-raised? 33 $print [normal exit; result ] result 10/newline 34 } 35 { 36 break-unless exception-raised? 37 $print [error caught: ] err 10/newline 38 } 39 ] 40 41 # A callee function that can raise an exception has some weird constraints at 42 # the moment. 43 # 44 # The caller's 'call-with-continuation-mark' instruction may return with 45 # either a regular 'return' or a 'return-continuation-until-mark'. 46 # To handle both cases, regular 'return' instructions in the callee must 47 # prepend an extra 0 result, in place of the continuation that may have been 48 # returned. 49 # This change to number of outputs violates our type system, so the call has 50 # to be dynamically typed. The callee can't have a header. 51 def f [ 52 local-scope 53 raise-exception?:bool <- next-input 54 { 55 break-unless raise-exception? 56 # throw/raise: 2 results + implicit continuation (ignoring the continuation tag) 57 return-continuation-until-mark 999/exception-tag, [error will robinson!], 0/unused 58 } 59 # normal return: 3 results including 0 continuation placeholder at start 60 return 0/continuation-placeholder, 0/no-error, 34/regular-result 61 ]