Changeset 4aba055


Ignore:
Timestamp:
Jun 15, 2021, 12:27:20 PM (16 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
2f19e03
Parents:
471ff17
Message:

Andrew MMath: Folded in features feedback and redid the reraise comparison. (3/3 for this group.)

File:
1 edited

Legend:

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

    r471ff17 r4aba055  
    22\label{c:features}
    33
    4 This chapter covers the design and user interface of the \CFA
    5 exception-handling mechanism (EHM). % or exception system.
    6 
    7 We will begin with an overview of EHMs in general. It is not a strict
    8 definition of all EHMs nor an exaustive list of all possible features.
     4This chapter covers the design and user interface of the \CFA EHM
     5and begins with a general overview of EHMs. It is not a strict
     6definition of all EHMs nor an exhaustive list of all possible features.
    97However it does cover the most common structure and features found in them.
    108
     9\section{Overview of EHMs}
    1110% We should cover what is an exception handling mechanism and what is an
    1211% exception before this. Probably in the introduction. Some of this could
    1312% move there.
    14 \paragraph{Raise / Handle}
     13\subsection{Raise / Handle}
    1514An exception operation has two main parts: raise and handle.
    1615These terms are sometimes also known as throw and catch but this work uses
    1716throw/catch as a particular kind of raise/handle.
    18 These are the two parts that the user will write themselves and may
     17These are the two parts that the user writes and may
    1918be the only two pieces of the EHM that have any syntax in the language.
    2019
    21 \subparagraph{Raise}
     20\paragraph{Raise}
    2221The raise is the starting point for exception handling. It marks the beginning
    23 of exception handling by raising an excepion, which passes it to
     22of exception handling by raising an exception, which passes it to
    2423the EHM.
    2524
     
    2928purposes of this overview that can be ignored.
    3029
    31 \subparagraph{Handle}
     30\paragraph{Handle}
    3231The purpose of most exception operations is to run some user code to handle
    3332that exception. This code is given, with some other information, in a handler.
    3433
    3534A handler has three common features: the previously mentioned user code, a
    36 region of code they cover and an exception label/condition that matches
     35region of code they guard and an exception label/condition that matches
    3736certain exceptions.
    38 Only raises inside the covered region and raising exceptions that match the
     37Only raises inside the guarded region and raising exceptions that match the
    3938label can be handled by a given handler.
    40 Different EHMs will have different rules to pick a handler
    41 if multipe handlers could be used such as ``best match" or ``first found".
     39Different EHMs use different rules to pick a handler,
     40if multiple handlers could be used such as ``best match" or ``first found".
    4241
    4342The @try@ statements of \Cpp, Java and Python are common examples. All three
    44 also show another common feature of handlers, they are grouped by the covered
     43also show another common feature of handlers, they are grouped by the guarded
    4544region.
    4645
    47 \paragraph{Propagation}
     46\subsection{Propagation}
    4847After an exception is raised comes what is usually the biggest step for the
    49 EHM: finding and setting up the handler. The propogation from raise to
     48EHM: finding and setting up the handler. The propagation from raise to
    5049handler can be broken up into three different tasks: searching for a handler,
    5150matching against the handler and installing the handler.
    5251
    53 \subparagraph{Searching}
     52\paragraph{Searching}
    5453The EHM begins by searching for handlers that might be used to handle
    5554the exception. Searching is usually independent of the exception that was
    56 thrown as it looks for handlers that have the raise site in their covered
     55thrown as it looks for handlers that have the raise site in their guarded
    5756region.
    58 This includes handlers in the current function, as well as any in callers
    59 on the stack that have the function call in their covered region.
    60 
    61 \subparagraph{Matching}
     57The search includes handlers in the current function, as well as any in
     58callers on the stack that have the function call in their guarded region.
     59
     60\paragraph{Matching}
    6261Each handler found has to be matched with the raised exception. The exception
    63 label defines a condition that be use used with exception and decides if
     62label defines a condition that is used with exception and decides if
    6463there is a match or not.
    6564
    66 In languages where the first match is used this step is intertwined with
    67 searching, a match check is preformed immediately after the search finds
     65In languages where the first match is used, this step is intertwined with
     66searching; a match check is preformed immediately after the search finds
    6867a possible handler.
    6968
    70 \subparagraph{Installing}
     69\paragraph{Installing}
    7170After a handler is chosen it must be made ready to run.
    7271The implementation can vary widely to fit with the rest of the
     
    7574case when stack unwinding is involved.
    7675
    77 If a matching handler is not guarantied to be found the EHM will need a
    78 different course of action here in the cases where no handler matches.
    79 This is only required with unchecked exceptions as checked exceptions
    80 (such as in Java) can make than guaranty.
    81 This different action can also be installing a handler but it is usually an
    82 implicat and much more general one.
    83 
    84 \subparagraph{Hierarchy}
     76If a matching handler is not guarantied to be found, the EHM needs a
     77different course of action for the case where no handler matches.
     78This situation only occurs with unchecked exceptions as checked exceptions
     79(such as in Java) can make the guarantee.
     80This unhandled action is usually very general, such as aborting the program.
     81
     82\paragraph{Hierarchy}
    8583A common way to organize exceptions is in a hierarchical structure.
    86 This is especially true in object-orientated languages where the
     84This pattern comes from object-orientated languages where the
    8785exception hierarchy is a natural extension of the object hierarchy.
    8886
     
    9290\end{center}
    9391
    94 A handler labelled with any given exception can handle exceptions of that
     92A handler labeled with any given exception can handle exceptions of that
    9593type or any child type of that exception. The root of the exception hierarchy
    9694(here \code{C}{exception}) acts as a catch-all, leaf types catch single types
     
    106104% Could I cite the rational for the Python IO exception rework?
    107105
    108 \paragraph{Completion}
     106\subsection{Completion}
    109107After the handler has finished the entire exception operation has to complete
    110108and continue executing somewhere else. This step is usually simple,
     
    113111
    114112The EHM can return control to many different places,
    115 the most common are after the handler definition and after the raise.
    116 
    117 \paragraph{Communication}
     113the most common are after the handler definition (termination)
     114and after the raise (resumption).
     115
     116\subsection{Communication}
    118117For effective exception handling, additional information is often passed
    119 from the raise to the handler.
     118from the raise to the handler and back again.
    120119So far only communication of the exceptions' identity has been covered.
    121 A common method is putting fields into the exception instance and giving the
    122 handler access to them.
     120A common communication method is putting fields into the exception instance
     121and giving the handler access to them.
     122Passing the exception by reference instead of by value can allow data to be
     123passed in both directions.
    123124
    124125\section{Virtuals}
    125126Virtual types and casts are not part of \CFA's EHM nor are they required for
    126127any EHM.
    127 However the \CFA uses a hierarchy built with the virtual system as the basis
    128 for exceptions and exception matching.
    129 
    130 The virtual system would have ideally been part of \CFA before the work
     128However, it is one of the best ways to support an exception hierachy
     129is via a virtual hierarchy and dispatch system.
     130
     131Ideally, the virtual system would have been part of \CFA before the work
    131132on exception handling began, but unfortunately it was not.
    132 Because of this only the features and framework needed for the EHM were
     133Hence, only the features and framework needed for the EHM were
    133134designed and implemented. Other features were considered to ensure that
    134 the structure could accomidate other desirable features but they were not
    135 implemented.
    136 The rest of this section will only discuss the finalized portion of the
    137 virtual system.
     135the structure could accommodate other desirable features in the future
     136but they were not implemented.
     137The rest of this section will only discuss the implemented subset of the
     138virtual system design.
    138139
    139140The virtual system supports multiple ``trees" of types. Each tree is
     
    145146% A type's ancestors are its parent and its parent's ancestors.
    146147% The root type has no ancestors.
    147 % A type's decendents are its children and its children's decendents.
     148% A type's descendants are its children and its children's descendants.
    148149
    149150Every virtual type also has a list of virtual members. Children inherit
     
    151152It is important to note that these are virtual members, not virtual methods
    152153of object-orientated programming, and can be of any type.
     154
    153155\CFA still supports virtual methods as a special case of virtual members.
    154 Function pointers that take a pointer to the virtual type will be modified
     156Function pointers that take a pointer to the virtual type are modified
    155157with each level of inheritance so that refers to the new type.
    156158This means an object can always be passed to a function in its virtual table
    157159as if it were a method.
     160\todo{Clarify (with an example) virtual methods.}
    158161
    159162Each virtual type has a unique id.
    160 This unique id and all the virtual members are combined
     163This id and all the virtual members are combined
    161164into a virtual table type. Each virtual type has a pointer to a virtual table
    162165as a hidden field.
     166\todo{Might need a diagram for virtual structure.}
    163167
    164168Up until this point the virtual system is similar to ones found in
    165169object-orientated languages but this where \CFA diverges. Objects encapsulate a
    166170single set of behaviours in each type, universally across the entire program,
    167 and indeed all programs that use that type definition. In this sense the
     171and indeed all programs that use that type definition. In this sense, the
    168172types are ``closed" and cannot be altered.
    169173
    170 In \CFA types do not encapsulate any behaviour. Traits are local and
    171 types can begin to statify a trait, stop satifying a trait or satify the same
     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
    172176trait in a different way at any lexical location in the program.
    173 In this sense they are ``open" as they can change at any time. This means it
    174 is implossible to pick a single set of functions that repersent the type's
    175 implementation across the program.
     177In this sense, they are ``open" as they can change at any time.
     178This capability means it is impossible to pick a single set of functions
     179that represent the type's implementation across the program.
    176180
    177181\CFA side-steps this issue by not having a single virtual table for each
    178 type. A user can define virtual tables which are filled in at their
    179 declaration and given a name. Anywhere that name is visible, even if it was
    180 defined locally inside a function (although that means it will not have a
     182type. A user can define virtual tables that are filled in at their
     183declaration and given a name. Anywhere that name is visible, even if it is
     184defined locally inside a function (although that means it does not have a
    181185static lifetime), it can be used.
    182 Specifically, a virtual type is ``bound" to a virtual table which
     186Specifically, a virtual type is ``bound" to a virtual table that
    183187sets the virtual members for that object. The virtual members can be accessed
    184188through the object.
     
    212216\end{cfa}
    213217The trait is defined over two types, the exception type and the virtual table
    214 type. Each exception type should have but a single virtual table type.
    215 Now there are no actual assertions in this trait because the trait system
    216 actually can't express them (adding such assertions would be part of
     218type. Each exception type should have a single virtual table type.
     219There are no actual assertions in this trait because the trait system
     220cannot express them yet (adding such assertions would be part of
    217221completing the virtual system). The imaginary assertions would probably come
    218222from a trait defined by the virtual system, and state that the exception type
    219 is a virtual type, is a decendent of @exception_t@ (the base exception type)
     223is a virtual type, is a descendant of @exception_t@ (the base exception type)
    220224and note its virtual table type.
    221225
     
    236240};
    237241\end{cfa}
    238 Both traits ensure a pair of types are an exception type and its virtual table
     242Both traits ensure a pair of types are an exception type, its virtual table
     243type
    239244and defines one of the two default handlers. The default handlers are used
    240245as fallbacks and are discussed in detail in \vref{s:ExceptionHandling}.
     
    264269\section{Exception Handling}
    265270\label{s:ExceptionHandling}
     271As stated,
    266272\CFA provides two kinds of exception handling: termination and resumption.
    267273These twin operations are the core of \CFA's exception handling mechanism.
     
    271277Both operations follow the same set of steps.
    272278Both start with the user preforming a raise on an exception.
    273 Then the exception propogates up the stack.
     279Then the exception propagates up the stack.
    274280If a handler is found the exception is caught and the handler is run.
    275 After that control returns to normal execution.
    276 If the search fails a default handler is run and then control
    277 returns to normal execution after the raise.
     281After that control continues at a raise-dependent location.
     282If the search fails a default handler is run and, if it returns, then control
     283continues after the raise.
    278284
    279285This general description covers what the two kinds have in common.
    280 Differences include how propogation is preformed, where exception continues
     286Differences include how propagation is preformed, where exception continues
    281287after an exception is caught and handled and which default handler is run.
    282288
     
    285291Termination handling is the familiar kind and used in most programming
    286292languages with exception handling.
    287 It is dynamic, non-local goto. If the raised exception is matched and
    288 handled the stack is unwound and control will (usually) continue the function
     293It is a dynamic, non-local goto. If the raised exception is matched and
     294handled, the stack is unwound and control (usually) continues in the function
    289295on the call stack that defined the handler.
    290296Termination is commonly used when an error has occurred and recovery is
     
    301307termination exception is any type that satisfies the trait
    302308@is_termination_exception@ at the call site.
    303 Through \CFA's trait system the trait functions are implicity passed into the
     309Through \CFA's trait system, the trait functions are implicitly passed into the
    304310throw code and the EHM.
    305311A new @defaultTerminationHandler@ can be defined in any scope to
    306 change the throw's behavior (see below).
    307 
    308 The throw will copy the provided exception into managed memory to ensure
     312change the throw's behaviour (see below).
     313
     314The throw copies the provided exception into managed memory to ensure
    309315the exception is not destroyed if the stack is unwound.
    310316It is the user's responsibility to ensure the original exception is cleaned
    311 up wheither the stack is unwound or not. Allocating it on the stack is
     317up whether the stack is unwound or not. Allocating it on the stack is
    312318usually sufficient.
    313319
    314 Then propogation starts with the search. \CFA uses a ``first match" rule so
     320% How to say propagation starts, its first sub-step is the search.
     321Then propagation starts with the search. \CFA uses a ``first match" rule so
    315322matching is preformed with the copied exception as the search continues.
    316 It starts from the throwing function and proceeds to the base of the stack,
     323It starts from the throwing function and proceeds towards base of the stack,
    317324from callee to caller.
    318325At each stack frame, a check is made for resumption handlers defined by the
     
    327334}
    328335\end{cfa}
    329 When viewed on its own, a try statement will simply execute the statements
    330 in \snake{GUARDED_BLOCK} and when those are finished the try statement finishes.
     336When viewed on its own, a try statement simply executes the statements
     337in \snake{GUARDED_BLOCK} and when those are finished,
     338the try statement finishes.
    331339
    332340However, while the guarded statements are being executed, including any
    333 invoked functions, all the handlers in the statement are now on the search
    334 path. If a termination exception is thrown and not handled further up the
    335 stack they will be matched against the exception.
     341invoked functions, all the handlers in these statements are included in the
     342search path.
     343Hence, if a termination exception is raised these handlers may be matched
     344against the exception and may handle it.
    336345
    337346Exception matching checks the handler in each catch clause in the order
    338 they appear, top to bottom. If the representation of the thrown exception type
     347they appear, top to bottom. If the representation of the raised exception type
    339348is the same or a descendant of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$
    340349(if provided) is
     
    344353
    345354If no termination handler is found during the search then the default handler
    346 (\defaultTerminationHandler) is run.
    347 Through \CFA's trait system the best match at the throw sight will be used.
    348 This function is run and is passed the copied exception. After the default
    349 handler is run control continues after the throw statement.
     355(\defaultTerminationHandler) visible at the raise statement is run.
     356Through \CFA's trait system the best match at the raise statement will be used.
     357This function is run and is passed the copied exception.
     358If the default handler is run control continues after the raise statement.
    350359
    351360There is a global @defaultTerminationHandler@ that is polymorphic over all
    352 exception types. Since it is so general a more specific handler can be
    353 defined and will be used for those types, effectively overriding the handler
    354 for particular exception type.
     361termination 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.
    355365The global default termination handler performs a cancellation
    356366(see \vref{s:Cancellation}) on the current stack with the copied exception.
     
    362372just as old~\cite{Goodenough75} and is simpler in many ways.
    363373It is a dynamic, non-local function call. If the raised exception is
    364 matched a closure will be taken from up the stack and executed,
    365 after which the raising function will continue executing.
    366 These are most often used when an error occurred and if the error is repaired
    367 then the function can continue.
     374matched a closure is taken from up the stack and executed,
     375after which the raising function continues executing.
     376The common uses for resumption exceptions include
     377potentially repairable errors, where execution can continue in the same
     378function once the error is corrected, and
     379ignorable events, such as logging where nothing needs to happen and control
     380should always continue from the same place.
    368381
    369382A resumption raise is started with the @throwResume@ statement:
     
    371384throwResume EXPRESSION;
    372385\end{cfa}
     386\todo{Decide on a final set of keywords and use them everywhere.}
    373387It works much the same way as the termination throw.
    374388The expression must return a reference to a resumption exception,
     
    379393
    380394At run-time, no exception copy is made.
    381 As the stack is not unwound the exception and
    382 any values on the stack will remain in scope while the resumption is handled.
    383 
    384 The EHM then begins propogation. The search starts from the raise in the
    385 resuming function and proceeds to the base of the stack, from callee to caller.
     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
     399resuming function and proceeds towards the base of the stack,
     400from callee to caller.
    386401At each stack frame, a check is made for resumption handlers defined by the
    387402@catchResume@ clauses of a @try@ statement.
     
    398413Note that termination handlers and resumption handlers may be used together
    399414in a single try statement, intermixing @catch@ and @catchResume@ freely.
    400 Each type of handler will only interact with exceptions from the matching
    401 type of raise.
    402 When a try statement is executed it simply executes the statements in the
     415Each type of handler only interacts with exceptions from the matching
     416kind of raise.
     417When a try statement is executed, it simply executes the statements in the
    403418@GUARDED_BLOCK@ and then finishes.
    404419
    405420However, while the guarded statements are being executed, including any
    406 invoked functions, all the handlers in the statement are now on the search
    407 path. If a resumption exception is reported and not handled further up the
    408 stack they will be matched against the exception.
     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.
    409425
    410426Exception matching checks the handler in each catch clause in the order
    411 they appear, top to bottom. If the representation of the thrown exception type
     427they appear, top to bottom. If the representation of the raised exception type
    412428is the same or a descendant of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$
    413429(if provided) is bound to a pointer to the exception and the statements in
     
    416432the raise statement that raised the handled exception.
    417433
    418 Like termination, if no resumption handler is found, the default handler
    419 visible at the throw statement is called. It will use the best match at the
    420 call sight according to \CFA's overloading rules. The default handler is
    421 passed the exception given to the throw. When the default handler finishes
     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
    422439execution continues after the raise statement.
    423440
    424441There is a global \defaultResumptionHandler{} is polymorphic over all
    425 termination exceptions and preforms a termination throw on the exception.
    426 The \defaultTerminationHandler{} for that raise is matched at the
    427 original raise statement (the resumption @throw@\-@Resume@) and it can be
    428 customized by introducing a new or better match as well.
     442resumption exceptions and preforms a termination throw on the exception.
     443The \defaultTerminationHandler{} can be overriden by providing a new
     444function that is a better match.
    429445
    430446\subsubsection{Resumption Marking}
     
    433449not unwind the stack. A side effect that is that when a handler is matched
    434450and run it's try block (the guarded statements) and every try statement
    435 searched before it are still on the stack. This can lead to the recursive
    436 resumption problem.
     451searched before it are still on the stack. There presence can lead to
     452the recursive resumption problem.
    437453
    438454The recursive resumption problem is any situation where a resumption handler
     
    446462}
    447463\end{cfa}
    448 When this code is executed the guarded @throwResume@ will throw, start a
    449 search and match the handler in the @catchResume@ clause. This will be
    450 call and placed on the stack on top of the try-block. The second throw then
    451 throws and will search the same try block and put call another instance of the
    452 same handler leading to an infinite loop.
    453 
    454 This situation is trivial and easy to avoid, but much more complex cycles
     464When this code is executed, the guarded @throwResume@ starts a
     465search and matches the handler in the @catchResume@ clause. This
     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
     468same handler on the stack leading to infinite recursion.
     469
     470While this situation is trivial and easy to avoid, much more complex cycles
    455471can form with multiple handlers and different exception types.
    456472
    457 To prevent all of these cases we mark try statements on the stack.
    458 A try statement is marked when a match check is preformed with it and an
    459 exception. The statement will be unmarked when the handling of that exception
    460 is completed or the search completes without finding a handler.
    461 While a try statement is marked its handlers are never matched, effectify
     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
     476of the stack.
     477While a try statement is marked, its handlers are never matched, effectively
    462478skipping over it to the next try statement.
    463479
     
    466482\end{center}
    467483
    468 These rules mirror what happens with termination.
    469 When a termination throw happens in a handler the search will not look at
    470 any handlers from the original throw to the original catch because that
    471 part of the stack has been unwound.
    472 A resumption raise in the same situation wants to search the entire stack,
    473 but it will not try to match the exception with try statements in the section
    474 that would have been unwound as they are marked.
    475 
    476 The symmetry between resumption termination is why this pattern was picked.
    477 Other patterns, such as marking just the handlers that caught, also work but
    478 lack the symmetry means there are more rules to remember.
     484There are other sets of marking rules that could be used,
     485for instance, marking just the handlers that caught the exception,
     486would also prevent recursive resumption.
     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
     491between the handler and the raise statement.
     492This symmetry applies to the default handler as well, as both kinds of
     493default handlers are run at the raise statement, rather than (physically
     494or logically) at the bottom of the stack.
     495% In early development having the default handler happen after
     496% unmarking was just more useful. We assume that will continue.
    479497
    480498\section{Conditional Catch}
     
    491509did not match.
    492510
    493 The condition matching allows finer matching by allowing the match to check
     511The condition matching allows finer matching by checking
    494512more kinds of information than just the exception type.
    495513\begin{cfa}
     
    506524// Can't handle a failure relating to f2 here.
    507525\end{cfa}
    508 In this example the file that experianced the IO error is used to decide
     526In this example the file that experienced the IO error is used to decide
    509527which handler should be run, if any at all.
    510528
     
    536554\subsection{Comparison with Reraising}
    537555A more popular way to allow handlers to match in more detail is to reraise
    538 the exception after it has been caught if it could not be handled here.
    539 On the surface these two features seem interchangable.
    540 
    541 If we used @throw;@ to start a termination reraise then these two statements
    542 would have the same behaviour:
     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:
    543562\begin{cfa}
    544563try {
     
    560579}
    561580\end{cfa}
    562 If there are further handlers after this handler only the first version will
    563 check them. If multiple handlers on a single try block that could handle the
    564 same exception the translations get more complex but they are equivilantly
    565 powerful.
    566 
    567 Until stack unwinding comes into the picture. In termination handling, a
    568 conditional catch happens before the stack is unwound, but a reraise happens
    569 afterwards. Normally this might only cause you to loose some debug
    570 information you could get from a stack trace (and that can be side stepped
    571 entirely by collecting information during the unwind). But for \CFA there is
    572 another issue, if the exception isn't handled the default handler should be
    573 run at the site of the original raise.
    574 
    575 There are two problems with this: the site of the original raise doesn't
    576 exist anymore and the default handler might not exist anymore. The site will
    577 always be removed as part of the unwinding, often with the entirety of the
    578 function it was in. The default handler could be a stack allocated nested
    579 function removed during the unwind.
    580 
    581 This means actually trying to pretend the catch didn't happening, continuing
    582 the original raise instead of starting a new one, is infeasible.
    583 That is the expected behaviour for most languages and we can't replicate
    584 that behaviour.
     581That is, they will have the same behaviour in isolation.
     582Two things can expose differences between these cases.
     583
     584One is the existance of multiple handlers on a single try statement.
     585A reraise skips all later handlers on this try statement but a conditional
     586catch does not.
     587Hence, if an earlier handler contains a reraise later handlers are
     588implicitly skipped, with a conditional catch they are not.
     589Still, they are equivalently powerful,
     590both can be used two mimick the behaviour of the other,
     591as reraise can pack arbitrary code in the handler and conditional catches
     592can put arbitrary code in the predicate.
     593% I was struggling with a long explination about some simple solutions,
     594% like repeating a condition on later handlers, and the general solution of
     595% merging everything together. I don't think it is useful though unless its
     596% for a proof.
     597% https://en.cppreference.com/w/cpp/language/throw
     598
     599The question then becomes ``Which is a better default?"
     600We believe that not skipping possibly useful handlers is a better default.
     601If a handler can handle an exception it should and if the handler can not
     602handle the exception then it is probably safer to have that explicitly
     603described in the handler itself instead of implicitly described by its
     604ordering with other handlers.
     605% Or you could just alter the semantics of the throw statement. The handler
     606% index is in the exception so you could use it to know where to start
     607% searching from in the current try statement.
     608% No place for the `goto else;` metaphor.
     609
     610The other issue is all of the discussion above assumes that the only
     611way to tell apart two raises is the exception being raised and the remaining
     612search path.
     613This is not true generally, the current state of the stack can matter in
     614a number of cases, even only for a stack trace after an program abort.
     615But \CFA has a much more significant need of the rest of the stack, the
     616default handlers for both termination and resumption.
     617
     618% For resumption it turns out it is possible continue a raise after the
     619% exception has been caught, as if it hadn't been caught in the first place.
     620This becomes a problem combined with the stack unwinding used in termination
     621exception handling.
     622The stack is unwound before the handler is installed, and hence before any
     623reraises can run. So if a reraise happens the previous stack is gone,
     624the place on the stack where the default handler was supposed to run is gone,
     625if the default handler was a local function it may have been unwound too.
     626There is no reasonable way to restore that information, so the reraise has
     627to be considered as a new raise.
     628This is the strongest advantage conditional catches have over reraising,
     629they happen before stack unwinding and avoid this problem.
     630
     631% The one possible disadvantage of conditional catch is that it runs user
     632% code during the exception search. While this is a new place that user code
     633% can be run destructors and finally clauses are already run during the stack
     634% unwinding.
     635%
     636% https://www.cplusplus.com/reference/exception/current_exception/
     637%   `exception_ptr current_exception() noexcept;`
     638% https://www.python.org/dev/peps/pep-0343/
    585639
    586640\section{Finally Clauses}
     
    614668
    615669Not all languages with unwinding have finally clauses. Notably \Cpp does
    616 without it as descructors serve a similar role. Although destructors and
    617 finally clauses can be used in many of the same areas they have their own
    618 use cases like top-level functions and lambda functions with closures.
    619 Destructors take a bit more work to set up but are much easier to reuse while
    620 finally clauses are good for one-off uses and
    621 can easily include local information.
     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,
     672they have their own strengths, similar to top-level function and lambda
     673functions with closures.
     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
     676to set-up.
     677On the other hand finally clauses capture the local context, so is easy to
     678use when the clean-up is not dependent on the type of a variable or requires
     679information from multiple variables.
     680% To Peter: I think these are the main points you were going for.
    622681
    623682\section{Cancellation}
     
    635694
    636695After @cancel_stack@ is called the exception is copied into the EHM's memory
    637 and the current stack is
    638 unwound. After that it depends one which stack is being cancelled.
     696and the current stack is unwound.
     697The behaviour after that depends on the kind of stack being cancelled.
    639698
    640699\paragraph{Main Stack}
     
    643702After the main stack is unwound there is a program-level abort.
    644703
    645 There are two reasons for this. The first is that it obviously had to do this
     704There are two reasons for these semantics.
     705The first is that it had to do this abort.
    646706in a sequential program as there is nothing else to notify and the simplicity
    647707of keeping the same behaviour in sequential and concurrent programs is good.
    648 Also, even in concurrent programs there is no stack that an innate connection
    649 to, so it would have be explicitly managed.
     708Also, even in concurrent programs there may not currently be any other stacks
     709and even if other stacks do exist, main has no way to know where they are.
    650710
    651711\paragraph{Thread Stack}
    652712A thread stack is created for a \CFA @thread@ object or object that satisfies
    653713the @is_thread@ trait.
    654 After a thread stack is unwound there exception is stored until another
     714After a thread stack is unwound, the exception is stored until another
    655715thread attempts to join with it. Then the exception @ThreadCancelled@,
    656716which stores a reference to the thread and to the exception passed to the
    657 cancellation, is reported from the join.
     717cancellation, is reported from the join to the joining thread.
    658718There is one difference between an explicit join (with the @join@ function)
    659719and an implicit join (from a destructor call). The explicit join takes the
    660720default handler (@defaultResumptionHandler@) from its calling context while
    661 the implicit join provides its own which does a program abort if the
     721the implicit join provides its own; which does a program abort if the
    662722@ThreadCancelled@ exception cannot be handled.
    663723
    664 Communication is done at join because a thread only has to have to points of
    665 communication with other threads: start and join.
     724The communication and synchronization are done here because threads only have
     725two structural points (not dependent on user-code) where
     726communication/synchronization happens: start and join.
    666727Since a thread must be running to perform a cancellation (and cannot be
    667728cancelled from another stack), the cancellation must be after start and
    668 before the join. So join is the one that we will use.
     729before the join, so join is used.
    669730
    670731% TODO: Find somewhere to discuss unwind collisions.
     
    678739A coroutine stack is created for a @coroutine@ object or object that
    679740satisfies the @is_coroutine@ trait.
    680 After a coroutine stack is unwound control returns to the resume function
    681 that most recently resumed it. The resume statement reports a
     741After a coroutine stack is unwound, control returns to the @resume@ function
     742that most recently resumed it. @resume@ reports a
    682743@CoroutineCancelled@ exception, which contains a references to the cancelled
    683744coroutine and the exception used to cancel it.
    684 The resume function also takes the \defaultResumptionHandler{} from the
     745The @resume@ function also takes the \defaultResumptionHandler{} from the
    685746caller's context and passes it to the internal report.
    686747
    687748A coroutine knows of two other coroutines, its starter and its last resumer.
    688 The starter has a much more distant connection while the last resumer just
     749The starter has a much more distant connection, while the last resumer just
    689750(in terms of coroutine state) called resume on this coroutine, so the message
    690751is passed to the latter.
Note: See TracChangeset for help on using the changeset viewer.