Ignore:
Timestamp:
Feb 4, 2021, 9:56:11 AM (10 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
9af0fe2d
Parents:
6a99803
Message:

Andrew MMath: Supposed to be focused on features but it ended up leaking out.

File:
1 edited

Legend:

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

    r6a99803 r29c9b23  
    55
    66\section{Virtuals}
     7Virtual types and casts are not part of the exception system nor are they
     8required for an exception system. But an object-oriented style hierarchy is a
     9great way of organizing exceptions so a minimal virtual system has been added
     10to \CFA.
     11
     12The pattern of a simple hierarchy was borrowed from object-oriented
     13programming was chosen for several reasons.
     14The first is that it allows new exceptions to be added in user code
     15and in libraries independently of each other. Another is it allows for
     16different levels of exception grouping (all exceptions, all IO exceptions or
     17a particular IO exception). Also it also provides a simple way of passing
     18data back and forth across the throw.
     19
    720Virtual types and casts are not required for a basic exception-system but are
    821useful for advanced exception features. However, \CFA is not object-oriented so
    922there is no obvious concept of virtuals. Hence, to create advanced exception
    10 features for this work, I needed to designed and implemented a virtual-like
     23features for this work, I needed to design and implement a virtual-like
    1124system for \CFA.
    1225
     26% NOTE: Maybe we should but less of the rational here.
    1327Object-oriented languages often organized exceptions into a simple hierarchy,
    1428\eg Java.
     
    6175While much of the virtual infrastructure is created, it is currently only used
    6276internally for exception handling. The only user-level feature is the virtual
    63 cast, which is the same as the \CC \lstinline[language=C++]|dynamic_cast|.
     77cast, which is the same as the \Cpp \lstinline[language=C++]|dynamic_cast|.
    6478\label{p:VirtualCast}
    6579\begin{cfa}
    6680(virtual TYPE)EXPRESSION
    6781\end{cfa}
    68 Note, the syntax and semantics matches a C-cast, rather than the unusual \CC
    69 syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be a
    70 pointer to a virtual type. The cast dynamically checks if the @EXPRESSION@ type
    71 is the same or a subtype of @TYPE@, and if true, returns a pointer to the
     82Note, the syntax and semantics matches a C-cast, rather than the function-like
     83\Cpp syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be
     84a pointer to a virtual type.
     85The cast dynamically checks if the @EXPRESSION@ type is the same or a subtype
     86of @TYPE@, and if true, returns a pointer to the
    7287@EXPRESSION@ object, otherwise it returns @0p@ (null pointer).
    7388
     
    8297\begin{cfa}
    8398trait is_exception(exceptT &, virtualT &) {
    84         virtualT const & @get_exception_vtable@(exceptT *);
     99        virtualT const & get_exception_vtable(exceptT *);
    85100};
    86101\end{cfa}
    87 The function takes any pointer, including the null pointer, and returns a
    88 reference to the virtual-table object. Defining this function also establishes
    89 the virtual type and a virtual-table pair to the \CFA type-resolver and
    90 promises @exceptT@ is a virtual type and a child of the base exception-type.
    91 
    92 \PAB{I do not understand this paragraph.}
    93 One odd thing about @get_exception_vtable@ is that it should always be a
    94 constant function, returning the same value regardless of its argument. A
    95 pointer or reference to the virtual table instance could be used instead,
    96 however using a function has some ease of implementation advantages and allows
    97 for easier disambiguation because the virtual type name (or the address of an
    98 instance that is in scope) can be used instead of the mangled virtual table
    99 name. Also note the use of the word ``promise'' in the trait
    100 description. Currently, \CFA cannot check to see if either @exceptT@ or
    101 @virtualT@ match the layout requirements. This is considered part of
    102 @get_exception_vtable@'s correct implementation.
     102The trait is defined over two types, the exception type and the virtual table
     103type. This should be one-to-one, each exception type has only one virtual
     104table type and vice versa. The only assertion in the trait is
     105@get_exception_vtable@, which takes a pointer of the exception type and
     106returns a reference to the virtual table type instance.
     107
     108The function @get_exception_vtable@ is actually a constant function.
     109Recardless of the value passed in (including the null pointer) it should
     110return a reference to the virtual table instance for that type.
     111The reason it is a function instead of a constant is that it make type
     112annotations easier to write as you can use the exception type instead of the
     113virtual table type; which usually has a mangled name.
     114% Also \CFA's trait system handles functions better than constants and doing
     115% it this way
     116
     117% I did have a note about how it is the programmer's responsibility to make
     118% sure the function is implemented correctly. But this is true of every
     119% similar system I know of (except Agda's I guess) so I took it out.
    103120
    104121\section{Raise}
     
    109126trait is_termination_exception(
    110127                exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
    111         void @defaultTerminationHandler@(exceptT &);
     128        void defaultTerminationHandler(exceptT &);
    112129};
    113130\end{cfa}
     
    119136trait is_resumption_exception(
    120137                exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
    121         void @defaultResumptionHandler@(exceptT &);
     138        void defaultResumptionHandler(exceptT &);
    122139};
    123140\end{cfa}
     
    126143
    127144Finally there are three convenience macros for referring to the these traits:
    128 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@. Each
    129 takes the virtual type's name, and for polymorphic types only, the
    130 parenthesized list of polymorphic arguments. These macros do the name mangling
    131 to get the virtual-table name and provide the arguments to both sides
    132 \PAB{What's a ``side''?}
     145@IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@.
     146All three traits are hard to use while naming the virtual table as it has an
     147internal mangled name. These macros take the exception name as their first
     148argument and do the mangling. They all take a second argument for polymorphic
     149types which is the parenthesized list of polymorphic arguments. These
     150arguments are passed to both the exception type and the virtual table type as
     151the arguments do have to match.
     152
     153For example consider a function that is polymorphic over types that have a
     154defined arithmetic exception:
     155\begin{cfa}
     156forall(Num | IS_EXCEPTION(Arithmetic, (Num)))
     157void some_math_function(Num & left, Num & right);
     158\end{cfa}
    133159
    134160\subsection{Termination}
     
    147173throw EXPRESSION;
    148174\end{cfa}
    149 The expression must return a termination-exception reference, where the
    150 termination exception has a type with a @void defaultTerminationHandler(T &)@
    151 (default handler) defined. The handler is found at the call site using \CFA's
    152 trait system and passed into the exception system along with the exception
    153 itself.
    154 
    155 At runtime, a representation of the exception type and an instance of the
    156 exception type is copied into managed memory (heap) to ensure it remains in
     175The expression must return a reference to a termination exception, where the
     176termination exception is any type that satifies @is_termination_exception@
     177at the call site.
     178Through \CFA's trait system the functions in the traits are passed into the
     179throw code. A new @defaultTerminationHandler@ can be defined in any scope to
     180change the throw's behavior (see below).
     181
     182At runtime, the exception returned by the expression
     183is copied into managed memory (heap) to ensure it remains in
    157184scope during unwinding. It is the user's responsibility to ensure the original
    158185exception object at the throw is freed when it goes out of scope. Being
     
    166193try {
    167194        GUARDED_BLOCK
    168 } @catch (EXCEPTION_TYPE$\(_1\)$ * NAME)@ { // termination handler 1
     195} catch (EXCEPTION_TYPE$\(_1\)$ * NAME$\(_1\)$) { // termination handler 1
    169196        HANDLER_BLOCK$\(_1\)$
    170 } @catch (EXCEPTION_TYPE$\(_2\)$ * NAME)@ { // termination handler 2
     197} catch (EXCEPTION_TYPE$\(_2\)$ * NAME$\(_2\)$) { // termination handler 2
    171198        HANDLER_BLOCK$\(_2\)$
    172199}
     
    179206Exception matching checks the representation of the thrown exception-type is
    180207the same or a descendant type of the exception types in the handler clauses. If
    181 there is a match, a pointer to the exception object created at the throw is
    182 bound to @NAME@ and the statements in the associated @HANDLER_BLOCK@ are
    183 executed. If control reaches the end of the handler, the exception is freed,
    184 and control continues after the try statement.
     208it is the same of a descendent of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$ is
     209bound to a pointer to the exception and the statements in @HANDLER_BLOCK@$_i$
     210are executed. If control reaches the end of the handler, the exception is
     211freed and control continues after the try statement.
    185212
    186213The default handler visible at the throw statement is used if no matching
    187214termination handler is found after the entire stack is searched. At that point,
    188215the default handler is called with a reference to the exception object
    189 generated at the throw. If the default handler returns, the system default
    190 action is executed, which often terminates the program. This feature allows
     216generated at the throw. If the default handler returns, control continues
     217from after the throw statement. This feature allows
    191218each exception type to define its own action, such as printing an informative
    192219error message, when an exception is not handled in the program.
     220However the default handler for all exception types triggers a cancellation
     221using the exception.
    193222
    194223\subsection{Resumption}
     
    197226Resumption raise, called ``resume'', is as old as termination
    198227raise~\cite{Goodenough75} but is less popular. In many ways, resumption is
    199 simpler and easier to understand, as it is simply a dynamic call (as in
    200 Lisp). The semantics of resumption is: search the stack for a matching handler,
     228simpler and easier to understand, as it is simply a dynamic call.
     229The semantics of resumption is: search the stack for a matching handler,
    201230execute the handler, and continue execution after the resume. Notice, the stack
    202231cannot be unwound because execution returns to the raise point. Resumption is
     
    210239\end{cfa}
    211240The semantics of the @throwResume@ statement are like the @throw@, but the
    212 expression has a type with a @void defaultResumptionHandler(T &)@ (default
    213 handler) defined, where the handler is found at the call site by the type
    214 system. At runtime, a representation of the exception type and an instance of
    215 the exception type is \emph{not} copied because the stack is maintained during
    216 the handler search.
     241expression has return a reference a type that satifies the trait
     242@is_resumption_exception@. Like with termination the exception system can
     243use these assertions while (throwing/raising/handling) the exception.
     244
     245At runtime, no copies are made. As the stack is not unwound the exception and
     246any values on the stack will remain in scope while the resumption is handled.
    217247
    218248Then the exception system searches the stack starting from the resume and
    219 proceeding towards the base of the stack, from callee to caller. At each stack
     249proceeding to the base of the stack, from callee to caller. At each stack
    220250frame, a check is made for resumption handlers defined by the @catchResume@
    221251clauses of a @try@ statement.
     
    223253try {
    224254        GUARDED_BLOCK
    225 } @catchResume (EXCEPTION_TYPE$\(_1\)$ * NAME)@ { // resumption handler 1
     255} catchResume (EXCEPTION_TYPE$\(_1\)$ * NAME$\(_1\)$) {
    226256        HANDLER_BLOCK$\(_1\)$
    227 } @catchResume (EXCEPTION_TYPE$\(_2\)$ * NAME)@ { // resumption handler 2
     257} catchResume (EXCEPTION_TYPE$\(_2\)$ * NAME$\(_2\)$) {
    228258        HANDLER_BLOCK$\(_2\)$
    229259}
     
    254284current point on the stack because new try statements may have been pushed by
    255285the handler or functions called from the handler. If there is no match back to
    256 the point of the current handler, the search skips\label{p:searchskip} the stack frames already
    257 searched by the first resume and continues after the try statement. The default
    258 handler always continues from default handler associated with the point where
    259 the exception is created.
     286the point of the current handler, the search skips\label{p:searchskip} the
     287stack frames already searched by the first resume and continues after
     288the try statement. The default handler always continues from default
     289handler associated with the point where the exception is created.
    260290
    261291% This might need a diagram. But it is an important part of the justification
     
    276306\end{verbatim}
    277307
    278 This resumption search-pattern reflect the one for termination, which matches
    279 with programmer expectations. However, it avoids the \emph{recursive
    280 resumption} problem. If parts of the stack are searched multiple times, loops
     308This resumption search pattern reflects the one for termination, and so
     309should come naturally to most programmers.
     310However, it avoids the \emph{recursive resumption} problem.
     311If parts of the stack are searched multiple times, loops
    281312can easily form resulting in infinite recursion.
    282313
     
    284315\begin{cfa}
    285316try {
    286         throwResume$\(_1\)$ (E &){};
    287 } catch( E * ) {
    288         throwResume;
    289 }
    290 \end{cfa}
    291 Based on termination semantics, programmer expectation is for the re-resume to
    292 continue searching the stack frames after the try statement. However, the
    293 current try statement is still on the stack below the handler issuing the
    294 reresume \see{\VRef{s:Reraise}}. Hence, the try statement catches the re-raise
    295 again and does another re-raise \emph{ad infinitum}, which is confusing and
    296 difficult to debug. The \CFA resumption search-pattern skips the try statement
    297 so the reresume search continues after the try, mathcing programmer
    298 expectation.
     317        throwResume (E &){}; // first
     318} catchResume(E *) {
     319        throwResume (E &){}; // second
     320}
     321\end{cfa}
     322If this handler is ever used it will be placed on top of the stack above the
     323try statement. If the stack was not masked than the @throwResume@ in the
     324handler would always be caught by the handler, leading to an infinite loop.
     325Masking avoids this problem and other more complex versions of it involving
     326multiple handlers and exception types.
     327
     328Other masking stratagies could be used; such as masking the handlers that
     329have caught an exception. This one was choosen because it creates a symmetry
     330with termination (masked sections of the stack would be unwound with
     331termination) and having only one pattern to learn is easier.
    299332
    300333\section{Conditional Catch}
    301 Both termination and resumption handler-clauses may perform conditional matching:
     334Both termination and resumption handler clauses can be given an additional
     335condition to further control which exceptions they handle:
    302336\begin{cfa}
    303337catch (EXCEPTION_TYPE * NAME ; @CONDITION@)
     
    323357
    324358\section{Reraise}
     359\color{red}{From Andrew: I recomend we talk about why the language doesn't
     360have rethrows/reraises instead.}
     361
    325362\label{s:Reraise}
    326363Within the handler block or functions called from the handler block, it is
     
    328365@throwResume@, respective.
    329366\begin{cfa}
    330 catch( ... ) {
     367try {
     368        ...
     369} catch( ... ) {
    331370        ... throw; // rethrow
    332371} catchResume( ... ) {
     
    341380handler is generated that does a program-level abort.
    342381
    343 
    344382\section{Finally Clauses}
    345383A @finally@ clause may be placed at the end of a @try@ statement.
     
    347385try {
    348386        GUARDED_BLOCK
    349 } ...   // any number or kind of handler clauses
    350 } finally {
     387} ... // any number or kind of handler clauses
     388... finally {
    351389        FINALLY_BLOCK
    352390}
    353391\end{cfa}
    354 The @FINALLY_BLOCK@ is executed when the try statement is unwound from the
    355 stack, \ie when the @GUARDED_BLOCK@ or any handler clause finishes. Hence, the
    356 finally block is always executed.
     392The @FINALLY_BLOCK@ is executed when the try statement is removed from the
     393stack, including when the @GUARDED_BLOCK@ or any handler clause finishes or
     394during an unwind.
     395The only time the block is not executed is if the program is exited before
     396that happens.
    357397
    358398Execution of the finally block should always finish, meaning control runs off
     
    370410possible forwards the cancellation exception to a different stack.
    371411
     412Cancellation is not an exception operation like termination or resumption.
    372413There is no special statement for starting a cancellation; instead the standard
    373414library function @cancel_stack@ is called passing an exception. Unlike a
     
    379420\item[Main Stack:]
    380421The main stack is the one used by the program main at the start of execution,
    381 and is the only stack in a sequential program. Hence, when cancellation is
    382 forwarded to the main stack, there is no other forwarding stack, so after the
    383 stack is unwound, there is a program-level abort.
     422and is the only stack in a sequential program. Even in a concurrent program
     423the main stack is only dependent on the environment that started the program.
     424Hence, when the main stack is cancelled there is nowhere else in the program
     425to notify. After the stack is unwound, there is a program-level abort.
    384426
    385427\item[Thread Stack:]
     
    387429@is_thread@ trait. A thread only has two points of communication that must
    388430happen: start and join. As the thread must be running to perform a
    389 cancellation, it must occur after start and before join, so join is a
    390 cancellation point. After the stack is unwound, the thread halts and waits for
    391 another thread to join with it. The joining thread, checks for a cancellation,
     431cancellation, it must occur after start and before join, so join is used
     432for communication here.
     433After the stack is unwound, the thread halts and waits for
     434another thread to join with it. The joining thread checks for a cancellation,
    392435and if present, resumes exception @ThreadCancelled@.
    393436
     
    397440the exception is not caught. The implicit join does a program abort instead.
    398441
    399 This semantics is for safety. One difficult problem for any exception system is
    400 defining semantics when an exception is raised during an exception search:
    401 which exception has priority, the original or new exception? No matter which
    402 exception is selected, it is possible for the selected one to disrupt or
    403 destroy the context required for the other. \PAB{I do not understand the
    404 following sentences.} This loss of information can happen with join but as the
    405 thread destructor is always run when the stack is being unwound and one
    406 termination/cancellation is already active. Also since they are implicit they
    407 are easier to forget about.
     442This semantics is for safety. If an unwind is triggered while another unwind
     443is underway only one of them can proceed as they both want to ``consume'' the
     444stack. Letting both try to proceed leads to very undefined behaviour.
     445Both termination and cancellation involve unwinding and, since the default
     446@defaultResumptionHandler@ preforms a termination that could more easily
     447happen in an implicate join inside a destructor. So there is an error message
     448and an abort instead.
     449
     450The recommended way to avoid the abort is to handle the intial resumption
     451from the implicate join. If required you may put an explicate join inside a
     452finally clause to disable the check and use the local
     453@defaultResumptionHandler@ instead.
    408454
    409455\item[Coroutine Stack:] A coroutine stack is created for a @coroutine@ object
Note: See TracChangeset for help on using the changeset viewer.