Changes in / [9373b6a:478c610]


Ignore:
Files:
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/features.tex

    r9373b6a r478c610  
    1616throw/catch as a particular kind of raise/handle.
    1717These are the two parts that the user writes and may
    18 be the only two pieces of the EHM that have any syntax in a language.
     18be the only two pieces of the EHM that have any syntax in the language.
    1919
    2020\paragraph{Raise}
    21 The raise is the starting point for exception handling
    22 by raising an exception, which passes it to
     21The raise is the starting point for exception handling. It marks the beginning
     22of exception handling by raising an exception, which passes it to
    2323the EHM.
    2424
    2525Some well known examples include the @throw@ statements of \Cpp and Java and
    26 the \code{Python}{raise} statement of Python. In real systems, a raise may
    27 perform some other work (such as memory management) but for the
     26the \code{Python}{raise} statement from Python. In real systems a raise may
     27preform some other work (such as memory management) but for the
    2828purposes of this overview that can be ignored.
    2929
    3030\paragraph{Handle}
    31 The primary purpose of an EHM is to run some user code to handle a raised
    32 exception. This code is given, with some other information, in a handler.
     31The purpose of most exception operations is to run some user code to handle
     32that exception. This code is given, with some other information, in a handler.
    3333
    3434A handler has three common features: the previously mentioned user code, a
    35 region of code it guards, and an exception label/condition that matches
    36 the raised exception.
     35region of code they guard and an exception label/condition that matches
     36certain exceptions.
    3737Only raises inside the guarded region and raising exceptions that match the
    3838label can be handled by a given handler.
    3939If multiple handlers could can handle an exception,
    40 EHMs define a rule to pick one, such as ``best match" or ``first found".
     40EHMs will define a rule to pick one, such as ``best match" or ``first found".
    4141
    4242The @try@ statements of \Cpp, Java and Python are common examples. All three
    43 show the common features of guarded region, raise, matching and handler.
    44 \begin{cfa}
    45 try {                           // guarded region
    46         ...     
    47         throw exception;        // raise
    48         ...     
    49 } catch( exception ) {  // matching condition, with exception label
    50         ...                             // handler code
    51 }
    52 \end{cfa}
     43also show another common feature of handlers, they are grouped by the guarded
     44region.
    5345
    5446\subsection{Propagation}
    5547After an exception is raised comes what is usually the biggest step for the
    56 EHM: finding and setting up the handler for execution. The propagation from raise to
     48EHM: finding and setting up the handler. The propagation from raise to
    5749handler can be broken up into three different tasks: searching for a handler,
    5850matching against the handler and installing the handler.
     
    6052\paragraph{Searching}
    6153The EHM begins by searching for handlers that might be used to handle
    62 the exception. The search is restricted to
    63 handlers that have the raise site in their guarded
     54the exception. Searching is usually independent of the exception that was
     55thrown as it looks for handlers that have the raise site in their guarded
    6456region.
    6557The search includes handlers in the current function, as well as any in
     
    6759
    6860\paragraph{Matching}
    69 Each handler found is matched with the raised exception. The exception
    70 label defines a condition that is used with the exception and decides if
     61Each handler found has to be matched with the raised exception. The exception
     62label defines a condition that is used with exception and decides if
    7163there is a match or not.
     64
    7265In languages where the first match is used, this step is intertwined with
    73 searching; a match check is performed immediately after the search finds
    74 a handler.
     66searching; a match check is preformed immediately after the search finds
     67a possible handler.
    7568
    7669\paragraph{Installing}
    77 After a handler is chosen, it must be made ready to run.
     70After a handler is chosen it must be made ready to run.
    7871The implementation can vary widely to fit with the rest of the
    7972design of the EHM. The installation step might be trivial or it could be
     
    8275
    8376If a matching handler is not guaranteed to be found, the EHM needs a
    84 different course of action for this case.
     77different course of action for the case where no handler matches.
    8578This situation only occurs with unchecked exceptions as checked exceptions
    86 (such as in Java) are guaranteed to find a matching handler.
    87 The unhandled action is usually very general, such as aborting the program.
     79(such as in Java) can make the guarantee.
     80This unhandled action is usually very general, such as aborting the program.
    8881
    8982\paragraph{Hierarchy}
     
    9285exception hierarchy is a natural extension of the object hierarchy.
    9386
    94 Consider the following exception hierarchy:
     87Consider the following hierarchy of exceptions:
    9588\begin{center}
    9689\input{exception-hierarchy}
    9790\end{center}
     91
    9892A handler labeled with any given exception can handle exceptions of that
    9993type or any child type of that exception. The root of the exception hierarchy
    100 (here \code{C}{exception}) acts as a catch-all, leaf types catch single types,
     94(here \code{C}{exception}) acts as a catch-all, leaf types catch single types
    10195and the exceptions in the middle can be used to catch different groups of
    10296related exceptions.
    10397
    10498This system has some notable advantages, such as multiple levels of grouping,
    105 the ability for libraries to add new exception types, and the isolation
     99the ability for libraries to add new exception types and the isolation
    106100between different sub-hierarchies.
    107101This design is used in \CFA even though it is not a object-orientated
     
    116110is usually set up to do most of the work.
    117111
    118 The EHM can return control to many different places, where
     112The EHM can return control to many different places,
    119113the most common are after the handler definition (termination)
    120114and after the raise (resumption).
     
    123117For effective exception handling, additional information is often passed
    124118from the raise to the handler and back again.
    125 So far, only communication of the exception's identity is covered.
    126 A common communication method for passing more information is putting fields into the exception instance
     119So far only communication of the exceptions' identity has been covered.
     120A common communication method is putting fields into the exception instance
    127121and giving the handler access to them.
    128 Using reference fields pointing to data at the raise location allows data to be
     122Passing the exception by reference instead of by value can allow data to be
    129123passed in both directions.
    130124
    131125\section{Virtuals}
    132126Virtual types and casts are not part of \CFA's EHM nor are they required for
    133 an EHM.
    134 However, one of the best ways to support an exception hierarchy
     127any EHM.
     128However, it is one of the best ways to support an exception hierarchy
    135129is via a virtual hierarchy and dispatch system.
    136130
    137 Ideally, the virtual system should have been part of \CFA before the work
     131Ideally, the virtual system would have been part of \CFA before the work
    138132on exception handling began, but unfortunately it was not.
    139133Hence, only the features and framework needed for the EHM were
    140 designed and implemented for this thesis. Other features were considered to ensure that
     134designed and implemented. Other features were considered to ensure that
    141135the structure could accommodate other desirable features in the future
    142 but are not implemented.
    143 The rest of this section only discusses the implemented subset of the
    144 virtual-system design.
     136but they were not implemented.
     137The rest of this section will only discuss the implemented subset of the
     138virtual system design.
    145139
    146140The virtual system supports multiple ``trees" of types. Each tree is
     
    158152It is important to note that these are virtual members, not virtual methods
    159153of object-orientated programming, and can be of any type.
    160 
    161 \PAB{Need to look at these when done.
    162154
    163155\CFA still supports virtual methods as a special case of virtual members.
     
    173165as a hidden field.
    174166\todo{Might need a diagram for virtual structure.}
    175 }%
    176167
    177168Up until this point the virtual system is similar to ones found in
    178 object-orientated languages but this is where \CFA diverges. Objects encapsulate a
    179 single set of methods in each type, universally across the entire program,
    180 and indeed all programs that use that type definition. Even if a type inherits and adds methods, it still encapsulate a
    181 single set of methods. In this sense,
    182 object-oriented types are ``closed" and cannot be altered.
    183 
    184 In \CFA, types do not encapsulate any code. Traits are local for each function and
    185 types can satisfy a local trait, stop satisfying it or, satisfy the same
    186 trait in a different way at any lexical location in the program where a function is call.
    187 In this sense, the set of functions/variables that satisfy a trait for a type is ``open" as the set can change at every call site.
     169object-orientated languages but this where \CFA diverges. Objects encapsulate a
     170single set of behaviours in each type, universally across the entire program,
     171and indeed all programs that use that type definition. In this sense, the
     172types are ``closed" and cannot be altered.
     173
     174In \CFA, types do not encapsulate any behaviour. Traits are local and
     175types can begin to satisfy a trait, stop satisfying a trait or satisfy the same
     176trait in a different way at any lexical location in the program.
     177In this sense, they are ``open" as they can change at any time.
    188178This capability means it is impossible to pick a single set of functions
    189 that represent a type's implementation across a program.
     179that represent the type's implementation across the program.
    190180
    191181\CFA side-steps this issue by not having a single virtual table for each
    192182type. A user can define virtual tables that are filled in at their
    193183declaration and given a name. Anywhere that name is visible, even if it is
    194 defined locally inside a function \PAB{What does this mean? (although that means it does not have a
    195 static lifetime)}, it can be used.
     184defined locally inside a function (although that means it does not have a
     185static lifetime), it can be used.
    196186Specifically, a virtual type is ``bound" to a virtual table that
    197187sets the virtual members for that object. The virtual members can be accessed
     
    231221completing the virtual system). The imaginary assertions would probably come
    232222from a trait defined by the virtual system, and state that the exception type
    233 is a virtual type, is a descendant of @exception_t@ (the base exception type),
     223is a virtual type, is a descendant of @exception_t@ (the base exception type)
    234224and note its virtual table type.
    235225
     
    251241\end{cfa}
    252242Both traits ensure a pair of types are an exception type, its virtual table
    253 type,
     243type
    254244and defines one of the two default handlers. The default handlers are used
    255245as fallbacks and are discussed in detail in \vref{s:ExceptionHandling}.
     
    260250facing way. So these three macros are provided to wrap these traits to
    261251simplify referring to the names:
    262 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@, and @IS_RESUMPTION_EXCEPTION@.
     252@IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@.
    263253
    264254All three take one or two arguments. The first argument is the name of the
     
    282272\CFA provides two kinds of exception handling: termination and resumption.
    283273These twin operations are the core of \CFA's exception handling mechanism.
    284 This section covers the general patterns shared by the two operations and
    285 then goes on to cover the details of each individual operation.
     274This section will cover the general patterns shared by the two operations and
     275then go on to cover the details each individual operation.
    286276
    287277Both operations follow the same set of steps.
    288 First, a user raises an exception.
    289 Second, the exception propagates up the stack.
    290 Third, if a handler is found, the exception is caught and the handler is run.
     278Both start with the user preforming a raise on an exception.
     279Then the exception propagates up the stack.
     280If a handler is found the exception is caught and the handler is run.
    291281After that control continues at a raise-dependent location.
    292 Fourth, if a handler is not found, a default handler is run and, if it returns, then control
     282If the search fails a default handler is run and, if it returns, then control
    293283continues after the raise.
    294284
    295 %This general description covers what the two kinds have in common.
    296 The differences in the two operations include how propagation is performed, where execution continues
    297 after an exception is caught and handled, and which default handler is run.
     285This general description covers what the two kinds have in common.
     286Differences include how propagation is preformed, where exception continues
     287after an exception is caught and handled and which default handler is run.
    298288
    299289\subsection{Termination}
    300290\label{s:Termination}
    301 Termination handling is the familiar EHM and used in most programming
     291Termination handling is the familiar kind and used in most programming
    302292languages with exception handling.
    303293It is a dynamic, non-local goto. If the raised exception is matched and
     
    318308@is_termination_exception@ at the call site.
    319309Through \CFA's trait system, the trait functions are implicitly passed into the
    320 throw code for use by the EHM.
     310throw code and the EHM.
    321311A new @defaultTerminationHandler@ can be defined in any scope to
    322 change the throw's behaviour when a handler is not found (see below).
     312change the throw's behaviour (see below).
    323313
    324314The throw copies the provided exception into managed memory to ensure
     
    330320% How to say propagation starts, its first sub-step is the search.
    331321Then propagation starts with the search. \CFA uses a ``first match" rule so
    332 matching is performed with the copied exception as the search key.
    333 It starts from the raise in the throwing function and proceeds towards the base of the stack,
     322matching is preformed with the copied exception as the search continues.
     323It starts from the throwing function and proceeds towards base of the stack,
    334324from callee to caller.
    335 At each stack frame, a check is made for termination handlers defined by the
     325At each stack frame, a check is made for resumption handlers defined by the
    336326@catch@ clauses of a @try@ statement.
    337327\begin{cfa}
     
    345335\end{cfa}
    346336When viewed on its own, a try statement simply executes the statements
    347 in the \snake{GUARDED_BLOCK}, and when those are finished,
     337in \snake{GUARDED_BLOCK} and when those are finished,
    348338the try statement finishes.
    349339
     
    351341invoked functions, all the handlers in these statements are included in the
    352342search path.
    353 Hence, if a termination exception is raised, these handlers may be matched
     343Hence, if a termination exception is raised these handlers may be matched
    354344against the exception and may handle it.
    355345
    356346Exception matching checks the handler in each catch clause in the order
    357347they appear, top to bottom. If the representation of the raised exception type
    358 is the same or a descendant of @EXCEPTION_TYPE@$_i$, then @NAME@$_i$
     348is the same or a descendant of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$
    359349(if provided) is
    360350bound to a pointer to the exception and the statements in @HANDLER_BLOCK@$_i$
     
    362352freed and control continues after the try statement.
    363353
    364 If no termination handler is found during the search, then the default handler
    365 (\defaultTerminationHandler) visible at the raise statement is called.
    366 Through \CFA's trait system the best match at the raise statement is used.
     354If no termination handler is found during the search then the default handler
     355(\defaultTerminationHandler) visible at the raise statement is run.
     356Through \CFA's trait system the best match at the raise statement will be used.
    367357This function is run and is passed the copied exception.
    368 If the default handler finishes, control continues after the raise statement.
     358If the default handler is run control continues after the raise statement.
    369359
    370360There is a global @defaultTerminationHandler@ that is polymorphic over all
    371361termination exception types.
     362Since it is so general a more specific handler can be
     363defined and is used for those types, effectively overriding the handler
     364for a particular exception type.
    372365The global default termination handler performs a cancellation
    373 (see \vref{s:Cancellation} for the justification) on the current stack with the copied exception.
    374 Since it is so general, a more specific handler is usually
    375 defined, possibly with a detailed message, and used for specific exception type, effectively overriding the default handler.
     366(see \vref{s:Cancellation}) on the current stack with the copied exception.
    376367
    377368\subsection{Resumption}
    378369\label{s:Resumption}
    379370
    380 Resumption exception handling is the less familar EHM, but is
     371Resumption exception handling is less common than termination but is
    381372just as old~\cite{Goodenough75} and is simpler in many ways.
    382373It is a dynamic, non-local function call. If the raised exception is
    383 matched, a closure is taken from up the stack and executed,
     374matched a closure is taken from up the stack and executed,
    384375after which the raising function continues executing.
    385376The common uses for resumption exceptions include
     
    387378function once the error is corrected, and
    388379ignorable events, such as logging where nothing needs to happen and control
    389 should always continue from the raise point.
     380should always continue from the same place.
    390381
    391382A resumption raise is started with the @throwResume@ statement:
     
    401392the exception system while handling the exception.
    402393
    403 At run-time, no exception copy is made, since
    404 resumption does not unwind the stack nor otherwise remove values from the
    405 current scope, so there is no need to manage memory to keep the exception in scope.
    406 
    407 Then propagation starts with the search. It starts from the raise in the
     394At run-time, no exception copy is made.
     395Resumption does not unwind the stack nor otherwise remove values from the
     396current scope, so there is no need to manage memory to keep things in scope.
     397
     398The EHM then begins propagation. The search starts from the raise in the
    408399resuming function and proceeds towards the base of the stack,
    409400from callee to caller.
     
    419410}
    420411\end{cfa}
    421 % PAB, you say this above.
    422 % When a try statement is executed, it simply executes the statements in the
    423 % @GUARDED_BLOCK@ and then finishes.
    424 %
    425 % However, while the guarded statements are being executed, including any
    426 % invoked functions, all the handlers in these statements are included in the
    427 % search path.
    428 % Hence, if a resumption exception is raised, these handlers may be matched
    429 % against the exception and may handle it.
    430 %
    431 % Exception matching checks the handler in each catch clause in the order
    432 % they appear, top to bottom. If the representation of the raised exception type
    433 % is the same or a descendant of @EXCEPTION_TYPE@$_i$, then @NAME@$_i$
    434 % (if provided) is bound to a pointer to the exception and the statements in
    435 % @HANDLER_BLOCK@$_i$ are executed.
    436 % If control reaches the end of the handler, execution continues after the
    437 % the raise statement that raised the handled exception.
    438 %
    439 % Like termination, if no resumption handler is found during the search,
    440 % then the default handler (\defaultResumptionHandler) visible at the raise
    441 % statement is called. It will use the best match at the raise sight according
    442 % to \CFA's overloading rules. The default handler is
    443 % passed the exception given to the raise. When the default handler finishes
    444 % execution continues after the raise statement.
    445 %
    446 % There is a global @defaultResumptionHandler{} is polymorphic over all
    447 % resumption exceptions and performs a termination throw on the exception.
    448 % The \defaultTerminationHandler{} can be overridden by providing a new
    449 % function that is a better match.
    450 
    451 The @GUARDED_BLOCK@ and its associated nested guarded statements work the same
    452 for resumption as for termination, as does exception matching at each
    453 @catchResume@. Similarly, if no resumption handler is found during the search,
    454 then the currently visible default handler (\defaultResumptionHandler) is
    455 called and control continues after the raise statement if it returns. Finally,
    456 there is also a global @defaultResumptionHandler@, which can be overridden,
    457 that is polymorphic over all resumption exceptions but performs a termination
    458 throw on the exception rather than a cancellation.
    459 
    460 Throwing the exception in @defaultResumptionHandler@ has the positive effect of
    461 walking the stack a second time for a recovery handler. Hence, a programmer has
    462 two chances for help with a problem, fixup or recovery, should either kind of
    463 handler appear on the stack. However, this dual stack walk leads to following
    464 apparent anomaly:
    465 \begin{cfa}
    466 try {
    467         throwResume E;
    468 } catch (E) {
    469         // this handler runs
    470 }
    471 \end{cfa}
    472 because the @catch@ appears to handle a @throwResume@, but a @throwResume@ only
    473 matches with @catchResume@. The anomaly results because the unmatched
    474 @catchResuem@, calls @defaultResumptionHandler@, which in turn throws @E@.
    475 
    476412% I wonder if there would be some good central place for this.
    477 Note, termination and resumption handlers may be used together
     413Note that termination handlers and resumption handlers may be used together
    478414in a single try statement, intermixing @catch@ and @catchResume@ freely.
    479415Each type of handler only interacts with exceptions from the matching
    480416kind of raise.
     417When a try statement is executed, it simply executes the statements in the
     418@GUARDED_BLOCK@ and then finishes.
     419
     420However, while the guarded statements are being executed, including any
     421invoked functions, all the handlers in these statements are included in the
     422search path.
     423Hence, if a resumption exception is raised these handlers may be matched
     424against the exception and may handle it.
     425
     426Exception matching checks the handler in each catch clause in the order
     427they appear, top to bottom. If the representation of the raised exception type
     428is the same or a descendant of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$
     429(if provided) is bound to a pointer to the exception and the statements in
     430@HANDLER_BLOCK@$_i$ are executed.
     431If control reaches the end of the handler, execution continues after the
     432the raise statement that raised the handled exception.
     433
     434Like termination, if no resumption handler is found during the search,
     435the default handler (\defaultResumptionHandler) visible at the raise
     436statement is called. It will use the best match at the raise sight according
     437to \CFA's overloading rules. The default handler is
     438passed the exception given to the raise. When the default handler finishes
     439execution continues after the raise statement.
     440
     441There is a global \defaultResumptionHandler{} is polymorphic over all
     442resumption exceptions and preforms a termination throw on the exception.
     443The \defaultTerminationHandler{} can be overridden by providing a new
     444function that is a better match.
    481445
    482446\subsubsection{Resumption Marking}
    483447\label{s:ResumptionMarking}
    484448A key difference between resumption and termination is that resumption does
    485 not unwind the stack. A side effect is that, when a handler is matched
    486 and run, its try block (the guarded statements) and every try statement
     449not unwind the stack. A side effect that is that when a handler is matched
     450and run it's try block (the guarded statements) and every try statement
    487451searched before it are still on the stack. There presence can lead to
    488 the \emph{recursive resumption problem}.
     452the recursive resumption problem.
    489453
    490454The recursive resumption problem is any situation where a resumption handler
     
    500464When this code is executed, the guarded @throwResume@ starts a
    501465search and matches the handler in the @catchResume@ clause. This
    502 call is placed on the stack above the try-block. Now the second raise in the handler
    503 searches the same try block, matches, and puts another instance of the
     466call is placed on the stack above the try-block. The second raise then
     467searches the same try block and puts another instance of the
    504468same handler on the stack leading to infinite recursion.
    505469
    506 While this situation is trivial and easy to avoid, much more complex cycles can
    507 form with multiple handlers and different exception types.  The key point is
    508 that the programmer's intuition expects every raise in a handler to start
    509 searching \emph{below} the @try@ statement, making it difficult to understand
    510 and fix the problem.
    511 
    512 To prevent all of these cases, each try statement is ``marked" from the
    513 time the exception search reaches it to either when a matching handler
    514 completes or when the search reaches the base
     470While this situation is trivial and easy to avoid, much more complex cycles
     471can form with multiple handlers and different exception types.
     472
     473To prevent all of these cases, a each try statement is ``marked" from the
     474time the exception search reaches it to either when the exception is being
     475handled completes the matching handler or when the search reaches the base
    515476of the stack.
    516477While a try statement is marked, its handlers are never matched, effectively
     
    524485for instance, marking just the handlers that caught the exception,
    525486would also prevent recursive resumption.
    526 However, the rule selected mirrors what happens with termination,
    527 and hence, matches programmer intuition that a raise searches below a try.
    528 
    529 In detail, the marked try statements are the ones that would be removed from
    530 the stack for a termination exception, \ie those on the stack
     487However, these rules mirror what happens with termination.
     488
     489The try statements that are marked are the ones that would be removed from
     490the stack if this was a termination exception, that is those on the stack
    531491between the handler and the raise statement.
    532492This symmetry applies to the default handler as well, as both kinds of
     
    562522        // Only handle IO failure for f3.
    563523}
    564 // Handle a failure relating to f2 further down the stack.
     524// Can't handle a failure relating to f2 here.
    565525\end{cfa}
    566526In this example the file that experienced the IO error is used to decide
     
    593553
    594554\subsection{Comparison with Reraising}
    595 Without conditional catch, the only approach to match in more detail is to reraise
    596 the exception after it has been caught, if it could not be handled.
    597 \begin{center}
    598 \begin{tabular}{l|l}
     555A more popular way to allow handlers to match in more detail is to reraise
     556the exception after it has been caught, if it could not be handled here.
     557On the surface these two features seem interchangeable.
     558
     559If @throw;@ (no argument) starts a termination reraise,
     560which is the same as a raise but reuses the last caught exception,
     561then these two statements have the same behaviour:
    599562\begin{cfa}
    600563try {
    601         do_work_may_throw();
    602 } catch(excep_t * ex; can_handle(ex)) {
    603 
    604         handle(ex);
    605 
    606 
    607 
     564    do_work_may_throw();
     565} catch(exception_t * exc ; can_handle(exc)) {
     566    handle(exc);
    608567}
    609568\end{cfa}
    610 &
     569
    611570\begin{cfa}
    612571try {
    613         do_work_may_throw();
    614 } catch(excep_t * ex) {
    615         if (can_handle(ex)) {
    616                 handle(ex);
    617         } else {
    618                 throw;
    619         }
     572    do_work_may_throw();
     573} catch(exception_t * exc) {
     574    if (can_handle(exc)) {
     575        handle(exc);
     576    } else {
     577        throw;
     578    }
    620579}
    621580\end{cfa}
    622 \end{tabular}
    623 \end{center}
    624 Notice catch-and-reraise increases complexity by adding additional data and
    625 code to the exception process. Nevertheless, catch-and-reraise can simulate
    626 conditional catch straightforwardly, when exceptions are disjoint, \ie no
    627 inheritance.
    628 
    629 However, catch-and-reraise simulation becomes unusable for exception inheritance.
    630 \begin{flushleft}
    631 \begin{cfa}[xleftmargin=6pt]
    632 exception E1;
    633 exception E2(E1); // inheritance
    634 \end{cfa}
    635 \begin{tabular}{l|l}
    636 \begin{cfa}
    637 try {
    638         ... foo(); ... // raise E1/E2
    639         ... bar(); ... // raise E1/E2
    640 } catch( E2 e; e.rtn == foo ) {
    641         ...
    642 } catch( E1 e; e.rtn == foo ) {
    643         ...
    644 } catch( E1 e; e.rtn == bar ) {
    645         ...
    646 }
    647 
    648 \end{cfa}
    649 &
    650 \begin{cfa}
    651 try {
    652         ... foo(); ...
    653         ... bar(); ...
    654 } catch( E2 e ) {
    655         if ( e.rtn == foo ) { ...
    656         } else throw; // reraise
    657 } catch( E1 e ) {
    658         if (e.rtn == foo) { ...
    659         } else if (e.rtn == bar) { ...
    660         else throw; // reraise
    661 }
    662 \end{cfa}
    663 \end{tabular}
    664 \end{flushleft}
    665 The derived exception @E2@ must be ordered first in the catch list, otherwise
    666 the base exception @E1@ catches both exceptions. In the catch-and-reraise code
    667 (right), the @E2@ handler catches exceptions from both @foo@ and
    668 @bar@. However, the reraise misses the following catch clause. To fix this
    669 problem, an enclosing @try@ statement is need to catch @E2@ for @bar@ from the
    670 reraise, and its handler must duplicate the inner handler code for @bar@. To
    671 generalize, this fix for any amount of inheritance and complexity of try
    672 statement requires a technique called \emph{try-block
    673 splitting}~\cite{Krischer02}, which is not discussed in this thesis. It is
    674 sufficient to state that conditional catch is more expressive than
    675 catch-and-reraise in terms of complexity.
    676 
    677 \begin{comment}
    678 That is, they have the same behaviour in isolation.
     581That is, they will have the same behaviour in isolation.
    679582Two things can expose differences between these cases.
    680583
    681584One is the existence of multiple handlers on a single try statement.
    682 A reraise skips all later handlers for a try statement but a conditional
     585A reraise skips all later handlers on this try statement but a conditional
    683586catch does not.
    684 % Hence, if an earlier handler contains a reraise later handlers are
    685 % implicitly skipped, with a conditional catch they are not.
     587Hence, if an earlier handler contains a reraise later handlers are
     588implicitly skipped, with a conditional catch they are not.
    686589Still, they are equivalently powerful,
    687590both can be used two mimic the behaviour of the other,
     
    734637%   `exception_ptr current_exception() noexcept;`
    735638% https://www.python.org/dev/peps/pep-0343/
    736 \end{comment}
    737639
    738640\section{Finally Clauses}
     
    750652The @FINALLY_BLOCK@ is executed when the try statement is removed from the
    751653stack, including when the @GUARDED_BLOCK@ finishes, any termination handler
    752 finishes, or during an unwind.
     654finishes or during an unwind.
    753655The only time the block is not executed is if the program is exited before
    754656the stack is unwound.
     
    766668
    767669Not all languages with unwinding have finally clauses. Notably \Cpp does
    768 without it as destructors, and the RAII design pattern, serve a similar role.
    769 Although destructors and finally clauses can be used for the same cases,
     670without it as descructors, and the RAII design pattern, serve a similar role.
     671Although destructors and finally clauses can be used in the same cases,
    770672they have their own strengths, similar to top-level function and lambda
    771673functions with closures.
    772 Destructors take more work for their creation, but if there is clean-up code
    773 that needs to be run every time a type is used, they are much easier
     674Destructors take more work for their first use, but if there is clean-up code
     675that needs to be run every time a type is used they soon become much easier
    774676to set-up.
    775677On the other hand finally clauses capture the local context, so is easy to
    776678use when the clean-up is not dependent on the type of a variable or requires
    777679information from multiple variables.
     680% To Peter: I think these are the main points you were going for.
    778681
    779682\section{Cancellation}
     
    788691raise, this exception is not used in matching only to pass information about
    789692the cause of the cancellation.
    790 Finaly, since a cancellation only unwinds and forwards, there is no default handler.
     693(This also means matching cannot fail so there is no default handler.)
    791694
    792695After @cancel_stack@ is called the exception is copied into the EHM's memory
     
    799702After the main stack is unwound there is a program-level abort.
    800703
    801 The reasons for this semantics in a sequential program is that there is no more code to execute.
    802 This semantics also applies to concurrent programs, too, even if threads are running.
    803 That is, if any threads starts a cancellation, it implies all threads terminate.
    804 Keeping the same behaviour in sequential and concurrent programs is simple.
     704There are two reasons for these semantics.
     705The first is that it had to do this abort.
     706in a sequential program as there is nothing else to notify and the simplicity
     707of keeping the same behaviour in sequential and concurrent programs is good.
    805708Also, even in concurrent programs there may not currently be any other stacks
    806709and even if other stacks do exist, main has no way to know where they are.
     
    847750caller's context and passes it to the internal report.
    848751
    849 A coroutine only knows of two other coroutines, its starter and its last resumer.
     752A coroutine knows of two other coroutines, its starter and its last resumer.
    850753The starter has a much more distant connection, while the last resumer just
    851754(in terms of coroutine state) called resume on this coroutine, so the message
     
    855758cascade an error across any number of coroutines, cleaning up each in turn,
    856759until the error is handled or a thread stack is reached.
    857 
    858 \PAB{Part of this I do not understand. A cancellation cannot be caught. But you
    859 talk about handling a cancellation in the last sentence. Which is correct?}
  • doc/theses/andrew_beach_MMath/uw-ethesis.tex

    r9373b6a r478c610  
    247247\input{performance}
    248248\input{future}
    249 \input{conclusion}
    250249
    251250%----------------------------------------------------------------------
  • tests/io/manipulatorsOutput3.cfa

    r9373b6a r478c610  
    11//
    22// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
    3 //
    4 // The contents of this file are covered under the licence agreement in the
    5 // file "LICENCE" distributed with Cforall.
    6 //
     3//
    74// manipulatorsOutput3.cfa --
    85//
     
    107// Created On       : Tue Apr 13 17:54:23 2021
    118// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  8 22:37:20 2021
    13 // Update Count     : 2
     9// Last Modified On : Tue Apr 13 17:54:48 2021
     10// Update Count     : 1
    1411//
    1512
  • tests/sum.cfa

    r9373b6a r478c610  
    1111// Created On       : Wed May 27 17:56:53 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Thu Aug  5 21:27:25 2021
    14 // Update Count     : 346
     13// Last Modified On : Tue Jul 16 09:51:37 2019
     14// Update Count     : 336
    1515//
    1616
     
    2020trait sumable( T ) {
    2121        void ?{}( T &, zero_t );                                                        // 0 literal constructor
    22         void ?{}( T &, one_t );                                                         // 1 literal constructor
    2322        T ?+?( T, T );                                                                          // assortment of additions
    24         T ?+=?( T &, T );                                                                       // get pre/post ++ with += and one_t
     23        T ?+=?( T &, T );
     24        T ++?( T & );
     25        T ?++( T & );
    2526}; // sumable
    2627
    27 forall( T | sumable( T ) )                                                              // use trait
     28forall( T | sumable( T ) )                                              // use trait
    2829T sum( size_t size, T a[] ) {
    2930        T total = 0;                                                                            // initialize by 0 constructor
     
    3435
    3536int main( void ) {
     37#if 0
    3638        const int low = 5, High = 15, size = High - low;
    3739
     
    9294        S ?+?( S t1, S t2 ) { return (S){ t1.i + t2.i, t1.j + t2.j }; }
    9395        S ?+=?( S & t1, S t2 ) { t1 = t1 + t2; return t1; }
     96        S ++?( S & t ) { t += (S){1}; return t; }
     97        S ?++( S & t ) { S temp = t; t += (S){1}; return temp; }
    9498        ofstream & ?|?( ofstream & os, S v ) { return os | v.i | v.j; }
    9599        void ?|?( ofstream & os, S v ) { (ofstream &)(os | v); ends( os ); }
    96100
    97         S s = 0, a[size], v = { low, low };
     101        S s = (S){0}, a[size], v = { low, low };
    98102        for ( int i = 0; i < size; i += 1, v += (S){1} ) {
    99103                s += (S)v;
     
    118122                 | sum( size, gs.x ) | ", check" | (int)s;              // add field array in generic type
    119123        delete( gs.x );
     124#else
     125        const int low = 5, High = 15, size = High - low;
     126
     127        signed char s = 0, a[size], v = (char)low;
     128        for ( int i = 0; i < size; i += 1, v += 1hh ) {
     129                s += v;
     130                a[i] = v;
     131        } // for
     132        printf( "sum from %d to %d is %hhd, check %hhd\n", low, High,
     133                 sum( size, (signed char *)a ), (signed char)s );
     134
     135        unsigned char s = 0, a[size], v = low;
     136        for ( int i = 0; i < size; i += 1, v += 1hhu ) {
     137                s += (unsigned char)v;
     138                a[i] = (unsigned char)v;
     139        } // for
     140        printf( "sum from %d to %d is %hhu, check %hhu\n", low, High,
     141                 sum( size, (unsigned char *)a ), (unsigned char)s );
     142
     143        short int s = 0, a[size], v = low;
     144        for ( int i = 0; i < size; i += 1, v += 1h ) {
     145                s += (short int)v;
     146                a[i] = (short int)v;
     147        } // for
     148        printf( "sum from %d to %d is %hd, check %hd\n", low, High,
     149                 sum( size, (short int *)a ), (short int)s );
     150
     151        int s = 0, a[size], v = low;
     152        for ( int i = 0; i < size; i += 1, v += 1 ) {
     153                s += (int)v;
     154                a[i] = (int)v;
     155        } // for
     156        printf( "sum from %d to %d is %d, check %d\n", low, High,
     157                 sum( size, (int *)a ), (int)s );
     158
     159        float s = 0.0f, a[size], v = low / 10.0f;
     160        for ( int i = 0; i < size; i += 1, v += 0.1f ) {
     161                s += (float)v;
     162                a[i] = (float)v;
     163        } // for
     164        printf( "sum from %g to %g is %g, check %g\n", low / 10.0f, High / 10.0f,
     165                 sum( size, (float *)a ), (float)s );
     166
     167        double s = 0.0, a[size], v = low / 10.0;
     168        for ( int i = 0; i < size; i += 1, v += 0.1 ) {
     169                s += (double)v;
     170                a[i] = (double)v;
     171        } // for
     172        printf( "sum from %g to %g is %g, check %g\n", low / 10.0f, High / 10.0f,
     173                 sum( size, (double *)a ), (double)s );
     174
     175        struct S { int i, j; };
     176        void ?{}( S & s ) { s.[i, j] = 0; }
     177        void ?{}( S & s, int i ) { s.[i, j] = [i, 0]; }
     178        void ?{}( S & s, int i, int j ) { s.[i, j] = [i, j]; }
     179        void ?{}( S & s, zero_t ) { s.[i, j] = 0; }
     180        void ?{}( S & s, one_t ) { s.[i, j] = 1; }
     181        S ?+?( S t1, S t2 ) { return (S){ t1.i + t2.i, t1.j + t2.j }; }
     182        S ?+=?( S & t1, S t2 ) { t1 = t1 + t2; return t1; }
     183        S ++?( S & t ) { t += (S){1}; return t; }
     184        S ?++( S & t ) { S temp = t; t += (S){1}; return temp; }
     185        ofstream & ?|?( ofstream & os, S v ) { return os | v.i | v.j; }
     186        void ?|?( ofstream & os, S v ) { (ofstream &)(os | v); ends( os ); }
     187
     188        S s = 0, a[size], v = { low, low };
     189        for ( int i = 0; i < size; i += 1, v += (S){1} ) {
     190                s += (S)v;
     191                a[i] = (S)v;
     192        } // for
     193        printf( "sum from %d to %d is %d %d, check %d %d\n", low, High,
     194                 sum( size, (S *)a ).[i, j], s.[i, j] );
     195
     196        forall( Impl | sumable( Impl ) )
     197        struct GS {
     198                Impl * x, * y;
     199        };
     200        GS(int) gs;
     201        // FIX ME, resolution problem with anew not picking up the LH type
     202        gs.x = (typeof(gs.x))anew( size );                                      // create array storage for field
     203        s = 0; v = low;
     204        for ( int i = 0; i < size; i += 1, v += 1 ) {
     205                s += (int)v;
     206                gs.x[i] = (int)v;                                                               // set field array in generic type
     207        } // for
     208        printf( "sum from %d to %d is %d, check %d\n", low, High,
     209                 sum( size, gs.x ), (int)s );           // add field array in generic type
     210        delete( gs.x );
     211#endif
    120212} // main
    121213
Note: See TracChangeset for help on using the changeset viewer.