Changeset 6f9f338


Ignore:
Timestamp:
Mar 14, 2025, 3:44:30 AM (6 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
e48aca8
Parents:
6cb3e5d (diff), 8b639f9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
2 added
9 edited

Legend:

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

    r6cb3e5d r6f9f338  
    468468\VRef[Figure]{f:ContiguousNon-contiguous} shows a powerful extension made in C99 for manipulating contiguous \vs non-contiguous arrays.\footnote{C90 also supported non-contiguous arrays.}
    469469For contiguous-array (including VLA) arguments, C99 conjoins one or more of the parameters as a downstream dimension(s), \eg @cols@, implicitly using this parameter to compute the row stride of @m@.
    470 There is now sufficient information to support subscript checking along the columns to prevent buffer-overflow problems, but subscript checking is not provided.
     470There is now sufficient information to support array copying and subscript checking along the columns to prevent changing the argument or buffer-overflow problems, but neither feature is provided.
    471471If the declaration of @fc@ is changed to:
    472472\begin{cfa}
     
    12211221This representation means that there is no real limit to how long a string can be, but programs have to scan one completely to determine its length.~\cite[p.~36]{C:old}
    12221222\end{quote}
    1223 Unfortunately, this design decision is both unsafe and inefficient.
    1224 It is common error in C to forget the storage in a character array for the terminator or overwrite the terminator, resulting in array overruns in string operations.
    1225 The need to repeatedly scan an entire string to determine its length can result in significant cost, as it is impossible to cache the length in many cases.
     1223This property is only preserved by the compiler with respect to character constants, \eg @"abc"@ is actually @"abc\0"@, \ie 4 characters rather than 3.
     1224Otherwise, the compiler does not participate, making string operations both unsafe and inefficient.
     1225For example, it is common in C to: forget that a character constant is larger than it appears during manipulation, that extra storage is needed in a character array for the terminator, or that the terminator must be preserved during string operations, otherwise there are array overruns.
     1226Finally, the need to repeatedly scan an entire string to determine its length can result in significant cost, as it is impossible to cache the length in many cases, \eg when a string is passed into another function.
    12261227
    12271228C strings are fixed size because arrays are used for the implementation.
  • doc/theses/mike_brooks_MMath/string.tex

    r6cb3e5d r6f9f338  
    11\chapter{String}
    22
     3\vspace*{-20pt}
    34This chapter presents my work on designing and building a modern string type in \CFA.
    4 The discussion starts with examples of interesting string problems, followed by examples of how these issues are solved in my design.
     5The discussion starts with examples of interesting string problems, followed by examples of how these issues are resolved in my design.
    56
    67
     
    89
    910To prepare for the following discussion, comparisons among C, \CC, Java and \CFA strings are presented, beginning in \VRef[Figure]{f:StrApiCompare}.
    10 It provides a classic ``cheat sheet'' presentation, summarizing the names of the typical operations.
    11 
    12 \begin{figure}
     11It provides a classic ``cheat sheet'' presentation, summarizing the names of the most common closely-equivalent operations.
     12The over-arching commonality is that operations work on groups of characters for assigning, copying, scanning, and updating.
     13
     14\begin{figure}[h]
    1315\begin{cquote}
    1416\begin{tabular}{@{}l|l|l|l@{}}
     
    3436\end{figure}
    3537
    36 The key commonality is that operations work on groups of characters for assigning, copying, scanning, and updating.
    37 Because a C string is null terminated and requires explicit storage management \see{\VRef{s:String}}, most of its group operations are error prone and expensive.
    38 Most high-level string libraries use a separate length field and specialized storage management to support group operations.
    39 \CC strings retain null termination to interface with library functions requiring C strings.
    40 \begin{cfa}
    41 int open( const char * pathname, int flags );
     38As mentioned in \VRef{s:String}, a C string differs from other string types as it uses null termination rather than a length, which leads to explicit storage management;
     39hence, most of its group operations are error prone and expensive.
     40Most high-level string libraries use a separate length field and specialized storage management to implement group operations.
     41Interestingly, \CC strings retain null termination just in case it is needed to interface with C library functions.
     42\begin{cfa}
     43int open( @const char * pathname@, int flags );
    4244string fname{ "test.cc" );
    4345open( fname.@c_str()@, O_RDONLY );
    4446\end{cfa}
    45 The function @c_str@ does not create a new null-terminated C string from the \CC string, as that requires passing ownership of the C string to the caller for eventual deletion.\footnote{
     47Here, the \CC @c_str@ function does not create a new null-terminated C string from the \CC string, as that requires passing ownership of the C string to the caller for eventual deletion.\footnote{
    4648C functions like \lstinline{strdup} do return allocated storage that must be freed by the caller.}
    47 Instead, each \CC string is null terminated just in case it might be needed for this purpose.
     49% Instead, each \CC string is null terminated just in case it might be needed for this purpose.
    4850Providing this backwards compatibility with C has a ubiquitous performance and storage cost.
    4951
    50 While \VRef[Figure]{f:StrApiCompare} emphasizes cross-language similarities, it elides differences in how a certain function is used.
    51 For example, the @replace@ function in \CC performs a modification on its @this@ parameter, while the Java one allocates and returns a new string with the result, leaving @this@ unmodified.
     52While \VRef[Figure]{f:StrApiCompare} emphasizes cross-language similarities, it elides many specific operational differences.
     53For example, the @replace@ function selects a substring in the target and substitutes it with the source string, which can be smaller or larger than the substring.
     54\CC performs the modification on the mutable receiver object.
     55\begin{cfa}
     56string s1 = "abcde";
     57s1.replace( 2, 3, "xy" );  $\C[2.25in]{// replace by position (zero origin) and length, mutable}\CRT$
     58cout << s1 << endl;
     59$\texttt{abxy}$
     60\end{cfa}
     61while Java allocates and returns a new string with the result, leaving the receiver unmodified.
     62\begin{java}
     63String s = "abcde";
     64String r = s.replace( "cde", "xy" );  $\C[2.25in]{// replace by text, immutable}$
     65StringBuffer sb = new StringBuffer( "abcde" );
     66sb.replace( 2, 5, "xy" );  $\C{// replace by position, mutable}\CRT$
     67System.out.println( s + ' ' + r + ' ' + sb );
     68$\texttt{abcde abxy abxy}$
     69\end{java}
    5270Generally, Java's @String@ type is immutable.
    53 Java provides a @StringBuffer@ near-analog that is mutable, but the differences are significant; for example, this class's @substring@ functions still return copies rather than mutable selections.
    54 
    55 These more significant differences are summarized in \VRef[Figure]{f:StrSemanticCompare}.  It calls out the consequences of each language taking a different approach on the ``internal'' issues, like storage management and null-terminator interoperability.  The discussion following justifies the figure's yes/no entries.
    56 
    57 \begin{figure}
    58 \begin{tabular}{@{}p{0.5in}p{2in}p{2in}>{\centering\arraybackslash}p{0.2in}>{\centering\arraybackslash}>{\centering\arraybackslash}p{0.2in}>{\centering\arraybackslash}p{0.2in}>{\centering\arraybackslash}p{0.2in}@{}}
    59                                         &                       &                       & \multicolumn{4}{c}{\underline{Supports Helpful?}} \\
     71Java provides a @StringBuffer@ near-analog that is mutable, but the differences are significant; for example, @StringBuffer@'s @substring@ functions still return copies rather than mutable selections.
     72Finally, the operations between these type are asymmetric, \eg @string@ has @replace@ by text but not replace by position and vice versa for @StringBuffer@.
     73
     74More significant operational differences relate to storage management, often appearing through assignment (@target = source@), and are summarized in \VRef[Figure]{f:StrSemanticCompare}.
     75% It calls out the consequences of each language taking a different approach on ``internal'' storage management.
     76The following discussion justifies the figure's yes/no entries per language.
     77
     78\begin{figure}
     79\setlength{\extrarowheight}{2pt}
     80\begin{tabularx}{\textwidth}{@{}p{0.6in}XXcccc@{}}
     81                                        &                       &                       & \multicolumn{4}{@{}c@{}}{\underline{Supports Helpful?}} \\
    6082                                        & Required      & Helpful       & C                     & \CC           & Java          & \CFA \\
    6183\hline
    6284Type abst'n
    63                                         & Low-level: A ``string'' type represents a varying amount of text that is communicated with a function as a parameter/return.
    64                                                                 & High-level: Using a string-typed variable relieves the user of managing a distinct allocation for the text.
    65                                                                                         & \xmark        & \cmark        & \cmark        & \cmark \\
     85                                        & Low-level: The string type is a varying amount of text communicated via a parameter or return.
     86                                                                & High-level: The string-typed relieves the user of managing memory for the text.
     87                                                                                        & no    & yes   & yes   & yes \\
    6688\hline
    67 \multirow{2}{0.5in}
    68 {State}
     89State
    6990                                        & \multirow{2}{2in}
    70                                         {Fast Initialize: The target receives the characters of the original, but no time is spent copying characters.  The result is one of Alias or Snapshot.}
    71                                                                 & Alias: The target is a further name for the text in the original; changes made in either variable are visible in both.
    72                                                                                         & \cmark        & \cmark        & \xmark        & \cmark \\
     91                                        {Fast Initialize: The target receives the characters of the source without copying the characters, resulting in an Alias or Snapshot.}
     92                                                                & Alias: The target name is within the source text; changes made in either variable are visible in both.
     93                                                                                        & yes   & yes   & no    & yes \\
    7394\cline{3-7}
    7495                                        &
    75                                                                 & Snapshot: The target (resp.\ source) contains the value of the source at the time of the initialization until the target (resp.\ source) is explicitly changed.
    76                                                                                         & \xmark        & \xmark        & \cmark        & \cmark \\
     96                                                                & Snapshot: The target is an alias within the source until the target changes (copy on write).
     97                                                                                        & no    & no    & yes   & yes \\
    7798\hline
    7899Symmetry
    79                                         & Laxed: The targets type is anything string-like; it may have a different status concerning ownership.
    80                                                                 & Strict: The target’s type is the same as the original; both strings are equivalent peers concerning ownership.
    81                                                                                         & --            & \xmark        & \cmark        & \cmark \\
     100                                        & Laxed: The target's type is anything string-like; it may have a different status concerning ownership.
     101                                                                & Strict: The target's type is the same as the source; both strings are equivalent peers concerning ownership.
     102                                                                                        & --            & no    & yes   & yes \\
    82103\hline
    83104Referent
    84                                         & Variable-Constrained: The target can accept the entire text of the original.
    85                                                                 & Fragment: The target can accept an arbitrary substring of the original.
    86                                                                                         & \xmark        & \xmark        & \cmark        & \cmark
    87 \end{tabular}
     105                                        & Variable-Constrained: The target can accept the entire text of the source.
     106                                                                & Fragment: The target can accept an arbitrary substring of the source.
     107                                                                                        & no    & no    & yes   & yes
     108\end{tabularx}
    88109
    89110\noindent
    90111Notes
    91 \begin{itemize}
     112\begin{itemize}[parsep=0pt]
    92113\item
    93114        All languages support Required in all criteria.
     
    95116        A language gets ``Supports Helpful'' in one criterion if it can do so without sacrificing the Required achievement on all other criteria.
    96117\item
    97         The C ``string'' is @char *@, under the conventions that @<string.h>@ requires.  Symmetry is not applicable to C.
     118        The C ``string'' is actually @char []@, under the conventions that @<string.h>@ requires. Hence, there is no actual string type in C, so symmetry does not apply.
    98119\item
    99120        The Java @String@ class is analyzed; its @StringBuffer@ class behaves similarly to @C++@.
    100121\end{itemize}
    101 \caption{Comparison of languages' strings, assignment-semantics perspective.}
     122\caption{Comparison of languages' strings, storage management perspective.}
    102123\label{f:StrSemanticCompare}
    103124\end{figure}
    104125
    105 In C:
    106 \begin{cfa}
    107 char * s1 = ...; // assumed
    108 char * s2 = s1;  // alias state, variable-constrained referent
    109 char * s3 = s1 + 2;  // alias state, variable-constrained referent
    110 \end{cfa}
    111 The issue of symmetry is trivial for a low-level type, and so, scored as not applicable to C.
    112 With the type not managing the text buffer, there is no ownership question, \ie nothing done with the @s1@ or @s2@ variables leads to the memory that their text currently occupies becoming reusable.
    113 While @s3@ is a valid C-string that contains a proper substring of @s1@, the @s3@ technique does not constitue having a fragment referent because null termination implies the substring cannot be chosen arbitrarily; the technique works only for suffixes.
    114 
    115 In \CC:
    116 \begin{cfa}
    117 string s1 = ...; // assumed
    118 string & s2 = s1;  // alias state, lax symmetry, variable-constrained referent
    119 string s3 = s1;  // NOT fast-initialize (strict symmetry, variable-constrained referent)
    120 string s4 = s1.substr(2,4);  // NOT fast-initialize (strict symmetry, fragment referent)
    121 string & s5 = s1.substr(2,4);  // memory-use error
    122 \end{cfa}
    123 The lax symmetry of the @s2@ technique reflects how the validity of @s2@ depends on the lifetime of @s1@.
    124 It is common practice in \CC to use the @s2@ technique for parameter passing, but the safest-bet advice has to be that the callee can only use the referenced string for the duration of the call.
    125 So, when the called function is a constructor, it is typical that the implementation is doing an @s3@-style initialization of a string-object-typed member.
    126 Exceptions of this pattern are possible, of course, but they represent the programmer taking responsiblity to assure safety where the type system does not.
    127 The @s4@ initialization is constrained by specification to copy the substring because of @c_str@ being specified to be a null-terminated character run that is not its own allocation.
    128 TODO: address caveat that @s3@ could be done fast by reference counting in the text area.
    129 
    130 
    131 In Java:
    132 \begin{cfa}
    133 String s1 = ...;  // assumed
    134 String s2 = s1;  // snapshot state, strict symmetry, variable-constrained referent
    135 String s3 = s1.substring(2,4);  // snapshot state (possible), strict symmetry, fragment referent
    136 \end{cfa}
    137 Here, facts about Java's implicit pointers and pointer equality can overcomplicate the picture.
    138 The further fact of Java's string immutability means that string variables behave as simple values.
    139 The result in @s2@ is the value of @s1@, and their pointer equality certainly assures that no time is spent copying characters.
    140 With @s3@, the case for fast-copy is more subtle.
    141 Certainly, its value is not pointer-equal to @s1@, implying at least a further allocation.
     126In C, the declaration
     127\begin{cfa}
     128char s[$\,$] = "abcde";
     129\end{cfa}
     130creates a second-class fixed-sized string-variable, as it can only be used in its lexical context;
     131it cannot be passed by value to string operations or user functions as C array's cannot be copied because there is no string-length information passed to the function.
     132Therefore, only pointers to strings are first-class, and discussed further.
     133\begin{cfa}
     134(const) char * s = "abcde";  $\C[2.25in]{// alias state, n/a symmetry, variable-constrained referent}$
     135char * s1 = s;  $\C{// alias state, n/a symmetry, variable-constrained referent}$
     136char * s2 = s;  $\C{// alias state, n/a symmetry, variable-constrained referent}$
     137char * s3 = &s[1];  $\C{// alias state, n/a symmetry, variable-constrained referent}$
     138char * s4 = &s3[1];  $\C{// alias state, n/a symmetry, variable-constrained referent}\CRT$
     139printf( "%s %s %s %s %s\n", s, s1, s2, s3, s4 );
     140$\texttt{\small abcde abcde abcde bcde cde}$
     141\end{cfa}
     142Note, all of these strings rely on the single null termination character at the end of @s@.
     143The issue of symmetry does not apply to C strings because the value and pointer strings are essentially different types, and so this feature is scored as not applicable for C.
     144With the type not managing the text buffer, there is no ownership question, \ie operations on @s1@ or @s2@ never leads to their memory becoming reusable.
     145While @s3@ is a valid C-string that contains a proper substring of @s1@, the @s3@ technique does not constitute having a fragment referent because null termination implies the substring cannot be chosen arbitrarily; the technique works only for suffixes.
     146
     147In \CC, @string@ offers a high-level abstraction.
     148\begin{cfa}
     149string s = "abcde";
     150string & s1 = s;  $\C[2.25in]{// alias state, lax symmetry, variable-constrained referent}$
     151string s2 = s;  $\C{// copy (strict symmetry, variable-constrained referent)}$
     152string s3 = s.substr( 1, 2 );  $\C{// copy (strict symmetry, fragment referent)}$
     153string s4 = s3.substr( 1, 1 );  $\C{// copy (strict symmetry, fragment referent)}$
     154cout << s << ' ' << s1 << ' ' << s2 << ' ' << s3 << ' ' << s4 << endl;
     155$\texttt{\small abcde abcde abcde bc c}$
     156string & s5 = s.substr(2,4);  $\C{// error: cannot point to temporary}\CRT$
     157\end{cfa}
     158The lax symmetry reflects how the validity of @s1@ depends on the content and lifetime of @s@.
     159It is common practice in \CC to use the @s1@-style pass by reference, with the understanding that the callee only use the referenced string for the duration of the call, \ie no side-effect using the parameter.
     160So, when the called function is a constructor, it is typical to use an @s2@-style copy initialization to string-object-typed member.
     161Exceptions to this pattern are possible, but require the programmer to assure safety where the type system does not.
     162The @s3@ initialization is constrained to copy the substring because @c_str@ always provides a null-terminated character, which is different from source string.
     163@s3@ assignment could be fast by reference counting the text area and using copy-on-write, but would require an implementation upgrade.
     164
     165In Java, @String@ also offers a high-level abstraction:
     166\begin{cfa}
     167String s = "abcde";
     168String s1 = s;  $\C[2.25in]{// snapshot state, strict symmetry, variable-constrained referent}$
     169String s2 = s.substring( 1, 3 );  $\C{// snapshot state (possible), strict symmetry, fragment referent}$
     170String s3 = s2.substring( 1, 2 );  $\C{// snapshot state (possible), strict symmetry, fragment referent}\CRT$
     171System.out.println( s + ' ' + s1 + ' ' + s2 + ' ' + s3 );
     172System.out.println( (s == s1) + " " + (s == s2) + " " + (s2 == s3) );
     173$\texttt{\small abcde abcde bc c}$
     174$\texttt{\small true false false}$
     175\end{cfa}
     176Note, @substring@ takes a start and end position, rather than a start position and length.
     177Here, facts about Java's implicit pointers and pointer equality can over complicate the picture, and so are ignored.
     178Furthermore, Java's string immutability means string variables behave as simple values.
     179The result in @s1@ is the pointer in @s@, and their pointer equality confirm no time is spent copying characters.
     180With @s2@, the case for fast-copy is more subtle.
     181Certainly, its value is not pointer-equal to @s@, implying at least a further allocation.
    142182TODO: finish the fast-copy case.
    143 Java strings lacking mutation means that aliasing is not possible with the @String@ type.
     183Java's immutable strings mean aliasing is impossible with the @String@ type.
    144184Java's @StringBuffer@ provides aliasing, though without supporting symmetric treatment of a fragment referent; as a result, @StringBuffer@ scores as \CC.
    145185The easy symmetry that the Java string enjoys is aided by Java's garbage collection; Java's @s2@ is doing effectively the operation of \CC's @s2@, though without the consequence to of complicating memory management.
    146186
    147 Finally, in \CFA,
    148 \begin{cfa}
    149 string s1 = ...; // assumed
    150 string s2 = s1; // snapshot state, strict symmetry, variable-constrained referent
    151 string s3 = s1`shareEdits; // alias state, strict symmetry, variable-constrained referent
    152 string s4 = s1(2,4); // snapshot state, strict symmetry, fragment referent
    153 string s5 = s1(2,4)`shareEdits; // alias state, strict symmetry, fragment referent
    154 \end{cfa}
    155 all helpful criteria of \VRef[Figure]{f:StrSemanticCompare} are satisfied.
    156 The \CFA string manages storage, handles all assignments, including those of fragment referents, with fast initialization, provides the choice between snapshot and alias semantics, does so symmetrically with one type (which assures text validity according to the lifecycles of the string variables).
     187Finally, In \CFA, @string@ also offers a high-level abstraction:
     188\begin{cfa}
     189string s = "abcde";
     190string & s1 = s; $\C[2.25in]{// alias state, strict symmetry, variable-constrained referent}$
     191string s2 = s; $\C{// snapshot state, strict symmetry, variable-constrained referent}$
     192string s3 = s`shareEdits; $\C{// alias state, strict symmetry, variable-constrained referent}\CRT$
     193string s4 = s( 1, 2 );
     194string s5 = s4( 1, 1 );
     195sout | s | s1 | s2 | s3 | s4 | s5;
     196$\texttt{\small abcde abcde abcde abcde bc c}$
     197\end{cfa}
     198% all helpful criteria of \VRef[Figure]{f:StrSemanticCompare} are satisfied.
     199The \CFA string manages storage, handles all assignments, including those of fragment referents with fast initialization, provides the choice between snapshot and alias semantics, and does so symmetrically with one type (which assures text validity according to the lifecycles of the string variables).
    157200With aliasing, the intuition is that each string is an editor on an open shared document.
    158 With fragment aliasing, the intuition is that these editor views have been scolled or zoomed to overlapping, but potentially different, ranges.
     201With fragment aliasing, the intuition is that these editor views have been scrolled or zoomed to overlapping, but potentially different, ranges.
    159202
    160203The remainder of this chapter explains how the \CFA string achieves this usage style.
     
    243286Earlier work on \CFA~\cite[ch.~2]{Schluntz17} implemented object constructors and destructors for all types (basic and user defined).
    244287A constructor is a user-defined function run implicitly \emph{after} an object's declaration-storage is created, and a destructor is a user-defined function run \emph{before} an object's declaration-storage is deleted.
    245 This feature, called RAII~\cite[p.~389]{Stroustrup94}, guarantees pre invariants for users before accessing an object and post invariants for the programming environment after an object terminates.
     288This feature, called RAII~\cite[p.~389]{Stroustrup94}, guarantees pre-invariants for users before accessing an object and post invariants for the programming environment after an object terminates.
    246289
    247290The purposes of these invariants goes beyond ensuring authentic values inside an object.
  • libcfa/prelude/prelude-gen.cc

    r6cb3e5d r6f9f338  
    1010// Created On       : Sat Feb 16 08:44:58 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 13 14:15:29 2025
    13 // Update Count     : 55
     12// Last Modified On : Mon Mar 10 17:30:48 2025
     13// Update Count     : 65
    1414//
    1515
  • libcfa/prelude/prototypes.awk

    r6cb3e5d r6f9f338  
    1010# Created On       : Sat May 16 07:57:37 2015
    1111# Last Modified By : Peter A. Buhr
    12 # Last Modified On : Sat Feb 15 13:16:28 2025
    13 # Update Count     : 60
     12# Last Modified On : Mon Mar 10 17:52:39 2025
     13# Update Count     : 73
    1414#
    1515
     
    160160        printf( "double _Complex __builtin_complex( double, double );\n" );
    161161        printf( "long double _Complex __builtin_complex( long double, long double );\n" );
     162
     163        # assorted gcc builltin types
     164        # ARM vector floating-point types, strip off text "__builtin.*__"
     165        printf( "struct __builtin__Float32x4_t__ {};\n" );
     166        printf( "struct __builtin__Float64x2_t__ {};\n" );
     167        printf( "struct __builtin__SVFloat32_t__ {};\n" );
     168        printf( "struct __builtin__SVFloat64_t__ {};\n" );
     169        printf( "struct __builtin__SVBool_t__ {};\n" );
    162170} # END
    163171
  • src/BasicTypes-gen.cpp

    r6cb3e5d r6f9f338  
    5353        Float128xComplex,
    5454        NUMBER_OF_BASIC_TYPES,
    55 
    56         Float32x4,                                                                                      // ARM, gcc-14
    57         Float64x2,
    58         Svfloat32,
    59         Svfloat64,
    60         Svbool,
    6155};
    6256
  • src/Common/Iterate.hpp

    r6cb3e5d r6f9f338  
    208208        return group_iterate_t<Args...>( std::forward<Args>( args )... );
    209209}
    210 
    211 // -----------------------------------------------------------------------------
    212 // Helper struct and function to support
    213 // for ( val : lazy_map( container1, f ) ) {}
    214 // syntax to have a for each that iterates a container,
    215 // mapping each element by applying f.
    216 
    217 template< typename T, typename Func >
    218 struct lambda_iterate_t {
    219         const T & ref;
    220         std::function<Func> f;
    221 
    222         struct iterator {
    223                 typedef decltype(begin(ref)) Iter;
    224                 Iter it;
    225                 std::function<Func> f;
    226                 iterator( Iter it, std::function<Func> f ) : it(it), f(f) {}
    227                 iterator & operator++() {
    228                         ++it; return *this;
    229                 }
    230                 bool operator!=( const iterator &other ) const { return it != other.it; }
    231                 auto operator*() const -> decltype(f(*it)) { return f(*it); }
    232         };
    233 
    234         lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {}
    235 
    236         auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }
    237         auto end() const   -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }
    238 };
    239 
    240 template< typename... Args >
    241 lambda_iterate_t<Args...> lazy_map( const Args &... args ) {
    242         return lambda_iterate_t<Args...>( args...);
    243 }
    244 
    245 // Local Variables: //
    246 // tab-width: 4 //
    247 // mode: c++ //
    248 // compile-command: "make install" //
    249 // End: //
  • src/GenPoly/InstantiateGeneric.cpp

    r6cb3e5d r6f9f338  
    1010// Created On       : Tue Aug 16 10:51:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Oct 31 16:48:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Wed Mar 12 15:18:00 2025
     13// Update Count     : 2
    1414//
    1515
     
    159159}
    160160
     161/// Get the scrubbed type of a declaration (see scrubTypeVars functions).
     162ast::TypeExpr const * scrubTypeDecl(
     163                CodeLocation const & location, ast::TypeDecl const * typeDecl ) {
     164        switch ( typeDecl->kind ) {
     165        // Erase any incomplete dtype to `void` (`T *` -> `void *`).
     166        case ast::TypeDecl::Dtype:
     167                return new ast::TypeExpr( location, new ast::VoidType() );
     168        // Erase any ftype to `void (*)(void)`.
     169        case ast::TypeDecl::Ftype:
     170                return new ast::TypeExpr( location, new ast::FunctionType() );
     171        // Remaining cases are not supported.
     172        case ast::TypeDecl::Ttype:
     173                assertf( false, "Ttype parameters are not currently allowed as parameters to generic types." );
     174                break;
     175        default:
     176                assertf( false, "Unhandled type parameter kind" );
     177                break;
     178        }
     179}
     180
    161181/// Makes substitutions of params into baseParams; returns dtypeStatic if
    162182/// there is a concrete instantiation based only on {d,f}type-to-void
     
    190210                                gt |= GenericType::concrete;
    191211                        }
    192                 } else switch ( (*baseParam)->kind ) {
    193                 case ast::TypeDecl::Dtype:
    194                         // Here, pretend that any incomplete dtype is `void`.
    195                         out.emplace_back( new ast::TypeExpr( paramExpr->location,
    196                                 new ast::VoidType() ) );
    197                         break;
    198                 case ast::TypeDecl::Ftype:
    199                         // Here, pretend that any ftype is `void (*)(void)`.
    200                         out.emplace_back( new ast::TypeExpr( paramExpr->location,
    201                                 new ast::FunctionType() ) );
    202                         break;
    203                 case ast::TypeDecl::Ttype:
    204                         assertf( false, "Ttype parameters are not currently allowed as parameters to generic types." );
    205                         break;
    206                 default:
    207                         assertf( false, "Unhandled type parameter kind" );
    208                         break;
     212                } else {
     213                        out.emplace_back( scrubTypeDecl( paramExpr->location, *baseParam ) );
    209214                }
    210215        }
     
    443448                instantiations(), dtypeStatics(), typeNamer("_conc_") {}
    444449
     450        ast::StructDecl const * previsit( ast::StructDecl const * );
     451        ast::UnionDecl const * previsit( ast::UnionDecl const * );
     452
    445453        ast::Type const * postvisit( ast::StructInstType const * inst );
    446454        ast::Type const * postvisit( ast::UnionInstType const * inst );
     
    481489
    482490        template<typename AggrDecl>
     491        AggrDecl const * fixAggrDecl( AggrDecl const * decl );
     492
     493        template<typename AggrDecl>
    483494        ast::Type const * fixInstType( ast::SueInstType<AggrDecl> const * inst );
    484495
     
    489500                ast::vector<ast::TypeExpr> const & typeSubs );
    490501};
     502
     503ast::StructDecl const * GenericInstantiator::previsit( ast::StructDecl const * decl ) {
     504        return fixAggrDecl( decl );
     505}
     506
     507ast::UnionDecl const * GenericInstantiator::previsit( ast::UnionDecl const * decl ) {
     508        return fixAggrDecl( decl );
     509}
     510
     511template<typename AggrDecl>
     512AggrDecl const * GenericInstantiator::fixAggrDecl( AggrDecl const * decl ) {
     513        // This function and stripDtypeParams handle declarations before their
     514        // first use (required to be in the previsit for types with a self use).
     515        if ( decl->params.empty() || !isDtypeStatic( decl->params ) ) {
     516                return decl;
     517        }
     518
     519        ast::vector<ast::TypeExpr> typeSubs;
     520        for ( auto const & param : decl->params ) {
     521                assert( !param->isComplete() );
     522                typeSubs.emplace_back( scrubTypeDecl( param->location, param ) );
     523        }
     524
     525        assert( decl->unique() );
     526        auto mutDecl = ast::mutate( decl );
     527        stripDtypeParams( mutDecl, mutDecl->params, typeSubs );
     528
     529        return mutDecl;
     530}
    491531
    492532ast::Type const * GenericInstantiator::postvisit(
     
    531571        case GenericType::dtypeStatic:
    532572        {
     573                // This call to stripDtypeParams is used when a forward declaration
     574                // has allowed an instance to appear before the full declaration.
    533575                auto mutInst = ast::mutate( inst );
    534576                assert( mutInst->base->unique() );
  • src/Parser/parser.yy

    r6cb3e5d r6f9f338  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Mar  2 18:46:32 2025
    13 // Update Count     : 7253
     12// Last Modified On : Thu Mar 13 09:23:21 2025
     13// Update Count     : 7255
    1414//
    1515
     
    16241624                { SemanticError( yylloc, "illegal syntax, missing low/high value for ascending/descending range so index is uninitialized." ); $$ = nullptr; }
    16251625
    1626         | comma_expression ';' type_type_specifier                                              // CFA, enum type
     1626        | comma_expression ';' type_type_specifier                      // CFA, enum type
    16271627                {
    16281628                        $$ = enumRangeCtrl( $1, OperKinds::LEThan, new ExpressionNode( new ast::TypeExpr( yylloc, $3->clone()->buildType() ) ), $3 );
  • tests/include/includes.cfa

    r6cb3e5d r6f9f338  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 22 10:16:58 2023
    13 // Update Count     : 811
     12// Last Modified On : Thu Mar 13 11:56:08 2025
     13// Update Count     : 831
    1414//
    1515
     
    6363#include <ftw.h>
    6464#include <sys/types.h>
    65 //#include <gawkapi.h>                                                                  // CFA bug #240 nested anonymous enum fails
    6665#include <gconv.h>
    6766#include <getopt.h>
     
    7271#include <gshadow.h>
    7372#include <iconv.h>
    74 //#include <ifaddrs.h>                                                                  // causes warning messages that break the build
     73#include <ifaddrs.h>
    7574#include <inttypes.h>
    7675#include <langinfo.h>
     
    7978#include <libintl.h>
    8079#include <limits.h>
    81 //#include <link.h>                                                                             // CFA bug #240 nested anonymous enum fails
     80#include <link.h>
    8281#include <locale.h>
    8382#if __has_include( "ltdl.h" )
     
    9796#include <ncurses_dll.h>                                                                // may not be installed, comes with ncurses
    9897#endif
    99 //#include <netdb.h>
     98#include <netdb.h>
    10099#include <nl_types.h>
    101100#include <nss.h>
     
    111110#include <pwd.h>
    112111#include <regex.h>
    113 //#include <resolv.h>
     112#include <resolv.h>
    114113#include <re_comp.h>
    115114#include <sched.h>
     
    125124#include <stdint.h>
    126125#include <stdio.h>
     126#if __has_include( "gawkapi.h" )
     127#include <gawkapi.h>                                                                    // requires stdio.h, so appears after it
     128#endif
    127129#include <stdio_ext.h>
    128130#include <stdlib.h>
     
    140142#include <termio.h>
    141143#include <termios.h>
    142 // #include <term_entry.h>                                                              // conflicts with search.h on some machines
     144#include <term_entry.h>
    143145#include <tgmath.h>
    144 //#include <threads.h>                                                                  // does not exist
     146#include <threads.h>                                                                    // does not exist
    145147#include <thread_db.h>
    146148#include <time.h>
Note: See TracChangeset for help on using the changeset viewer.