Changes in / [5546eee4:0fa0201d]


Ignore:
Files:
9 deleted
48 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/mike_brooks_MMath/array.tex

    r5546eee4 r0fa0201d  
    11\chapter{Array}
    22
    3 \section{Introduction}
    4 
    5 This chapter describes my contribution of language and library features that provide a length-checked array type, as in:
    6 
    7 \begin{lstlisting}
    8     array(float, 99) x;    // x contains 99 floats
    9 
    10     void f( array(float, 42) & a ) {}
    11     f(x);                  // statically rejected: types are different
    12 
    13     forall( T, [N] )
    14     void g( array(T, N) & a, int i ) {
    15         T elem = a[i];     // dynamically checked: requires 0 <= i < N
    16     }
    17     g(x, 0);               // T is float, N is 99, succeeds
    18     g(x, 1000);            // T is float, N is 99, dynamic check fails
    19 \end{lstlisting}
    20 
    21 This example first declares @x@ a variable, whose type is an instantiation of the generic type named @array@, with arguments @float@ and @99@.
    22 Next, it declares @f@ as a function that expects a length-42 array; the type system rejects the call's attempt to pass @x@ to @f@, because the lengths do not match.
    23 Next, the @forall@ annotation on function @g@ introduces @T@ as a familiar type parameter and @N@ as a \emph{dimension} parameter, a new feature that represents a count of elements, as managed by the type system.
    24 Because @g@ accepts any length of array; the type system accepts the calls' passing @x@ to @g@, inferring that this length is 99.
    25 Just as the caller's code does not need to explain that @T@ is @float@, the safe capture and communication of the value @99@ occurs without programmer involvement.
    26 In the case of the second call (which passes the value 1000 for @i@), within the body of @g@, the attempt to subscript @a@ by @i@ fails with a runtime error, since $@i@ \nless @N@$.
    27 
    28 The type @array@, as seen above, comes from my additions to the \CFA standard library.
    29 It is very similar to the built-in array type, which \CFA inherits from C.
    30 Its runtime characteristics are often identical, and some features are available in both.
    31 
    32 \begin{lstlisting}
    33     forall( [N] )
    34     void declDemo() {
    35         float a1[N];         // built-in type ("C array")
    36         array(float, N) a2;  // type from library
    37     }
    38 \end{lstlisting}
    39 
    40 If a caller instantiates @N@ with 42, then both locally-declared array variables, @a1@ and @a2@, become arrays of 42 elements, each element being a @float@.
    41 The two variables have identical size and layout; they both encapsulate 42-float stack allocations, no heap allocations, and no further "bookkeeping" allocations/header.
    42 Having the @array@ library type (that of @a2@) is a tactical measure, an early implementation that offers full feature support.
    43 A future goal (TODO xref) is to port all of its features into the built-in array type (that of @a1@); then, the library type could be removed, and \CFA would have only one array type.
    44 In present state, the built-in array has partial support for the new features.
    45 The fully-featured library type is used exclusively in introductory examples; feature support and C compatibility are revisited in sec TODO.
    46 
    47 Offering the @array@ type, as a distinct alternative from the the C array, is consistent with \CFA's extension philosophy (TODO xref background) to date.
    48 A few compatibility-breaking changes to the behaviour of the C array were also made, both as an implementation convenience, and as justified fixes to C's lax treatment.
    49 
    50 The @array@ type is an opportunity to start from a clean slate and show a cohesive selection of features.
    51 A clean slate was an important starting point because it meant not having to deal with every inherited complexity introduced in TODO xref background-array.
    52 
    53 
    54 My contributions are
    55 \begin{itemize}
    56     \item a type system enhancement that lets polymorphic functions and generic types be parameterized by a numeric value: @forall( [N] )@
    57     \item [TODO: general parking...]
    58     \item identify specific abilities brought by @array@
    59     \item Where there is a gap concerning this feature's readiness for prime-time, identification of specific workable improvements that are likely to close the gap
    60 \end{itemize}
    61 
    62 
    63 
    64 \section{Definitions and design considerations}
    65 
    66 \subsection{Dependent typing}
    67 
    68 
    69 
    70 
    713\section{Features Added}
    724
    735The present work adds a type @array@ to the \CFA standard library~\cite{Cforall}.
    746
    75 This array's length is statically managed and dynamically valued.  This static management achieves argument safety and suggests a path to subscript safety as future work (TODO: cross reference).
    76 
    77 This section presents motivating examples of the new array type's usage and follows up with definitions of the notations that appear.
    78 
    79 The core of the new array management is tracking all array lengths in the type system.  Dynamically valued lengths are represented using type variables.  The stratification of type variables preceding object declarations makes a length referenceable everywhere that it is needed.  For example, a declaration can share one length, @N@, among a pair of parameters and the return.
    80 \lstinputlisting[language=CFA, firstline=10, lastline=17]{hello-array.cfa}
    81 Here, the function @f@ does a pointwise comparison, checking if each pair of numbers is within half a percent of each other, returning the answers in a newly allocated @bool@ array.
    82 
    83 The array type uses the parameterized length information in its @sizeof@ determination, illustrated in the example's call to @alloc@.  That call requests an allocation of type @array(bool, N)@, which the type system deduces from the left-hand side of the initialization, into the return type of the @alloc@ call.  Preexisting \CFA behaviour is leveraged here, both in the return-type-only polymorphism, and the @sized(T)@-aware standard-library @alloc@ routine.  The new @array@ type plugs into this behaviour by implementing the @sized@/@sizeof@ assertion to have the intuitive meaning.  As a result, this design avoids an opportunity for programmer error by making the size/length communication to a called routine implicit, compared with C's @calloc@ (or the low-level \CFA analog @aalloc@), which take an explicit length parameter not managed by the type system.
    84 
    85 \VRef[Figure]{f:fHarness} shows the harness to use the @f@ function illustrating how dynamic values are fed into the system.
    86 Here, the @a@ array is loaded with decreasing values, and the @b@ array with amounts off by a constant, giving relative differences within tolerance at first and out of tolerance later.  The program main is run with two different inputs of sequence length.
    87 
    88 \begin{figure}
    89 \lstinputlisting[language=CFA, firstline=30, lastline=49]{hello-array.cfa}
    90 \caption{\lstinline{f} Harness}
    91 \label{f:fHarness}
    92 \end{figure}
    93 
    94 The loops in the program main follow the more familiar pattern of using the ordinary variable @n@ to convey the length.  The type system implicitly captures this value at the call site (@main@ calling @f@) and makes it available within the callee (@f@'s loop bound).
    95 
    96 The two parts of the example show @n@ adapting a variable into a type-system managed length (at @main@'s declarations of @a@, @b@, and @result@), @N@ adapting in the opposite direction (at @f@'s loop bound), and a pass-thru use of a managed length (at @f@'s declaration of @ret@).
    97 
    98 The @forall( ...[N] )@ participates in the user-relevant declaration of the name @N@, which becomes usable in parameter/return declarations and in the function @b@. The present form is chosen to parallel the existing @forall@ forms:
    99 \begin{cfa}
    100 forall( @[N]@ ) ... // array kind
    101 forall( & T  ) ...  // reference kind (dtype)
    102 forall( T  ) ...    // value kind (otype)
    103 \end{cfa}
    104 
    105 The notation @array(thing, N)@ is a single-dimensional case, giving a generic type instance.
     7This array's length is statically governed and dynamically valued.  This static governance achieves argument safety and suggests a path to subscript safety as future work (TODO: cross reference).  In present state, this work is a runtime libray accessed through a system of macros, while section [TODO: discuss C conexistence] discusses a path for the new array type to be accessed directly by \CFA's array syntax, replacing the lifted C array that this syntax currently exposes.
     8
     9This section presents motivating examples of the new array type's usage, and follows up with definitions of the notations that appear.
     10
     11The core of the new array governance is tracking all array lengths in the type system.  Dynamically valued lengths are represented using type variables.  The stratification of type variables preceding object declarations makes a length referenceable everywhere that it is needed.  For example, a declaration can share one length, @N@, among a pair of parameters and the return.
     12\lstinputlisting[language=CFA, firstline=50, lastline=59]{hello-array.cfa}
     13Here, the function @f@ does a pointwise comparison, checking if each pair of numbers is within half a percent of each other, returning the answers in a newly allocated bool array.
     14
     15The array type uses the parameterized length information in its @sizeof(-)@ determination, illustrated in the example's call to @alloc@.  That call requests an allocation of type @array(bool, N)@, which the type system deduces from the left-hand side of the initialization, into the return type of the @alloc@ call.  Preexesting \CFA behaviour is leveraged here, both in the return-type-only polymorphism, and the @sized(T)@-aware standard-library @alloc@ routine.  The new @array@ type plugs into this behaviour by implementing the @sized@/@sizeof(-)@ assertion to have the intuitive meaning.  As a result, this design avoids an opportunity for programmer error by making the size/length communication to a called routine implicit, compared with C's @calloc@ (or the low-level \CFA analog @aalloc@) which take an explicit length parameter not managed by the type system.
     16
     17A harness for this @f@ function shows how dynamic values are fed into the system.
     18\lstinputlisting[language=CFA, firstline=100, lastline=119]{hello-array.cfa}
     19Here, the @a@ sequence is loaded with decreasing values, and the @b@ sequence with amounts off by a constant, giving relative differences within tolerance at first and out of tolerance later.  The driver program is run with two different inputs of sequence length.
     20
     21The loops in the driver follow the more familiar pattern of using the ordinary variable @n@ to convey the length.  The type system implicitly captures this value at the call site (@main@ calling @f@) and makes it available within the callee (@f@'s loop bound).
     22
     23The two parts of the example show @Z(n)@ adapting a variable into a type-system governed length (at @main@'s declarations of @a@, @b@, and @result@), @z(N)@ adapting in the opposite direction (at @f@'s loop bound), and a passthru use of a governed length (at @f@'s declaration of @ret@.)  It is hoped that future language integration will allow the macros @Z@ and @z@ to be omitted entirely from the user's notation, creating the appearance of seamlessly interchanging numeric values with appropriate generic parameters.
     24
     25The macro-assisted notation, @forall...ztype@, participates in the user-relevant declaration of the name @N@, which becomes usable in parameter/return declarations and in the function body.  So future language integration only sweetens this form and does not seek to elimimate the declaration.  The present form is chosen to parallel, as closely as a macro allows, the existing forall forms:
     26\begin{lstlisting}
     27  forall( dtype T  ) ...
     28  forall( otype T  ) ...
     29  forall( ztype(N) ) ...
     30\end{lstlisting}
     31
     32The notation @array(thing, N)@ is also macro-assisted, though only in service of enabling multidimensional uses discussed further in section \ref{toc:mdimpl}.  In a single-dimensional case, the marco expansion gives a generic type instance, exactly like the original form suggests.
     33
     34
     35
    10636In summary:
    107 \begin{itemize}
    108 \item
    109 @[N]@ -- within a forall, declares the type variable @N@ to be a managed length
    110 \item
    111 $e$ -- a type representing the value of $e$ as a managed length, where $e$ is a @size_t@-typed expression
    112 \item
    113 N -- an expression of type @size_t@, whose value is the managed length @N@
    114 \item
    115 @array( thing, N0, N1, ... )@ -- a type wrapping $\prod_i N_i$ adjacent occurrences of @thing@ objects
    116 \end{itemize}
    117 Unsigned integers have a special status in this type system.  Unlike how C++ allows @template< size_t N, char * msg, typename T >...@ declarations, \CFA does not accommodate values of any user-provided type.  TODO: discuss connection with dependent types.
     37
     38\begin{tabular}{p{15em}p{20em}}
     39  @ztype( N )@ & within a forall, declares the type variable @N@ to be a governed length \\[0.25em]
     40  @Z( @ $e$ @ )@ & a type representing the value of $e$ as a governed length, where $e$ is a @size_t@-typed expression \\[0.25em]
     41  @z( N )@ & an expression of type @size_t@, whose value is the governed length @N@ \\[0.25em]
     42  @array( thing, N0, N1, ... )@
     43  &  a type wrapping $\prod_i N_i$ adjacent occurrences of @thing@ objects
     44\end{tabular}
     45
     46Unsigned integers have a special status in this type system.  Unlike how C++ allows @template< size_t N, char * msg, typename T >...@ declarations, this system does not accommodate values of any user-provided type.  TODO: discuss connection with dependent types.
     47
    11848
    11949An example of a type error demonstrates argument safety.  The running example has @f@ expecting two arrays of the same length.  A compile-time error occurs when attempting to call @f@ with arrays whose lengths may differ.
    120 \lstinputlisting[language=CFA, firstline=60, lastline=65]{hello-array.cfa}
    121 As is common practice in C, the programmer is free to cast, to assert knowledge not shared with the type system.
    122 \lstinputlisting[language=CFA, firstline=70, lastline=75]{hello-array.cfa}
    123 
    124 Argument safety and the associated implicit communication of array length work with \CFA's generic types too.
    125 \CFA allows aggregate types to be generalized with multiple type parameters, including parameterized element type, so can it be defined over a parameterized length.
    126 Doing so gives a refinement of C's ``flexible array member'' pattern, that allows nesting structures with array members anywhere within other structures.
    127 \lstinputlisting[language=CFA, firstline=10, lastline=16]{hello-accordion.cfa}
    128 This structure's layout has the starting offset of @cost_contribs@ varying in @Nclients@, and the offset of @total_cost@ varying in both generic parameters.  For a function that operates on a @request@ structure, the type system handles this variation transparently.
    129 \lstinputlisting[language=CFA, firstline=40, lastline=47]{hello-accordion.cfa}
    130 In the example, different runs of the program result in different offset values being used.
    131 \lstinputlisting[language=CFA, firstline=60, lastline=76]{hello-accordion.cfa}
     50\lstinputlisting[language=CFA, firstline=150, lastline=155]{hello-array.cfa}
     51As is common practice in C, the programmer is free to cast, to assert knownledge not shared with the type system.
     52\lstinputlisting[language=CFA, firstline=200, lastline=202]{hello-array.cfa}
     53
     54Argument safety, and the associated implicit communication of length, work with \CFA's generic types too.  As a structure can be defined over a parameterized element type, so can it be defined over a parameterized length.  Doing so gives a refinement of C's ``flexible array member'' pattern, that allows nesting structures with array members anywhere within other structures.
     55\lstinputlisting[language=CFA, firstline=20, lastline=26]{hello-accordion.cfa}
     56This structure's layout has the starting offest of @cost_contribs@ varying in @Nclients@, and the offset of @total_cost@ varying in both generic paramters.  For a function that operates on a @request@ structure, the type system handles this variation transparently.
     57\lstinputlisting[language=CFA, firstline=50, lastline=57]{hello-accordion.cfa}
     58In the example runs of a driver program, different offset values are navigated in the two cases.
     59\lstinputlisting[language=CFA, firstline=100, lastline=115]{hello-accordion.cfa}
    13260The output values show that @summarize@ and its caller agree on both the offsets (where the callee starts reading @cost_contribs@ and where the callee writes @total_cost@).  Yet the call site still says just, ``pass the request.''
    13361
     
    13967TODO: introduce multidimensional array feature and approaches
    14068
    141 The new \CFA standard library @array@ datatype supports multidimensional uses more richly than the C array.  The new array's multidimensional interface and implementation, follows an array-of-arrays setup, meaning, like C's @float[n][m]@ type, one contiguous object, with coarsely-strided dimensions directly wrapping finely-strided dimensions.  This setup is in contrast with the pattern of array of pointers to other allocations representing a sub-array.  Beyond what C's type offers, the new array brings direct support for working with a noncontiguous array slice, allowing a program to work with dimension subscripts given in a non-physical order.  C and C++ require a programmer with such a need to manage pointer/offset arithmetic manually.
    142 
    143 Examples are shown using a $5 \times 7$ float array, @a@, loaded with increments of $0.1$ when stepping across the length-7 finely-strided dimension shown on columns, and with increments of $1.0$ when stepping across the length-5 coarsely-strided dimension shown on rows.
    144 \lstinputlisting[language=CFA, firstline=120, lastline=126]{hello-md.cfa}
     69The new \CFA standard library @array@ datatype supports multidimensional uses more richly than the C array.  The new array's multimentsional interface and implementation, follows an array-of-arrays setup, meaning, like C's @float[n][m]@ type, one contiguous object, with coarsely-strided dimensions directly wrapping finely-strided dimensions.  This setup is in contrast with the pattern of array of pointers to other allocations representing a sub-array.  Beyond what C's type offers, the new array brings direct support for working with a noncontiguous array slice, allowing a program to work with dimension subscripts given in a non-physical order.  C and C++ require a programmer with such a need to manage pointer/offset arithmetic manually.
     70
     71Examples are shown using a $5 \times 7$ float array, @a@, loaded with increments of $0.1$ when stepping across the length-7 finely-strided dimension shown on columns, and with increments of $1.0$ when stepping across the length-5 corsely-strided dimension shown on rows.
     72\lstinputlisting[language=CFA, firstline=120, lastline=128]{hello-md.cfa}
    14573The memory layout of @a@ has strictly increasing numbers along its 35 contiguous positions.
    14674
    147 A trivial form of slicing extracts a contiguous inner array, within an array-of-arrays.  Like with the C array, a lesser-dimensional array reference can be bound to the result of subscripting a greater-dimensional array, by a prefix of its dimensions.  This action first subscripts away the most coarsely strided dimensions, leaving a result that expects to be be subscripted by the more finely strided dimensions.
     75A trivial form of slicing extracts a contiguous inner array, within an array-of-arrays.  Like with the C array, a lesser-dimensional array reference can be bound to the result of subscripting a greater-dimensional array, by a prefix of its dimensions.  This action first subscripts away the most coaresly strided dimensions, leaving a result that expects to be be subscripted by the more finely strided dimensions.
    14876\lstinputlisting[language=CFA, firstline=60, lastline=66]{hello-md.cfa}
    149 \lstinputlisting[aboveskip=0pt, language=CFA, firstline=140, lastline=140]{hello-md.cfa}
    150 
    151 This function declaration is asserting too much knowledge about its parameter @c@, for it to be usable for printing either a row slice or a column slice.  Specifically, declaring the parameter @c@ with type @array@ means that @c@ is contiguous.  However, the function does not use this fact.  For the function to do its job, @c@ need only be of a container type that offers a subscript operator (of type @ptrdiff_t@ $\rightarrow$ @float@), with managed length @N@.  The new-array library provides the trait @ix@, so-defined.  With it, the original declaration can be generalized, while still implemented with the same body, to the latter declaration:
     77\lstinputlisting[language=CFA, firstline=140, lastline=140]{hello-md.cfa}
     78
     79This function declaration is asserting too much knowledge about its parameter @c@, for it to be usable for printing either a row slice or a column slice.  Specifically, declaring the parameter @c@ with type @array@ means that @c@ is contiguous.  However, the function does not use this fact.  For the function to do its job, @c@ need only be of a container type that offers a subscript operator (of type @ptrdiff_t@ $\rightarrow$ @float@), with governed length @N@.  The new-array library provides the trait @ix@, so-defined.  With it, the original declaration can be generalized, while still implemented with the same body, to the latter declaration:
    15280\lstinputlisting[language=CFA, firstline=40, lastline=44]{hello-md.cfa}
    153 \lstinputlisting[aboveskip=0pt, language=CFA, firstline=145, lastline=145]{hello-md.cfa}
     81\lstinputlisting[language=CFA, firstline=145, lastline=145]{hello-md.cfa}
    15482
    15583Nontrivial slicing, in this example, means passing a noncontiguous slice to @print1d@.  The new-array library provides a ``subscript by all'' operation for this purpose.  In a multi-dimensional subscript operation, any dimension given as @all@ is left ``not yet subscripted by a value,'' implementing the @ix@ trait, waiting for such a value.
     
    194122\begin{figure}
    195123    \includegraphics{measuring-like-layout}
    196     \caption{Visualization of subscripting by value and by \lstinline[language=CFA,basicstyle=\ttfamily]{all}, for \lstinline[language=CFA,basicstyle=\ttfamily]{a} of type \lstinline[language=CFA,basicstyle=\ttfamily]{array( float, 5, 7 )}. The horizontal dimension represents memory addresses while vertical layout is conceptual.}
     124    \caption{Visualization of subscripting by value and by \lstinline[language=CFA,basicstyle=\ttfamily]{all}, for \lstinline[language=CFA,basicstyle=\ttfamily]{a} of type \lstinline[language=CFA,basicstyle=\ttfamily]{array( float, Z(5), Z(7) )}. The horizontal dimension represents memory addresses while vertical layout is conceptual.}
    197125    \label{fig:subscr-all}
    198126\end{figure}
    199127
    200 \noindent While the latter description implies overlapping elements, Figure \ref{fig:subscr-all} shows that the overlaps only occur with unused spaces between elements.  Its depictions of @a[all][...]@ show the navigation of a memory layout with nontrivial strides, that is, with ``spaced \_ floats apart'' values that are greater or smaller than the true count of valid indices times the size of a logically indexed element.  Reading from the bottom up, the expression @a[all][3][2]@ shows a float, that is masquerading as a @float[7]@, for the purpose of being arranged among its peers; five such occurrences form @a[all][3]@.  The tail of flatter boxes extending to the right of a proper element represents this stretching.  At the next level of containment, the structure @a[all][3]@ masquerades as a @float[1]@, for the purpose of being arranged among its peers; seven such occurrences form @a[all]@.  The vertical staircase arrangement represents this compression, and resulting overlapping.
    201 
    202 The new-array library defines types and operations that ensure proper elements are accessed soundly in spite of the overlapping.  The private @arpk@ structure (array with explicit packing) is generic over these two types (and more): the contained element, what it is masquerading as.  This structure's public interface is the @array(...)@ construction macro and the two subscript operators.  Construction by @array@ initializes the masquerading-as type information to be equal to the contained-element information.  Subscripting by @all@ rearranges the order of masquerading-as types to achieve, in general, nontrivial striding.  Subscripting by a number consumes the masquerading-as size of the contained element type, does normal array stepping according to that size, and returns there element found there, in unmasked form.
     128\noindent While the latter description implies overlapping elements, Figure \ref{fig:subscr-all} shows that the overlaps only occur with unused spaces between elements.  Its depictions of @a[all][...]@ show the navigation of a memory layout with nontrivial strides, that is, with ``spaced \_ floats apart'' values that are greater or smaller than the true count of valid indeces times the size of a logically indexed element.  Reading from the bottom up, the expression @a[all][3][2]@ shows a float, that is masquerading as a @float[7]@, for the purpose of being arranged among its peers; five such occurrences form @a[all][3]@.  The tail of flatter boxes extending to the right of a poper element represents this stretching.  At the next level of containment, the structure @a[all][3]@ masquerades as a @float[1]@, for the purpose of being arranged among its peers; seven such occurrences form @a[all]@.  The verical staircase arrangement represents this compression, and resulting overlapping.
     129
     130The new-array library defines types and operations that ensure proper elements are accessed soundly in spite of the overlapping.  The private @arpk@ structure (array with explicit packing) is generic over these two types (and more): the contained element, what it is masquerading as.  This structure's public interface is the @array(...)@ construction macro and the two subscript operators.  Construction by @array@ initializes the masquerading-as type information to be equal to the contained-element information.  Subscrpting by @all@ rearranges the order of masquerading-as types to achieve, in genernal, nontrivial striding.  Subscripting by a number consumes the masquerading-as size of the contained element type, does normal array stepping according to that size, and returns there element found there, in unmasked form.
    203131
    204132The @arpk@ structure and its @-[i]@ operator are thus defined as:
     
    210138      ) {
    211139    struct arpk {
    212         S strides[N];           // so that sizeof(this) is N of S
     140        S strides[z(N)];        // so that sizeof(this) is N of S
    213141    };
    214142
     
    220148\end{lstlisting}
    221149
    222 An instantiation of the @arpk@ generic is given by the @array(E_base, N0, N1, ...)@ expansion, which is @arpk( N0, Rec, Rec, E_base )@, where @Rec@ is @array(E_base, N1, ...)@.  In the base case, @array(E_base)@ is just @E_base@.  Because this construction uses the same value for the generic parameters @S@ and @E_im@, the resulting layout has trivial strides.
    223 
    224 Subscripting by @all@, to operate on nontrivial strides, is a dequeue-enqueue operation on the @E_im@ chain, which carries @S@ instantiations, intact, to new positions.  Expressed as an operation on types, this rotation is:
     150An instantion of the @arpk@ generic is given by the @array(E_base, N0, N1, ...)@ exapnsion, which is @arpk( N0, Rec, Rec, E_base )@, where @Rec@ is @array(E_base, N1, ...)@.  In the base case, @array(E_base)@ is just @E_base@.  Because this construction uses the same value for the generic parameters @S@ and @E_im@, the resulting layout has trivial strides.
     151
     152Subscripting by @all@, to operate on nontrivial strides, is a dequeue-enqueue operation on the @E_im@ chain, which carries @S@ instatiations, intact, to new positions.  Expressed as an operation on types, this rotation is:
    225153\begin{eqnarray*}
    226154suball( arpk(N, S, E_i, E_b) ) & = & enq( N, S, E_i, E_b ) \\
     
    232160\section{Bound checks, added and removed}
    233161
    234 \CFA array subscripting is protected with runtime bound checks.  Having dependent typing causes the optimizer to remove more of these bound checks than it would without them.  This section provides a demonstration of the effect.
    235 
    236 The experiment compares the \CFA array system with the padded-room system [TODO:xref] most typically exemplified by Java arrays, but also reflected in the C++ pattern where restricted vector usage models a checked array.  The essential feature of this padded-room system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based.  The experiment compares with the C++ version to keep access to generated assembly code simple.
    237 
    238 As a control case, a simple loop (with no reused dimension sizes) is seen to get the same optimization treatment in both the \CFA and C++ versions.  When the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code.  But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch an occurrence the mistake.
    239 
    240 TODO: paste source and assembly codes
     162\CFA array subscripting is protected with runtime bound checks.  Having dependent typing causes the opimizer to remove more of these bound checks than it would without them.  This section provides a demonstration of the effect.
     163
     164The experiment compares the \CFA array system with the padded-room system [todo:xref] most typically exemplified by Java arrays, but also reflected in the C++ pattern where restricted vector usage models a checked array.  The essential feature of this padded-room system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based.  The experiment compares with the C++ version to keep access to generated assembly code simple.
     165
     166As a control case, a simple loop (with no reused dimension sizes) is seen to get the same optimization treatment in both the \CFA and C++ versions.  When the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code.  But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assemly, ready to catch an occurrence the mistake.
     167
     168TODO: paste source and assemby codes
    241169
    242170Incorporating reuse among dimension sizes is seen to give \CFA an advantage at being optimized.  The case is naive matrix multiplication over a row-major encoding.
     
    250178\section{Comparison with other arrays}
    251179
    252 \CFA's array is the first lightweight application of dependently-typed bound tracking to an extension of C.  Other extensions of C that apply dependently-typed bound tracking are heavyweight, in that the bound tracking is part of a linearly typed ownership system that further helps guarantee statically the validity of every pointer deference.  These systems, therefore, ask the programmer to convince the type checker that every pointer dereference is valid.  \CFA imposes the lighter-weight obligation, with the more limited guarantee, that initially-declared bounds are respected thereafter.
     180\CFA's array is the first lightweight application of dependently-typed bound tracking to an extension of C.  Other extensions of C that apply dependently-typed bound tracking are heavyweight, in that the bound tracking is part of a linearly typed ownership system that further helps guarantee statically the validity of every pointer deference.  These systems, therefore, ask the programmer to convince the typechecker that every pointer dereference is valid.  \CFA imposes the lighter-weight obligation, with the more limited guarantee, that initially-declared bounds are respected thereafter.
    253181
    254182\CFA's array is also the first extension of C to use its tracked bounds to generate the pointer arithmetic implied by advanced allocation patterns.  Other bound-tracked extensions of C either forbid certain C patterns entirely, or address the problem of \emph{verifying} that the user's provided pointer arithmetic is self-consistent.  The \CFA array, applied to accordion structures [TOD: cross-reference] \emph{implies} the necessary pointer arithmetic, generated automatically, and not appearing at all in a user's program.
     
    256184\subsection{Safety in a padded room}
    257185
    258 Java's array [TODO:cite] is a straightforward example of assuring safety against undefined behaviour, at a cost of expressiveness for more applied properties.  Consider the array parameter declarations in:
     186Java's array [todo:cite] is a straightforward example of assuring safety against undefined behaviour, at a cost of expressiveness for more applied properties.  Consider the array parameter declarations in:
    259187
    260188\begin{tabular}{rl}
     
    263191\end{tabular}
    264192
    265 Java's safety against undefined behaviour assures the callee that, if @a@ is non-null, then @a.length@ is a valid access (say, evaluating to the number $\ell$) and if @i@ is in $[0, \ell)$ then @a[i]@ is a valid access.  If a value of @i@ outside this range is used, a runtime error is guaranteed.  In these respects, C offers no guarantees at all.  Notably, the suggestion that @n@ is the intended size of the first dimension of @a@ is documentation only.  Indeed, many might prefer the technically equivalent declarations @float a[][m]@ or @float (*a)[m]@ as emphasizing the ``no guarantees'' nature of an infrequently used language feature, over using the opportunity to explain a programmer intention.  Moreover, even if @a[0][0]@ is valid for the purpose intended, C's basic infamous feature is the possibility of an @i@, such that @a[i][0]@ is not valid for the same purpose, and yet, its evaluation does not produce an error.
     193Java's safety against undefined behaviour assures the callee that, if @a@ is non-null, then @a.length@ is a valid access (say, evaluating to the number $\ell$) and if @i@ is in $[0, \ell)$ then @a[i]@ is a valid access.  If a value of @i@ outside this range is used, a runtime error is guaranteed.  In these respects, C offers no guarantess at all.  Notably, the suggestion that @n@ is the intended size of the first dimension of @a@ is documentation only.  Indeed, many might prefer the technically equivalent declarations @float a[][m]@ or @float (*a)[m]@ as emphasizing the ``no guarantees'' nature of an infrequently used language feature, over using the opportunity to explain a programmer intention.  Moreover, even if @a[0][0]@ is valid for the purpose intended, C's basic infamous feature is the possibility of an @i@, such that @a[i][0]@ is not valid for the same purpose, and yet, its evaluation does not produce an error.
    266194
    267195Java's lack of expressiveness for more applied properties means these outcomes are possible:
     
    273201C's array has none of these limitations, nor do any of the ``array language'' comparators discussed in this section.
    274202
    275 This Java level of safety and expressiveness is also exemplified in the C family, with the commonly given advice [TODO:cite example], for C++ programmers to use @std::vector@ in place of the C++ language's array, which is essentially the C array.  The advice is that, while a vector is also more powerful (and quirky) than an array, its capabilities include options to preallocate with an upfront size, to use an available bound-checked accessor (@a.at(i)@ in place of @a[i]@), to avoid using @push_back@, and to use a vector of vectors.  Used with these restrictions, out-of-bound accesses are stopped, and in-bound accesses never exercise the vector's ability to grow, which is to say, they never make the program slow to reallocate and copy, and they never invalidate the program's other references to the contained values.  Allowing this scheme the same referential integrity assumption that \CFA enjoys [TODO:xref], this scheme matches Java's safety and expressiveness exactly.  [TODO: decide about going deeper; some of the Java expressiveness concerns have mitigations, up to even more tradeoffs.]
     203This Java level of safety and expressiveness is also exemplified in the C family, with the commonly given advice [todo:cite example], for C++ programmers to use @std::vector@ in place of the C++ language's array, which is essentially the C array.  The advice is that, while a vector is also more powerful (and quirky) than an arry, its capabilities include options to preallocate with an upfront size, to use an available bound-checked accessor (@a.at(i)@ in place of @a[i]@), to avoid using @push_back@, and to use a vector of vectors.  Used with these restrictions, out-of-bound accesses are stopped, and in-bound accesses never exercise the vector's ability to grow, which is to say, they never make the program slow to reallocate and copy, and they never invalidate the program's other references to the contained values.  Allowing this scheme the same referential integrity assumption that \CFA enjoys [todo:xref], this scheme matches Java's safety and expressiveness exactly.  [TODO: decide about going deeper; some of the Java expressiveness concerns have mitigations, up to even more tradeoffs.]
    276204
    277205\subsection{Levels of dependently typed arrays}
     
    283211    \item a formulation of matrix multiplication, where the two operands must agree on a middle dimension, and where the result dimensions match the operands' outer dimensions
    284212\end{itemize}
    285 Across this field, this expressiveness is not just an available place to document such assumption, but these requirements are strongly guaranteed by default, with varying levels of statically/dynamically checked and ability to opt out.  Along the way, the \CFA array also closes the safety gap (with respect to bounds) that Java has over C.
     213Across this field, this expressiveness is not just an avaiable place to document such assumption, but these requirements are strongly guaranteed by default, with varying levels of statically/dynamically checked and ability to opt out.  Along the way, the \CFA array also closes the safety gap (with respect to bounds) that Java has over C.
     214
     215
    286216
    287217Dependent type systems, considered for the purpose of bound-tracking, can be full-strength or restricted.  In a full-strength dependent type system, a type can encode an arbitrarily complex predicate, with bound-tracking being an easy example.  The tradeoff of this expressiveness is complexity in the checker, even typically, a potential for its nontermination.  In a restricted dependent type system (purposed for bound tracking), the goal is to check helpful properties, while keeping the checker well-behaved; the other restricted checkers surveyed here, including \CFA's, always terminate.  [TODO: clarify how even Idris type checking terminates]
    288218
    289 Idris is a current, general-purpose dependently typed programming language.  Length checking is a common benchmark for full dependent type systems.  Here, the capability being considered is to track lengths that adjust during the execution of a program, such as when an \emph{add} operation produces a collection one element longer than the one on which it started.  [TODO: finish explaining what Data.Vect is and then the essence of the comparison]
     219Idris is a current, general-purpose dependently typed programming language.  Length checking is a common benchmark for full dependent type stystems.  Here, the capability being considered is to track lengths that adjust during the execution of a program, such as when an \emph{add} operation produces a collection one element longer than the one on which it started.  [todo: finish explaining what Data.Vect is and then the essence of the comparison]
    290220
    291221POINTS:
    292 here is how our basic checks look (on a system that does not have to compromise);
     222here is how our basic checks look (on a system that deosn't have to compromise);
    293223it can also do these other cool checks, but watch how I can mess with its conservativeness and termination
    294224
    295 Two current, state-of-the-art array languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, offer offer novel contributions concerning similar, restricted dependent types for tracking array length.  Unlike \CFA, both are garbage-collected functional languages.  Because they are garbage-collected, referential integrity is built-in, meaning that the heavyweight analysis, that \CFA aims to avoid, is unnecessary.  So, like \CFA, the checking in question is a lightweight bounds-only analysis.  Like \CFA, their checks that are conservatively limited by forbidding arithmetic in the depended-upon expression.
     225Two current, state-of-the-art array languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, offer offer novel contributions concerning similar, restricted dependent types for tracking array length.  Unlike \CFA, both are garbage-collected functional languages.  Because they are garbage-collected, referential integrity is built-in, meaning that the heavyweight analysis, that \CFA aims to avoid, is unnecessary.  So, like \CFA, the checking in question is a leightweight bounds-only analysis.  Like \CFA, their checks that are conservatively limited by forbidding arithmetic in the depended-upon expression.
    296226
    297227
     
    301231Dex uses a novel conception of size, embedding its quantitative information completely into an ordinary type.
    302232
    303 Futhark and full-strength dependently typed languages treat array sizes are ordinary values.  Futhark restricts these expressions syntactically to variables and constants, while a full-strength dependent system does not.
     233Futhark and full-strength dependently typed lanaguages treat array sizes are ordinary values.  Futhark restricts these expressions syntactically to variables and constants, while a full-strength dependent system does not.
    304234
    305235CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet has no instances.  Belonging to the type system means it is inferred at a call site and communicated implicitly, like in Dex and unlike in Futhark.  Having no instances means there is no type for a variable @i@ that constrains @i@ to be in the range for @N@, unlike Dex, [TODO: verify], but like Futhark.
     
    350280If \CFA gets such a system for describing the list of values in a type, then \CFA arrays are poised to move from the Futhark level of expressiveness, up to the Dex level.
    351281
    352 [TODO: introduce Ada in the comparators]
     282[TODO: indroduce Ada in the comparators]
    353283
    354284In Ada and Dex, an array is conceived as a function whose domain must satisfy only certain structural assumptions, while in C, C++, Java, Futhark and \CFA today, the domain is a prefix of the natural numbers.  The generality has obvious aesthetic benefits for programmers working on scheduling resources to weekdays, and for programmers who prefer to count from an initial number of their own choosing.
    355285
    356 This change of perspective also lets us remove ubiquitous dynamic bound checks.  [TODO: xref] discusses how automatically inserted bound checks can often be optimized away.  But this approach is unsatisfying to a programmer who believes she has written code in which dynamic checks are unnecessary, but now seeks confirmation.  To remove the ubiquitous dynamic checking is to say that an ordinary subscript operation is only valid when it can be statically verified to be in-bound (and so the ordinary subscript is not dynamically checked), and an explicit dynamic check is available when the static criterion is impractical to meet.
     286This change of perspective also lets us remove ubiquitous dynamic bound checks.  [TODO: xref] discusses how automatically inserted bound checks can often be otimized away.  But this approach is unsatisfying to a programmer who believes she has written code in which dynamic checks are unnecessary, but now seeks confirmation.  To remove the ubiquitious dynamic checking is to say that an ordinary subscript operation is only valid when it can be statically verified to be in-bound (and so the ordinary subscript is not dynamically checked), and an explicit dynamic check is available when the static criterion is impractical to meet.
    357287
    358288[TODO, fix confusion:  Idris has this arrangement of checks, but still the natural numbers as the domain.]
     
    366296\end{lstlisting}
    367297
    368 Dex uses this foundation of a trait (as an array type's domain) to achieve polymorphism over shapes.  This flavour of polymorphism lets a function be generic over how many (and the order of) dimensions a caller uses when interacting with arrays communicated with this function.  Dex's example is a routine that calculates pointwise differences between two samples.  Done with shape polymorphism, one function body is equally applicable to a pair of single-dimensional audio clips (giving a single-dimensional result) and a pair of two-dimensional photographs (giving a two-dimensional result).  In both cases, but with respectively dimensioned interpretations of ``size,'' this function requires the argument sizes to match, and it produces a result of the that size.
    369 
    370 The polymorphism plays out with the pointwise-difference routine advertising a single-dimensional interface whose domain type is generic.  In the audio instantiation, the duration-of-clip type argument is used for the domain.  In the photograph instantiation, it's the tuple-type of $ \langle \mathrm{img\_wd}, \mathrm{img\_ht} \rangle $.  This use of a tuple-as-index is made possible by the built-in rule for implementing @Ix@ on a pair, given @Ix@ implementations for its elements
     298Dex uses this foundation of a trait (as an array type's domain) to achieve polymorphism over shapes.  This flavour of polymorphism lets a function be generic over how many (and the order of) dimensions a caller uses when interacting with arrays communicated with this funciton.  Dex's example is a routine that calculates pointwise differences between two samples.  Done with shape polymorphism, one function body is equally applicable to a pair of single-dimensional audio clips (giving a single-dimensional result) and a pair of two-dimensional photographs (giving a two-dimensional result).  In both cases, but with respectively dimensoned interpretations of ``size,'' this function requries the argument sizes to match, and it produces a result of the that size.
     299
     300The polymorphism plays out with the pointwise-difference routine advertizing a single-dimensional interface whose domain type is generic.  In the audio instantiation, the duration-of-clip type argument is used for the domain.  In the photograph instantiation, it's the tuple-type of $ \langle \mathrm{img\_wd}, \mathrm{img\_ht} \rangle $.  This use of a tuple-as-index is made possible by the built-in rule for implementing @Ix@ on a pair, given @Ix@ implementations for its elements
    371301\begin{lstlisting}
    372302instance {a b} [Ix a, Ix b] Ix (a & b)
  • doc/theses/mike_brooks_MMath/background.tex

    r5546eee4 r0fa0201d  
    11\chapter{Background}
    22
    3 This chapter states facts about the prior work, upon which my contributions build.
    4 Each receives a justification of the extent to which its statement is phrased to provoke controversy or surprise.
     3\section{Arrays}
    54
    6 \section{C}
    7 
    8 \subsection{Common knowledge}
    9 
    10 The reader is assumed to have used C or \CC for the coursework of at least four university-level courses, or have equivalent experience.
    11 The current discussion introduces facts, unaware of which, such a functioning novice may be operating.
    12 
    13 % TODO: decide if I'm also claiming this collection of facts, and test-oriented presentation is a contribution; if so, deal with (not) arguing for its originality
    14 
    15 \subsection{Convention: C is more touchable than its standard}
    16 
    17 When it comes to explaining how C works, I like illustrating definite program semantics.
    18 I prefer doing so, over a quoting manual's suggested programmer's intuition, or showing how some compiler writers chose to model their problem.
    19 To illustrate definite program semantics, I devise a program, whose behaviour exercises the point at issue, and I show its behaviour.
    20 
    21 This behaviour is typically one of
    22 \begin{itemize}
    23     \item my statement that the compiler accepts or rejects the program
    24     \item the program's printed output, which I show
    25     \item my implied assurance that its assertions do not fail when run
    26 \end{itemize}
    27 
    28 The compiler whose program semantics is shown is
    29 \begin{lstlisting}
    30 $ gcc --version
    31 gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
    32 \end{lstlisting}
    33 running on Architecture @x86_64@, with the same environment targeted.
    34 
    35 Unless explicit discussion ensues about differences among compilers or with (versions of) the standard, it is further implied that there exists a second version of GCC and some version of Clang, running on and for the same platform, that give substantially similar behaviour.
    36 In this case, I do not argue that my sample of major Linux compilers is doing the right thing with respect to the C standard.
    37 
    38 
    39 \subsection{C reports many ill-typed expressions as warnings}
    40 
    41 TODO: typeset
    42 \lstinputlisting[language=C, firstline=13, lastline=56]{bkgd-c-tyerr.c}
    43 
    44 
    45 \section{C Arrays}
    46 
    47 \subsection{C has an array type (!)}
    48 
    49 TODO: typeset
    50 \lstinputlisting[language=C, firstline=35, lastline=116]{bkgd-carray-arrty.c}
    51 
    52 My contribution is enabled by recognizing
    53 \begin{itemize}
    54     \item There is value in using a type that knows how big the whole thing is.
    55     \item The type pointer to (first) element does not.
    56     \item C \emph{has} a type that knows the whole picture: array, e.g. @T[10]@.
    57     \item This type has all the usual derived forms, which also know the whole picture.  A usefully noteworthy example is pointer to array, e.g. @T(*)[10]@.
    58 \end{itemize}
    59 
    60 Each of these sections, which introduces another layer of of the C arrays' story,
    61 concludes with an \emph{Unfortunate Syntactic Reference}.
    62 It shows how to spell the types under discussion,
    63 along with interactions with orthogonal (but easily confused) language features.
    64 Alterrnate spellings are listed withing a row.
    65 The simplest occurrences of types distinguished in the preceding discussion are marked with $\triangleright$.
    66 The Type column gives the spelling used in a cast or error message (though note Section TODO points out that some types cannot be casted to).
    67 The Declaration column gives the spelling used in an object declaration, such as variable or aggregate member; parameter declarations (section TODO) follow entirely different rules.
    68 
    69 After all, reading a C array type is easy: just read it from the inside out, and know when to look left and when to look right!
    70 
    71 
    72 \CFA-specific spellings (not yet introduced) are also included here for referenceability; these can be skipped on linear reading.
    73 The \CFA-C column gives the, more fortunate, ``new'' syntax of section TODO, for spelling \emph{exactly the same type}.
    74 This fortunate syntax does not have different spellings for types vs declarations;
    75 a declaration is always the type followed by the declared identifier name;
    76 for the example of letting @x@ be a \emph{pointer to array}, the declaration is spelled:
    77 \begin{lstlisting}
    78 [ * [10] T ] x;
    79 \end{lstlisting}
    80 The \CFA-Full column gives the spelling of a different type, introduced in TODO, which has all of my contributed improvements for safety and ergonomics.
    81 
    82 \noindent
    83 \textbf{Unfortunate Syntactic Reference}
    84 
    85 \noindent
    86 \begin{tabular}{llllll}
    87     & Description & Type & Declaration & \CFA-C  & \CFA-Full \\ \hline
    88     $\triangleright$ & val.
    89         & @T@
    90         & @T x;@
    91         & @[ T ]@
    92         &
    93         \\ \hline
    94     & \pbox{20cm}{ \vspace{2pt} val.\\ \footnotesize{no writing the val.\ in \lstinline{x}}   }\vspace{2pt}
    95         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T} \\ \lstinline{T const}   }
    96         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T x;} \\ \lstinline{T const x;}   }
    97         & @[ const T ]@
    98         &
    99         \\ \hline
    100     $\triangleright$ & ptr.\ to val.
    101         & @T *@
    102         & @T * x;@
    103         & @[ * T ]@
    104         &
    105         \\ \hline
    106     & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x}}   }\vspace{2pt}
    107         & @T * const@
    108         & @T * const x;@
    109         & @[ const * T ]@
    110         &
    111         \\ \hline
    112     & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{*x}}   }\vspace{2pt}
    113         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T *} \\ \lstinline{T const *}   }
    114         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * x;} \\ \lstinline{T const * x;}   }
    115         & @[ * const T ]@
    116         &
    117         \\ \hline
    118     $\triangleright$ & ar.\ of val.
    119         & @T[10]@
    120         & @T x[10];@
    121         & @[ [10] T ]@
    122         & @[ array(T, 10) ]@
    123         \\ \hline
    124     & \pbox{20cm}{ \vspace{2pt} ar.\ of val.\\ \footnotesize{no writing the val.\ in \lstinline{x[5]}}   }\vspace{2pt}
    125         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T[10]} \\ \lstinline{T const[10]}   }
    126         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T x[10];} \\ \lstinline{T const x[10];}   }
    127         & @[ [10] const T ]@
    128         & @[ const array(T, 10) ]@
    129         \\ \hline
    130     & ar.\ of ptr.\ to val.
    131         & @T*[10]@
    132         & @T *x[10];@
    133         & @[ [10] * T ]@
    134         & @[ array(* T, 10) ]@
    135         \\ \hline
    136     & \pbox{20cm}{ \vspace{2pt} ar.\ of ptr.\ to val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x[5]}}   }\vspace{2pt}
    137         & @T * const [10]@
    138         & @T * const x[10];@
    139         & @[ [10] const * T ]@
    140         & @[ array(const * T, 10) ]@
    141         \\ \hline
    142     & \pbox{20cm}{ \vspace{2pt} ar.\ of ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{*(x[5])}}   }\vspace{2pt}
    143         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * [10]} \\ \lstinline{T const * [10]}   }
    144         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * x[10];} \\ \lstinline{T const * x[10];}   }
    145         & @[ [10] * const T ]@
    146         & @[ array(* const T, 10) ]@
    147         \\ \hline
    148     $\triangleright$ & ptr.\ to ar.\ of val.
    149         & @T(*)[10]@
    150         & @T (*x)[10];@
    151         & @[ * [10] T ]@
    152         & @[ * array(T, 10) ]@
    153         \\ \hline
    154     & \pbox{20cm}{ \vspace{2pt} ptr.\ to ar.\ of val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x}}   }\vspace{2pt}
    155         & @T(* const)[10]@
    156         & @T (* const x)[10];@
    157         & @[ const * [10] T ]@
    158         & @[ const * array(T, 10) ]@
    159         \\ \hline
    160     & \pbox{20cm}{ \vspace{2pt} ptr.\ to ar.\ of val.\\ \footnotesize{no writing the val.\ in \lstinline{(*x)[5]}}   }\vspace{2pt}
    161         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T(*)[10]} \\ \lstinline{T const (*) [10]}   }
    162         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T (*x)[10];} \\ \lstinline{T const (*x)[10];}   }
    163         & @[ * [10] const T ]@
    164         & @[ * const array(T, 10) ]@
    165         \\ \hline
    166     & ptr.\ to ar.\ of ptr.\ to val.
    167         & @T*(*)[10]@
    168         & @T *(*x)[10];@
    169         & @[ * [10] * T ]@
    170         & @[ * array(* T, 10) ]@
    171         \\ \hline
    172 \end{tabular}
    173 
    174 
    175 \subsection{Arrays decay and pointers diffract}
    176 
    177 TODO: typeset
    178 \lstinputlisting[language=C, firstline=4, lastline=26]{bkgd-carray-decay.c}
    179 
    180 
    181 So, C provides an implicit conversion from @float[10]@ to @float*@, as described in ARM-6.3.2.1.3:
    182 
    183 \begin{quote}
    184     Except when it is the operand of the @sizeof@ operator, or the unary @&@ operator, or is a
    185     string literal used to initialize an array
    186     an expression that has type ``array of type'' is
    187     converted to an expression with type ``pointer to type'' that points to the initial element of
    188     the array object
    189 \end{quote}
    190 
    191 This phenomenon is the famous ``pointer decay,'' which is a decay of an array-typed expression into a pointer-typed one.
    192 
    193 It is worthy to note that the list of exception cases does not feature the occurrence of @a@ in @a[i]@.
    194 Thus, subscripting happens on pointers, not arrays.
    195 
    196 Subscripting proceeds first with pointer decay, if needed.  Next, ARM-6.5.2.1.2 explains that @a[i]@ is treated as if it were @(*((a)+(i)))@.
    197 ARM-6.5.6.8 explains that the addition, of a pointer with an integer type,  is defined only when the pointer refers to an element that is in an array, with a meaning of ``@i@ elements away from,'' which is valid if @a@ is big enough and @i@ is small enough.
    198 Finally, ARM-6.5.3.2.4 explains that the @*@ operator's result is the referenced element.
    199 
    200 Taken together, these rules also happen to illustrate that @a[i]@ and @i[a]@ mean the same thing.
    201 
    202 Subscripting a pointer when the target is standard-inappropriate is still practically well-defined.
    203 While the standard affords a C compiler freedom about the meaning of an out-of-bound access,
    204 or of subscripting a pointer that does not refer to an array element at all,
    205 the fact that C is famously both generally high-performance, and specifically not bound-checked,
    206 leads to an expectation that the runtime handling is uniform across legal and illegal accesses.
    207 Moreover, consider the common pattern of subscripting on a malloc result:
    208 \begin{lstlisting}
    209     float * fs = malloc( 10 * sizeof(float) );
    210     fs[5] = 3.14;
    211 \end{lstlisting}
    212 The @malloc@ behaviour is specified as returning a pointer to ``space for an object whose size is'' as requested (ARM-7.22.3.4.2).
    213 But program says \emph{nothing} more about this pointer value, that might cause its referent to \emph{be} an array, before doing the subscript.
    214 
    215 Under this assumption, a pointer being subscripted (or added to, then dereferenced)
    216 by any value (positive, zero, or negative), gives a view of the program's entire address space,
    217 centred around the @p@ address, divided into adjacent @sizeof(*p)@ chunks,
    218 each potentially (re)interpreted as @typeof(*p)@.
    219 
    220 I call this phenomenon ``array diffraction,''  which is a diffraction of a single-element pointer
    221 into the assumption that its target is in the middle of an array whose size is unlimited in both directions.
    222 
    223 No pointer is exempt from array diffraction.
    224 
    225 No array shows its elements without pointer decay.
    226 
    227 A further pointer--array confusion, closely related to decay, occurs in parameter declarations.
    228 ARM-6.7.6.3.7 explains that when an array type is written for a parameter,
    229 the parameter's type becomes a type that I summarize as being the array-decayed type.
    230 The respective handlings of the following two parameter spellings shows that the array-spelled one is really, like the other, a pointer.
    231 \lstinputlisting[language=C, firstline=40, lastline=44]{bkgd-carray-decay.c}
    232 As the @sizeof(x)@ meaning changed, compared with when run on a similarly-spelled local variariable declaration,
    233 GCC also gives this code the warning: ```sizeof' on array function parameter `x' will return size of `float *'.''
    234 
    235 The caller of such a function is left with the reality that a pointer parameter is a pointer, no matter how it's spelled:
    236 \lstinputlisting[language=C, firstline=60, lastline=63]{bkgd-carray-decay.c}
    237 This fragment gives no warnings.
    238 
    239 The shortened parameter syntax @T x[]@ is a further way to spell ``pointer.''
    240 Note the opposite meaning of this spelling now, compared with its use in local variable declarations.
    241 This point of confusion is illustrated in:
    242 \lstinputlisting[language=C, firstline=80, lastline=87]{bkgd-carray-decay.c}
    243 The basic two meanings, with a syntactic difference helping to distinguish,
    244 are illustrated in the declarations of @ca@ vs.\ @cp@,
    245 whose subsequent @edit@ calls behave differently.
    246 The syntax-caused confusion is in the comparison of the first and last lines,
    247 both of which use a literal to initialze an object decalared with spelling @T x[]@.
    248 But these initialized declarations get opposite meanings,
    249 depending on whether the object is a local variable or a parameter.
    250 
    251 
    252 In sumary, when a funciton is written with an array-typed parameter,
    253 \begin{itemize}
    254     \item an appearance of passing an array by value is always an incorrect understanding
    255     \item a dimension value, if any is present, is ignorred
    256     \item pointer decay is forced at the call site and the callee sees the parameter having the decayed type
    257 \end{itemize}
    258 
    259 Pointer decay does not affect pointer-to-array types, because these are already pointers, not arrays.
    260 As a result, a function with a pointer-to-array parameter sees the parameter exactly as the caller does:
    261 \lstinputlisting[language=C, firstline=100, lastline=110]{bkgd-carray-decay.c}
    262 
    263 
    264 \noindent
    265 \textbf{Unfortunate Syntactic Reference}
    266 
    267 \noindent
    268 (Parameter declaration; ``no writing'' refers to the callee's ability)
    269 
    270 \noindent
    271 \begin{tabular}{llllll}
    272     & Description & Type & Param. Decl & \CFA-C  \\ \hline
    273     $\triangleright$ & ptr.\ to val.
    274         & @T *@
    275         & \pbox{20cm}{ \vspace{2pt} \lstinline{T * x,} \\ \lstinline{T x[10],} \\ \lstinline{T x[],}   }\vspace{2pt}
    276         & \pbox{20cm}{ \vspace{2pt} \lstinline{[ * T ]} \\ \lstinline{[ [10] T ]} \\ \lstinline{[ [] T  ]}   }
    277         \\ \hline
    278     & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x}}   }\vspace{2pt}
    279         & @T * const@
    280         & \pbox{20cm}{ \vspace{2pt} \lstinline{T * const x,} \\ \lstinline{T x[const 10],} \\ \lstinline{T x[const],}   }\vspace{2pt}
    281         & \pbox{20cm}{ \vspace{2pt} \lstinline{[ const * T ]} \\ \lstinline{[ [const 10] T ]} \\ \lstinline{[ [const] T  ]}   }
    282         \\ \hline
    283     & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{*x}}   }\vspace{2pt}
    284         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T *} \\ \lstinline{T const *}   }
    285         & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * x,} \\ \lstinline{T const * x,} \\ \lstinline{const T x[10],} \\ \lstinline{T const x[10],} \\ \lstinline{const T x[],} \\ \lstinline{T const x[],}   }\vspace{2pt}
    286         & \pbox{20cm}{ \vspace{2pt} \lstinline{[* const T]} \\ \lstinline{[ [10] const T ]} \\ \lstinline{[ [] const T  ]}   }
    287         \\ \hline
    288     $\triangleright$ & ptr.\ to ar.\ of val.
    289         & @T(*)[10]@
    290         & \pbox{20cm}{ \vspace{2pt} \lstinline{T (*x)[10],} \\ \lstinline{T x[3][10],} \\ \lstinline{T x[][10],}   }\vspace{2pt}
    291         & \pbox{20cm}{ \vspace{2pt} \lstinline{[* [10] T]} \\ \lstinline{[ [3] [10] T ]} \\ \lstinline{[ [] [10] T  ]}   }
    292         \\ \hline
    293     & ptr.\ to ptr.\ to val.
    294         & @T **@
    295         & \pbox{20cm}{ \vspace{2pt} \lstinline{T ** x,} \\ \lstinline{T *x[10],} \\ \lstinline{T *x[],}   }\vspace{2pt}
    296         & \pbox{20cm}{ \vspace{2pt} \lstinline{[ * * T ]} \\ \lstinline{[ [10] * T ]} \\ \lstinline{[ [] * T  ]}   }
    297         \\ \hline
    298     & \pbox{20cm}{ \vspace{2pt} ptr.\ to ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{**argv}}   }\vspace{2pt}
    299         & @const char **@
    300         & \pbox{20cm}{ \vspace{2pt} \lstinline{const char *argv[],} \\ \footnotesize{(others elided)}   }\vspace{2pt}
    301         & \pbox{20cm}{ \vspace{2pt} \lstinline{[ [] * const char ]} \\ \footnotesize{(others elided)}   }
    302         \\ \hline
    303 \end{tabular}
    304 
    305 
    306 
    307 \subsection{Lengths may vary, checking does not}
    308 
    309 When the desired number of elements is unknown at compile time,
    310 a variable-length array is a solution:
    311 \begin{lstlisting}
    312     int main( int argc, const char *argv[] ) {
    313 
    314         assert( argc == 2 );
    315         size_t n = atol( argv[1] );
    316         assert( 0 < n && n < 1000 );
    317 
    318         float a[n];
    319         float b[10];
    320 
    321         // ... discussion continues here
    322     }
    323 \end{lstlisting}
    324 This arrangement allocates @n@ elements on the @main@ stack frame for @a@,
    325 just as it puts 10 elements on the @main@ stack frame for @b@.
    326 The variable-sized allocation of @a@ is provided by @alloca@.
    327 
    328 In a situation where the array sizes are not known to be small enough
    329 for stack allocation to be sensible,
    330 corresponding heap allocations are achievable as:
    331 \begin{lstlisting}
    332     float *ax1 = malloc( sizeof( float[n] ) );
    333     float *ax2 = malloc( n * sizeof( float ) );
    334     float *bx1 = malloc( sizeof( float[1000000] ) );
    335     float *bx2 = malloc( 1000000 * sizeof( float ) );
    336 \end{lstlisting}
    337 
    338 
    339 VLA
    340 
    341 Parameter dependency
    342 
    343 Checking is best-effort / unsound
    344 
    345 Limited special handling to get the dimension value checked (static)
    346 
    347 
    348 
    349 \subsection{C has full-service, dynamically sized, multidimensional arrays (and \CC does not)}
    350 
    351 In C and \CC, ``multidimensional array'' means ``array of arrays.''  Other meanings are discussed in TODO.
    352 
    353 Just as an array's element type can be @float@, so can it be @float[10]@.
    354 
    355 While any of @float*@, @float[10]@ and @float(*)[10]@ are easy to tell apart from @float@,
    356 telling them apart from each other may need occasional reference back to TODO intro section.
    357 The sentence derived by wrapping each type in @-[3]@ follows.
    358 
    359 While any of @float*[3]@, @float[3][10]@ and @float(*)[3][10]@ are easy to tell apart from @float[3]@,
    360 telling them apart from each other is what it takes to know what ``array of arrays'' really means.
    361 
    362 
    363 Pointer decay affects the outermost array only
    364 
    365 
    366 TODO: unfortunate syntactic reference with these cases:
    367 
    368 \begin{itemize}
    369     \item ar. of ar. of val (be sure about ordering of dimensions when the declaration is dropped)
    370     \item ptr. to ar. of ar. of val
    371 \end{itemize}
    372 
    373 
    374 
    375 
    376 
    377 \subsection{Arrays are (but) almost values}
    378 
    379 Has size; can point to
    380 
    381 Can't cast to
    382 
    383 Can't pass as value
    384 
    385 Can initialize
    386 
    387 Can wrap in aggregate
    388 
    389 Can't assign
    390 
    391 
    392 \subsection{Returning an array is (but) almost possible}
    393 
    394 
    395 
    396 
    397 \subsection{The pointer-to-array type has been noticed before}
    398 
    399 
    400 \section{\CFA}
    401 
    402 Traditionally, fixing C meant leaving the C-ism alone, while providing a better alternative beside it.
    403 (For later:  That's what I offer with array.hfa, but in the future-work vision for arrays, the fix includes helping programmers stop accidentally using a broken C-ism.)
    404 
    405 \subsection{\CFA features interacting with arrays}
    406 
    407 Prior work on \CFA included making C arrays, as used in C code from the wild,
    408 work, if this code is fed into @cfacc@.
    409 The quality of this this treatment was fine, with no more or fewer bugs than is typical.
    410 
    411 More mixed results arose with feeding these ``C'' arrays into preexisting \CFA features.
    412 
    413 A notable success was with the \CFA @alloc@ function,
    414 which type information associated with a polymorphic return type
    415 replaces @malloc@'s use of programmer-supplied size information.
    416 \begin{lstlisting}
    417     // C, library
    418     void * malloc( size_t );
    419     // C, user
    420     struct tm * el1 = malloc(      sizeof(struct tm) );
    421     struct tm * ar1 = malloc( 10 * sizeof(struct tm) );
    422 
    423     // CFA, library
    424     forall( T * ) T * alloc();
    425     // CFA, user
    426     tm * el2 = alloc();
    427     tm (*ar2)[10] = alloc();
    428 \end{lstlisting}
    429 The alloc polymorphic return compiles into a hidden parameter, which receives a compiler-generated argument.
    430 This compiler's argument generation uses type information from the left-hand side of the initialization to obtain the intended type.
    431 Using a compiler-produced value eliminates an opportunity for user error.
    432 
    433 TODO: fix in following: even the alloc call gives bad code gen: verify it was always this way; walk back the wording about things just working here; assignment (rebind) seems to offer workaround, as in bkgd-cfa-arrayinteract.cfa
    434 
    435 Bringing in another \CFA feature, reference types, both resolves a sore spot of the last example, and gives a first example of an array-interaction bug.
    436 In the last example, the choice of ``pointer to array'' @ar2@ breaks a parallel with @ar1@.
    437 They are not subscripted in the same way.
    438 \begin{lstlisting}
    439     ar1[5];
    440     (*ar2)[5];
    441 \end{lstlisting}
    442 Using ``reference to array'' works at resolving this issue.  TODO: discuss connection with Doug-Lea \CC proposal.
    443 \begin{lstlisting}
    444     tm (&ar3)[10] = *alloc();
    445     ar3[5];
    446 \end{lstlisting}
    447 The implicit size communication to @alloc@ still works in the same ways as for @ar2@.
    448 
    449 Using proper array types (@ar2@ and @ar3@) addresses a concern about using raw element pointers (@ar1@), albeit a theoretical one.
    450 TODO xref C standard does not claim that @ar1@ may be subscripted,
    451 because no stage of interpreting the construction of @ar1@ has it be that ``there is an \emph{array object} here.''
    452 But both @*ar2@ and the referent of @ar3@ are the results of \emph{typed} @alloc@ calls,
    453 where the type requested is an array, making the result, much more obviously, an array object.
    454 
    455 The ``reference to array'' type has its sore spots too.  TODO see also @dimexpr-match-c/REFPARAM_CALL (under TRY_BUG_1)@
    456 
    457 
    458 
    459 TODO: I fixed a bug associated with using an array as a T.  I think.  Did I really?  What was the bug?
     5\section{Strings}
  • doc/theses/mike_brooks_MMath/intro.tex

    r5546eee4 r0fa0201d  
    11\chapter{Introduction}
    2 
    3 \cite{Blache19}
    4 \cite{Oorschot23}
    5 \cite{Ruef19}
    62
    73\section{Arrays}
  • doc/theses/mike_brooks_MMath/list.tex

    r5546eee4 r0fa0201d  
    210210\label{toc:lst:issue:derection}
    211211
    212 Axis?
    213 
    214212\PAB{I'm not sure about the term \newterm{Directionality}. Directionality to me, means going forward or backwards through a list.
    215213Would \newterm{dimensionality} work? Think of each list containing the node as a different dimension in which the node sits.}
  • doc/theses/mike_brooks_MMath/programs/hello-accordion.cfa

    r5546eee4 r0fa0201d  
    1 #include <fstream.hfa>
    2 #include <stdlib.hfa>
    3 #include <array.hfa>
    4 
    5 
    6 
    7 
    8 
    9 
    10 
    11 forall( T, [Nclients], [Ncosts] )
    12 struct request {
    13     unsigned int requestor_id;
    14     array( T, Nclients ) impacted_client_ids; // nested VLA
    15     array( float, Ncosts ) cost_contribs; // nested VLA
    16     float total_cost;
    17 };
    18 
    19 
    20 // TODO: understand (fix?) why these are needed (autogen seems to be failing ... is typeof as struct member nayok?)
    21 
    22 forall( T, [Nclients], [Ncosts] )
    23         void ?{}( T &, request( T, Nclients, Ncosts ) & this ) {}
    24 
    25 forall( T &, [Nclients], [Ncosts] )
    26         void ^?{}( request( T, Nclients, Ncosts ) & this ) {}
     1#include "stdlib.hfa"
     2#include "array.hfa"
    273
    284
     
    3915
    4016
    41 forall( T, [Nclients], [Ncosts] )
    42 void summarize( request( T, Nclients, Ncosts ) & r ) {
     17
     18
     19
     20forall( ztype(Nclients), ztype(Ncosts) )
     21struct request {
     22    unsigned int requestor_id;
     23    array( unsigned int, Nclients ) impacted_client_ids;
     24    array( float, Ncosts ) cost_contribs;
     25    float total_cost;
     26};
     27
     28
     29// TODO: understand (fix?) why these are needed (autogen seems to be failing ... is typeof as struct member nayok?)
     30
     31forall( ztype(Nclients), ztype(Ncosts) )
     32void ?{}( request(Nclients, Ncosts) & this ) {}
     33
     34forall( ztype(Nclients), ztype(Ncosts) )
     35void ^?{}( request(Nclients, Ncosts) & this ) {}
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50forall( ztype(Nclients), ztype(Ncosts) )
     51void summarize( request(Nclients, Ncosts) & r ) {
    4352    r.total_cost = 0;
    44     for( i; Ncosts )
     53    for( i; z(Ncosts) )
    4554        r.total_cost += r.cost_contribs[i];
    4655    // say the cost is per-client, to make output vary
    47     r.total_cost *= Nclients;
     56    r.total_cost *= z(Nclients);
    4857}
    4958
     
    5968
    6069
    61 int main( int argc, char * argv[] ) {
    62         const int ncl = ato( argv[1] );
    63         const int nco = 2;
    6470
    65         request( int, ncl, nco ) r;
    66         r.cost_contribs[0] = 100;
    67         r.cost_contribs[1] = 0.1;
    6871
    69         summarize(r);
    70         sout | "Total cost:" | r.total_cost;
    71 }
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96int main( int argc, char ** argv ) {
     97
     98
     99
     100const int ncl = atoi(argv[1]);
     101const int nco = 2;
     102
     103request( Z(ncl), Z(nco) ) r;
     104r.cost_contribs[0] = 100;
     105r.cost_contribs[1] = 0.1;
     106
     107summarize(r);
     108printf("Total cost: %.1f\n", r.total_cost);
     109
    72110/*
    73 $\$$ ./a.out 5
     111./a.out 5
    74112Total cost: 500.5
    75 $\$$ ./a.out 6
     113./a.out 6
    76114Total cost: 600.6
    77115*/
     116
     117
     118
     119
     120}
  • doc/theses/mike_brooks_MMath/programs/hello-array.cfa

    r5546eee4 r0fa0201d  
    1 #include <fstream.hfa>
    2 #include <stdlib.hfa>
    3 #include <array.hfa> // learned has to come afer stdlib, which uses the word tag
     1
     2#include <common.hfa>
     3#include <bits/align.hfa>
     4
     5extern "C" {
     6    int atoi(const char *str);
     7}
     8
     9
     10#include "stdlib.hfa"
     11#include "array.hfa" // learned has to come afer stdlib, which uses the word tag
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
    427
    528// Usage:
     
    831
    932
    10 forall( [N] ) // array bound
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50forall( ztype( N ) )
    1151array(bool, N) & f( array(float, N) & a, array(float, N) & b ) {
    12     array(bool, N) & ret = *alloc(); // sizeof used by alloc
    13     for( i; N ) {
    14         ret[i] = 0.005 > 2 * (abs(a[i] - b[i])) / (abs(a[i]) + abs(b[i]));
     52    array(bool, N) & ret = *alloc();
     53    for( i; z(N) ) {
     54        float fracdiff = 2 * abs( a[i] - b[i] )
     55                       / ( abs( a[i] ) + abs( b[i] ) );
     56        ret[i] = fracdiff < 0.005;
    1557    }
    1658    return ret;
     
    2668
    2769
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
    2898// TODO: standardize argv
    2999
    30 int main( int argc, char * argv[] ) {
    31     int n = ato( argv[1] );
    32     array(float, n) a, b; // VLA
    33     for ( i; n ) {
    34         a[i] = 3.14 / (i + 1);
     100int main( int argc, char ** argv ) {
     101    int n = atoi(argv[1]);
     102    array(float, Z(n)) a, b;
     103    for (i; n) {
     104        a[i] = 3.14 / (i+1);
    35105        b[i] = a[i] + 0.005 ;
    36106    }
    37     array(bool, n) & result = f( a, b ); // call
    38     sout | "result: " | nonl;
    39     for ( i; n )
    40         sout | result[i] | nonl;
    41     sout | nl;
    42     free( &result ); // free returned storage
     107    array(bool, Z(n)) & answer = f( a, b );
     108    printf("answer:");
     109    for (i; n)
     110        printf(" %d", answer[i]);
     111    printf("\n");
     112    free( & answer );
    43113}
    44114/*
    45 $\$$ ./a.out 5
    46 result: true true true false false
    47 $\$$ ./a.out 7
    48 result: true true true false false false false
     115$ ./a.out 5
     116answer: 1 1 1 0 0
     117$ ./a.out 7
     118answer: 1 1 1 0 0 0 0
    49119*/
    50120
    51 void fred() {
    52         array(float, 10) a;
    53         array(float, 20) b;
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
     132
     133
     134
     135
     136forall( ztype(M), ztype(N) )
     137void not_so_bad(array(float, M) &a, array(float, N) &b ) {
    54138    f( a, a );
    55139    f( b, b );
    56     f( a, b );
    57 }
     140}
     141
     142
     143
     144
     145
     146
    58147
    59148#ifdef SHOWERR1
    60 forall( [M], [N] )
     149
     150forall( ztype(M), ztype(N) )
    61151void bad( array(float, M) &a, array(float, N) &b ) {
    62152    f( a, a ); // ok
     
    64154    f( a, b ); // error
    65155}
     156
    66157#endif
    67158
    68159
    69160
    70 forall( [M], [N] )
    71 void bad_fixed( array(float, M) & a, array(float, N) & b ) {
    72     if ( M == N ) {
    73         f( a, (array(float, M) &)b ); // cast b to matching type
     161
     162
     163
     164
     165
     166
     167
     168
     169
     170
     171
     172
     173
     174
     175
     176
     177
     178
     179
     180
     181
     182
     183
     184
     185
     186
     187
     188
     189
     190
     191
     192
     193
     194
     195
     196forall( ztype(M), ztype(N) )
     197void bad_fixed( array(float, M) &a, array(float, N) &b ) {
     198   
     199
     200    if ( z(M) == z(N) ) {
     201        f( a, ( array(float, M) & ) b ); // fixed
    74202    }
    75 }
     203
     204}
  • doc/theses/mike_brooks_MMath/programs/hello-md.cfa

    r5546eee4 r0fa0201d  
    1 #include <fstream.hfa>
    2 #include <array.hfa>
     1#include "array.hfa"
     2
    33
    44
     
    6060forall( [N] )
    6161void print1d_cstyle( array(float, N) & c ) {
    62     for ( i; N ) {
    63         sout | c[i] | nonl;
     62    for( i; N ) {
     63        printf("%.1f  ", c[i]);
    6464    }
    65     sout | nl;
     65    printf("\n");
    6666}
     67
    6768
    6869
     
    8081void print1d( C & c ) {
    8182    for( i; N ) {
    82         sout | c[i] | nonl;
     83        printf("%.1f  ", c[i]);
    8384    }
    84     sout | nl;
     85    printf("\n");
    8586}
    8687
     
    102103        for ( j; 7 ) {
    103104            a[i,j] = 1.0 * i + 0.1 * j;
    104             sout | a[[i,j]] | nonl;
     105            printf("%.1f  ", a[i,j]);
    105106        }
    106         sout | nl;
     107        printf("\n");
    107108    }
    108     sout | nl;
     109    printf("\n");
    109110}
    110111
    111112int main() {
     113
    112114
    113115
     
    126128*/
    127129   
    128 
    129 
    130130
    131131
     
    168168
    169169}
     170
     171
     172
  • doc/theses/mike_brooks_MMath/programs/lst-features-intro.run.cfa

    r5546eee4 r0fa0201d  
    1 #include <collections/list.hfa>
     1#include <containers/list.hfa>
    22
    33
  • doc/theses/mike_brooks_MMath/programs/lst-features-multidir.run.cfa

    r5546eee4 r0fa0201d  
    1 #include <collections/list.hfa>
     1#include <containers/list.hfa>
    22
    33
  • doc/theses/mike_brooks_MMath/programs/sharing-demo.cfa

    r5546eee4 r0fa0201d  
    66
    77void demo1() {
    8         sout | sepOff;
     8        sout | sepDisable;;
    99        sout | "Consider two strings @s1@ and @s1a@ that are in an aliasing relationship, and a third, @s2@, made by a simple copy from @s1@.";
    1010        sout | "\\par\\noindent";
     
    219219
    220220        assert( s1 == "affd" );
    221 //      assert( s1_mid == "fc" );                                                     // ????????? bug?
     221        assert( s1_mid == "fc" );                                                     // ????????? bug?
    222222        sout | xstr(D2_s2_gg) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
    223223
  • doc/theses/mike_brooks_MMath/string.tex

    r5546eee4 r0fa0201d  
    1111Earlier work on \CFA [to cite Schluntz] implemented the feature of constructors and destructors.  A constructor is a user-defined function that runs implicitly, when control passes an object's declaration, while a destructor runs at the exit of the declaration's lexical scope.  The feature allows programmers to assume that, whenever a runtime object of a certain type is accessible, the system called one of the programmer's constuctor functions on that object, and a matching destructor call will happen in the future.  The feature helps programmers know that their programs' invariants obtain.
    1212
    13 The purposes of such invariants go beyond ensuring authentic values for the bits inside the object.   These invariants can track occurrences of the managed objects in other data structures.  Reference counting is a typical application of the latter invariant type.  With a reference-counting smart pointer, the consturctor and destructor \emph{of the pointer type} track the lifecycles of occurrences of these pointers, by incrementing and decrementing a counter (ususally) on the referent object, that is, they maintain a that is state separate from the objects to whose lifecycles they are attached.  Both the \CC and \CFA RAII systems ares powerful enough to achive such reference counting.
    14 
    15 The \CC RAII system supports a more advanced application.  A lifecycle function has access to the object under managamanet, by location; constructors and destuctors receive a @this@ parameter providing its memory address.  A lifecycle-function implementation can then add its objects to a collection upon creation, and remove them at destruction.  A modulue that provides such objects, by using and encapsulating such a collection, can traverse the collection at relevant times, to keep the objects ``good.''  Then, if you are the user of such an module, declaring an object of its type means not only receiving an authentically ``good'' value at initialization, but receiving a subscription to a service that will keep the value ``good'' until you are done with it.
    16 
    17 In many cases, the relationship between memory location and lifecycle is simple.  But with stack-allocated objects being used as parameters and returns, there is a sender version in one stack frame and a receiver version in another.  \CC is able to treat those versions as distinct objects and guarantee a copy-constructor call for communicating the value from one to the other.  This ability has implications on the language's calling convention.  Consider an ordinary function @void f( Vehicle x )@, which receives an aggregate by value.  If the type @Vehicle@ has custom lifecycle functions, then a call to a user-provided copy constructor occurs, after the caller evaluates its argument expression, after the callee's stack frame exists, with room for its variable @x@ (which is the location that the copy-constructor must target), but before the user-provided body of @f@ begins executing.  \CC achieves this ordering by changing the function signature, in the compiled form, to pass-by-reference and having the callee invoke the copy constructor in its preamble.  On the other hand, if @Vehicle@ is a simple structure then the C calling convention is applied as the code originally appeared, that is, the callsite implementation code performs a bitwise copy from the caller's expression result, into the callee's x.
     13The purposes of such invariants go beyond ensuring authentic values for the bits inside the object.   These invariants can track occurrences of the managed objects in other data structures.  Reference counting is a typical application of the latter invariant type.  With a reference-counting smart pointer, the consturctor and destructor \emph{of the pointer type} track the lifecycles of occurrences of these pointers, by incrementing and decrementing a counter (ususally) on the referent object, that is, they maintain a that is state separate from the objects to whose lifecycles they are attached.  Both the C++ and \CFA RAII systems ares powerful enough to achive such reference counting.
     14
     15The C++ RAII system supports a more advanced application.  A lifecycle function has access to the object under managamanet, by location; constructors and destuctors receive a @this@ parameter providing its memory address.  A lifecycle-function implementation can then add its objects to a collection upon creation, and remove them at destruction.  A modulue that provides such objects, by using and encapsulating such a collection, can traverse the collection at relevant times, to keep the objects ``good.''  Then, if you are the user of such an module, declaring an object of its type means not only receiving an authentically ``good'' value at initialization, but receiving a subscription to a service that will keep the value ``good'' until you are done with it.
     16
     17In many cases, the relationship between memory location and lifecycle is simple.  But with stack-allocated objects being used as parameters and returns, there is a sender version in one stack frame and a receiver version in another.  C++ is able to treat those versions as distinct objects and guarantee a copy-constructor call for communicating the value from one to the other.  This ability has implications on the language's calling convention.  Consider an ordinary function @void f( Vehicle x )@, which receives an aggregate by value.  If the type @Vehicle@ has custom lifecycle functions, then a call to a user-provided copy constructor occurs, after the caller evaluates its argument expression, after the callee's stack frame exists, with room for its variable @x@ (which is the location that the copy-constructor must target), but before the user-provided body of @f@ begins executing.  C++ achieves this ordering by changing the function signature, in the compiled form, to pass-by-reference and having the callee invoke the copy constructor in its preamble.  On the other hand, if @Vehicle@ is a simple structure then the C calling convention is applied as the code originally appeared, that is, the callsite implementation code performs a bitwise copy from the caller's expression result, into the callee's x.
    1818
    1919TODO: learn correction to fix inconcsistency: this discussion says the callee invokes the copy constructor, but only the caller knows which copy constructor to use!
  • doc/theses/mike_brooks_MMath/uw-ethesis.bib

    r5546eee4 r0fa0201d  
    44% --------------------------------------------------
    55% Cforall
    6 
    76@misc{cfa:frontpage,
    8     url         = {https://cforall.uwaterloo.ca}
     7  url = {https://cforall.uwaterloo.ca/}
    98}
    109@article{cfa:typesystem,
    11     author    = {Aaron Moss and Robert Schluntz and Peter A. Buhr},
    12     title     = {{\CFA} : Adding modern programming language features to {C}},
    13     journal   = {Softw. Pract. Exp.},
    14     volume    = {48},
    15     number    = {12},
    16     pages     = {2111--2146},
    17     year      = {2018},
     10  author    = {Aaron Moss and Robert Schluntz and Peter A. Buhr},
     11  title     = {{\CFA} : Adding modern programming language features to {C}},
     12  journal   = {Softw. Pract. Exp.},
     13  volume    = {48},
     14  number    = {12},
     15  pages     = {2111--2146},
     16  year      = {2018},
     17  url       = {https://doi.org/10.1002/spe.2624},
     18  doi       = {10.1002/spe.2624},
     19  timestamp = {Thu, 09 Apr 2020 17:14:14 +0200},
     20  biburl    = {https://dblp.org/rec/journals/spe/MossSB18.bib},
     21  bibsource = {dblp computer science bibliography, https://dblp.org}
    1822}
     23
    1924
    2025% --------------------------------------------------
     
    2227
    2328@inproceedings{arr:futhark:tytheory,
    24     author      = {Troels Henriksen and Martin Elsman},
    25     title       = {Towards Size-Dependent Types for Array Programming},
    26     year        = {2021},
    27     publisher   = {Association for Computing Machinery},
    28     address     = {New York, NY, USA},
    29     booktitle   = {Proceedings of the 7th ACM SIGPLAN International Workshop on Libraries, Languages and Compilers for Array Programming},
    30     pages       = {1-14},
    31     numpages    = {14},
    32     location    = {Virtual, Canada},
    33     series      = {ARRAY 2021}
     29    author = {Henriksen, Troels and Elsman, Martin},
     30    title = {Towards Size-Dependent Types for Array Programming},
     31    year = {2021},
     32    isbn = {9781450384667},
     33    publisher = {Association for Computing Machinery},
     34    address = {New York, NY, USA},
     35    url = {https://doi.org/10.1145/3460944.3464310},
     36    doi = {10.1145/3460944.3464310},
     37    abstract = {We present a type system for expressing size constraints on array types in an ML-style type system. The goal is to detect shape mismatches at compile-time, while being simpler than full dependent types. The main restrictions is that the only terms that can occur in types are array sizes, and syntactically they must be variables or constants. For those programs where this is not sufficient, we support a form of existential types, with the type system automatically managing the requisite book-keeping. We formalise a large subset of the type system in a small core language, which we prove sound. We also present an integration of the type system in the high-performance parallel functional language Futhark, and show on a collection of 44 representative programs that the restrictions in the type system are not too problematic in practice.},
     38    booktitle = {Proceedings of the 7th ACM SIGPLAN International Workshop on Libraries, Languages and Compilers for Array Programming},
     39    pages = {1–14},
     40    numpages = {14},
     41    keywords = {functional programming, parallel programming, type systems},
     42    location = {Virtual, Canada},
     43    series = {ARRAY 2021}
    3444}
    3545
    3646@article{arr:dex:long,
    37     author      = {Adam Paszke and Daniel D. Johnson and David Duvenaud and
    38                    Dimitrios Vytiniotis and Alexey Radul and Matthew J. Johnson and
    39                    Jonathan Ragan-Kelley and Dougal Maclaurin},
    40     title       = {Getting to the Point. Index Sets and Parallelism-Preserving Autodiff
    41                    for Pointful Array Programming},
    42     publisher   = {Association for Computing Machinery},
    43     address     = {New York, NY, USA},
    44     volume      = 5,
    45     number      = {ICFP},
    46     year        = 2021,
    47     journal     = {Proc. ACM Program. Lang.},
    48     month       = {aug},
     47  author    = {Adam Paszke and
     48               Daniel D. Johnson and
     49               David Duvenaud and
     50               Dimitrios Vytiniotis and
     51               Alexey Radul and
     52               Matthew J. Johnson and
     53               Jonathan Ragan{-}Kelley and
     54               Dougal Maclaurin},
     55  title     = {Getting to the Point. Index Sets and Parallelism-Preserving Autodiff
     56               for Pointful Array Programming},
     57  journal   = {CoRR},
     58  volume    = {abs/2104.05372},
     59  year      = {2021},
     60  url       = {https://arxiv.org/abs/2104.05372},
     61  eprinttype = {arXiv},
     62  eprint    = {2104.05372},
     63  timestamp = {Mon, 25 Oct 2021 07:55:47 +0200},
     64  biburl    = {https://dblp.org/rec/journals/corr/abs-2104-05372.bib},
     65  bibsource = {dblp computer science bibliography, https://dblp.org}
    4966}
    5067
     
    5774    title       = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs},
    5875    year        = 2018,
    59     howpublished= {\url{https://cforall.uwaterloo.ca/CFAStackEvaluation.zip}},
     76    howpublished= {\href{https://cforall.uwaterloo.ca/CFAStackEvaluation.zip}{https://cforall.uwaterloo.ca/\-CFAStackEvaluation.zip}},
    6077}
    6178
    6279@misc{lst:linuxq,
    63     title       = {queue(7) -- Linux manual page},
    64     howpublished= {\url{https://man7.org/linux/man-pages/man3/queue.3.html}},
     80  title     = {queue(7) — Linux manual page},
     81  howpublished= {\href{https://man7.org/linux/man-pages/man3/queue.3.html}{https://man7.org/linux/man-pages/man3/queue.3.html}},
    6582}
    66 % see also https://man7.org/linux/man-pages/man7/queue.7.license.html
    67 %          https://man7.org/tlpi/
    68 %          https://www.kernel.org/doc/man-pages/
     83  % see also https://man7.org/linux/man-pages/man7/queue.7.license.html
     84  %          https://man7.org/tlpi/
     85  %          https://www.kernel.org/doc/man-pages/
    6986
    7087@misc{lst:stl,
    71     title       = {std::list},
    72     howpublished= {\url{https://en.cppreference.com/w/cpp/container/list}},
     88  title     = {std::list},
     89  howpublished= {\href{https://en.cppreference.com/w/cpp/container/list}{https://en.cppreference.com/w/cpp/container/list}},
    7390}
    7491
    75 @article{Blache19,
    76     author      = {Gunter Blache},
    77     title       = {Handling Index-out-of-bounds in safety-critical embedded {C} code using model-based development},
    78     journal     = {Software \& Systems Modeling},
    79     volume      = 18,
    80     year        = 2019,
    81     pages       = {1795-1805},
    82 }
    83 
    84 @article{Oorschot23,
    85     author      = {van Oorschot, Paul C.},
    86     journal     = {IEEE Security \& Privacy},
    87     title       = {Memory Errors and Memory Safety: {C} as a Case Study},
    88     year        = 2023,
    89     volume      = 21,
    90     number      = 2,
    91     pages       = {70-76},
    92 }
    93 
    94 @InProceedings{Ruef19,
    95     author      = {Andrew Ruef and Leonidas Lampropoulos and Ian Sweet and David Tarditi and Michael Hicks},
    96     title       = {Achieving Safety Incrementally with {Checked C}},
    97     editor      = {Flemming Nielson and David Sands},
    98     booktitle   = {Principles of Security and Trust},
    99     publisher   = {Springer International Publishing},
    100     address     = {Cham},
    101     year        = {2019},
    102     pages       = {76-98},
    103 }
    104 
  • doc/theses/mike_brooks_MMath/uw-ethesis.tex

    r5546eee4 r0fa0201d  
    9393\usepackage{algorithm}
    9494\usepackage{algpseudocode}
    95 
    96 \usepackage{pbox}
    9795
    9896% Hyperlinks make it very easy to navigate an electronic document.
     
    129127    urlcolor=black
    130128}}{} % end of ifthenelse (no else)
    131 \urlstyle{sf}
    132129
    133130%\usepackage[automake,toc,abbreviations]{glossaries-extra} % Exception to the rule of hyperref being the last add-on package
  • libcfa/src/exception.c

    r5546eee4 r0fa0201d  
    309309                struct _Unwind_Context * unwind_context)
    310310{
    311         //! __cfadbg_print_safe(exception, "CFA: 0x%lx\n", _Unwind_GetCFA(unwind_context));
     311
     312        //__cfadbg_print_safe(exception, "CFA: 0x%lx\n", _Unwind_GetCFA(context));
    312313        __cfadbg_print_safe(exception, "Personality function (%d, %x, %llu, %p, %p):",
    313314                        version, actions, exception_class, unwind_exception, unwind_context);
  • src/AST/Decl.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Dec  9 16:28:51 2023
    13 // Update Count     : 31
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu May  5 12:10:00 2022
     13// Update Count     : 24
    1414//
    1515
     
    113113// --- EnumDecl
    114114
    115 bool EnumDecl::valueOf( const Decl * enumerator, long long & value ) const {
     115bool EnumDecl::valueOf( const Decl * enumerator, long long& value ) const {
    116116        if ( enumValues.empty() ) {
    117117                Evaluation crntVal = {0, true, true};  // until expression is given, we know to start counting from 0
    118118                for ( const Decl * member : members ) {
    119                         const ObjectDecl * field = strict_dynamic_cast< const ObjectDecl * >( member );
     119                        const ObjectDecl* field = strict_dynamic_cast< const ObjectDecl* >( member );
    120120                        if ( field->init ) {
    121                                 const SingleInit * init = strict_dynamic_cast< const SingleInit * >( field->init.get() );
     121                                const SingleInit * init = strict_dynamic_cast< const SingleInit* >( field->init.get() );
    122122                                crntVal = eval( init->value );
    123123                                if ( ! crntVal.isEvaluableInGCC ) {
    124                                         SemanticError( init->location, "Non-constexpr in initialization of enumerator %s", field->name.c_str() );
     124                                        SemanticError( init->location, ::toString( "Non-constexpr in initialization of "
     125                                                "enumerator: ", field ) );
    125126                                }
    126127                        }
    127128                        if ( enumValues.count( field->name ) != 0 ) {
    128                                 SemanticError( location, "Enum %s has multiple members with %s", name.c_str(), field->name.c_str() );
     129                                SemanticError( location, ::toString( "Enum ", name, " has multiple members with the "   "name ", field->name ) );
    129130                        }
    130131                        if (crntVal.hasKnownValue) {
  • src/AST/Expr.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May 15 17:00:00 2019
    11 // Last Modified By : Peter A. Buhr
     11// Last Modified By : Andrew Beach
    1212// Created On       : Wed May 18 13:56:00 2022
    13 // Update Count     : 12
     13// Update Count     : 8
    1414//
    1515
     
    168168                        return addrType( refType->base );
    169169                } else {
    170                         SemanticError( loc, "Attempt to take address of non-lvalue expression %s",
    171                                                    toString( arg->result.get() ).c_str() );
     170                        SemanticError( loc, arg->result.get(),
     171                                "Attempt to take address of non-lvalue expression: " );
    172172                }
    173173        }
     
    240240                return 1;
    241241        }
    242         SemanticError( this->location, "Constant expression of non-integral type %s",
    243                                    toString( this ).c_str() );
     242        SemanticError( this, "Constant expression of non-integral type " );
    244243}
    245244
  • src/AST/LinkageSpec.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 11 16:08:58 2023
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu May 9 10:00:00 2019
     13// Update Count     : 1
    1414//
    1515
     
    3737                return spec;
    3838        } else {
    39                 SemanticError( loc, "Invalid linkage specifier %s", cmd->c_str() );
     39                SemanticError( loc, "Invalid linkage specifier " + *cmd );
    4040        }
    4141}
  • src/AST/TypeSubstitution.hpp

    r5546eee4 r0fa0201d  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 11 16:07:30 2023
    13 // Update Count     : 15
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr May 25 12:31:00 2023
     13// Update Count     : 10
    1414//
    1515
     
    156156                                } // if
    157157                        } else {
    158                                 SemanticError( formal->location, "Attempt to provide non-type parameter %s for type parameter %s",
    159                                                            toString( *actualIt ).c_str(), formal->name.c_str() );
     158                                SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
    160159                        } // if
    161160                } else {
  • src/CodeGen/CodeGenerator.cpp

    r5546eee4 r0fa0201d  
    10261026        output << " ) ";
    10271027
    1028         output << "{" << endl;
     1028        output << "{";
    10291029        ++indent;
    10301030        for ( auto node : stmt->cases ) {
  • src/CodeGen/FixMain.cc

    r5546eee4 r0fa0201d  
    1111// Last Modified By :
    1212// Last Modified On :
    13 // Update Count     : 1
     13// Update Count     : 0
    1414//
    1515
     
    3939                if ( isMain( decl ) ) {
    4040                        if ( main_declaration ) {
    41                                 SemanticError( decl, "Multiple definition of main routine" );
     41                                SemanticError( decl, "Multiple definition of main routine\n" );
    4242                        }
    4343                        main_declaration = decl;
  • src/CodeGen/FixNames.cc

    r5546eee4 r0fa0201d  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 16:16:51 2023
    13 // Update Count     : 25
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jul 20 11:49:00 2022
     13// Update Count     : 24
    1414//
    1515
     
    5757                        int nargs = mutDecl->params.size();
    5858                        if ( 0 != nargs && 2 != nargs && 3 != nargs ) {
    59                                 SemanticError( functionDecl, "Main expected to have 0, 2 or 3 arguments" );
     59                                SemanticError( functionDecl, "Main expected to have 0, 2 or 3 arguments\n" );
    6060                        }
    6161                        ast::chain_mutate( mutDecl->stmts )->kids.push_back(
  • src/Common/ErrorObjects.h

    r5546eee4 r0fa0201d  
    4646        std::list< error > errors;
    4747};
     48
     49void SemanticWarningImpl( CodeLocation location, std::string error );
     50
     51template< typename T >
     52static inline void SemanticWarningImpl( const T * obj, const std::string & error ) {
     53        SemanticWarning( obj->location, toString( error, obj ) );
     54}
     55
     56template< typename T >
     57static inline void SemanticWarningImpl( CodeLocation location, const T * obj, const std::string & error ) {
     58        SemanticWarningImpl( location, toString( error, obj ) );
     59}
  • src/Common/SemanticError.cc

    r5546eee4 r0fa0201d  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 13:45:28 2023
    13 // Update Count     : 34
     12// Last Modified On : Thu Jun  7 08:05:26 2018
     13// Update Count     : 10
    1414//
    1515
     
    2323#include <vector>
    2424
    25 using namespace std;
    26 
    2725#include "Common/utility.h"                                                             // for to_string, CodeLocation (ptr only)
    2826#include "SemanticError.h"
     
    3028//-----------------------------------------------------------------------------
    3129// Severity Handling
    32 vector<Severity> & get_severities() {
    33         static vector<Severity> severities;
     30std::vector<Severity> & get_severities() {
     31        static std::vector<Severity> severities;
    3432        if(severities.empty()) {
    3533                severities.reserve((size_t)Warning::NUMBER_OF_WARNINGS);
     
    6260        size_t idx = 0;
    6361        for ( const auto & w : WarningFormats ) {
    64                 if ( strcmp( name, w.name ) == 0 ) {
     62                if ( std::strcmp( name, w.name ) == 0 ) {
    6563                        get_severities()[idx] = s;
    6664                        break;
     
    7270//-----------------------------------------------------------------------------
    7371// Semantic Error
    74 
    7572bool SemanticErrorThrow = false;
    7673
    77 SemanticErrorException::SemanticErrorException( CodeLocation location, string error ) {
     74SemanticErrorException::SemanticErrorException( CodeLocation location, std::string error ) {
    7875        append( location, error );
    7976}
     
    8380}
    8481
    85 void SemanticErrorException::append( CodeLocation location, const string & msg ) {
     82void SemanticErrorException::append( CodeLocation location, const std::string & msg ) {
    8683        errors.emplace_back( location, msg );
    8784}
     
    9289
    9390void SemanticErrorException::print() {
    94 //      using to_string;
     91        using std::to_string;
    9592
    9693        errors.sort([](const error & lhs, const error & rhs) -> bool {
     
    10299
    103100        for( auto err : errors ) {
    104                 cerr << ErrorHelpers::bold() << err.location << ErrorHelpers::error_str() << ErrorHelpers::reset_font() << err.description << endl;
    105         }
    106 }
    107 
    108 void SemanticError( CodeLocation location, const char * fmt, ... ) {
    109         char msg[2048];                                                                         // worst-case error-message buffer
    110         va_list args;
    111         va_start( args, fmt );
    112         vsnprintf( msg, sizeof(msg), fmt, args );                       // always null terminated, but may be truncated
    113         va_end( args );
    114 
     101                std::cerr << ErrorHelpers::bold() << err.location << ErrorHelpers::error_str() << ErrorHelpers::reset_font() << err.description << std::endl;
     102        }
     103}
     104
     105void SemanticError( CodeLocation location, std::string error ) {
    115106        SemanticErrorThrow = true;
    116         throw SemanticErrorException( location, msg );          // convert msg to string
    117 }
    118 
    119 void SemanticWarning( CodeLocation location, Warning warning, ... ) {
     107        throw SemanticErrorException( location, error );
     108}
     109
     110namespace {
     111        // convert format string and arguments into a single string
     112        std::string fmtToString(const char * fmt, va_list ap) {
     113                int size = 128;
     114                while ( true ) {
     115                        char buf[size];
     116                        va_list args;
     117                        va_copy( args, ap );
     118                        int n = vsnprintf(&buf[0], size, fmt, args);
     119                        va_end( args );
     120                        if ( n < size && n >= 0 ) return buf;
     121                        size *= 2;
     122                }
     123                assert( false );
     124        }
     125}
     126
     127void SemanticWarningImpl( CodeLocation location, Warning warning, const char * const fmt, ... ) {
    120128        Severity severity = get_severities()[(int)warning];
    121 
    122         switch ( severity ) {
     129        switch(severity) {
    123130        case Severity::Suppress :
    124131                break;
    125132        case Severity::Warn :
     133                {
     134                        va_list args;
     135                        va_start(args, fmt);
     136                        std::string msg = fmtToString( fmt, args );
     137                        va_end(args);
     138                        std::cerr << ErrorHelpers::bold() << location << ErrorHelpers::warning_str() << ErrorHelpers::reset_font() << msg << std::endl;
     139                }
     140                break;
    126141        case Severity::Error :
    127142                {
    128                         char msg[2048];                                                         // worst-case error-message buffer
    129143                        va_list args;
    130                         va_start( args, warning );
    131                         vsnprintf( msg, sizeof(msg), WarningFormats[(int)warning].message, args ); // always null terminated, but may be truncated
    132                         va_end( args );
    133 
    134                         if ( severity == Severity::Warn ) {
    135                                 cerr << ErrorHelpers::bold() << location << ErrorHelpers::warning_str() << ErrorHelpers::reset_font() << msg << endl;
    136                         } else {
    137                                 SemanticError( location, string( msg ) );
    138                         }
     144                        va_start(args, fmt);
     145                        std::string msg = fmtToString( fmt, args );
     146                        va_end(args);
     147                        SemanticError(location, msg);
    139148                }
    140149                break;
     
    154163        }
    155164
    156         const string & error_str() {
    157                 static string str = with_colors() ? "\e[31merror:\e[39m " : "error: ";
    158                 return str;
    159         }
    160 
    161         const string & warning_str() {
    162                 static string str = with_colors() ? "\e[95mwarning:\e[39m " : "warning: ";
    163                 return str;
    164         }
    165 
    166         const string & bold_ttycode() {
    167                 static string str = with_colors() ? "\e[1m" : "";
    168                 return str;
    169         }
    170 
    171         const string & reset_font_ttycode() {
    172                 static string str = with_colors() ? "\e[0m" : "";
    173                 return str;
    174         }
    175 
    176         string make_bold( const string & str ) {
     165        const std::string & error_str() {
     166                static std::string str = with_colors() ? "\e[31merror:\e[39m " : "error: ";
     167                return str;
     168        }
     169
     170        const std::string & warning_str() {
     171                static std::string str = with_colors() ? "\e[95mwarning:\e[39m " : "warning: ";
     172                return str;
     173        }
     174
     175        const std::string & bold_ttycode() {
     176                static std::string str = with_colors() ? "\e[1m" : "";
     177                return str;
     178        }
     179
     180        const std::string & reset_font_ttycode() {
     181                static std::string str = with_colors() ? "\e[0m" : "";
     182                return str;
     183        }
     184
     185        std::string make_bold( const std::string & str ) {
    177186                return bold_ttycode() + str + reset_font_ttycode();
    178187        }
    179188
    180         ostream & operator<<(ostream & os, bold) {
     189        std::ostream & operator<<(std::ostream & os, bold) {
    181190                os << bold_ttycode();
    182191                return os;
    183192        }
    184193
    185         ostream & operator<<(ostream & os, reset_font) {
     194        std::ostream & operator<<(std::ostream & os, reset_font) {
    186195                os << reset_font_ttycode();
    187196                return os;
  • src/Common/SemanticError.h

    r5546eee4 r0fa0201d  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 13:48:07 2023
    13 // Update Count     : 72
     12// Last Modified On : Sat Feb 25 12:01:31 2023
     13// Update Count     : 37
    1414//
    1515
     
    1818#include "ErrorObjects.h"
    1919#include "AST/Node.hpp"
    20 #include "AST/ParseNode.hpp"
    2120#include <cstring>
    2221
     
    2625extern bool SemanticErrorThrow;
    2726
    28 __attribute__((noreturn, format(printf, 2, 3))) void SemanticError( CodeLocation location, const char fmt[], ... );
     27__attribute__((noreturn)) void SemanticError( CodeLocation location, std::string error );
    2928
    30 __attribute__((noreturn)) static inline void SemanticError( CodeLocation location, std::string error ) {
    31         SemanticErrorThrow = true;
    32         throw SemanticErrorException( location, error );
    33 }
    34 
    35 __attribute__((noreturn)) static inline void SemanticError( const ast::ParseNode * obj, const std::string & error ) {
     29template< typename T >
     30__attribute__((noreturn)) static inline void SemanticError( const T * obj, const std::string & error ) {
    3631        SemanticError( obj->location, toString( error, obj ) );
    3732}
    3833
    39 __attribute__((noreturn)) static inline void SemanticError( CodeLocation location, const ast::Node * obj, const std::string & error ) {
     34template< typename T >
     35__attribute__((noreturn)) static inline void SemanticError( CodeLocation location, const T * obj, const std::string & error ) {
    4036        SemanticError( location, toString( error, obj ) );
    4137}
     
    5854
    5955constexpr WarningData WarningFormats[] = {
    60         {"self-assign"              , Severity::Warn, "self assignment of expression: %s"                          },
    61         {"reference-conversion"     , Severity::Warn, "rvalue to reference conversion of rvalue: %s"               },
    62         {"qualifiers-zero_t-one_t"  , Severity::Warn, "questionable use of type qualifier(s) with %s"              },
    63         {"aggregate-forward-decl"   , Severity::Warn, "forward declaration of nested aggregate: %s"                },
    64         {"superfluous-decl"         , Severity::Warn, "declaration does not allocate storage: %s"                  },
    65         {"superfluous-else"         , Severity::Warn, "else clause never executed for empty loop conditional"      },
    66         {"gcc-attributes"           , Severity::Warn, "invalid attribute: %s"                                      },
    67         {"c++-like-copy"            , Severity::Warn, "Constructor from reference is not a valid copy constructor" },
    68         {"depreciated-trait-syntax" , Severity::Warn, "trait type-parameters are now specified using the forall clause" },
     56        {"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
     57        {"reference-conversion"     , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
     58        {"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier(s) with %s"              },
     59        {"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
     60        {"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
     61        {"superfluous-else"         , Severity::Warn    , "else clause never executed for empty loop conditional"      },
     62        {"gcc-attributes"           , Severity::Warn    , "invalid attribute: %s"                                      },
     63        {"c++-like-copy"            , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     64        {"depreciated-trait-syntax" , Severity::Warn    , "trait type-parameters are now specified using the forall clause" },
    6965};
    7066
     
    7975        CppCopy,
    8076        DeprecTraitSyntax,
    81         NUMBER_OF_WARNINGS, // MUST be last warning
     77        NUMBER_OF_WARNINGS, // This MUST be the last warning
    8278};
    8379
     
    8783);
    8884
    89 void SemanticWarning( CodeLocation loc, Warning warn, ... );
     85#define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id].message, ##__VA_ARGS__)
    9086
    91 void SemanticWarning_SuppressAll();
    92 void SemanticWarning_EnableAll();
     87void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4)));
     88
     89void SemanticWarning_SuppressAll   ();
     90void SemanticWarning_EnableAll     ();
    9391void SemanticWarning_WarningAsError();
    94 void SemanticWarning_Set(const char * const name, Severity s);
     92void SemanticWarning_Set           (const char * const name, Severity s);
    9593
    9694// SKULLDUGGERY: cfa.cc is built before SemanticError.cc but needs this routine.
  • src/Concurrency/Corun.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Colby Parsons
    1010// Created On       : Monday October 9 15:16:42 2023
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 17:32:17 2023
    13 // Update Count     : 1
     11// Last Modified By : Colby Parsons
     12// Last Modified On : Monday October 9 15:16:42 2023
     13// Update Count     : 0
    1414//
    1515
     
    5757    Stmt * postvisit( const CoforStmt * stmt ) {
    5858        if ( !runnerBlockDecl || !coforRunnerDecl )
    59             SemanticError( stmt->location, "To use cofor statements add #include <cofor.hfa>" );
     59            SemanticError( stmt->location, "To use cofor statements add #include <cofor.hfa>\n" );
    6060
    6161        if ( stmt->inits.size() != 1 )
    62             SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control" );
     62            SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control\n" );
    6363
    6464        if ( !stmt->body )
     
    7777        const DeclStmt * declStmtPtr = dynamic_cast<const DeclStmt *>(stmt->inits.at(0).get());
    7878        if ( ! declStmtPtr )
    79             SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl statement?" );
     79            SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl statement?\n" );
    8080
    8181        const Decl * declPtr = dynamic_cast<const Decl *>(declStmtPtr->decl.get());
    8282        if ( ! declPtr )
    83             SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl?" );
     83            SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl?\n" );
    8484
    8585        Type * initType = new TypeofType( new NameExpr( loc, declPtr->name ) );
     
    246246    Stmt * postvisit( const CorunStmt * stmt ) {
    247247        if ( !runnerBlockDecl || !coforRunnerDecl )
    248             SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>" );
     248            SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>\n" );
    249249
    250250        if ( !stmt->stmt )
  • src/Concurrency/Keywords.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Tue Nov 16  9:53:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 18:02:25 2023
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 11 10:40:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    682682
    683683        if ( 0 != decl->returns.size() ) {
    684                 SemanticError( decl->location, "Generator main must return void." );
     684                SemanticError( decl->location, "Generator main must return void" );
    685685        }
    686686
     
    789789        case ast::SuspendStmt::Generator:
    790790                // Generator suspends must be directly in a generator.
    791                 if ( !in_generator ) SemanticError( stmt->location, "\"suspend generator\" must be used inside main of generator type." );
     791                if ( !in_generator ) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type." );
    792792                return make_generator_suspend( stmt );
    793793        }
     
    847847
    848848        if ( !decl_suspend ) {
    849                 SemanticError( location, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>." );
     849                SemanticError( location, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n" );
    850850        }
    851851        if ( stmt->then ) {
     
    918918                        // If it is a monitor, then it is a monitor.
    919919                        if( baseStruct->base->is_monitor() || baseStruct->base->is_thread() ) {
    920                                 SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters " );
     920                                SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters\n" );
    921921                        }
    922922                }
     
    926926        // Monitors can't be constructed with mutual exclusion.
    927927        if ( CodeGen::isConstructor( decl->name ) && is_first_argument_mutex ) {
    928                 SemanticError( decl, "constructors cannot have mutex parameters " );
     928                SemanticError( decl, "constructors cannot have mutex parameters\n" );
    929929        }
    930930
    931931        // It makes no sense to have multiple mutex parameters for the destructor.
    932932        if ( isDtor && mutexArgs.size() != 1 ) {
    933                 SemanticError( decl, "destructors can only have 1 mutex argument " );
     933                SemanticError( decl, "destructors can only have 1 mutex argument\n" );
    934934        }
    935935
     
    945945        // Check to if the required headers have been seen.
    946946        if ( !monitor_decl || !guard_decl || !dtor_guard_decl ) {
    947                 SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>." );
     947                SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>\n" );
    948948        }
    949949
     
    952952        if ( isDtor && isThread( mutexArgs.front() ) ) {
    953953                if ( !thread_guard_decl ) {
    954                         SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>." );
     954                        SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
    955955                }
    956956                newBody = addThreadDtorStatements( decl, body, mutexArgs );
     
    987987const ast::Stmt * MutexKeyword::postvisit( const ast::MutexStmt * stmt ) {
    988988        if ( !lock_guard_decl ) {
    989                 SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>." );
     989                SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>\n" );
    990990        }
    991991        ast::CompoundStmt * body =
     
    15471547        if ( !type->base->is_thread() ) return decl;
    15481548        if ( !thread_decl || !thread_ctor_seen ) {
    1549                 SemanticError( type->base->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>." );
     1549                SemanticError( type->base->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>" );
    15501550        }
    15511551        const ast::CompoundStmt * stmt = decl->stmts;
  • src/ControlStruct/FixLabels.cpp

    r5546eee4 r0fa0201d  
    1010// Created On       : Mon Nov  1 09:39:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Nov 26 15:06:51 2023
    13 // Update Count     : 10
     12// Last Modified On : Mon Jan 31 22:19:17 2022
     13// Update Count     : 9
    1414//
    1515
     
    4747        for ( auto kvp : labelTable ) {
    4848                if ( nullptr == kvp.second ) {
    49                         SemanticError( kvp.first.location, "Use of undefined label %s.", kvp.first.name.c_str() );
     49                        SemanticError( kvp.first.location,
     50                                                   "Use of undefined label: " + kvp.first.name );
    5051                }
    5152        }
  • src/ControlStruct/MultiLevelExit.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Nov  1 13:48:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 17:34:12 2023
    13 // Update Count     : 39
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Sep  8 17:04:00 2023
     13// Update Count     : 36
    1414//
    1515
     
    254254                                if ( enclosing_control_structures.empty() ) {
    255255                                          SemanticError( stmt->location,
    256                                                                          "\"break\" outside a loop, \"switch\", or labelled block" );
     256                                                                         "'break' outside a loop, 'switch', or labelled block" );
    257257                                }
    258258                                targetEntry = findEnclosingControlStructure( isBreakTarget );
     
    268268                // Ensure that selected target is valid.
    269269                if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
    270                         SemanticError( stmt->location, toString( (isContinue ? "\"continue\"" : "\"break\""),
     270                        SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
    271271                                                        " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
    272272                                                        stmt->originalTarget ) );
     
    279279                // Check that target is valid.
    280280                if ( targetEntry == enclosing_control_structures.rend() ) {
    281                         SemanticError( stmt->location, "\"fallthrough\" must be enclosed in a \"switch\" or \"choose\"" );
     281                        SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    282282                }
    283283                if ( ! stmt->target.empty() ) {
    284284                        // Labelled fallthrough: target must be a valid fallthough label.
    285285                        if ( ! fallthrough_labels.count( stmt->target ) ) {
    286                                 SemanticError( stmt->location, toString( "\"fallthrough\" target must be a later case statement: ",
     286                                SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
    287287                                                                                                                   stmt->originalTarget ) );
    288288                        }
     
    296296                // Check if in switch or choose statement.
    297297                if ( targetEntry == enclosing_control_structures.rend() ) {
    298                         SemanticError( stmt->location, "\"fallthrough\" must be enclosed in a \"switch\" or \"choose\"" );
     298                        SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    299299                }
    300300
     
    309309                }
    310310                if ( ! foundDefault ) {
    311                         SemanticError( stmt->location, "\"fallthrough default\" must be enclosed in a \"switch\" or \"choose\""
    312                                                    "control structure with a \"default\" clause" );
     311                        SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
     312                                                   "control structure with a 'default' clause" );
    313313                }
    314314                break;
     
    338338                // Check that fallthrough default comes before the default clause.
    339339                if ( ! targetEntry->isFallDefaultValid() ) {
    340                         SemanticError( stmt->location, "\"fallthrough default\" must precede the \"default\" clause" );
     340                        SemanticError( stmt->location, "'fallthrough default' must precede the 'default' clause" );
    341341                }
    342342                break;
     
    521521                assert(0);
    522522        }
    523         SemanticError( stmt->location, "\"return\" may not appear in a %s", context );
     523        SemanticError( stmt->location, toString( "'return' may not appear in a ", context ) );
    524524}
    525525
  • src/GenPoly/Box.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Thr Oct  6 13:39:00 2022
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 17:42:17 2023
    13 // Update Count     : 7
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Oct  2 17:00:00 2023
     13// Update Count     : 0
    1414//
    1515
     
    777777                if ( !concrete ) {
    778778                        // Should this be an assertion?
    779                         SemanticError( expr->location, "\nunbound type variable %s in application %s",
    780                                                    toString( typeSubs ).c_str(), typeVar->typeString().c_str() );
     779                        SemanticError( expr, toString( typeSubs,
     780                                "\nunbound type variable: ", typeVar->typeString(),
     781                                " in application " ) );
    781782                }
    782783                arg = expr->args.insert( arg,
  • src/InitTweak/FixInit.cpp

    r5546eee4 r0fa0201d  
    10571057        )
    10581058        if ( ! diff.empty() ) {
    1059                 SemanticError( stmt->location, "jump to label \"%s\" crosses initialization of \"%s\".",
    1060                                            stmt->target.name.c_str(), (*diff.begin())->name.c_str() );
     1059                SemanticError( stmt, std::string("jump to label '") + stmt->target.name + "' crosses initialization of " + (*diff.begin())->name + " " );
    10611060        } // if
    10621061}
     
    10771076
    10781077bool checkWarnings( const ast::FunctionDecl * funcDecl ) {
    1079         // only check for warnings if the current function is a user-defined constructor or destructor
     1078        // only check for warnings if the current function is a user-defined
     1079        // constructor or destructor
    10801080        if ( ! funcDecl ) return false;
    10811081        if ( ! funcDecl->stmts ) return false;
  • src/Parser/DeclarationNode.cc

    r5546eee4 r0fa0201d  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 19:05:17 2023
    13 // Update Count     : 1407
     12// Last Modified On : Sat Jun 17 14:41:48 2023
     13// Update Count     : 1405
    1414//
    1515
     
    632632                                        dst->basictype = src->basictype;
    633633                                } else if ( src->basictype != DeclarationNode::NoBasicType )
    634                                         SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
    635                                                                    DeclarationNode::basicTypeNames[ dst->basictype ],
    636                                                                    DeclarationNode::basicTypeNames[ src->basictype ] );
     634                                        SemanticError( yylloc, string( "multiple declaration types \"" ) + DeclarationNode::basicTypeNames[ dst->basictype ] +
     635                                                                   "\" and \"" + DeclarationNode::basicTypeNames[ src->basictype ] + "\"." );
     636
    637637                                if ( dst->complextype == DeclarationNode::NoComplexType ) {
    638638                                        dst->complextype = src->complextype;
    639639                                } else if ( src->complextype != DeclarationNode::NoComplexType )
    640                                         SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
    641                                                                    DeclarationNode::complexTypeNames[ src->complextype ],
    642                                                                    DeclarationNode::complexTypeNames[ src->complextype ] );
     640                                        SemanticError( yylloc, string( "multiple declaration types \"" ) + DeclarationNode::complexTypeNames[ src->complextype ] +
     641                                                                   "\" and \"" + DeclarationNode::complexTypeNames[ src->complextype ] + "\"." );
     642
    643643                                if ( dst->signedness == DeclarationNode::NoSignedness ) {
    644644                                        dst->signedness = src->signedness;
    645645                                } else if ( src->signedness != DeclarationNode::NoSignedness )
    646                                         SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
    647                                                                    DeclarationNode::signednessNames[ dst->signedness ],
    648                                                                    DeclarationNode::signednessNames[ src->signedness ] );
     646                                        SemanticError( yylloc, string( "conflicting type specifier \"" ) + DeclarationNode::signednessNames[ dst->signedness ] +
     647                                                                   "\" and \"" + DeclarationNode::signednessNames[ src->signedness ] + "\"." );
     648
    649649                                if ( dst->length == DeclarationNode::NoLength ) {
    650650                                        dst->length = src->length;
     
    652652                                        dst->length = DeclarationNode::LongLong;
    653653                                } else if ( src->length != DeclarationNode::NoLength )
    654                                         SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
    655                                                                    DeclarationNode::lengthNames[ dst->length ],
    656                                                                    DeclarationNode::lengthNames[ src->length ] );
     654                                        SemanticError( yylloc, string( "conflicting type specifier \"" ) + DeclarationNode::lengthNames[ dst->length ] +
     655                                                                   "\" and \"" + DeclarationNode::lengthNames[ src->length ] + "\"." );
    657656                        } // if
    658657                        break;
  • src/Parser/ExpressionNode.cc

    r5546eee4 r0fa0201d  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat May 16 13:17:07 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 18:57:07 2023
    13 // Update Count     : 1087
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 11:07:00 2023
     13// Update Count     : 1083
    1414//
    1515
     
    193193
    194194#if ! defined(__SIZEOF_INT128__)
    195         if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target \"%s\"", str.c_str() );
     195        if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str );
    196196#endif // ! __SIZEOF_INT128__
    197197
     
    204204                        } else {                                                                        // hex int128 constant
    205205                                unsigned int len = str.length();
    206                                 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large \"%s\"", str.c_str() );
     206                                if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str );
    207207                                // hex digits < 2^64
    208208                                if ( len > (2 + 16) ) {
     
    219219                        unsigned int len = str.length();
    220220                        if ( type == 5 && len > 2 + 64 ) {
    221                                 if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large \"%s\".", str.c_str() );
     221                                if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large " + str );
    222222                                str2 = "0b" + str.substr( len - 64 );
    223223                                str = str.substr( 0, len - 64 );
     
    233233                        } else {                                                                        // octal int128 constant
    234234                                unsigned int len = str.length();
    235                                 if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large \"%s\"", str.c_str() );
     235                                if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large " + str );
    236236                                char buf[32];
    237237                                if ( len <= 1 + 21 ) {                                  // value < 21 octal digitis
     
    266266                        unsigned int len = str.length();
    267267                        if ( str.length() == 39 && str > (Unsigned ? "340282366920938463463374607431768211455" : "170141183460469231731687303715884105727") )
    268                                 SemanticError( yylloc, "128-bit decimal constant to large \"%s\".", str.c_str() );
     268                                SemanticError( yylloc, "128-bit decimal constant to large " + str );
    269269                        char buf[32];
    270270                        if ( len <= 19 ) {                                                      // value < 19 decimal digitis
     
    502502ast::Expr * build_field_name_FLOATING_FRACTIONconstant(
    503503                const CodeLocation & location, const string & str ) {
    504         if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index \"%s\".", str.c_str() );
     504        if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str );
    505505        ast::Expr * ret = build_constantInteger( location,
    506506                *new string( str.substr(1) ) );
     
    511511ast::Expr * build_field_name_FLOATING_DECIMALconstant(
    512512                const CodeLocation & location, const string & str ) {
    513         if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index \"%s\".", str.c_str() );
     513        if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str );
    514514        ast::Expr * ret = build_constantInteger(
    515515                location, *new string( str.substr( 0, str.size()-1 ) ) );
  • src/Parser/ParseNode.h

    r5546eee4 r0fa0201d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:28:16 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Dec  9 17:39:34 2023
    13 // Update Count     : 945
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Apr  3 17:55:00 2023
     13// Update Count     : 942
    1414//
    1515
     
    3737class ExpressionNode;
    3838struct StatementNode;
    39 
    4039
    4140//##############################################################################
     
    9897std::ostream & operator<<( std::ostream & out, const ParseNode * node );
    9998
    100 __attribute__((noreturn)) static inline void SemanticError( const ParseNode * obj, const std::string & error ) {
    101         SemanticError( obj->location, toString( error, obj ) );
    102 }
    103 
    10499// Local Variables: //
    105100// tab-width: 4 //
  • src/Parser/TypeData.cc

    r5546eee4 r0fa0201d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 15:12:51 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 18:59:12 2023
    13 // Update Count     : 684
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 13:39:00 2023
     13// Update Count     : 680
    1414//
    1515
     
    864864
    865865static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
    866         SemanticError( yylloc, "invalid type specifier \"%s\" for type \"%s\".", msg.c_str(), DeclarationNode::basicTypeNames[basictype] );
     866        SemanticError( yylloc, string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
    867867} // genTSError
    868868
     
    14961496                                // type set => parameter name already transformed by a declaration names so there is a duplicate
    14971497                                // declaration name attempting a second transformation
    1498                                 if ( param->type ) SemanticError( param->location, "duplicate declaration name \"%s\".", param->name->c_str() );
     1498                                if ( param->type ) SemanticError( param->location, string( "duplicate declaration name " ) + *param->name );
    14991499                                // declaration type reset => declaration already transformed by a parameter name so there is a duplicate
    15001500                                // parameter name attempting a second transformation
    1501                                 if ( ! decl->type ) SemanticError( param->location, "duplicate parameter name \"%s\".", param->name->c_str() );
     1501                                if ( ! decl->type ) SemanticError( param->location, string( "duplicate parameter name " ) + *param->name );
    15021502                                param->type = decl->type;                               // set copy declaration type to parameter type
    15031503                                decl->type = nullptr;                                   // reset declaration type
     
    15071507                } // for
    15081508                // declaration type still set => type not moved to a matching parameter so there is a missing parameter name
    1509                 if ( decl->type ) SemanticError( decl->location, "missing name in parameter list %s", decl->name->c_str() );
     1509                if ( decl->type ) SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
    15101510        } // for
    15111511
  • src/Parser/parser.yy

    r5546eee4 r0fa0201d  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Nov 26 13:18:06 2023
    13 // Update Count     : 6398
     12// Last Modified On : Tue Oct  3 17:14:12 2023
     13// Update Count     : 6396
    1414//
    1515
     
    260260                } // if
    261261        } else {
    262                 SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed." ); return nullptr;
     262                SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed. ." ); return nullptr;
    263263        } // if
    264264} // forCtrl
    265265
    266266static void IdentifierBeforeIdentifier( string & identifier1, string & identifier2, const char * kind ) {
    267         SemanticError( yylloc, "syntax error, adjacent identifiers \"%s\" and \"%s\" are not meaningful in an %s.\n"
    268                                    "Possible cause is misspelled type name or missing generic parameter.",
    269                                    identifier1.c_str(), identifier2.c_str(), kind );
     267        SemanticError( yylloc, ::toString( "syntax error, adjacent identifiers \"", identifier1, "\" and \"", identifier2, "\" are not meaningful in a", kind, ".\n"
     268                                   "Possible cause is misspelled type name or missing generic parameter." ) );
    270269} // IdentifierBeforeIdentifier
    271270
    272271static void IdentifierBeforeType( string & identifier, const char * kind ) {
    273         SemanticError( yylloc, "syntax error, identifier \"%s\" cannot appear before a %s.\n"
    274                                    "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter.",
    275                                    identifier.c_str(), kind );
     272        SemanticError( yylloc, ::toString( "syntax error, identifier \"", identifier, "\" cannot appear before a ", kind, ".\n"
     273                                   "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter." ) );
    276274} // IdentifierBeforeType
    277275
     
    691689        //      { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
    692690        | IDENTIFIER IDENTIFIER                                                         // invalid syntax rule
    693                 { IdentifierBeforeIdentifier( *$1.str, *$2.str, "expression" ); $$ = nullptr; }
     691                { IdentifierBeforeIdentifier( *$1.str, *$2.str, "n expression" ); $$ = nullptr; }
    694692        | IDENTIFIER type_qualifier                                                     // invalid syntax rule
    695693                { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; }
     
    11571155        | identifier_or_type_name ':' attribute_list_opt error // invalid syntax rule
    11581156                {
    1159                         SemanticError( yylloc, "syntx error, label \"%s\" must be associated with a statement, "
    1160                                                    "where a declaration, case, or default is not a statement.\n"
    1161                                                    "Move the label or terminate with a semicolon.", $1.str->c_str() );
     1157                        SemanticError( yylloc, ::toString( "syntx error, label \"", *$1.str, "\" must be associated with a statement, "
     1158                                                                                           "where a declaration, case, or default is not a statement. "
     1159                                                                                           "Move the label or terminate with a semi-colon." ) );
    11621160                        $$ = nullptr;
    11631161                }
     
    21032101        | sue_declaration_specifier invalid_types                       // invalid syntax rule
    21042102                {
    2105                         SemanticError( yylloc, "syntax error, expecting ';' at end of \"%s\" declaration.",
    2106                                                    $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ) );
     2103                        SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of ",
     2104                                $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
     2105                                " declaration." ) );
    21072106                        $$ = nullptr;
    21082107                }
     
    21622161type_qualifier:
    21632162        type_qualifier_name
    2164         | attribute                                                                                     // trick handles most attribute locations
     2163        | attribute                                                                                     // trick handles most atrribute locations
    21652164        ;
    21662165
     
    25862585        | type_specifier field_declaring_list_opt '}'           // invalid syntax rule
    25872586                {
    2588                         SemanticError( yylloc, "syntax error, expecting ';' at end of previous declaration." );
     2587                        SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of previous declaration." ) );
    25892588                        $$ = nullptr;
    25902589                }
  • src/ResolvExpr/CurrentObject.cc

    r5546eee4 r0fa0201d  
    99// Author           : Rob Schluntz
    1010// Created On       : Tue Jun 13 15:28:32 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Dec  9 17:49:51 2023
    13 // Update Count     : 20
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Apr 10  9:40:00 2023
     13// Update Count     : 18
    1414//
    1515
     
    181181                auto res = eval( expr );
    182182                if ( !res.hasKnownValue ) {
    183                         SemanticError( location, "Array designator must be a constant expression %s", toString( expr ).c_str() );
     183                        SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
    184184                }
    185185                return res.knownValue;
  • src/ResolvExpr/Resolver.cc

    r5546eee4 r0fa0201d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 18:44:43 2023
    13 // Update Count     : 251
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Apr 20 10:41:00 2022
     13// Update Count     : 248
    1414//
    1515
     
    632632                                                maybe_accept( mutDecl->init.get(), res );
    633633                                                if ( !res.core.result ) {
    634                                                         SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object.\n"
    635                                                                                    "If this is really what you want, initialize with @=." );
     634                                                        SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
    636635                                                }
    637636                                        }
     
    959958                                                                ++n_mutex_param;
    960959
    961                                                                 // Check if the argument matches the parameter type in the current scope.
     960                                                                // Check if the argument matches the parameter type in the current
     961                                                                // scope
    962962                                                                // ast::ptr< ast::Type > paramType = (*param)->get_type();
    963 
    964963                                                                if (
    965964                                                                        ! unify(
  • src/Validate/FixQualifiedTypes.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Thr Apr 21 11:13:00 2022
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 13 09:00:25 2023
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Sep 20 16:15:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    4141                                auto td = symtab.globalLookupType( inst->name );
    4242                                if ( !td ) {
    43                                         SemanticError( *location, "Use of undefined global type %s.", inst->name.c_str() );
     43                                        SemanticError( *location, toString("Use of undefined global type ", inst->name) );
    4444                                }
    4545                                auto base = td->base;
     
    5050                        } else {
    5151                                // .T => T is not a type name.
    52                                 assertf( false, "unhandled global qualified child type: %s", toCString( child ) );
     52                                assertf( false, "unhandled global qualified child type: %s", toCString(child) );
    5353                        }
    5454                } else {
     
    6363                                instp = inst;
    6464                        } else {
    65                                 SemanticError( *location, "Qualified type requires an aggregate on the left, but has %s.", toCString( parent ) );
     65                                SemanticError( *location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
    6666                        }
    6767                        // TODO: Need to handle forward declarations.
     
    8181                                } else {
    8282                                        // S.T - S is not an aggregate => error.
    83                                         assertf( false, "unhandled qualified child type %s.", toCString( type ) );
     83                                        assertf( false, "unhandled qualified child type: %s", toCString(type) );
    8484                                }
    8585                        }
    8686                        // failed to find a satisfying definition of type
    87                         SemanticError( *location, "Undefined type in qualified type %s", toCString( type ) );
     87                        SemanticError( *location, toString("Undefined type in qualified type: ", type) );
    8888                }
    8989        }
  • src/Validate/ForallPointerDecay.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Tue Dec  7 16:15:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Nov 26 18:49:57 2023
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Sat Apr 23 13:10:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    213213                auto type = obj->type->stripDeclarator();
    214214                if ( dynamic_cast< const ast::FunctionType * >( type ) ) return;
    215                 SemanticError( obj->location, "operator %s is not a function or function pointer.", obj->name.c_str() );
     215                SemanticError( obj->location,
     216                        toCString( "operator ", obj->name.c_str(),
     217                        " is not a function or function pointer." ) );
    216218        }
    217219};
  • src/Validate/ReplaceTypedef.cpp

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Tue Jun 29 14:59:00 2022
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 14 16:11:51 2023
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Sep 20 17:00:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    111111                        if ( !rtt ) {
    112112                                assert( location );
    113                                 SemanticError( *location, "Cannot apply type parameters to base type of %s.", type->name.c_str() );
     113                                SemanticError( *location, "Cannot apply type parameters to base type of " + type->name );
    114114                        }
    115115                        rtt->params.clear();
     
    125125                if ( base == typedeclNames.end() ) {
    126126                        assert( location );
    127                         SemanticError( *location, "Use of undefined type %s.", type->name.c_str() );
     127                        SemanticError( *location, toString( "Use of undefined type ", type->name ) );
    128128                }
    129129                return ast::mutate_field( type, &ast::TypeInstType::base, base->second );
     
    152152                                || ast::Pass<VarLenChecker>::read( t0 )
    153153                                || ast::Pass<VarLenChecker>::read( t1 ) ) {
    154                         SemanticError( decl->location, "Cannot redefine typedef %s", decl->name.c_str() );
     154                        SemanticError( decl->location, "Cannot redefine typedef: " + decl->name );
    155155                }
    156156        } else {
  • src/Virtual/ExpandCasts.cc

    r5546eee4 r0fa0201d  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jul 24 13:59:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Nov 27 09:28:20 2023
    13 // Update Count     : 10
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug 11 12:06:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    160160
    161161        // Helper function for throwing semantic errors.
    162         auto throwError = [&fieldName, &errorLocation, &oldDecl]( std::string const & message ) {
    163                 SemanticError( errorLocation, "While following head pointer of %s named \"%s\": %s",
    164                                            oldDecl->name.c_str(), fieldName.c_str(), message.c_str() );
     162        auto throwError = [&fieldName, &errorLocation, &oldDecl](
     163                        std::string const & message ) {
     164                std::string const & context = "While following head pointer of " +
     165                        oldDecl->name + " named '" + fieldName + "': ";
     166                SemanticError( errorLocation, context + message );
    165167        };
    166168
  • tests/.expect/nested-types-ERR1.txt

    r5546eee4 r0fa0201d  
    11nested-types.cfa:100:25: warning: Compiled
    2 nested-types.cfa:83:1 error: Use of undefined type T.
     2nested-types.cfa:83:1 error: Use of undefined type T
  • tests/.expect/nested-types-ERR2.txt

    r5546eee4 r0fa0201d  
    11nested-types.cfa:100:25: warning: Compiled
    2 nested-types.cfa:86:1 error: Use of undefined global type Z.
    3 nested-types.cfa:87:1 error: Qualified type requires an aggregate on the left, but has signed int.
    4 nested-types.cfa:88:1 error: Undefined type in qualified type Qualified Type:
     2nested-types.cfa:86:1 error: Use of undefined global type Z
     3nested-types.cfa:87:1 error: Qualified type requires an aggregate on the left, but has: signed int
     4nested-types.cfa:88:1 error: Undefined type in qualified type: Qualified Type:
    55  instance of struct S with body
    66  instance of type Z (not function type)
  • tests/.expect/typedefRedef-ERR1.txt

    r5546eee4 r0fa0201d  
    11typedefRedef.cfa:75:25: warning: Compiled
    2 typedefRedef.cfa:4:1 error: Cannot redefine typedef Foo
    3 typedefRedef.cfa:31:1 error: Cannot redefine typedef ARR
    4 typedefRedef.cfa:65:1 error: Cannot redefine typedef ARR
     2typedefRedef.cfa:4:1 error: Cannot redefine typedef: Foo
     3typedefRedef.cfa:31:1 error: Cannot redefine typedef: ARR
     4typedefRedef.cfa:65:1 error: Cannot redefine typedef: ARR
  • tests/concurrency/.expect/ctor-check.txt

    r5546eee4 r0fa0201d  
    1 concurrency/ctor-check.cfa:11:1 error: constructors cannot have mutex parameters ?{}: function
     1concurrency/ctor-check.cfa:11:1 error: constructors cannot have mutex parameters
     2?{}: function
    23... with parameters
    34  this: mutex reference to instance of struct Empty with body
  • tests/exceptions/.expect/try-ctrl-flow.txt

    r5546eee4 r0fa0201d  
    1 exceptions/try-ctrl-flow.cfa:7:1 error: "break" outside a loop, "switch", or labelled block
    2 exceptions/try-ctrl-flow.cfa:15:1 error: "break" outside a loop, "switch", or labelled block
    3 exceptions/try-ctrl-flow.cfa:23:1 error: "break" outside a loop, "switch", or labelled block
    4 exceptions/try-ctrl-flow.cfa:31:1 error: "continue" target must be an enclosing loop:
    5 exceptions/try-ctrl-flow.cfa:48:1 error: "break" target must be an enclosing control structure: mainLoop
    6 exceptions/try-ctrl-flow.cfa:56:1 error: "continue" target must be an enclosing loop: mainLoop
    7 exceptions/try-ctrl-flow.cfa:65:1 error: "break" outside a loop, "switch", or labelled block
    8 exceptions/try-ctrl-flow.cfa:76:1 error: "break" outside a loop, "switch", or labelled block
    9 exceptions/try-ctrl-flow.cfa:87:1 error: "fallthrough" must be enclosed in a "switch" or "choose"
    10 exceptions/try-ctrl-flow.cfa:98:1 error: "break" target must be an enclosing control structure: mainBlock
    11 exceptions/try-ctrl-flow.cfa:111:1 error: "fallthrough" must be enclosed in a "switch" or "choose"
    12 exceptions/try-ctrl-flow.cfa:124:1 error: "fallthrough" must be enclosed in a "switch" or "choose"
    13 exceptions/try-ctrl-flow.cfa:133:1 error: "return" may not appear in a finally clause
    14 exceptions/try-ctrl-flow.cfa:139:1 error: "return" may not appear in a finally clause
    15 exceptions/try-ctrl-flow.cfa:148:1 error: "break" outside a loop, "switch", or labelled block
    16 exceptions/try-ctrl-flow.cfa:159:1 error: "return" may not appear in a try statement with a catch clause
    17 exceptions/try-ctrl-flow.cfa:187:1 error: "return" may not appear in a catch clause
    18 exceptions/try-ctrl-flow.cfa:195:1 error: "return" may not appear in a catchResume clause
     1exceptions/try-ctrl-flow.cfa:7:1 error: 'break' outside a loop, 'switch', or labelled block
     2exceptions/try-ctrl-flow.cfa:15:1 error: 'break' outside a loop, 'switch', or labelled block
     3exceptions/try-ctrl-flow.cfa:23:1 error: 'break' outside a loop, 'switch', or labelled block
     4exceptions/try-ctrl-flow.cfa:31:1 error: 'continue' target must be an enclosing loop:
     5exceptions/try-ctrl-flow.cfa:48:1 error: 'break' target must be an enclosing control structure: mainLoop
     6exceptions/try-ctrl-flow.cfa:56:1 error: 'continue' target must be an enclosing loop: mainLoop
     7exceptions/try-ctrl-flow.cfa:65:1 error: 'break' outside a loop, 'switch', or labelled block
     8exceptions/try-ctrl-flow.cfa:76:1 error: 'break' outside a loop, 'switch', or labelled block
     9exceptions/try-ctrl-flow.cfa:87:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
     10exceptions/try-ctrl-flow.cfa:98:1 error: 'break' target must be an enclosing control structure: mainBlock
     11exceptions/try-ctrl-flow.cfa:111:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
     12exceptions/try-ctrl-flow.cfa:124:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
     13exceptions/try-ctrl-flow.cfa:133:1 error: 'return' may not appear in a finally clause
     14exceptions/try-ctrl-flow.cfa:139:1 error: 'return' may not appear in a finally clause
     15exceptions/try-ctrl-flow.cfa:148:1 error: 'break' outside a loop, 'switch', or labelled block
     16exceptions/try-ctrl-flow.cfa:159:1 error: 'return' may not appear in a try statement with a catch clause
     17exceptions/try-ctrl-flow.cfa:187:1 error: 'return' may not appear in a catch clause
     18exceptions/try-ctrl-flow.cfa:195:1 error: 'return' may not appear in a catchResume clause
  • tests/raii/.expect/dtor-early-exit-ERR1.txt

    r5546eee4 r0fa0201d  
    1 raii/dtor-early-exit.cfa:150:1 error: jump to label "L1" crosses initialization of "y".
     1raii/dtor-early-exit.cfa:150:1 error: jump to label 'L1' crosses initialization of y Branch (Goto)
     2  with target: L1
     3  with original target: L1
     4
  • tests/raii/.expect/dtor-early-exit-ERR2.txt

    r5546eee4 r0fa0201d  
    1 raii/dtor-early-exit.cfa:214:1 error: jump to label "L2" crosses initialization of "y".
     1raii/dtor-early-exit.cfa:214:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)
     2  with target: L2
     3  with original target: L2
     4
Note: See TracChangeset for help on using the changeset viewer.