Design of Exceptions and EHM in Cforall: Exception Instances: Currently, exceptions are integers (like errno). They are planned to be the new "tagged structures", which allows them to exist in a simple hierarchy which shared functionality throughout. However the tagged structures are not yet implemented so that will wait. A single built in exception is at the top of the hierarchy and all other exceptions are its children. When you match against an exception, you match for an exception and its children, so the top of the hierarchy is used as a catch-all option. The shared functionality across exceptions has not been finalized, but will probably include things like human readable descriptions and default handlers. Throwing: There are currently two kinds of throws, "throw" for termination and "throwResume" for resumption. Both keywords can be used to create a throw statement. The kind of throw decides what handlers may catch the exception and weither control flow can return to the throw site. Syntax "throw" exception ";" "throwResume" exception ";" Non-local throws are allowed for resumption only. A target is an object with a stack, with which it may propagate and handle the exception. Syntax "throwResume" exception "_At" target ";" Termination throws unwind the stack until a handler is reached, control moves onwards from the end of the handler. Resumption throws do not unwind, if a handler is found and control will return to the throw after the exception is handled. Catching: The catch and handle of an exception is preformed with a try statement, which also can have finally clauses to exceute on exit from the scope. Syntax "try" try-block ( ("catch" | "catchResume") "(" exception_type [identifier] [";" conditional_expression] ")" catch-block )* ("finally" finally-block )? Either at least 1 handler clause or the finally clasue must be given on each try block. Each handler clause handles 1 of the two types of throws. Each handler also specifies a type of exception it handles, and will handle all children exceptions as well. In addition, a conditional expression which, if included, must be true for the handler to catch the exception. The two types of handlers may be intermixed. Multiple handlers catching the same type may also be used, to allow for fallbacks on false conditionals. Implementation Overview: The implementation has two main parts. The first is just a collection of the support definitions we need, the data types and functions used within the exception handling code. Second is a translation from Cforall code to C code that uses those definitions to throw, catch and handle exceptions. Termination handlers call a specially annotated function, passing it inner functions that act as the varius sub-blocks. Termination throws use the unwind library that checks the underlying code for those annotations. Each time one is found some magic is used to check for a matching handler, if one is found control goes to the special function which excecutes the handler and returns. Resumption handlers maintain a linked list of stack allocated nodes that have the handler functions attached. Throwing a resumption exception traverses this list, and calls each handler, the handlers handle the exception if they can and return if they did or not. Finally clauses just use stack cleanup to force a nested function, which has the code from the finally clause, to execute when we leave that section. Alternative Error Handling: Return Unions Return unions (Maybe and Result), are types that can encode a success or other result in a single value. Maybe stores a value or nothing, Result stores a value or an error. For errors that are usually handled quite close to where they occur, these can replace exceptions. They tend to be faster and require similar or less amounts of code to handle. However they can slow down the normal path with some extra conditionals and can mix the normal and exceptional control flow path. If handling the error is simple, and happens relatively frequently, this might be prefered but in other cases it just hurts speed and readability. In short, these errors seem to be more effective when errors are likely and immediate. High failure operations, especially ones with failures that can be handled locally, might be better off using these instead of exceptions. Also the return unions could use exceptions as well. Getting the improper side of a return union might throw an exception. Or we can provide helpers for results withe exceptions as in: forall(otype T, otype E | exception(E)) T get_or_throw (Result(T, E) * this) { if (has_value(this)) { return get_value(this); } else { throw get_error(this); } }