Ignore:
Timestamp:
Sep 27, 2021, 2:09:55 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
Children:
cc287800
Parents:
4e28d2e9 (diff), 056cbdb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
doc/theses/andrew_beach_MMath
Files:
2 added
22 edited
10 moved

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/Makefile

    r4e28d2e9 r949339b  
    3131
    3232# The main rule, it does all the tex/latex processing.
    33 ${BUILD}/${BASE}.dvi: ${RAWSRC} ${FIGTEX} Makefile | ${BUILD}
     33${BUILD}/${BASE}.dvi: ${RAWSRC} ${FIGTEX} termhandle.pstex resumhandle.pstex Makefile | ${BUILD}
    3434        ${LATEX} ${BASE}
    3535        ${BIBTEX} ${BUILD}/${BASE}
     
    4040${FIGTEX}: ${BUILD}/%.tex: %.fig | ${BUILD}
    4141        fig2dev -L eepic $< > $@
     42
     43%.pstex : %.fig | ${Build}
     44        fig2dev -L pstex $< > ${BUILD}/$@
     45        fig2dev -L pstex_t -p ${BUILD}/$@ $< > ${BUILD}/$@_t
    4246
    4347# Step through dvi & postscript to handle xfig specials.
  • doc/theses/andrew_beach_MMath/code/FixupEmpty.java

    r4e28d2e9 r949339b  
    1 public class ResumeFixupEmpty {
     1public class FixupEmpty {
    22        public interface Fixup {
    33                public int op(int fixup);
  • doc/theses/andrew_beach_MMath/code/FixupOther.java

    r4e28d2e9 r949339b  
    1 public class ResumeFixupOther {
     1public class FixupOther {
    22        public interface Fixup {
    33                public int op(int fixup);
  • doc/theses/andrew_beach_MMath/code/cond-catch.py

    r4e28d2e9 r949339b  
    3232
    3333    end_time = thread_time_ns()
    34     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     34    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    3535
    3636
  • doc/theses/andrew_beach_MMath/code/fixup-empty-f.cfa

    r4e28d2e9 r949339b  
    22#include <clock.hfa>
    33#include <fstream.hfa>
    4 #include <stdlib.hfa>                                                                   // strto
     4#include <stdlib.hfa>
    55
    6 int nounwind_fixup(unsigned int frames, void (*raised_rtn)(int &)) {
     6void nounwind_fixup(unsigned int frames, void (*raised_rtn)(int &)) {
    77        if (frames) {
    8                 int rtn = nounwind_fixup(frames - 1, raised_rtn);
    9                 if ( rtn == 42 ) printf( "42" );                                // make non-tail recursive
    10                 return rtn;
    11 
     8                nounwind_fixup(frames - 1, raised_rtn);
     9                // "Always" false, but prevents recursion elimination.
     10                if (-1 == frames) printf("~");
    1211        } else {
    1312                int fixup = 17;
    1413                raised_rtn(fixup);
    15                 return fixup;
    1614        }
    1715}
     
    2725        }
    2826
     27        // Closures at the top level are allowed to be true closures.
    2928        void raised(int & fixup) {
    30                 fixup = total_frames + 42;                                              // use local scope => lexical link
    31                 if ( total_frames == 42 ) printf( "42" );
     29                fixup = total_frames + 42;
     30                if (total_frames == 42) printf("42");
    3231        }
    3332
  • doc/theses/andrew_beach_MMath/code/fixup-empty-r.cfa

    r4e28d2e9 r949339b  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    77exception fixup_exception {
     
    1010vtable(fixup_exception) fixup_vt;
    1111
    12 int nounwind_empty(unsigned int frames) {
     12void nounwind_empty(unsigned int frames) {
    1313        if (frames) {
    14                 int rtn = nounwind_empty(frames - 1);
    15                 if ( rtn == 42 ) printf( "42" );                                // make non-tail recursive
    16                 return rtn;
     14                nounwind_empty(frames - 1);
     15                // "Always" false, but prevents recursion elimination.
     16                if (-1 == frames) printf("~");
    1717        } else {
    1818                int fixup = 17;
    19                 throwResume (fixup_exception){&fixup_vt, fixup}; // change bad fixup
    20                 return fixup;
     19                throwResume (fixup_exception){&fixup_vt, fixup};
    2120        }
    2221}
  • doc/theses/andrew_beach_MMath/code/fixup-empty.py

    r4e28d2e9 r949339b  
    2525
    2626    end_time = thread_time_ns()
    27     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     27    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    2828
    2929
  • doc/theses/andrew_beach_MMath/code/fixup-other-f.cfa

    r4e28d2e9 r949339b  
    22#include <clock.hfa>
    33#include <fstream.hfa>
    4 #include <stdlib.hfa>                                                                   // strto
     4#include <stdlib.hfa>
    55
    6 unsigned int frames;                                                                    // use global because of gcc thunk problem
     6// Using a global value to allow hoisting (and avoid thunks).
     7unsigned int frames;
    78
    89void nounwind_fixup(unsigned int dummy, void (*raised_rtn)(int &), void (*not_raised_rtn)(int &)) {
    910        void not_raised(int & fixup) {
    10                 fixup = frames + 42;                                                    // use local scope => lexical link
     11                fixup = frames + 42;
    1112        }
    1213
     
    1415                frames -= 1;
    1516                nounwind_fixup(42, raised_rtn, not_raised);
     17                // Always false, but prevents recursion elimination.
     18                if (-1 == frames) printf("~");
    1619        } else {
    1720                int fixup = dummy;
     
    3134        frames = total_frames;
    3235
     36        // Closures at the top level are allowed to be true closures.
    3337        void raised(int & fixup) {
    34                 fixup = total_frames + 42;                                              // use local scope => lexical link
     38                fixup = total_frames + 42;
    3539        }
    3640        void not_raised(int & fixup) {
    37                 fixup = total_frames + 42;                                              // use local scope => lexical link
     41                fixup = total_frames + 42;
    3842        }
    3943
  • doc/theses/andrew_beach_MMath/code/fixup-other-r.cfa

    r4e28d2e9 r949339b  
    33#include <exception.hfa>
    44#include <fstream.hfa>
    5 #include <stdlib.hfa>                                                                   // strto
     5#include <stdlib.hfa>
    66
    77exception fixup_exception {
     
    1313};
    1414
    15 unsigned int frames;                                                                    // use global because of gcc thunk problem
     15// Using a global value to allow hoisting (and avoid thunks).
     16unsigned int frames;
    1617
    1718void nounwind_other(unsigned int dummy) {
     
    2021                try {
    2122                        nounwind_other(42);
     23                        // Always false, but prevents recursion elimination.
     24                        if (-1 == frames) printf("~");
    2225                } catchResume (not_raised_exception * ex) {
    23                         ex->fixup = frames + 42;                                        // use local scope => lexical link
     26                        ex->fixup = frames + 42;
    2427                }
    2528        } else {
    2629                int fixup = dummy;
    27                 throwResume (fixup_exception){&fixup_vt, fixup}; // change bad fixup
     30                throwResume (fixup_exception){&fixup_vt, fixup};
    2831        }
    2932}
  • doc/theses/andrew_beach_MMath/code/fixup-other.py

    r4e28d2e9 r949339b  
    2727
    2828    end_time = thread_time_ns()
    29     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     29    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    3030
    3131
  • doc/theses/andrew_beach_MMath/code/resume-empty.cfa

    r4e28d2e9 r949339b  
    1111        if (frames) {
    1212                nounwind_empty(frames - 1);
     13                if ( frames == -1 ) printf( "42" );                             // prevent recursion optimizations
    1314        } else {
    1415                throwResume (empty_exception){&empty_vt};
  • doc/theses/andrew_beach_MMath/code/run.sh

    r4e28d2e9 r949339b  
    11#!/usr/bin/env bash
    22
    3 readonly ALL_TESTS=(raise-{empty,detor,finally,other} try-{catch,finally} cond-match-{all,none} \
    4                     raise-{fixup-empty,fixup-other})
     3readonly ALL_TESTS=(raise-{empty,detor,finally,other} try-{catch,finally} \
     4                        cond-match-{all,none} fixup-{empty,other})
    55
    66gen-file-name() (
     
    1818)
    1919
    20 #readonly N=${1:-5}
    2120readonly N=${1:-1}
    2221readonly OUT_FILE=$(gen-file-name ${2:-run-%-$N})
  • doc/theses/andrew_beach_MMath/code/test.sh

    r4e28d2e9 r949339b  
    1313#   View the result from TEST in LANGUAGE stored in FILE.
    1414
    15 readonly ITERS_1M=1000000 # 1 000 000, one million
    16 readonly ITERS_10M=10000000 # 10 000 000, ten million
    17 readonly ITERS_100M=100000000 # 100 000 000, hundred million
    18 readonly ITERS_1000M=1000000000 # 1 000 000 000, billion
     15readonly DIR=$(dirname "$(readlink -f "$0")")
     16cd $DIR
     17
     18readonly MIL=000000
     19# Various preset values used as arguments.
     20readonly ITERS_1M=1$MIL
     21readonly ITERS_10M=10$MIL
     22readonly ITERS_100M=100$MIL
     23readonly ITERS_1000M=1000$MIL
    1924readonly STACK_HEIGHT=100
    2025
     
    3035        case "$1" in
    3136        *.cfa)
    32                 # Requires a symbolic link.
    33                 mmake "${1%.cfa}" "$1" cfa -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
     37                # A symbolic link/local copy can be used as an override.
     38                cmd=./cfa
     39                if [ ! -x $cmd ]; then
     40                        cmd=cfa
     41                fi
     42                mmake "${1%.cfa}" "$1" $cmd -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
    3443                ;;
    3544        *.cpp)
     
    4655)
    4756
    48 if [ "-a" = "$1" ]; then                        # build all
     57if [ "-a" = "$1" ]; then
    4958        for file in *.cfa *.cpp *.java; do
    5059                build $file
    5160        done
    5261        exit 0
    53 elif [ "-b" = "$1" ]; then                      # build given
     62elif [ "-b" = "$1" ]; then
    5463        for file in "${@:2}"; do
    5564                build $file
    5665        done
    5766        exit 0
    58 elif [ "-c" = "$1" ]; then                      # clean all
     67elif [ "-c" = "$1" ]; then
    5968        rm $(basename -s ".cfa" -a *.cfa)
    6069        rm $(basename -s ".cpp" -a *.cpp)
     
    8392raise-empty)
    8493        CFAT="./throw-empty $ITERS_1M $STACK_HEIGHT"
    85 # see resume-fixup-empty-r      CFAR="./resume-empty $ITERS_1M $STACK_HEIGHT"
     94        CFAR="./resume-empty $ITERS_10M $STACK_HEIGHT"
    8695        CPP="./throw-empty-cpp $ITERS_1M $STACK_HEIGHT"
    8796        JAVA="java ThrowEmpty $ITERS_1M $STACK_HEIGHT"
     
    9099raise-detor)
    91100        CFAT="./throw-detor $ITERS_1M $STACK_HEIGHT"
    92 # N/A   CFAR="./resume-detor $ITERS_1M $STACK_HEIGHT"
     101        CFAR="./resume-detor $ITERS_10M $STACK_HEIGHT"
    93102        CPP="./throw-detor-cpp $ITERS_1M $STACK_HEIGHT"
    94103        JAVA=unsupported
     
    97106raise-finally)
    98107        CFAT="./throw-finally $ITERS_1M $STACK_HEIGHT"
    99 # N/A   CFAR="./resume-finally $ITERS_1M $STACK_HEIGHT"
     108        CFAR="./resume-finally $ITERS_10M $STACK_HEIGHT"
    100109        CPP=unsupported
    101110        JAVA="java ThrowFinally $ITERS_1M $STACK_HEIGHT"
     
    104113raise-other)
    105114        CFAT="./throw-other $ITERS_1M $STACK_HEIGHT"
    106 # N/A   CFAR="./resume-other $ITERS_1M $STACK_HEIGHT"
     115        CFAR="./resume-other $ITERS_10M $STACK_HEIGHT"
    107116        CPP="./throw-other-cpp $ITERS_1M $STACK_HEIGHT"
    108117        JAVA="java ThrowOther $ITERS_1M $STACK_HEIGHT"
     
    125134cond-match-all)
    126135        CFAT="./cond-catch $ITERS_10M 1"
    127         CFAR="./cond-fixup $ITERS_10M 1"
     136        CFAR="./cond-fixup $ITERS_100M 1"
    128137        CPP="./cond-catch-cpp $ITERS_10M 1"
    129138        JAVA="java CondCatch $ITERS_10M 1"
     
    132141cond-match-none)
    133142        CFAT="./cond-catch $ITERS_10M 0"
    134         CFAR="./cond-fixup $ITERS_10M 0"
     143        CFAR="./cond-fixup $ITERS_100M 0"
    135144        CPP="./cond-catch-cpp $ITERS_10M 0"
    136145        JAVA="java CondCatch $ITERS_10M 0"
    137146        PYTHON="./cond-catch.py $ITERS_10M 0"
    138147        ;;
    139 raise-fixup-empty)
    140         CFAT="./resume-fixup-empty-f $ITERS_10M $STACK_HEIGHT"
    141         CFAR="./resume-fixup-empty-r $ITERS_10M $STACK_HEIGHT"
    142         CPP="./resume-fixup-empty-cpp $ITERS_10M $STACK_HEIGHT"
    143         JAVA="java ResumeFixupEmpty $ITERS_10M $STACK_HEIGHT"
    144         PYTHON="./resume-fixup-empty.py $ITERS_10M $STACK_HEIGHT"
     148fixup-empty)
     149        CFAT="./fixup-empty-f $ITERS_10M $STACK_HEIGHT"
     150        CFAR="./fixup-empty-r $ITERS_10M $STACK_HEIGHT"
     151        CPP="./fixup-empty-cpp $ITERS_10M $STACK_HEIGHT"
     152        JAVA="java FixupEmpty $ITERS_10M $STACK_HEIGHT"
     153        PYTHON="./fixup-empty.py $ITERS_10M $STACK_HEIGHT"
    145154        ;;
    146 raise-fixup-other)
    147         CFAT="./resume-fixup-other-f $ITERS_10M $STACK_HEIGHT"
    148         CFAR="./resume-fixup-other-r $ITERS_10M $STACK_HEIGHT"
    149         CPP="./resume-fixup-other-cpp $ITERS_10M $STACK_HEIGHT"
    150         JAVA="java ResumeFixupOther $ITERS_10M $STACK_HEIGHT"
    151         PYTHON="./resume-fixup-other.py $ITERS_10M $STACK_HEIGHT"
     155fixup-other)
     156        CFAT="./fixup-other-f $ITERS_10M $STACK_HEIGHT"
     157        CFAR="./fixup-other-r $ITERS_10M $STACK_HEIGHT"
     158        CPP="./fixup-other-cpp $ITERS_10M $STACK_HEIGHT"
     159        JAVA="java FixupOther $ITERS_10M $STACK_HEIGHT"
     160        PYTHON="./fixup-other.py $ITERS_10M $STACK_HEIGHT"
    152161        ;;
    153162*)
     
    158167
    159168case "$TEST_LANG" in
    160         cfa-t) CALL="$CFAT";;
    161         cfa-r) CALL="$CFAR";;
    162         cpp) CALL="$CPP";;
    163         java) CALL="$JAVA";;
    164         python) CALL="$PYTHON";;
    165         *)
    166                 echo "No such language: $TEST_LANG" >&2
    167                 exit 2
     169cfa-t) CALL="$CFAT";;
     170cfa-r) CALL="$CFAR";;
     171cpp) CALL="$CPP";;
     172java) CALL="$JAVA";;
     173python) CALL="$PYTHON";;
     174*)
     175        echo "No such language: $TEST_LANG" >&2
     176        exit 2
    168177        ;;
    169178esac
     
    172181
    173182if [ -n "$VIEW_FILE" ]; then
    174         grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p'
     183        grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time.*: !!;T;p'
    175184        exit
    176185fi
  • doc/theses/andrew_beach_MMath/code/throw-empty.cfa

    r4e28d2e9 r949339b  
    1111        if (frames) {
    1212                unwind_empty(frames - 1);
     13                if ( frames == -1 ) printf( "42" );                             // prevent recursion optimizations
    1314        } else {
    1415                throw (empty_exception){&empty_vt};
  • doc/theses/andrew_beach_MMath/code/throw-empty.cpp

    r4e28d2e9 r949339b  
    11// Throw Across Empty Function
    22#include <chrono>
     3#include <cstdio>
    34#include <cstdlib>
    45#include <exception>
     
    1415        if (frames) {
    1516                unwind_empty(frames - 1);
     17                if (-1 == frames) printf("~");
    1618        } else {
    1719                throw (EmptyException){};
  • doc/theses/andrew_beach_MMath/code/throw-empty.py

    r4e28d2e9 r949339b  
    3333
    3434    end_time = thread_time_ns()
    35     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     35    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    3636
    3737
  • doc/theses/andrew_beach_MMath/code/throw-finally.py

    r4e28d2e9 r949339b  
    3636
    3737    end_time = thread_time_ns()
    38     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     38    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    3939
    4040
  • doc/theses/andrew_beach_MMath/code/throw-other.py

    r4e28d2e9 r949339b  
    4040
    4141    end_time = thread_time_ns()
    42     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     42    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    4343
    4444
  • doc/theses/andrew_beach_MMath/code/throw-with.py

    r4e28d2e9 r949339b  
    4343
    4444    end_time = thread_time_ns()
    45     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     45    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    4646
    4747
  • doc/theses/andrew_beach_MMath/code/try-catch.py

    r4e28d2e9 r949339b  
    2323
    2424    end_time = thread_time_ns()
    25     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     25    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    2626
    2727
  • doc/theses/andrew_beach_MMath/code/try-finally.py

    r4e28d2e9 r949339b  
    2222
    2323    end_time = thread_time_ns()
    24     print('Run-Time (s) {:.1f}:'.format((end_time - start_time) / 1_000_000_000.))
     24    print('Run-Time (s): {:.1f}'.format((end_time - start_time) / 1_000_000_000.))
    2525
    2626
  • doc/theses/andrew_beach_MMath/conclusion.tex

    r4e28d2e9 r949339b  
    33% Just a little knot to tie the paper together.
    44
    5 In the previous chapters this thesis presents the design and implementation
     5In the previous chapters, this thesis presents the design and implementation
    66of \CFA's exception handling mechanism (EHM).
    77Both the design and implementation are based off of tools and
    88techniques developed for other programming languages but they were adapted to
    99better fit \CFA's feature set and add a few features that do not exist in
    10 other EHMs;
     10other EHMs,
    1111including conditional matching, default handlers for unhandled exceptions
    1212and cancellation though coroutines and threads back to the program main stack.
  • doc/theses/andrew_beach_MMath/existing.tex

    r4e28d2e9 r949339b  
    66compatibility with C and its programmers.  \CFA is designed to have an
    77orthogonal feature-set based closely on the C programming paradigm
    8 (non-object-oriented) and these features can be added incrementally to an
    9 existing C code-base allowing programmers to learn \CFA on an as-needed basis.
     8(non-object-oriented), and these features can be added incrementally to an
     9existing C code-base,
     10allowing programmers to learn \CFA on an as-needed basis.
    1011
    1112Only those \CFA features pertaining to this thesis are discussed.
     
    4546\CFA adds a reference type to C as an auto-dereferencing pointer.
    4647They work very similarly to pointers.
    47 Reference-types are written the same way as a pointer-type but each
     48Reference-types are written the same way as pointer-types, but each
    4849asterisk (@*@) is replaced with a ampersand (@&@);
    49 this includes cv-qualifiers and multiple levels of reference.
    50 
    51 Generally, references act like pointers with an implicate dereferencing
     50this includes cv-qualifiers (\snake{const} and \snake{volatile})
     51and multiple levels of reference.
     52
     53Generally, references act like pointers with an implicit dereferencing
    5254operation added to each use of the variable.
    5355These automatic dereferences may be disabled with the address-of operator
     
    8385Mutable references may be assigned to by converting them to a pointer
    8486with a @&@ and then assigning a pointer to them, as in @&ri = &j;@ above.
    85 % ???
    8687
    8788\section{Operators}
     
    9394For example,
    9495infixed multiplication is @?*?@, while prefix dereference is @*?@.
    95 This syntax make it easy to tell the difference between prefix operations
    96 (such as @++?@) and post-fix operations (@?++@).
     96This syntax makes it easy to tell the difference between prefix operations
     97(such as @++?@) and postfix operations (@?++@).
    9798
    9899As an example, here are the addition and equality operators for a point type.
     
    104105}
    105106\end{cfa}
    106 Note that this syntax works effectively but a textual transformation,
     107Note that this syntax works effectively as a textual transformation;
    107108the compiler converts all operators into functions and then resolves them
    108109normally. This means any combination of types may be used,
     
    113114%\subsection{Constructors and Destructors}
    114115In \CFA, constructors and destructors are operators, which means they are
    115 functions with special operator names rather than type names in \Cpp.
     116functions with special operator names, rather than type names as in \Cpp.
    116117Both constructors and destructors can be implicity called by the compiler,
    117118however the operator names allow explicit calls.
     
    137138@b@ because of the explicit call and @a@ implicitly.
    138139@c@ will be initalized with the second constructor.
    139 Currently, there is no general way to skip initialation.
     140Currently, there is no general way to skip initialization.
    140141% I don't use @= anywhere in the thesis.
    141142
     
    202203do_twice(i);
    203204\end{cfa}
    204 Any object with a type fulfilling the assertion may be passed as an argument to
     205Any value with a type fulfilling the assertion may be passed as an argument to
    205206a @do_twice@ call.
    206207
     
    222223function. The matched assertion function is then passed as a function pointer
    223224to @do_twice@ and called within it.
    224 The global definition of @do_once@ is ignored, however if quadruple took a
     225The global definition of @do_once@ is ignored, however if @quadruple@ took a
    225226@double@ argument, then the global definition would be used instead as it
    226227would then be a better match.\cite{Moss19}
    227228
    228229To avoid typing long lists of assertions, constraints can be collected into
    229 convenient a package called a @trait@, which can then be used in an assertion
     230a convenient package called a @trait@, which can then be used in an assertion
    230231instead of the individual constraints.
    231232\begin{cfa}
     
    241242functions and variables, and are usually used to create a shorthand for, and
    242243give descriptive names to, common groupings of assertions describing a certain
    243 functionality, like @sumable@, @listable@, \etc.
     244functionality, like @summable@, @listable@, \etc.
    244245
    245246Polymorphic structures and unions are defined by qualifying an aggregate type
    246247with @forall@. The type variables work the same except they are used in field
    247 declarations instead of parameters, returns, and local variable declarations.
     248declarations instead of parameters, returns and local variable declarations.
    248249\begin{cfa}
    249250forall(dtype T)
     
    261262
    262263\section{Control Flow}
    263 \CFA has a number of advanced control-flow features: @generator@, @coroutine@, @monitor@, @mutex@ parameters, and @thread@.
     264\CFA has a number of advanced control-flow features: @generator@, @coroutine@,
     265@monitor@, @mutex@ parameters, and @thread@.
    264266The two features that interact with
    265267the exception system are @coroutine@ and @thread@; they and their supporting
     
    268270\subsection{Coroutine}
    269271A coroutine is a type with associated functions, where the functions are not
    270 required to finish execution when control is handed back to the caller. Instead
     272required to finish execution when control is handed back to the caller.
     273Instead,
    271274they may suspend execution at any time and be resumed later at the point of
    272 last suspension. (Generators are stackless and coroutines are stackful.) These
     275last suspension.
     276Coroutine
    273277types are not concurrent but share some similarities along with common
    274 underpinnings, so they are combined with the \CFA threading library. Further
    275 discussion in this section only refers to the coroutine because generators are
    276 similar.
     278underpinnings, so they are combined with the \CFA threading library.
     279% I had mention of generators, but they don't actually matter here.
    277280
    278281In \CFA, a coroutine is created using the @coroutine@ keyword, which is an
     
    322325\end{cfa}
    323326
    324 When the main function returns the coroutine halts and can no longer be
     327When the main function returns, the coroutine halts and can no longer be
    325328resumed.
    326329
    327330\subsection{Monitor and Mutex Parameter}
    328 Concurrency does not guarantee ordering; without ordering results are
     331Concurrency does not guarantee ordering; without ordering, results are
    329332non-deterministic. To claw back ordering, \CFA uses monitors and @mutex@
    330333(mutual exclusion) parameters. A monitor is another kind of aggregate, where
     
    332335@mutex@ parameters.
    333336
    334 A function that requires deterministic (ordered) execution, acquires mutual
     337A function that requires deterministic (ordered) execution acquires mutual
    335338exclusion on a monitor object by qualifying an object reference parameter with
    336 @mutex@.
     339the @mutex@ qualifier.
    337340\begin{cfa}
    338341void example(MonitorA & mutex argA, MonitorB & mutex argB);
     
    344347
    345348\subsection{Thread}
    346 Functions, generators, and coroutines are sequential so there is only a single
     349Functions, generators and coroutines are sequential, so there is only a single
    347350(but potentially sophisticated) execution path in a program. Threads introduce
    348351multiple execution paths that continue independently.
    349352
    350353For threads to work safely with objects requires mutual exclusion using
    351 monitors and mutex parameters. For threads to work safely with other threads,
     354monitors and mutex parameters. For threads to work safely with other threads
    352355also requires mutual exclusion in the form of a communication rendezvous, which
    353356also supports internal synchronization as for mutex objects. For exceptions,
  • doc/theses/andrew_beach_MMath/features.tex

    r4e28d2e9 r949339b  
    55and begins with a general overview of EHMs. It is not a strict
    66definition of all EHMs nor an exhaustive list of all possible features.
    7 However it does cover the most common structure and features found in them.
     7However, it does cover the most common structure and features found in them.
    88
    99\section{Overview of EHMs}
     
    4242
    4343The @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 guarded
     44also show another common feature of handlers: they are grouped by the guarded
    4545region.
    4646
     
    8484\paragraph{Hierarchy}
    8585A common way to organize exceptions is in a hierarchical structure.
    86 This pattern comes from object-orientated languages where the
     86This pattern comes from object-oriented languages where the
    8787exception hierarchy is a natural extension of the object hierarchy.
    8888
     
    101101between different sub-hierarchies.
    102102This design is used in \CFA even though it is not a object-orientated
    103 language; so different tools are used to create the hierarchy.
     103language, so different tools are used to create the hierarchy.
    104104
    105105% Could I cite the rational for the Python IO exception rework?
     
    118118For effective exception handling, additional information is often passed
    119119from the raise to the handler and back again.
    120 So far, only communication of the exceptions' identity is covered.
     120So far, only communication of the exception's identity is covered.
    121121A common communication method for adding information to an exception
    122122is putting fields into the exception instance
     
    129129\section{Virtuals}
    130130\label{s:virtuals}
     131A common feature in many programming languages is a tool to pair code
     132(behaviour) with data.
     133In \CFA, this is done with the virtual system,
     134which allow type information to be abstracted away, recovered and allow
     135operations to be performed on the abstract objects.
     136
    131137Virtual types and casts are not part of \CFA's EHM nor are they required for
    132138an EHM.
     
    152158% A type's descendants are its children and its children's descendants.
    153159
    154 For the purposes of illustration, a proposed -- but unimplemented syntax --
     160For the purposes of illustration, a proposed, but unimplemented, syntax
    155161will be used. Each virtual type is represented by a trait with an annotation
    156162that makes it a virtual type. This annotation is empty for a root type, which
     
    177183\end{minipage}
    178184
    179 Every virtual type also has a list of virtual members and a unique id,
    180 both are stored in a virtual table.
     185Every virtual type also has a list of virtual members and a unique id.
     186Both are stored in a virtual table.
    181187Every instance of a virtual type also has a pointer to a virtual table stored
    182188in it, although there is no per-type virtual table as in many other languages.
    183189
    184 The list of virtual members is built up down the tree. Every virtual type
     190The list of virtual members is accumulated from the root type down the tree.
     191Every virtual type
    185192inherits the list of virtual members from its parent and may add more
    186193virtual members to the end of the list which are passed on to its children.
     
    198205% Consider adding a diagram, but we might be good with the explanation.
    199206
    200 As @child_type@ is a child of @root_type@ it has the virtual members of
     207As @child_type@ is a child of @root_type@, it has the virtual members of
    201208@root_type@ (@to_string@ and @size@) as well as the one it declared
    202209(@irrelevant_function@).
     
    206213The names ``size" and ``align" are reserved for the size and alignment of the
    207214virtual type, and are always automatically initialized as such.
    208 The other special case are uses of the trait's polymorphic argument
     215The other special case is uses of the trait's polymorphic argument
    209216(@T@ in the example), which are always updated to refer to the current
    210 virtual type. This allows functions that refer to to polymorphic argument
     217virtual type. This allows functions that refer to the polymorphic argument
    211218to act as traditional virtual methods (@to_string@ in the example), as the
    212219object can always be passed to a virtual method in its virtual table.
    213220
    214 Up until this point the virtual system is similar to ones found in
    215 object-oriented languages but this is where \CFA diverges.
     221Up until this point, the virtual system is similar to ones found in
     222object-oriented languages, but this is where \CFA diverges.
    216223Objects encapsulate a single set of methods in each type,
    217224universally across the entire program,
     
    223230
    224231In \CFA, types do not encapsulate any code.
    225 Whether or not satisfies any given assertion, and hence any trait, is
     232Whether or not a type satisfies any given assertion, and hence any trait, is
    226233context sensitive. Types can begin to satisfy a trait, stop satisfying it or
    227234satisfy the same trait at any lexical location in the program.
    228 In this sense, an type's implementation in the set of functions and variables
     235In this sense, a type's implementation in the set of functions and variables
    229236that allow it to satisfy a trait is ``open" and can change
    230237throughout the program.
     
    248255\end{cfa}
    249256
    250 Like any variable they may be forward declared with the @extern@ keyword.
     257Like any variable, they may be forward declared with the @extern@ keyword.
    251258Forward declaring virtual tables is relatively common.
    252259Many virtual types have an ``obvious" implementation that works in most
     
    259266Initialization is automatic.
    260267The type id and special virtual members ``size" and ``align" only depend on
    261 the virtual type, which is fixed given the type of the virtual table and
     268the virtual type, which is fixed given the type of the virtual table, and
    262269so the compiler fills in a fixed value.
    263 The other virtual members are resolved, using the best match to the member's
     270The other virtual members are resolved using the best match to the member's
    264271name and type, in the same context as the virtual table is declared using
    265272\CFA's normal resolution rules.
    266273
    267 While much of the virtual infrastructure is created, it is currently only used
     274While much of the virtual infrastructure has been created,
     275it is currently only used
    268276internally for exception handling. The only user-level feature is the virtual
    269277cast, which is the same as the \Cpp \code{C++}{dynamic_cast}.
     
    274282Note, the syntax and semantics matches a C-cast, rather than the function-like
    275283\Cpp syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be
    276 a pointer to a virtual type.
     284pointers to virtual types.
    277285The cast dynamically checks if the @EXPRESSION@ type is the same or a sub-type
    278286of @TYPE@, and if true, returns a pointer to the
    279287@EXPRESSION@ object, otherwise it returns @0p@ (null pointer).
     288This allows the expression to be used as both a cast and a type check.
    280289
    281290\section{Exceptions}
    282291
    283292The syntax for declaring an exception is the same as declaring a structure
    284 except the keyword that is swapped out:
     293except the keyword:
    285294\begin{cfa}
    286295exception TYPE_NAME {
     
    289298\end{cfa}
    290299
    291 Fields are filled in the same way as a structure as well. However an extra
     300Fields are filled in the same way as a structure as well. However, an extra
    292301field is added that contains the pointer to the virtual table.
    293302It must be explicitly initialized by the user when the exception is
     
    299308
    300309\begin{minipage}[t]{0.4\textwidth}
    301 Header:
     310Header (.hfa):
    302311\begin{cfa}
    303312exception Example {
     
    310319\end{minipage}
    311320\begin{minipage}[t]{0.6\textwidth}
    312 Source:
     321Implementation (.cfa):
    313322\begin{cfa}
    314323vtable(Example) example_base_vtable
     
    319328%\subsection{Exception Details}
    320329This is the only interface needed when raising and handling exceptions.
    321 However it is actually a short hand for a more complex
    322 trait based interface.
     330However, it is actually a shorthand for a more complex
     331trait-based interface.
    323332
    324333The language views exceptions through a series of traits.
     
    336345completing the virtual system). The imaginary assertions would probably come
    337346from a trait defined by the virtual system, and state that the exception type
    338 is a virtual type, is a descendant of @exception_t@ (the base exception type)
     347is a virtual type,
     348that that the type is a descendant of @exception_t@ (the base exception type)
    339349and allow the user to find the virtual table type.
    340350
     
    355365};
    356366\end{cfa}
    357 Both traits ensure a pair of types is an exception type, its virtual table
    358 type
     367Both traits ensure a pair of types is an exception type and
     368its virtual table type,
    359369and defines one of the two default handlers. The default handlers are used
    360 as fallbacks and are discussed in detail in \vref{s:ExceptionHandling}.
     370as fallbacks and are discussed in detail in \autoref{s:ExceptionHandling}.
    361371
    362372However, all three of these traits can be tricky to use directly.
    363373While there is a bit of repetition required,
    364374the largest issue is that the virtual table type is mangled and not in a user
    365 facing way. So these three macros are provided to wrap these traits to
     375facing way. So, these three macros are provided to wrap these traits to
    366376simplify referring to the names:
    367377@IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@.
     
    371381The second (optional) argument is a parenthesized list of polymorphic
    372382arguments. This argument is only used with polymorphic exceptions and the
    373 list is be passed to both types.
     383list is passed to both types.
    374384In the current set-up, the two types always have the same polymorphic
    375 arguments so these macros can be used without losing flexibility.
    376 
    377 For example consider a function that is polymorphic over types that have a
     385arguments, so these macros can be used without losing flexibility.
     386
     387For example, consider a function that is polymorphic over types that have a
    378388defined arithmetic exception:
    379389\begin{cfa}
     
    388398These twin operations are the core of \CFA's exception handling mechanism.
    389399This section covers the general patterns shared by the two operations and
    390 then goes on to cover the details each individual operation.
     400then goes on to cover the details of each individual operation.
    391401
    392402Both operations follow the same set of steps.
     
    407417\label{s:Termination}
    408418Termination handling is the familiar kind of handling
    409 and used in most programming
     419used in most programming
    410420languages with exception handling.
    411421It is a dynamic, non-local goto. If the raised exception is matched and
     
    483493Since it is so general, a more specific handler can be defined,
    484494overriding the default behaviour for the specific exception types.
     495
     496For example, consider an error reading a configuration file.
     497This is most likely a problem with the configuration file (@config_error@),
     498but the function could have been passed the wrong file name (@arg_error@).
     499In this case the function could raise one exception and then, if it is
     500unhandled, raise the other.
     501This is not usual behaviour for either exception so changing the
     502default handler will be done locally:
     503\begin{cfa}
     504{
     505        void defaultTerminationHandler(config_error &) {
     506                throw (arg_error){arg_vt};
     507        }
     508        throw (config_error){config_vt};
     509}
     510\end{cfa}
    485511
    486512\subsection{Resumption}
     
    542568@EXCEPTION_TYPE@$_i$ is matched and @NAME@$_i$ is bound to the exception,
    543569@HANDLER_BLOCK@$_i$ is executed right away without first unwinding the stack.
    544 After the block has finished running control jumps to the raise site, where
     570After the block has finished running, control jumps to the raise site, where
    545571the just handled exception came from, and continues executing after it,
    546572not after the try statement.
     573
     574For instance, a resumption used to send messages to the logger may not
     575need to be handled at all. Putting the following default handler
     576at the global scope can make handling that exception optional by default.
     577\begin{cfa}
     578void defaultResumptionHandler(log_message &) {
     579    // Nothing, it is fine not to handle logging.
     580}
     581// ... No change at raise sites. ...
     582throwResume (log_message){strlit_log, "Begin event processing."}
     583\end{cfa}
    547584
    548585\subsubsection{Resumption Marking}
     
    551588not unwind the stack. A side effect is that, when a handler is matched
    552589and run, its try block (the guarded statements) and every try statement
    553 searched before it are still on the stack. There presence can lead to
     590searched before it are still on the stack. Their presence can lead to
    554591the recursive resumption problem.\cite{Buhr00a}
    555592% Other possible citation is MacLaren77, but the form is different.
     
    585622\end{center}
    586623
    587 There are other sets of marking rules that could be used,
    588 for instance, marking just the handlers that caught the exception,
     624There are other sets of marking rules that could be used.
     625For instance, marking just the handlers that caught the exception
    589626would also prevent recursive resumption.
    590 However, the rules selected mirrors what happens with termination,
     627However, the rules selected mirror what happens with termination,
    591628so this reduces the amount of rules and patterns a programmer has to know.
    592629
     
    628665// Handle a failure relating to f2 further down the stack.
    629666\end{cfa}
    630 In this example the file that experienced the IO error is used to decide
     667In this example, the file that experienced the IO error is used to decide
    631668which handler should be run, if any at all.
    632669
     
    657694
    658695\subsection{Comparison with Reraising}
    659 In languages without conditional catch, that is no ability to match an
    660 exception based on something other than its type, it can be mimicked
     696In languages without conditional catch -- that is, no ability to match an
     697exception based on something other than its type -- it can be mimicked
    661698by matching all exceptions of the right type, checking any additional
    662699conditions inside the handler and re-raising the exception if it does not
     
    664701
    665702Here is a minimal example comparing both patterns, using @throw;@
    666 (no argument) to start a re-raise.
     703(no operand) to start a re-raise.
    667704\begin{center}
    668705\begin{tabular}{l r}
     
    692729\end{tabular}
    693730\end{center}
    694 At first glance catch-and-reraise may appear to just be a quality of life
     731At first glance, catch-and-reraise may appear to just be a quality-of-life
    695732feature, but there are some significant differences between the two
    696 stratagies.
     733strategies.
    697734
    698735A simple difference that is more important for \CFA than many other languages
    699 is that the raise site changes, with a re-raise but does not with a
     736is that the raise site changes with a re-raise, but does not with a
    700737conditional catch.
    701738This is important in \CFA because control returns to the raise site to run
    702 the per-site default handler. Because of this only a conditional catch can
     739the per-site default handler. Because of this, only a conditional catch can
    703740allow the original raise to continue.
    704741
     
    753790%   } else throw;
    754791% }
    755 In similar simple examples translating from re-raise to conditional catch
    756 takes less code but it does not have a general trivial solution either.
     792In similar simple examples, translating from re-raise to conditional catch
     793takes less code but it does not have a general, trivial solution either.
    757794
    758795So, given that the two patterns do not trivially translate into each other,
    759796it becomes a matter of which on should be encouraged and made the default.
    760 From the premise that if a handler that could handle an exception then it
     797From the premise that if a handler could handle an exception then it
    761798should, it follows that checking as many handlers as possible is preferred.
    762 So conditional catch and checking later handlers is a good default.
     799So, conditional catch and checking later handlers is a good default.
    763800
    764801\section{Finally Clauses}
    765802\label{s:FinallyClauses}
    766 Finally clauses are used to preform unconditional clean-up when leaving a
     803Finally clauses are used to perform unconditional cleanup when leaving a
    767804scope and are placed at the end of a try statement after any handler clauses:
    768805\begin{cfa}
     
    782819Execution of the finally block should always finish, meaning control runs off
    783820the end of the block. This requirement ensures control always continues as if
    784 the finally clause is not present, \ie finally is for cleanup not changing
     821the finally clause is not present, \ie finally is for cleanup, not changing
    785822control flow.
    786823Because of this requirement, local control flow out of the finally block
    787824is forbidden. The compiler precludes any @break@, @continue@, @fallthru@ or
    788825@return@ that causes control to leave the finally block. Other ways to leave
    789 the finally block, such as a long jump or termination are much harder to check,
    790 and at best requiring additional run-time overhead, and so are only
     826the finally block, such as a @longjmp@ or termination are much harder to check,
     827and at best require additional run-time overhead, and so are only
    791828discouraged.
    792829
    793 Not all languages with unwinding have finally clauses. Notably \Cpp does
     830Not all languages with unwinding have finally clauses. Notably, \Cpp does
    794831without it as destructors, and the RAII design pattern, serve a similar role.
    795832Although destructors and finally clauses can be used for the same cases,
     
    798835Destructors take more work to create, but if there is clean-up code
    799836that needs to be run every time a type is used, they are much easier
    800 to set-up for each use. % It's automatic.
    801 On the other hand finally clauses capture the local context, so is easy to
    802 use when the clean-up is not dependent on the type of a variable or requires
     837to set up for each use. % It's automatic.
     838On the other hand, finally clauses capture the local context, so are easy to
     839use when the cleanup is not dependent on the type of a variable or requires
    803840information from multiple variables.
    804841
     
    807844Cancellation is a stack-level abort, which can be thought of as as an
    808845uncatchable termination. It unwinds the entire current stack, and if
    809 possible forwards the cancellation exception to a different stack.
     846possible, forwards the cancellation exception to a different stack.
    810847
    811848Cancellation is not an exception operation like termination or resumption.
    812849There is no special statement for starting a cancellation; instead the standard
    813 library function @cancel_stack@ is called passing an exception. Unlike a
    814 raise, this exception is not used in matching only to pass information about
     850library function @cancel_stack@ is called, passing an exception. Unlike a
     851raise, this exception is not used in matching, only to pass information about
    815852the cause of the cancellation.
    816853Finally, as no handler is provided, there is no default handler.
    817854
    818 After @cancel_stack@ is called the exception is copied into the EHM's memory
     855After @cancel_stack@ is called, the exception is copied into the EHM's memory
    819856and the current stack is unwound.
    820857The behaviour after that depends on the kind of stack being cancelled.
    821858
    822859\paragraph{Main Stack}
    823 The main stack is the one used by the program main at the start of execution,
     860The main stack is the one used by
     861the program's main function at the start of execution,
    824862and is the only stack in a sequential program.
    825 After the main stack is unwound there is a program-level abort.
     863After the main stack is unwound, there is a program-level abort.
    826864
    827865The first reason for this behaviour is for sequential programs where there
    828 is only one stack, and hence to stack to pass information to.
     866is only one stack, and hence no stack to pass information to.
    829867Second, even in concurrent programs, the main stack has no dependency
    830868on another stack and no reliable way to find another living stack.
     
    842880and an implicit join (from a destructor call). The explicit join takes the
    843881default handler (@defaultResumptionHandler@) from its calling context while
    844 the implicit join provides its own; which does a program abort if the
     882the implicit join provides its own, which does a program abort if the
    845883@ThreadCancelled@ exception cannot be handled.
    846884
     
    870908After a coroutine stack is unwound, control returns to the @resume@ function
    871909that most recently resumed it. @resume@ reports a
    872 @CoroutineCancelled@ exception, which contains a references to the cancelled
     910@CoroutineCancelled@ exception, which contains a reference to the cancelled
    873911coroutine and the exception used to cancel it.
    874912The @resume@ function also takes the \defaultResumptionHandler{} from the
  • doc/theses/andrew_beach_MMath/future.tex

    r4e28d2e9 r949339b  
    33
    44The following discussion covers both possible interesting research
    5 that could follow from this work as long as simple implementation
     5that could follow from this work as well as simple implementation
    66improvements.
    77
     
    1010\CFA is a developing programming language. As such, there are partially or
    1111unimplemented features (including several broken components)
    12 that I had to workaround while building the EHM largely in
     12that I had to work around while building the EHM largely in
    1313the \CFA language (some C components). Below are a few of these issues
    1414and how implementing/fixing them would affect the EHM.
    15 In addition there are some simple improvements that had no interesting
     15In addition, there are some simple improvements that had no interesting
    1616research attached to them but would make using the language easier.
    1717\begin{itemize}
     
    2828Termination handlers cannot use local control-flow transfers, \eg by @break@,
    2929@return@, \etc. The reason is that current code generation hoists a handler
    30 into a nested function for convenience (versus assemble-code generation at the
     30into a nested function for convenience (versus assembly-code generation at the
    3131try statement). Hence, when the handler runs, it can still access local
    3232variables in the lexical scope of the try statement. Still, it does mean
    3333that seemingly local control flow is not in fact local and crosses a function
    3434boundary.
    35 Making the termination handlers code within the surrounding
     35Making the termination handler's code within the surrounding
    3636function would remove this limitation.
    3737% Try blocks are much more difficult to do practically (requires our own
    3838% assembly) and resumption handlers have some theoretical complexity.
    3939\item
    40 There is no detection of colliding unwinds. It is possible for clean-up code
    41 run during an unwind to trigger another unwind that escapes the clean-up code
    42 itself; such as a termination exception caught further down the stack or a
     40There is no detection of colliding unwinds. It is possible for cleanup code
     41run during an unwind to trigger another unwind that escapes the cleanup code
     42itself, such as a termination exception caught further down the stack or a
    4343cancellation. There do exist ways to handle this case, but currently there is
    4444no detection and the first unwind will simply be forgotten, often leaving
     
    6464Other features of the virtual system could also remove some of the
    6565special cases around exception virtual tables, such as the generation
    66 of the @msg@ function, could be removed.
     66of the @msg@ function.
    6767
    6868The full virtual system might also include other improvement like associated
     
    7474\section{Additional Raises}
    7575Several other kinds of exception raises were considered beyond termination
    76 (@throw@), resumption (@throwResume@), and reraise.
     76(@throw@), resumption (@throwResume@), and re-raise.
    7777
    7878The first is a non-local/concurrent raise providing asynchronous exceptions,
     
    110110passed on.
    111111
    112 However checked exceptions were never seriously considered for this project
     112Checked exceptions were never seriously considered for this project
    113113because they have significant trade-offs in usability and code reuse in
    114114exchange for the increased safety.
     
    116116higher-order functions from the functions the user passed into the
    117117higher-order function. There are no well known solutions to this problem
    118 that were satisfactory for \CFA (which carries some of C's flexibility
    119 over safety design) so additional research is needed.
     118that were satisfactory for \CFA (which carries some of C's
     119flexibility-over-safety design) so additional research is needed.
    120120
    121121Follow-up work might add some form of checked exceptions to \CFA,
     
    140140Zero-cost resumptions is still an open problem. First, because libunwind does
    141141not support a successful-exiting stack-search without doing an unwind.
    142 Workarounds are possible but awkward. Ideally an extension to libunwind could
     142Workarounds are possible but awkward. Ideally, an extension to libunwind could
    143143be made, but that would either require separate maintenance or gaining enough
    144144support to have it folded into the official library itself.
    145145
    146 Also new techniques to skip previously searched parts of the stack need to be
     146Also, new techniques to skip previously searched parts of the stack need to be
    147147developed to handle the recursive resume problem and support advanced algebraic
    148148effects.
  • doc/theses/andrew_beach_MMath/implement.tex

    r4e28d2e9 r949339b  
    1414\label{s:VirtualSystem}
    1515% Virtual table rules. Virtual tables, the pointer to them and the cast.
    16 While the \CFA virtual system currently has only one public features, virtual
     16While the \CFA virtual system currently has only two public features, virtual
    1717cast and virtual tables,
    18 % ??? refs (see the virtual cast feature \vpageref{p:VirtualCast}),
    1918substantial structure is required to support them,
    2019and provide features for exception handling and the standard library.
     
    3534as part of field-by-field construction.
    3635
    37 \subsection{Type Id}
    38 Every virtual type has a unique id.
     36\subsection{Type ID}
     37Every virtual type has a unique ID.
    3938These are used in type equality, to check if the representation of two values
    4039are the same, and to access the type's type information.
     
    4443
    4544Our approach for program uniqueness is using a static declaration for each
    46 type id, where the run-time storage address of that variable is guaranteed to
     45type ID, where the run-time storage address of that variable is guaranteed to
    4746be unique during program execution.
    48 The type id storage can also be used for other purposes,
     47The type ID storage can also be used for other purposes,
    4948and is used for type information.
    5049
    51 The problem is that a type id may appear in multiple TUs that compose a
    52 program (see \autoref{ss:VirtualTable}); so the initial solution would seem
    53 to be make it external in each translation unit. Hovever, the type id must
     50The problem is that a type ID may appear in multiple TUs that compose a
     51program (see \autoref{ss:VirtualTable}), so the initial solution would seem
     52to be make it external in each translation unit. However, the type ID must
    5453have a declaration in (exactly) one of the TUs to create the storage.
    5554No other declaration related to the virtual type has this property, so doing
    5655this through standard C declarations would require the user to do it manually.
    5756
    58 Instead the linker is used to handle this problem.
     57Instead, the linker is used to handle this problem.
    5958% I did not base anything off of C++17; they are solving the same problem.
    6059A new feature has been added to \CFA for this purpose, the special attribute
    6160\snake{cfa_linkonce}, which uses the special section @.gnu.linkonce@.
    62 When used as a prefix (\eg @.gnu.linkonce.example@) the linker does
     61When used as a prefix (\eg @.gnu.linkonce.example@), the linker does
    6362not combine these sections, but instead discards all but one with the same
    6463full name.
    6564
    66 So each type id must be given a unique section name with the linkonce
    67 prefix. Luckily \CFA already has a way to get unique names, the name mangler.
     65So, each type ID must be given a unique section name with the \snake{linkonce}
     66prefix. Luckily, \CFA already has a way to get unique names, the name mangler.
    6867For example, this could be written directly in \CFA:
    6968\begin{cfa}
     
    7473__attribute__((section(".gnu.linkonce._X1fFv___1"))) void _X1fFv___1() {}
    7574\end{cfa}
    76 This is done internally to access the name manglers.
     75This is done internally to access the name mangler.
    7776This attribute is useful for other purposes, any other place a unique
    7877instance required, and should eventually be made part of a public and
     
    8180\subsection{Type Information}
    8281
    83 There is data stored at the type id's declaration, the type information.
    84 The type information currently is only the parent's type id or, if the
     82There is data stored at the type ID's declaration, the type information.
     83The type information currently is only the parent's type ID or, if the
    8584type has no parent, the null pointer.
    86 The ancestors of a virtual type are found by traversing type ids through
     85The ancestors of a virtual type are found by traversing type IDs through
    8786the type information.
    8887An example using helper macros looks like:
     
    105104\item
    106105Generate a new structure definition to store the type
    107 information. The layout is the same in each case, just the parent's type id,
     106information. The layout is the same in each case, just the parent's type ID,
    108107but the types used change from instance to instance.
    109108The generated name is used for both this structure and, if relevant, the
     
    115114\item
    116115The definition is generated and initialized.
    117 The parent id is set to the null pointer or to the address of the parent's
     116The parent ID is set to the null pointer or to the address of the parent's
    118117type information instance. Name resolution handles the rest.
    119118\item
     
    151150file as if it was a forward declaration, except no definition is required.
    152151
    153 This technique is used for type-id instances. A link-once definition is
     152This technique is used for type ID instances. A link-once definition is
    154153generated each time the structure is seen. This will result in multiple
    155154copies but the link-once attribute ensures all but one are removed for a
     
    168167\subsection{Virtual Table}
    169168\label{ss:VirtualTable}
    170 Each virtual type has a virtual table type that stores its type id and
     169Each virtual type has a virtual table type that stores its type ID and
    171170virtual members.
    172 Each virtual type instance is bound to a table instance that is filled with
    173 the values of virtual members.
    174 Both the layout of the fields and their value are decided by the rules given
     171An instance of a virtual type is bound to a virtual table instance,
     172which have the values of the virtual members.
     173Both the layout of the fields (in the virtual table type)
     174and their value (in the virtual table instance) are decided by the rules given
    175175below.
    176176
    177177The layout always comes in three parts (see \autoref{f:VirtualTableLayout}).
    178 The first section is just the type id at the head of the table. It is always
     178The first section is just the type ID at the head of the table. It is always
    179179there to ensure that it can be found even when the accessing code does not
    180180know which virtual type it has.
    181 The second section are all the virtual members of the parent, in the same
     181The second section is all the virtual members of the parent, in the same
    182182order as they appear in the parent's virtual table. Note that the type may
    183183change slightly as references to the ``this" change. This is limited to
     
    199199This, combined with the fixed offset to the virtual table pointer, means that
    200200for any virtual type, it is always safe to access its virtual table and,
    201 from there, it is safe to check the type id to identify the exact type of the
     201from there, it is safe to check the type ID to identify the exact type of the
    202202underlying object, access any of the virtual members and pass the object to
    203203any of the method-like virtual members.
     
    207207the context of the declaration.
    208208
    209 The type id is always fixed; with each virtual table type having
    210 exactly one possible type id.
     209The type ID is always fixed, with each virtual table type having
     210exactly one possible type ID.
    211211The virtual members are usually filled in by type resolution.
    212212The best match for a given name and type at the declaration site is used.
    213213There are two exceptions to that rule: the @size@ field, the type's size,
    214 is set using a @sizeof@ expression and the @align@ field, the
     214is set using a @sizeof@ expression, and the @align@ field, the
    215215type's alignment, is set using an @alignof@ expression.
    216216
    217217Most of these tools are already inside the compiler. Using simple
    218 code transformations early on in compilation, allows most of that work to be
     218code transformations early on in compilation allows most of that work to be
    219219handed off to the existing tools. \autoref{f:VirtualTableTransformation}
    220 shows an example transformation, this example shows an exception virtual table.
     220shows an example transformation; this example shows an exception virtual table.
    221221It also shows the transformation on the full declaration.
    222222For a forward declaration, the @extern@ keyword is preserved and the
     
    312312        struct __cfavir_type_id * const * child );
    313313\end{cfa}
    314 The type id for the target type of the virtual cast is passed in as
     314The type ID for the target type of the virtual cast is passed in as
    315315@parent@ and
    316316the cast target is passed in as @child@.
     
    322322The virtual cast either returns the original pointer or the null pointer
    323323as the new type.
    324 So the function does the parent check and returns the appropriate value.
    325 The parent check is a simple linear search of child's ancestors using the
     324The function does the parent check and returns the appropriate value.
     325The parent check is a simple linear search of the child's ancestors using the
    326326type information.
    327327
     
    329329% The implementation of exception types.
    330330
    331 Creating exceptions can roughly divided into two parts,
     331Creating exceptions can be roughly divided into two parts:
    332332the exceptions themselves and the virtual system interactions.
    333333
     
    361361
    362362All types associated with a virtual type,
    363 the types of the virtual table and the type id,
     363the types of the virtual table and the type ID,
    364364are generated when the virtual type (the exception) is first found.
    365 The type id (the instance) is generated with the exception, if it is
     365The type ID (the instance) is generated with the exception, if it is
    366366a monomorphic type.
    367 However, if the exception is polymorphic, then a different type id has to
     367However, if the exception is polymorphic, then a different type ID has to
    368368be generated for every instance. In this case, generation is delayed
    369369until a virtual table is created.
     
    372372When a virtual table is created and initialized, two functions are created
    373373to fill in the list of virtual members.
    374 The first is a copy function that adapts the exception's copy constructor
     374The first is the @copy@ function that adapts the exception's copy constructor
    375375to work with pointers, avoiding some issues with the current copy constructor
    376376interface.
    377 Second is the msg function that returns a C-string with the type's name,
     377Second is the @msg@ function that returns a C-string with the type's name,
    378378including any polymorphic parameters.
    379379
     
    402402
    403403% Discussing multiple frame stack unwinding:
    404 Unwinding across multiple stack frames is more complex because that
     404Unwinding across multiple stack frames is more complex, because that
    405405information is no longer contained within the current function.
    406406With separate compilation,
    407407a function does not know its callers nor their frame layout.
    408408Even using the return address, that information is encoded in terms of
    409 actions in code, intermixed with the actions required finish the function.
     409actions in code, intermixed with the actions required to finish the function.
    410410Without changing the main code path it is impossible to select one of those
    411411two groups of actions at the return site.
    412412
    413 The traditional unwinding mechanism for C is implemented by saving a snap-shot
    414 of a function's state with @setjmp@ and restoring that snap-shot with
     413The traditional unwinding mechanism for C is implemented by saving a snapshot
     414of a function's state with @setjmp@ and restoring that snapshot with
    415415@longjmp@. This approach bypasses the need to know stack details by simply
    416 reseting to a snap-shot of an arbitrary but existing function frame on the
    417 stack. It is up to the programmer to ensure the snap-shot is valid when it is
    418 reset and that all required clean-up from the unwound stacks is performed.
    419 This approach is fragile and requires extra work in the surrounding code.
     416resetting to a snapshot of an arbitrary but existing function frame on the
     417stack. It is up to the programmer to ensure the snapshot is valid when it is
     418reset and that all required cleanup from the unwound stacks is performed.
     419Because it does not automate or check any of this cleanup,
     420it can be easy to make mistakes and always must be handled manually.
    420421
    421422With respect to the extra work in the surrounding code,
    422 many languages define clean-up actions that must be taken when certain
    423 sections of the stack are removed. Such as when the storage for a variable
     423many languages define cleanup actions that must be taken when certain
     424sections of the stack are removed, such as when the storage for a variable
    424425is removed from the stack, possibly requiring a destructor call,
    425426or when a try statement with a finally clause is
    426427(conceptually) popped from the stack.
    427 None of these cases should be handled by the user --- that would contradict the
    428 intention of these features --- so they need to be handled automatically.
     428None of these cases should be handled by the user -- that would contradict the
     429intention of these features -- so they need to be handled automatically.
    429430
    430431To safely remove sections of the stack, the language must be able to find and
    431 run these clean-up actions even when removing multiple functions unknown at
     432run these cleanup actions even when removing multiple functions unknown at
    432433the beginning of the unwinding.
    433434
     
    435436library that provides tools for stack walking, handler execution, and
    436437unwinding. What follows is an overview of all the relevant features of
    437 libunwind needed for this work, and how \CFA uses them to implement exception
    438 handling.
     438libunwind needed for this work.
     439Following that is the description of the \CFA code that uses libunwind
     440to implement termination.
    439441
    440442\subsection{libunwind Usage}
     
    529531provided storage object. It has two public fields: the @exception_class@,
    530532which is described above, and the @exception_cleanup@ function.
    531 The clean-up function is used by the EHM to clean-up the exception, if it
     533The cleanup function is used by the EHM to clean up the exception. If it
    532534should need to be freed at an unusual time, it takes an argument that says
    533535why it had to be cleaned up.
     
    551553of the most recent stack frame. It continues to call personality functions
    552554traversing the stack from newest to oldest until a function finds a handler or
    553 the end of the stack is reached. In the latter case, raise exception returns
    554 @_URC_END_OF_STACK@.
    555 
    556 Second, when a handler is matched, raise exception moves to the clean-up
    557 phase and walks the stack a second time.
     555the end of the stack is reached. In the latter case,
     556@_Unwind_RaiseException@ returns @_URC_END_OF_STACK@.
     557
     558Second, when a handler is matched, @_Unwind_RaiseException@
     559moves to the cleanup phase and walks the stack a second time.
    558560Once again, it calls the personality functions of each stack frame from newest
    559561to oldest. This pass stops at the stack frame containing the matching handler.
    560 If that personality function has not install a handler, it is an error.
    561 
    562 If an error is encountered, raise exception returns either
     562If that personality function has not installed a handler, it is an error.
     563
     564If an error is encountered, @_Unwind_RaiseException@ returns either
    563565@_URC_FATAL_PHASE1_ERROR@ or @_URC_FATAL_PHASE2_ERROR@ depending on when the
    564566error occurred.
     
    571573        _Unwind_Stop_Fn, void *);
    572574\end{cfa}
    573 It also unwinds the stack but it does not use the search phase. Instead another
     575It also unwinds the stack but it does not use the search phase. Instead,
     576another
    574577function, the stop function, is used to stop searching. The exception is the
    575 same as the one passed to raise exception. The extra arguments are the stop
     578same as the one passed to @_Unwind_RaiseException@.
     579The extra arguments are the stop
    576580function and the stop parameter. The stop function has a similar interface as a
    577581personality function, except it is also passed the stop parameter.
     
    721725one list per stack, with the
    722726list head stored in the exception context. Within each linked list, the most
    723 recently thrown exception is at the head followed by older thrown
     727recently thrown exception is at the head, followed by older thrown
    724728exceptions. This format allows exceptions to be thrown, while a different
    725729exception is being handled. The exception at the head of the list is currently
     
    732736exception into managed memory. After the exception is handled, the free
    733737function is used to clean up the exception and then the entire node is
    734 passed to free, returning the memory back to the heap.
     738passed to @free@, returning the memory back to the heap.
    735739
    736740\subsection{Try Statements and Catch Clauses}
     
    757761The three functions passed to try terminate are:
    758762\begin{description}
    759 \item[try function:] This function is the try block, it is where all the code
     763\item[try function:] This function is the try block. It is where all the code
    760764from inside the try block is placed. It takes no parameters and has no
    761765return value. This function is called during regular execution to run the try
     
    766770from the conditional part of each handler and runs each check, top to bottom,
    767771in turn, to see if the exception matches this handler.
    768 The match is performed in two steps, first a virtual cast is used to check
     772The match is performed in two steps: first, a virtual cast is used to check
    769773if the raised exception is an instance of the declared exception type or
    770774one of its descendant types, and then the condition is evaluated, if
    771775present.
    772776The match function takes a pointer to the exception and returns 0 if the
    773 exception is not handled here. Otherwise the return value is the id of the
     777exception is not handled here. Otherwise, the return value is the ID of the
    774778handler that matches the exception.
    775779
     
    782786\end{description}
    783787All three functions are created with GCC nested functions. GCC nested functions
    784 can be used to create closures,
     788can be used to create closures;
    785789in other words,
    786 functions that can refer to variables in their lexical scope even
     790functions that can refer to variables in their lexical scope even though
    787791those variables are part of a different function.
    788792This approach allows the functions to refer to all the
     
    869873At each node, the EHM checks to see if the try statement the node represents
    870874can handle the exception. If it can, then the exception is handled and
    871 the operation finishes, otherwise the search continues to the next node.
     875the operation finishes; otherwise, the search continues to the next node.
    872876If the search reaches the end of the list without finding a try statement
    873877with a handler clause
     
    879883if the exception is handled and false otherwise.
    880884The handler function checks each of its internal handlers in order,
    881 top-to-bottom, until it funds a match. If a match is found that handler is
     885top-to-bottom, until it finds a match. If a match is found that handler is
    882886run, after which the function returns true, ignoring all remaining handlers.
    883887If no match is found the function returns false.
    884 The match is performed in two steps, first a virtual cast is used to see
     888The match is performed in two steps. First a virtual cast is used to see
    885889if the raised exception is an instance of the declared exception type or one
    886 of its descendant types, if so then it is passed to the custom predicate
     890of its descendant types, if so, then the second step is to see if the
     891exception passes the custom predicate
    887892if one is defined.
    888893% You need to make sure the type is correct before running the predicate
     
    936941% Recursive Resumption Stuff:
    937942\autoref{f:ResumptionMarking} shows search skipping
    938 (see \vpageref{s:ResumptionMarking}), which ignores parts of
     943(see \autoref{s:ResumptionMarking}), which ignores parts of
    939944the stack
    940945already examined, and is accomplished by updating the front of the list as
     
    951956This structure also supports new handlers added while the resumption is being
    952957handled. These are added to the front of the list, pointing back along the
    953 stack --- the first one points over all the checked handlers ---
     958stack -- the first one points over all the checked handlers --
    954959and the ordering is maintained.
    955960
     
    979984%\autoref{code:cleanup}
    980985A finally clause is handled by converting it into a once-off destructor.
    981 The code inside the clause is placed into GCC nested-function
     986The code inside the clause is placed into a GCC nested-function
    982987with a unique name, and no arguments or return values.
    983988This nested function is
    984989then set as the cleanup function of an empty object that is declared at the
    985990beginning of a block placed around the context of the associated try
    986 statement (see \autoref{f:FinallyTransformation}).
     991statement, as shown in \autoref{f:FinallyTransformation}.
    987992
    988993\begin{figure}
     
    10241029% Stack selections, the three internal unwind functions.
    10251030
    1026 Cancellation also uses libunwind to do its stack traversal and unwinding,
    1027 however it uses a different primary function: @_Unwind_ForcedUnwind@. Details
    1028 of its interface can be found in the Section~\vref{s:ForcedUnwind}.
     1031Cancellation also uses libunwind to do its stack traversal and unwinding.
     1032However, it uses a different primary function: @_Unwind_ForcedUnwind@. Details
     1033of its interface can be found in Section~\vref{s:ForcedUnwind}.
    10291034
    10301035The first step of cancellation is to find the cancelled stack and its type:
  • doc/theses/andrew_beach_MMath/intro.tex

    r4e28d2e9 r949339b  
    2525All types of exception handling link a raise with a handler.
    2626Both operations are usually language primitives, although raises can be
    27 treated as a primitive function that takes an exception argument.
    28 Handlers are more complex as they are added to and removed from the stack
    29 during execution, must specify what they can handle and give the code to
     27treated as a function that takes an exception argument.
     28Handlers are more complex, as they are added to and removed from the stack
     29during execution, must specify what they can handle and must give the code to
    3030handle the exception.
    3131
     
    3939it returns control to that function.
    4040\begin{center}
    41 \input{termination}
     41%\input{termination}
     42%
     43%\medskip
     44\input{termhandle.pstex_t}
     45% I hate these diagrams, but I can't access xfig to fix them and they are
     46% better than the alternative.
    4247\end{center}
    4348
     
    4651The handler is run on top of the existing stack, often as a new function or
    4752closure capturing the context in which the handler was defined.
    48 After the handler has finished running it returns control to the function
     53After the handler has finished running, it returns control to the function
    4954that preformed the raise, usually starting after the raise.
    5055\begin{center}
    51 \input{resumption}
     56%\input{resumption}
     57%
     58%\medskip
     59\input{resumhandle.pstex_t}
     60% The other one.
    5261\end{center}
    5362
    5463Although a powerful feature, exception handling tends to be complex to set up
    55 and expensive to use
     64and expensive to use,
    5665so it is often limited to unusual or ``exceptional" cases.
    57 The classic example is error handling, exceptions can be used to
     66The classic example is error handling; exceptions can be used to
    5867remove error handling logic from the main execution path, and pay
    5968most of the cost only when the error actually occurs.
     
    6372The \CFA EHM implements all of the common exception features (or an
    6473equivalent) found in most other EHMs and adds some features of its own.
    65 The design of all the features had to be adapted to \CFA's feature set as
     74The design of all the features had to be adapted to \CFA's feature set, as
    6675some of the underlying tools used to implement and express exception handling
    6776in other languages are absent in \CFA.
    68 Still the resulting syntax resembles that of other languages:
     77Still, the resulting syntax resembles that of other languages:
    6978\begin{cfa}
    7079try {
     
    8897covering both changes to the compiler and the run-time.
    8998In addition, a suite of test cases and performance benchmarks were created
    90 along side the implementation.
     99alongside the implementation.
    91100The implementation techniques are generally applicable in other programming
    92101languages and much of the design is as well.
     
    100109\item Implementing stack unwinding and the \CFA EHM, including updating
    101110the \CFA compiler and the run-time environment.
    102 \item Designed and implemented a prototype virtual system.
     111\item Designing and implementing a prototype virtual system.
    103112% I think the virtual system and per-call site default handlers are the only
    104113% "new" features, everything else is a matter of implementation.
    105114\item Creating tests to check the behaviour of the EHM.
    106 \item Creating benchmarks to check the performances of the EHM,
     115\item Creating benchmarks to check the performance of the EHM,
    107116as compared to other languages.
    108117\end{enumerate}
     
    110119The rest of this thesis is organized as follows.
    111120The current state of exceptions is covered in \autoref{s:background}.
    112 The existing state of \CFA is also covered in \autoref{c:existing}.
     121The existing state of \CFA is covered in \autoref{c:existing}.
    113122New EHM features are introduced in \autoref{c:features},
    114123covering their usage and design.
     
    129138message as a payload\cite{Ada12}.
    130139
    131 The modern flag-ship for termination exceptions is \Cpp,
     140The modern flagship for termination exceptions -- if one exists -- is \Cpp,
    132141which added them in its first major wave of non-object-orientated features
    133142in 1990.\cite{CppHistory}
     
    137146inheriting from
    138147\code{C++}{std::exception}.
    139 Although there is a special catch-all syntax (@catch(...)@) there are no
     148Although there is a special catch-all syntax (@catch(...)@), there are no
    140149operations that can be performed on the caught value, not even type inspection.
    141 Instead the base exception-type \code{C++}{std::exception} defines common
     150Instead, the base exception-type \code{C++}{std::exception} defines common
    142151functionality (such as
    143152the ability to describe the reason the exception was raised) and all
     
    148157
    149158Java was the next popular language to use exceptions.\cite{Java8}
    150 Its exception system largely reflects that of \Cpp, except that requires
     159Its exception system largely reflects that of \Cpp, except that it requires
    151160you throw a child type of \code{Java}{java.lang.Throwable}
    152161and it uses checked exceptions.
    153162Checked exceptions are part of a function's interface,
    154163the exception signature of the function.
    155 Every function that could be raised from a function, either directly or
     164Every exception that could be raised from a function, either directly or
    156165because it is not handled from a called function, is given.
    157166Using this information, it is possible to statically verify if any given
    158 exception is handled and guarantee that no exception will go unhandled.
     167exception is handled, and guarantee that no exception will go unhandled.
    159168Making exception information explicit improves clarity and safety,
    160169but can slow down or restrict programming.
     
    169178recovery or repair. In theory that could be good enough to properly handle
    170179the exception, but more often is used to ignore an exception that the       
    171 programmer does not feel is worth the effort of handling it, for instance if
     180programmer does not feel is worth the effort of handling, for instance if
    172181they do not believe it will ever be raised.
    173 If they are incorrect the exception will be silenced, while in a similar
     182If they are incorrect, the exception will be silenced, while in a similar
    174183situation with unchecked exceptions the exception would at least activate   
    175 the language's unhandled exception code (usually program abort with an 
     184the language's unhandled exception code (usually, a program abort with an
    176185error message).
    177186
    178187%\subsection
    179188Resumption exceptions are less popular,
    180 although resumption is as old as termination; hence, few
     189although resumption is as old as termination; that is, few
    181190programming languages have implemented them.
    182191% http://bitsavers.informatik.uni-stuttgart.de/pdf/xerox/parc/techReports/
     
    186195included in the \Cpp standard.
    187196% https://en.wikipedia.org/wiki/Exception_handling
    188 Since then resumptions have been ignored in main-stream programming languages.
     197Since then, resumptions have been ignored in mainstream programming languages.
    189198However, resumption is being revisited in the context of decades of other
    190199developments in programming languages.
    191200While rejecting resumption may have been the right decision in the past,
    192201the situation has changed since then.
    193 Some developments, such as the function programming equivalent to resumptions,
     202Some developments, such as the functional programming equivalent to resumptions,
    194203algebraic effects\cite{Zhang19}, are enjoying success.
    195 A complete reexamination of resumptions is beyond this thesis,
    196 but there reemergence is enough to try them in \CFA.
     204A complete reexamination of resumption is beyond this thesis,
     205but their reemergence is enough reason to try them in \CFA.
    197206% Especially considering how much easier they are to implement than
    198207% termination exceptions and how much Peter likes them.
     
    208217
    209218%\subsection
    210 More recently exceptions seem to be vanishing from newer programming
     219More recently, exceptions seem to be vanishing from newer programming
    211220languages, replaced by ``panic".
    212221In Rust, a panic is just a program level abort that may be implemented by
    213222unwinding the stack like in termination exception
    214223handling.\cite{RustPanicMacro}\cite{RustPanicModule}
    215 Go's panic through is very similar to a termination, except it only supports
     224Go's panic though is very similar to a termination, except it only supports
    216225a catch-all by calling \code{Go}{recover()}, simplifying the interface at
    217226the cost of flexibility.\cite{Go:2021}
    218227
    219228%\subsection
    220 While exception handling's most common use cases are in error handling,
     229As exception handling's most common use cases are in error handling,
    221230here are some other ways to handle errors with comparisons with exceptions.
    222231\begin{itemize}
     
    233242is discarded to avoid this problem.
    234243Checking error codes also bloats the main execution path,
    235 especially if the error is not handled immediately hand has to be passed
     244especially if the error is not handled immediately and has to be passed
    236245through multiple functions before it is addressed.
     246
     247Here is an example of the pattern in Bash, where commands can only  ``return"
     248numbers and most output is done through streams of text.
     249\begin{lstlisting}[language=bash,escapechar={}]
     250# Immediately after running a command:
     251case $? in
     2520)
     253        # Success
     254        ;;
     2551)
     256        # Error Code 1
     257        ;;
     2582|3)
     259        # Error Code 2 or Error Code 3
     260        ;;
     261# Add more cases as needed.
     262asac
     263\end{lstlisting}
    237264
    238265\item\emph{Special Return with Global Store}:
    239266Similar to the error codes pattern but the function itself only returns
    240 that there was an error
    241 and store the reason for the error in a fixed global location.
    242 For example many routines in the C standard library will only return some
     267that there was an error,
     268and stores the reason for the error in a fixed global location.
     269For example, many routines in the C standard library will only return some
    243270error value (such as -1 or a null pointer) and the error code is written into
    244271the standard variable @errno@.
    245272
    246273This approach avoids the multiple results issue encountered with straight
    247 error codes but otherwise has the same disadvantages and more.
     274error codes as only a single error value has to be returned,
     275but otherwise has the same disadvantages and more.
    248276Every function that reads or writes to the global store must agree on all
    249277possible errors and managing it becomes more complex with concurrency.
     278
     279This example shows some of what has to be done to robustly handle a C
     280standard library function that reports errors this way.
     281\begin{lstlisting}[language=C]
     282// Now a library function can set the error.
     283int handle = open(path_name, flags);
     284if (-1 == handle) {
     285        switch (errno) {
     286    case ENAMETOOLONG:
     287                // path_name is a bad argument.
     288                break;
     289        case ENFILE:
     290                // A system resource has been exausted.
     291                break;
     292        // And many more...
     293    }
     294}
     295\end{lstlisting}
     296% cite open man page?
    250297
    251298\item\emph{Return Union}:
     
    253300Success is one tag and the errors are another.
    254301It is also possible to make each possible error its own tag and carry its own
    255 additional information, but the two branch format is easy to make generic
     302additional information, but the two-branch format is easy to make generic
    256303so that one type can be used everywhere in error handling code.
    257304
    258305This pattern is very popular in any functional or semi-functional language
    259306with primitive support for tagged unions (or algebraic data types).
     307Return unions can also be expressed as monads (evaluation in a context)
     308and often are in languages with special syntax for monadic evaluation,
     309such as Haskell's \code{haskell}{do} blocks.
     310
     311The main advantage is that an arbitrary object can be used to represent an
     312error, so it can include a lot more information than a simple error code.
     313The disadvantages include that the it does have to be checked along the main
     314execution, and if there aren't primitive tagged unions proper, usage can be
     315hard to enforce.
    260316% We need listing Rust/rust to format code snippets from it.
    261317% Rust's \code{rust}{Result<T, E>}
    262 The main advantage is that an arbitrary object can be used to represent an
    263 error so it can include a lot more information than a simple error code.
    264 The disadvantages include that the it does have to be checked along the main
    265 execution and if there aren't primitive tagged unions proper usage can be
    266 hard to enforce.
     318
     319This is a simple example of examining the result of a failing function in
     320Haskell, using its \code{haskell}{Either} type.
     321Examining \code{haskell}{error} further would likely involve more matching,
     322but the type of \code{haskell}{error} is user defined so there are no
     323general cases.
     324\begin{lstlisting}[language=haskell]
     325case failingFunction argA argB of
     326    Right value -> -- Use the successful computed value.
     327    Left error -> -- Handle the produced error.
     328\end{lstlisting}
     329
     330Return unions as monads will result in the same code, but can hide most
     331of the work to propagate errors in simple cases. The code to actually handle
     332the errors, or to interact with other monads (a common case in these
     333languages) still has to be written by hand.
     334
     335If \code{haskell}{failingFunction} is implemented with two helpers that
     336use the same error type, then it can be implemented with a \code{haskell}{do}
     337block.
     338\begin{lstlisting}[language=haskell,literate={}]
     339failingFunction x y = do
     340        z <- helperOne x
     341        helperTwo y z
     342\end{lstlisting}
    267343
    268344\item\emph{Handler Functions}:
     
    274350variable).
    275351C++ uses this approach as its fallback system if exception handling fails,
    276 such as \snake{std::terminate_handler} and, for a time,
    277 \snake{std::unexpected_handler}.
     352such as \snake{std::terminate} and, for a time,
     353\snake{std::unexpected}.\footnote{\snake{std::unexpected} was part of the
     354Dynamic Exception Specification, which has been removed from the standard
     355as of C++20.\cite{CppExceptSpec}}
    278356
    279357Handler functions work a lot like resumption exceptions,
     
    283361function calls, but cheaper (constant time) to call,
    284362they are more suited to more frequent (less exceptional) situations.
     363Although, in \Cpp and other languages that do not have checked exceptions,
     364they can actually be enforced by the type system be more reliable.
     365
     366This is a more local example in \Cpp, using a function to provide
     367a default value for a mapping.
     368\begin{lstlisting}[language=C++]
     369ValueT Map::key_or_default(KeyT key, ValueT(*make_default)(KeyT)) {
     370        ValueT * value = find_value(key);
     371        if (nullptr != value) {
     372                return *value;
     373        } else {
     374                return make_default(key);
     375        }
     376}
     377\end{lstlisting}
    285378\end{itemize}
    286379
     
    288381Because of their cost, exceptions are rarely used for hot paths of execution.
    289382Hence, there is an element of self-fulfilling prophecy as implementation
    290 techniques have been focused on making them cheap to set-up,
     383techniques have been focused on making them cheap to set up,
    291384happily making them expensive to use in exchange.
    292385This difference is less important in higher-level scripting languages,
    293 where using exception for other tasks is more common.
     386where using exceptions for other tasks is more common.
    294387An iconic example is Python's
    295 \code{Python}{StopIteration}\cite{PythonExceptions} exception that
     388\code{Python}{StopIteration}\cite{PythonExceptions} exception, that
    296389is thrown by an iterator to indicate that it is exhausted.
    297 When paired with Python's iterator-based for-loop this will be thrown every
     390When paired with Python's iterator-based for-loop, this will be thrown every
    298391time the end of the loop is reached.\cite{PythonForLoop}
  • doc/theses/andrew_beach_MMath/performance.tex

    r4e28d2e9 r949339b  
    55Instead, the focus was to get the features working. The only performance
    66requirement is to ensure the tests for correctness run in a reasonable
    7 amount of time. Hence, a few basic performance tests were performed to
     7amount of time. Hence, only a few basic performance tests were performed to
    88check this requirement.
    99
     
    1313one with termination and one with resumption.
    1414
    15 C++ is the most comparable language because both it and \CFA use the same
     15GCC C++ is the most comparable language because both it and \CFA use the same
    1616framework, libunwind.
    1717In fact, the comparison is almost entirely in quality of implementation.
     
    3737resumption exceptions. Even the older programming languages with resumption
    3838seem to be notable only for having resumption.
     39On the other hand, the functional equivalents to resumption are too new.
     40There does not seem to be any standard implementations in well-known
     41languages; so far, they seem confined to extensions and research languages.
     42% There was some maybe interesting comparison to an OCaml extension
     43% but I'm not sure how to get that working if it is interesting.
    3944Instead, resumption is compared to its simulation in other programming
    4045languages: fixup functions that are explicitly passed into a function.
     
    4651the number used in the timing runs is given with the results per test.
    4752The Java tests run the main loop 1000 times before
    48 beginning the actual test to ``warm-up" the JVM.
     53beginning the actual test to ``warm up" the JVM.
    4954% All other languages are precompiled or interpreted.
    5055
     
    5459unhandled exceptions in \Cpp and Java as that would cause the process to
    5560terminate.
    56 Luckily, performance on the ``give-up and kill the process" path is not
     61Luckily, performance on the ``give up and kill the process" path is not
    5762critical.
    5863
     
    7681using gcc-10 10.3.0 as a backend.
    7782g++-10 10.3.0 is used for \Cpp.
    78 Java tests are complied and run with version 11.0.11.
    79 Python used version 3.8.10.
     83Java tests are complied and run with Oracle OpenJDK version 11.0.11.
     84Python used CPython version 3.8.10.
    8085The machines used to run the tests are:
    8186\begin{itemize}[nosep]
     
    8590      \lstinline{@} 2.5 GHz running Linux v5.11.0-25
    8691\end{itemize}
    87 Representing the two major families of hardware architecture.
     92These represent the two major families of hardware architecture.
    8893
    8994\section{Tests}
     
    9398
    9499\paragraph{Stack Traversal}
    95 This group measures the cost of traversing the stack,
     100This group of tests measures the cost of traversing the stack
    96101(and in termination, unwinding it).
    97102Inside the main loop is a call to a recursive function.
     
    147152This group of tests measures the cost for setting up exception handling,
    148153if it is
    149 not used (because the exceptional case did not occur).
     154not used because the exceptional case did not occur.
    150155Tests repeatedly cross (enter, execute and leave) a try statement but never
    151156perform a raise.
     
    222227for that language and the result is marked N/A.
    223228There are also cases where the feature is supported but measuring its
    224 cost is impossible. This happened with Java, which uses a JIT that optimize
    225 away the tests and it cannot be stopped.\cite{Dice21}
     229cost is impossible. This happened with Java, which uses a JIT that optimizes
     230away the tests and cannot be stopped.\cite{Dice21}
    226231These tests are marked N/C.
    227232To get results in a consistent range (1 second to 1 minute is ideal,
     
    230235results and has a value in the millions.
    231236
    232 An anomaly in some results came from \CFA's use of gcc nested functions.
     237An anomaly in some results came from \CFA's use of GCC nested functions.
    233238These nested functions are used to create closures that can access stack
    234239variables in their lexical scope.
    235 However, if they do so, then they can cause the benchmark's run-time to
     240However, if they do so, then they can cause the benchmark's run time to
    236241increase by an order of magnitude.
    237242The simplest solution is to make those values global variables instead
    238 of function local variables.
     243of function-local variables.
    239244% Do we know if editing a global inside nested function is a problem?
    240245Tests that had to be modified to avoid this problem have been marked
     
    255260                         \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c|}{Python} \\
    256261\hline
    257 Empty Traversal (1M)   & 3.4   & 2.8   & 18.3  & 23.4      & 3.7   & 3.2   & 15.5  & 14.8  \\
    258 D'tor Traversal (1M)   & 48.4  & 23.6  & N/A   & N/A       & 64.2  & 29.0  & N/A   & N/A   \\
    259 Finally Traversal (1M) & 3.4*  & N/A   & 17.9  & 29.0      & 4.1*  & N/A   & 15.6  & 19.0  \\
    260 Other Traversal (1M)   & 3.6*  & 23.2  & 18.2  & 32.7      & 4.0*  & 24.5  & 15.5  & 21.4  \\
    261 Cross Handler (100M)   & 6.0   & 0.9   & N/C   & 37.4      & 10.0  & 0.8   & N/C   & 32.2  \\
    262 Cross Finally (100M)   & 0.9   & N/A   & N/C   & 44.1      & 0.8   & N/A   & N/C   & 37.3  \\
    263 Match All (10M)        & 32.9  & 20.7  & 13.4  & 4.9       & 36.2  & 24.5  & 12.0  & 3.1   \\
    264 Match None (10M)       & 32.7  & 50.3  & 11.0  & 5.1       & 36.3  & 71.9  & 12.3  & 4.2   \\
     262Empty Traversal (1M)   & 23.0  & 9.6   & 17.6  & 23.4      & 30.6  & 13.6  & 15.5  & 14.7  \\
     263D'tor Traversal (1M)   & 48.1  & 23.5  & N/A   & N/A       & 64.2  & 29.2  & N/A   & N/A   \\
     264Finally Traversal (1M) & 3.2*  & N/A   & 17.6  & 29.2      & 3.9*  & N/A   & 15.5  & 19.0  \\
     265Other Traversal (1M)   & 3.3*  & 23.9  & 17.7  & 32.8      & 3.9*  & 24.5  & 15.5  & 21.6  \\
     266Cross Handler (1B)     & 6.5   & 0.9   & N/C   & 38.0      & 9.6   & 0.8   & N/C   & 32.1  \\
     267Cross Finally (1B)     & 0.8   & N/A   & N/C   & 44.6      & 0.6   & N/A   & N/C   & 37.3  \\
     268Match All (10M)        & 30.5  & 20.6  & 11.2  & 3.9       & 36.9  & 24.6  & 10.7  & 3.1   \\
     269Match None (10M)       & 30.6  & 50.9  & 11.2  & 5.0       & 36.9  & 71.9  & 10.7  & 4.1   \\
    265270\hline
    266271\end{tabular}
     
    276281                        & AMD     & ARM  \\
    277282\hline
    278 Empty Traversal (10M)   & 0.2     & 0.3  \\
     283Empty Traversal (10M)   & 1.4     & 1.2  \\
    279284D'tor Traversal (10M)   & 1.8     & 1.0  \\
    280 Finally Traversal (10M) & 1.7     & 1.0  \\
    281 Other Traversal (10M)   & 22.6    & 25.9 \\
    282 Cross Handler (100M)    & 8.4     & 11.9 \\
     285Finally Traversal (10M) & 1.8     & 1.0  \\
     286Other Traversal (10M)   & 22.6    & 25.8 \\
     287Cross Handler (1B)      & 9.0     & 11.9 \\
    283288Match All (100M)        & 2.3     & 3.2  \\
    284 Match None (100M)       & 2.9     & 3.9  \\
     289Match None (100M)       & 3.0     & 3.8  \\
    285290\hline
    286291\end{tabular}
     
    300305              \multicolumn{1}{c}{Raise} & \multicolumn{1}{c}{\CFA} & \multicolumn{1}{c}{\Cpp} & \multicolumn{1}{c}{Java} & \multicolumn{1}{c|}{Python} \\
    301306\hline
    302 Resume Empty (10M)  & 1.5 & 1.5 & 14.7 & 2.3 & 176.1  & 1.0 & 1.4 & 8.9 & 1.2 & 119.9 \\
     307Resume Empty (10M)  & 1.4 & 1.4 & 15.4 & 2.3 & 178.0  & 1.2 & 1.2 & 8.9 & 1.2 & 118.4 \\
    303308\hline
    304309\end{tabular}
     
    312317\CFA, \Cpp and Java.
    313318% To be exact, the Match All and Match None cases.
    314 The most likely explanation is that, since exceptions
    315 are rarely considered to be the common case, the more optimized languages
    316 make that case expensive to improve other cases.
     319The most likely explanation is that
     320the generally faster languages have made ``common cases fast" at the expense
     321of the rarer cases. Since exceptions are considered rare, they are made
     322expensive to help speed up common actions, such as entering and leaving try
     323statements.
     324Python, on the other hand, while generally slower than the other languages,
     325uses exceptions more and has not sacrificed their performance.
    317326In addition, languages with high-level representations have a much
    318327easier time scanning the stack as there is less to decode.
     
    346355Performance is similar to Empty Traversal in all languages that support finally
    347356clauses. Only Python seems to have a larger than random noise change in
    348 its run-time and it is still not large.
     357its run time and it is still not large.
    349358Despite the similarity between finally clauses and destructors,
    350 finally clauses seem to avoid the spike that run-time destructors have.
     359finally clauses seem to avoid the spike that run time destructors have.
    351360Possibly some optimization removes the cost of changing contexts.
    352361
     
    356365This results in a significant jump.
    357366
    358 Other languages experience a small increase in run-time.
     367Other languages experience a small increase in run time.
    359368The small increase likely comes from running the checks,
    360369but they could avoid the spike by not having the same kind of overhead for
     
    362371
    363372\item[Cross Handler]
    364 Here \CFA falls behind \Cpp by a much more significant margin.
    365 This is likely due to the fact \CFA has to insert two extra function
    366 calls, while \Cpp does not have to do execute any other instructions.
     373Here, \CFA falls behind \Cpp by a much more significant margin.
     374This is likely due to the fact that \CFA has to insert two extra function
     375calls, while \Cpp does not have to execute any other instructions.
    367376Python is much further behind.
    368377
     
    375384\item[Conditional Match]
    376385Both of the conditional matching tests can be considered on their own.
    377 However for evaluating the value of conditional matching itself, the
     386However, for evaluating the value of conditional matching itself, the
    378387comparison of the two sets of results is useful.
    379 Consider the massive jump in run-time for \Cpp going from match all to match
     388Consider the massive jump in run time for \Cpp going from match all to match
    380389none, which none of the other languages have.
    381 Some strange interaction is causing run-time to more than double for doing
     390Some strange interaction is causing run time to more than double for doing
    382391twice as many raises.
    383 Java and Python avoid this problem and have similar run-time for both tests,
     392Java and Python avoid this problem and have similar run time for both tests,
    384393possibly through resource reuse or their program representation.
    385 However \CFA is built like \Cpp and avoids the problem as well, this matches
     394However, \CFA is built like \Cpp, and avoids the problem as well.
     395This matches
    386396the pattern of the conditional match, which makes the two execution paths
    387397very similar.
     
    391401\subsection{Resumption \texorpdfstring{(\autoref{t:PerformanceResumption})}{}}
    392402
    393 Moving on to resumption, there is one general note,
     403Moving on to resumption, there is one general note:
    394404resumption is \textit{fast}. The only test where it fell
    395405behind termination is Cross Handler.
    396406In every other case, the number of iterations had to be increased by a
    397 factor of 10 to get the run-time in an appropriate range
     407factor of 10 to get the run time in an appropriate range
    398408and in some cases resumption still took less time.
    399409
     
    408418
    409419\item[D'tor Traversal]
    410 Resumption does have the same spike in run-time that termination has.
    411 The run-time is actually very similar to Finally Traversal.
     420Resumption does have the same spike in run time that termination has.
     421The run time is actually very similar to Finally Traversal.
    412422As resumption does not unwind the stack, both destructors and finally
    413423clauses are run while walking down the stack during the recursive returns.
     
    416426\item[Finally Traversal]
    417427Same as D'tor Traversal,
    418 except termination did not have a spike in run-time on this test case.
     428except termination did not have a spike in run time on this test case.
    419429
    420430\item[Other Traversal]
     
    427437The only test case where resumption could not keep up with termination,
    428438although the difference is not as significant as many other cases.
    429 It is simply a matter of where the costs come from,
    430 both termination and resumption have some work to set-up or tear-down a
     439It is simply a matter of where the costs come from:
     440both termination and resumption have some work to set up or tear down a
    431441handler. It just so happens that resumption's work is slightly slower.
    432442
     
    434444Resumption shows a slight slowdown if the exception is not matched
    435445by the first handler, which follows from the fact the second handler now has
    436 to be checked. However the difference is not large.
     446to be checked. However, the difference is not large.
    437447
    438448\end{description}
     
    448458More experiments could try to tease out the exact trade-offs,
    449459but the prototype's only performance goal is to be reasonable.
    450 It has already in that range, and \CFA's fixup routine simulation is
     460It is already in that range, and \CFA's fixup routine simulation is
    451461one of the faster simulations as well.
    452 Plus exceptions add features and remove syntactic overhead,
    453 so even at similar performance resumptions have advantages
     462Plus, exceptions add features and remove syntactic overhead,
     463so even at similar performance, resumptions have advantages
    454464over fixup routines.
  • doc/theses/andrew_beach_MMath/uw-ethesis-frontpgs.tex

    r4e28d2e9 r949339b  
    129129\begin{center}\textbf{Abstract}\end{center}
    130130
    131 This is the abstract.
     131The \CFA (Cforall) programming language is an evolutionary refinement of
     132the C programming language, adding modern programming features without
     133changing the programming paradigms of C.
     134One of these modern programming features is more powerful error handling
     135through the addition of an exception handling mechanism (EHM).
     136
     137This thesis covers the design and implementation of the \CFA EHM,
     138along with a review of the other required \CFA features.
     139The EHM includes common features of termination exception handling,
     140which abandons and recovers from an operation,
     141and similar support for resumption exception handling,
     142which repairs and continues with an operation.
     143The design of both has been adapted to utilize other tools \CFA provides,
     144as well as fit with the assertion based interfaces of the language.
     145
     146The EHM has been implemented into the \CFA compiler and run-time environment.
     147Although it has not yet been optimized, performance testing has shown it has
     148comparable performance to other EHMs,
     149which is sufficient for use in current \CFA programs.
    132150
    133151\cleardoublepage
     
    138156\begin{center}\textbf{Acknowledgements}\end{center}
    139157
    140 I would like to thank all the little people who made this thesis possible.
     158As is tradition and his due, I would like to begin by thanking my
     159supervisor Peter Buhr. From accepting me in a first place,
     160to helping me run performance tests, I would not be here without him.
     161Also if there was an ``artist" field here he would be listed there as well,
     162he helped me a lot with the diagrams.
     163
     164I would like to thank the readers
     165Gregor Richards and Yizhou Zhang
     166for their feedback and approval.
     167The presentation of the thesis has definitely been improved with their
     168feedback.
     169
     170I also thank the entire Cforall Team who built the rest of the
     171\CFA compiler. From the existing features I used in my work, to the
     172internal tooling that makes further development easier and the optimizations
     173that make running tests pass by quickly.
     174This includes: Aaron Moss, Rob Schluntz, Thierry Delisle, Michael Brooks,
     175Mubeen Zulfieqar \& Fangren Yu.
     176
     177And thank-you Henry Xue, the co-op student who
     178converted my macro implementation of exception declarations into
     179the compiler features presented in this thesis.
     180
     181Finally I thank my family, who are still relieved I learned how to read.
     182
    141183\cleardoublepage
    142184
  • doc/theses/andrew_beach_MMath/uw-ethesis.bib

    r4e28d2e9 r949339b  
    4040}
    4141
     42@misc{CppExceptSpec,
     43    author={C++ Community},
     44    key={Cpp Reference Exception Specification},
     45    howpublished={\href{https://en.cppreference.com/w/cpp/language/except_spec}{https://\-en.cppreference.com/\-w/\-cpp/\-language/\-except\_spec}},
     46    addendum={Accessed 2021-09-08},
     47}
     48
    4249@misc{RustPanicMacro,
    4350    author={The Rust Team},
    4451    key={Rust Panic Macro},
    45     howpublished={\href{https://doc.rust-lang.org/std/panic/index.html}{https://\-doc.rust-lang.org/\-std/\-panic/\-index.html}},
     52    howpublished={\href{https://doc.rust-lang.org/std/macro.panic.html}{https://\-doc.rust-lang.org/\-std/\-macro.panic.html}},
    4653    addendum={Accessed 2021-08-31},
    4754}
Note: See TracChangeset for help on using the changeset viewer.