source: doc/working/exception/design.txt @ caf06aa

Last change on this file since caf06aa was 465ed18, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Update to the exception handling mechanism plan.

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[88e0080]1Design of Exceptions and EHM in Cforall:
2
3
[465ed18]4Exception Instances:
5Currently, exceptions are integers (like errno).
[88e0080]6
[465ed18]7They are planned to be the new "tagged structures", which allows them to
8exist in a simple hierarchy which shared functionality throughout. However
9the tagged structures are not yet implemented so that will wait.
[88e0080]10
[465ed18]11A single built in exception is at the top of the hierarchy and all other
12exceptions are its children. When you match against an exception, you match
13for an exception and its children, so the top of the hierarchy is used as a
14catch-all option.
[88e0080]15
[465ed18]16The shared functionality across exceptions has not been finalized, but will
17probably include things like human readable descriptions and default handlers.
[88e0080]18
19
[465ed18]20Throwing:
21There are currently two kinds of throws, "throw" for termination and
22"throwResume" for resumption. Both keywords can be used to create a throw
23statement. The kind of throw decides what handlers may catch the exception
24and weither control flow can return to the throw site.
[88e0080]25
[465ed18]26Syntax
27"throw" exception ";"
28"throwResume" exception ";"
[88e0080]29
[465ed18]30Non-local throws are allowed for resumption only. A target is an object with
31a stack, with which it may propagate and handle the exception.
[88e0080]32
[465ed18]33Syntax
34"throwResume" exception "_At" target ";"
[88e0080]35
[465ed18]36Termination throws unwind the stack until a handler is reached, control moves
37onwards from the end of the handler. Resumption throws do not unwind, if a
38handler is found and control will return to the throw after the exception is
39handled.
[88e0080]40
41
[465ed18]42Catching:
43The catch and handle of an exception is preformed with a try statement, which
44also can have finally clauses to exceute on exit from the scope.
[88e0080]45
[465ed18]46Syntax
47"try"
48        try-block
49( ("catch" | "catchResume")
50  "(" exception_type [identifier] [";" conditional_expression] ")"
51        catch-block
52)*
53("finally"
54        finally-block
55)?
[88e0080]56
[465ed18]57Either at least 1 handler clause or the finally clasue must be given on each
58try block. Each handler clause handles 1 of the two types of throws. Each
59handler also specifies a type of exception it handles, and will handle all
60children exceptions as well. In addition, a conditional expression which, if
61included, must be true for the handler to catch the exception.
[88e0080]62
[465ed18]63The two types of handlers may be intermixed. Multiple handlers catching the
64same type may also be used, to allow for fallbacks on false conditionals.
[88e0080]65
66
[465ed18]67Implementation Overview:
[88e0080]68
[465ed18]69The implementation has two main parts. The first is just a collection of the
70support definitions we need, the data types and functions used within the
71exception handling code. Second is a translation from Cforall code to C code
72that uses those definitions to throw, catch and handle exceptions.
[88e0080]73
[465ed18]74Termination handlers call a specially annotated function, passing it inner
75functions that act as the varius sub-blocks. Termination throws use the
76unwind library that checks the underlying code for those annotations. Each
77time one is found some magic is used to check for a matching handler, if one
78is found control goes to the special function which excecutes the handler and
79returns.
[88e0080]80
[465ed18]81Resumption handlers maintain a linked list of stack allocated nodes that have
82the handler functions attached. Throwing a resumption exception traverses this
83list, and calls each handler, the handlers handle the exception if they can
84and return if they did or not.
[88e0080]85
[465ed18]86Finally clauses just use stack cleanup to force a nested function, which has
87the code from the finally clause, to execute when we leave that section.
[88e0080]88
89
[465ed18]90Alternative Error Handling: Return Unions
[88e0080]91
[465ed18]92Return unions (Maybe and Result), are types that can encode a success or
93other result in a single value. Maybe stores a value or nothing, Result stores
94a value or an error.
[88e0080]95
[465ed18]96For errors that are usually handled quite close to where they occur, these
97can replace exceptions.
[88e0080]98
[465ed18]99They tend to be faster and require similar or less amounts of code to handle.
100However they can slow down the normal path with some extra conditionals and
101can mix the normal and exceptional control flow path. If handling the error
102is simple, and happens relatively frequently, this might be prefered but in
103other cases it just hurts speed and readability.
[88e0080]104
105In short, these errors seem to be more effective when errors are likely and
106immediate. High failure operations, especially ones with failures that can
107be handled locally, might be better off using these instead of exceptions.
108
[465ed18]109Also the return unions could use exceptions as well. Getting the improper
110side of a return union might throw an exception. Or we can provide helpers
111for results withe exceptions as in:
[88e0080]112                forall(otype T, otype E | exception(E))
113                T get_or_throw (Result(T, E) * this) {
[465ed18]114                        if (has_value(this)) {
115                                return get_value(this);
[88e0080]116                        } else {
[465ed18]117                                throw get_error(this);
[88e0080]118                        }
119                }
Note: See TracBrowser for help on using the repository browser.