Changes in / [67fa9f9:11dbfe1]


Ignore:
Files:
1 added
7 deleted
65 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    r67fa9f9 r11dbfe1  
    5454doc/user/pointer1.tex
    5555doc/user/pointer2.tex
    56 doc/user/EHMHierarchy.tex
  • doc/LaTeXmacros/lstlang.sty

    r67fa9f9 r11dbfe1  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Thu Jun 22 07:40:31 2017
    11 %% Update Count     : 10
     10%% Last Modified On : Fri May 26 12:47:09 2017
     11%% Update Count     : 8
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    116116                _Atomic, coroutine, is_coroutine, is_monitor, is_thread, monitor, mutex, nomutex,
    117117                resume, suspend, thread, _Thread_local, yield},
    118         moredirectives={defined,include_next}%
    119118}
    120119
  • doc/generic_types/mail

    r67fa9f9 r11dbfe1  
    7878
    7979- OOPSLA'17 Submissions
    80 
    81 
    82 
    83 From: "OOPSLA'17 HotCRP" <noreply@oopsla17.hotcrp.com>
    84 Subject: [OOPSLA'17] Paper #20 "Generic and Tuple Types with Efficient..."
    85 To: Peter Buhr <pabuhr@uwaterloo.ca>
    86 Cc: jonathan.aldrich@cs.cmu.edu
    87 Reply-To: jonathan.aldrich@cs.cmu.edu
    88 Date: Wed,  7 Jun 2017 13:33:40 +0000 (UTC)
    89 
    90 Dear Peter Buhr,
    91 
    92 The author response period for OOPSLA has started, and will continue until
    93 the end of June 10th (Anywhere on Earth).  No email with a snapshot of your
    94 reviews will be sent: you can see the live version of reviews (including
    95 current updates) on the HotCRP system (links at the bottom).
    96 
    97 An author response should aim to:
    98  -correct reviewers' mistakes or misunderstandings
    99  -offer new information only when this addresses reviewers' concerns (e.g.,
    100 "I wonder if A might work better...";  "we tried that, but...")
    101  -answer explicit questions by the reviewers. The key questions will be in a
    102 designated "Questions for Author Response" entry of a review.
    103 
    104 Please keep in mind that an author response is *not* a "rebuttal". You are
    105 not rebutting an opponent's arguments with your own, in front of an
    106 audience that weighs both sets of arguments. Instead, your audience is the
    107 same reviewers who offered the comments in the first place, and their
    108 subjective weighing of different factors is very unlikely to change.
    109 
    110 During author response, please keep in mind that the reviewers are still
    111 unaware of author identity. If you need to refer to author-identifying
    112 information during your response, the ideal course of action is to place it
    113 at an external location and include a URL, with an explicit warning (e.g.,
    114 "WARNING: following this link will reveal author identity").
    115 
    116 As with all external resources, your response should be self-contained,
    117 without consulting them. That is, the author-visible external URL is just
    118 evidence, but the claim that this evidence supports should be clear in the
    119 response text. For instance:
    120 "we have received public feedback from the developers of X that confirm the
    121 issue [supporting URL] (WARNING: following this link will reveal author
    122 identity)"
    123 
    124 Your paper's access information is below:
    125 
    126        Title: Generic and Tuple Types with Efficient Dynamic Layout in C∀
    127   Paper site: https://oopsla17.hotcrp.com/paper/20
    128 
    129 Use the link below to sign in to the site.
    130 
    131 https://oopsla17.hotcrp.com/?email=pabuhr%40uwaterloo.ca
    132 
    133 Please contact me <jonathan.aldrich@cs.cmu.edu> with any questions or
    134 concerns.
    135 
    136 Best Regards and wishes for a constructive response,
    137 
    138 Jonathan Aldrich
    139 
    140 
    141 
    142 From: "OOPSLA'17 HotCRP" <noreply@oopsla17.hotcrp.com>
    143 Subject: [OOPSLA'17] Paper #20 "Generic and Tuple Types with Efficient..."
    144 To: Peter Buhr <pabuhr@uwaterloo.ca>
    145 Cc: jonathan.aldrich@cs.cmu.edu
    146 Reply-To: jonathan.aldrich@cs.cmu.edu
    147 Date: Tue, 20 Jun 2017 00:33:10 +0000 (UTC)
    148 
    149 Dear Peter Buhr,
    150 
    151 I regret to inform you that your submission to OOPSLA'17 listed below has not
    152 been selected for the second phase of the review process. I understand this is
    153 not welcome news but selection was very competitive: 157 of the 223 papers
    154 submitted did not advance to the second phase. For several of these, there was
    155 a clear impression that in the future they can evolve into some of the
    156 strongest results of our community.
    157 
    158        Title: Generic and Tuple Types with Efficient Dynamic Layout in C∀
    159   Paper site: https://oopsla17.hotcrp.com/paper/20
    160   Login link: https://oopsla17.hotcrp.com/?email=pabuhr%40uwaterloo.ca
    161 
    162 Below you will find reviews, as well as author-visible comments--the latter may
    163 include further communication. I hope you will find the reviewers' feedback
    164 useful.
    165 
    166 Best Regards,
    167 
    168 - Jonathan Aldrich <jonathan.aldrich@cs.cmu.edu>, for OOPSLA 2017
    169 Submissions
    170 
    171 
    172 
    173 ===========================================================================
    174                            OOPSLA'17 Review #20A
    175 ---------------------------------------------------------------------------
    176  Paper #20: Generic and Tuple Types with Efficient Dynamic Layout in C∀
    177 ---------------------------------------------------------------------------
    178 
    179                       Overall merit: C. Weak paper, though I will not fight
    180                                         strongly against it
    181                          Confidence: X. I am an expert in this area
    182 
    183                          ===== Paper summary =====
    184 
    185 This presents an extension of the C programming language that tries to preserve the character of the existing language, while adding tuples and generics. Unlike C++ templates, generics preserve separate compilation. Types are represented at runtime, if needed, by size and alignment values, along with pointers to the code for any needed operators. A microbenchmark performance comparison is provided.
    186 
    187                       ===== Comments for author =====
    188 
    189 This is an interesting extension to C, that may be of interest to some C programmers. It generally seems to be fairly well engineered, and mostly respects C's design goals.
    190 
    191 Unfortunately, there have been enough proposals for extended C dialects that this sort of design is tough to sell. And I don't think the evaluation really went far enough to make that case.
    192 
    193 The ideas in the paper don't appear to be fundamentally new. The idea of passing types as runtime objects has certainly been explored before. An additional ancient reference is http://dl.acm.org/citation.cfm?doid=13310.13330.
    194 
    195 There seems to be a new idea of minimally describing types using alignment and size attributes instead of (?) pointers to assignment operators and the like. But this scheme is not very well described. Notably, it is not clear how, say, a struct with atomic field or bit-fields would be described.
    196 
    197 I wasn't quite clear on the extent to which operator overloading is supported. The MAX example appears to me like it would be quite controversial among C programmers.
    198 
    199 It is not obvious that type inference here always converges. An outline of the algorithm would be useful.
    200 
    201 Above all, this needs experience results from a more complete implementation.
    202 
    203 Details:
    204 
    205 Relying on TIOBE here seems a bit dubious. Since it counts web pages, and C isn't exactly new and hot, it may actually understate your case.
    206 
    207 The print example seems a little simplistic, since it's not clear how it handles formatting.
    208 
    209 "does not using the return type"
    210 
    211               ===== Questions for authors’ response =====
    212 
    213 How are atomics, volatile, and bit-fields in structs handled?
    214 
    215 ===========================================================================
    216                            OOPSLA'17 Review #20B
    217 ---------------------------------------------------------------------------
    218  Paper #20: Generic and Tuple Types with Efficient Dynamic Layout in C∀
    219 ---------------------------------------------------------------------------
    220 
    221                       Overall merit: D. Reject
    222                          Confidence: X. I am an expert in this area
    223 
    224                          ===== Paper summary =====
    225 
    226 The authors present an extension to C, adding universal polymorphism and tuples. These features are described in prose. There is an implementation, though this is not described in depth in the paper. There is a benchmark evaluation.
    227 
    228                       ===== Comments for author =====
    229 
    230 The paper is well-written and the concepts explained well. It is nice to see work in the low-level/C space - I believe that it is an area that has not been well-served by the OOPSLA community. My concerns with the paper are that the contribution is rather small and the concepts are not well-evaluated; specifically this is a language design paper and there is no attempt to evaluate the actual language design.
    231 
    232 While it is reasonable to describe only a couple of features in a paper, I would then expect a detailed description of the implementation and/or a formalism with proven safety properties and a thorough evaluation of the design. For a paper which only describes the design of a language the bar is higher than two features - for example, a description of a 'large' language such as D or Rust, even then I would expect a stronger evaluation.
    233 
    234 ## On the design of C-forall
    235 
    236 There are some interesting points in the design of generics, notably the otype/dtype distinction. The design seems reasonable and follows what I would expect from other languages. The design for tuples is more unusual - the usual design of simple anonymous records with anonymous fields is extended with a mix of 'spread'ing, variadics, and implicit conversions. Importantly, the authors neither justify nor evaluate this departure - that is a severe omission for this paper. Furthermore, the only in-depth description of the implementation in the paper concerns tuples, and it seems to me that this is only interesting because of the unusual design - further reason for justifying it.
    237 
    238 ## Evaluation
    239 
    240 The paper evaluates the implementation of C-forall with (effectively) a single micro-benchmark. That benchmark seems to show that C-forall performs worse than C++ on every measure, but this is not really discussed.
    241 
    242 A better performance evaluation would consist of multiple tests, both micro-benchmarks and realistic code and would test C-forall compared to alternatives (D, Rust, Go, etc.) not just C/C++.
    243 
    244 However, performance is not the really interesting thing to test here. The authors propose a new language and while performance is an important consideration for systems languages, it is far from the most important. I would like to see the usability of the language tested with user studies of different kinds (various levels of skill-level and coding scenarios). The authors could also use case studies or programming idioms to compare programming in C-forall vs the alternatives (again, comparing with D, Rust, etc. is more interesting to me than C).
    245 
    246 Finally, in designing C-forall, the authors make several assumptions about why C programmers use C. These should be backed up either with evaluation or citation. Statements in the paper certainly do not reflect my experience discussing language design with C programmers, and I would like to see them verified.
    247 
    248 
    249 ## Related work
    250 
    251 The related work section is broad and gives good descriptions of other languages. However, the comparisons between languages focus more on the high-level goals of the language. It would be more interesting to focus on the details of the languages - the comparisons between Cyclone, C++, Java, and C-forall generics are good, I would like to see more of this with D and Rust, which are the more modern alternatives to C-forall (for example, Rust's notion of Sized and ?Sized types seems similar to otypes/dtypes).
    252 
    253 The related work is really missing any discussion of why the C-forall design choices are better than other languages. To clarify, I mean the specific design of generics and tuples, c.f., the suitability of the language in general because of garbage collection or learning difficulties.
    254 
    255 ===========================================================================
    256                            OOPSLA'17 Review #20C
    257 ---------------------------------------------------------------------------
    258  Paper #20: Generic and Tuple Types with Efficient Dynamic Layout in C∀
    259 ---------------------------------------------------------------------------
    260 
    261                       Overall merit: D. Reject
    262                          Confidence: Z. I am not an expert; my evaluation
    263                                         is that of an informed outsider
    264 
    265                          ===== Paper summary =====
    266 
    267 The paper presents two language features of "Cforall": generics and tuples.
    268 
    269                       ===== Comments for author =====
    270 
    271 The authors really need to talk about C++ as early as possible IMHO. That's the first thing that came to mind when reading the abstract: how is this different from C++?
    272 
    273 Comparison with C++:
    274 The main difference with C++ seems to be that Cforall favors separate compilation at the expense of runtime overhead while C++ systematically avoids any runtime overhead (at the expense of slow compilation times). C++ approach makes more sense IMHO. While it's true that people where using C for almost everything 30 years ago, that is just not true anymore. Most people writing C today are doing system programming, otherwise there would be using a higher level programming language (C#, Java etc ...).
    275 Now, when doing system programming, one needs very fine grain control over the resources: memory layout, etc ...
    276 It is pretty clear to me that the people writing that kind of code will favor generics that do not cost any overhead at runtime, otherwise they would be writing Java in the first place.
    277 The authors need to better justify the runtime overhead, or give escape hatches for those who don't want to pay that cost at runtime.
    278 They very often go back to the benefit of separate compilation, but that's not enough IMHO. Here is a proposal: why not have 2 modes, one called debug mode, used while developing the code, that would compile generics with a runtime overhead. Another, called production, that would unfold the world like C++ does?
    279 
    280 About Tuples:
    281 The section about tuples is too long. I would have spent more time explaining generics.
    282 
    283 Feedback:
    284 "This installation base"
    285 Unclear what you mean by that.
    286 
    287 "Prior projects ... but failed ..."
    288 Hummm ... What about C++.
    289 
    290 "... object-oriented or functional programming with garbage collection ..."
    291 You are really mixing apples and oranges here. Many C programmers have nothing agains object-oriented features, not even functional programming (C++ 11 adds
    292 a bunch of features proving my point), but it's clear that most of them feel very strongly against automated garbage collection.
    293 
    294 "In many cases, C++ is often ..."
    295 This sentence feels like it is coming out of nowhere.
    296 
    297 "... the polymorphic runtime-cost ..."
    298 Is there any way to avoid that overhead? It's true it will make the compiler faster, but there are cases where the user might not want to pay for
    299 the overhead at runtime. Is there a way to force the compiler to specialize the code?
    300 
    301 "... to write a type-safe Cforall wrapper malloc based ..."
    302 That cannot be true in general. Malloc produces a pointer (of any type), given an integer (the size).
    303 It looks like Cforall is assuming that the integer is the result of a call to sizeof (a good practice in C).
    304 However, if that's the case, it should be explained.
    305 
    306 "... allows variable overloading ..."
    307 How are conflict resolved? In other words, what happens when two variables could be used?
    308 
    309 "... reuses the generated structure declarations where appropriate."
    310 This is too vague.
    311 
    312 "... have multiple outcomes, some exceptional."
    313 Humm, I would say these two things are distinct. Let's just way that this way of presenting things is strange, I woulds ay that a function can either
    314 return one or multiple values or throw an exception. Not that some of the values returned are "exceptional".
    315 
    316 "The type-resolver ..."
    317 What's that? Type-checker? Type-inference?
    318 
    319 "... applies C conversions."
    320 Noooo! That's exactly what leads to very subtle bugs. Is there any way to stop those conversions from happening?
    321 
    322 "The minimal cost ..."
    323 In what regard? Runtime cost? How does the "resolver" know how expensive the conversions are?
    324 
    325 "z = 10 // mass assignments"
    326 That stuff is completely unreadable. Why not introduce a new operator?
    327 
    328 "... roughly equivalent time ..."
    329 Well, C++ looks faster to me.
    330 
    331 "... is restricted because the resolution does not using ..."
    332 Did you mean, does not use?
    333 
    334 "... D and go are garbage collected ..."
    335 Yes, but in D, the use of the GC is optional.
    336 
    337 "... while respecting the talent and skill of C programmers."
    338 Are you implying that other approaches are not?
    339 
    340 "On the surface, the project may appear as a rehash of similar mechanisms in C++."
    341 Absolutely.
    342 
    343 "... integration with C and its programmers ..."
    344 Bold claim. What makes you think you are integrated with programmers? Number of users?
    345 
    346 "... inline annotation at polymorphic function call sites to create a template-specialization ..."
    347 This should have been mentioned sooner. Plus conflating inlining and specialization is unfortunate.
    348 Does "inline" also inline the function? Or does it only specialize the code?
    349 If it also inline, that's a very unfortunate design. I might want to specialize the code, but without inlining ...
    350 How do I specialize a recursive function?
  • doc/proposals/references.md

    r67fa9f9 r11dbfe1  
    1717derived rvalue types such as pointer types may include qualifiers;
    1818`const int *` is a distinct type from `int *`, though the latter is safely
    19 convertible to the former.
     19convertable to the former.
    2020In general, any number of qualifiers can be safely added to the
    2121pointed-to-type of a pointer type, e.g. `int *` converts safely to
     
    2323`const volatile int *`.
    2424
    25 Since lvalues are precisely "addressable objects", in C, only lvalues can be
     25Since lvalues are precicely "addressable objects", in C, only lvalues can be
    2626used as the operand of the `&` address-of operator.
    2727Similarly, only modifiable lvalues may be used as the assigned-to
     
    147147call "lvalue of type `T`" as `T&`.
    148148There's also an obvious argument that lvalues of a (possibly-qualified) type
    149 `T` should be convertible to references of type `T`, where `T` is also
     149`T` should be convertable to references of type `T`, where `T` is also
    150150so-qualified (e.g. lvalue `int` to `int&`, lvalue `const char` to
    151151`const char&`).
    152152By similar arguments to pointer types, qualifiers should be addable to the
    153153referred-to type of a reference (e.g. `int&` to `const int&`).
    154 As a note, since pointer arithmetic is explicitly not defined on `T&`,
     154As a note, since pointer arithmetic is explictly not defined on `T&`,
    155155`restrict T&` should be allowable and would have alias-analysis rules that
    156156are actually comprehensible to mere mortals.
  • doc/user/Makefile

    r67fa9f9 r11dbfe1  
    1212
    1313FIGURES = ${addsuffix .tex, \
    14 EHMHierarchy \
    1514Cdecl \
    1615pointer1 \
  • doc/user/user.tex

    r67fa9f9 r11dbfe1  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Jul  2 09:49:56 2017
    14 %% Update Count     : 2503
     13%% Last Modified On : Fri Jun 16 12:00:01 2017
     14%% Update Count     : 2433
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    2525\usepackage{textcomp}
    2626\usepackage[latin1]{inputenc}
     27% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     28% removes it as a variable-name character so keyworks in variables are highlighted
     29\DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}
     30
    2731
    2832\usepackage{fullpage,times,comment}
     
    4448\renewcommand{\UrlFont}{\small\sf}
    4549
    46 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    47 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    48 % AFTER HYPERREF.
    49 \renewcommand{\_}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    50 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    51 
    5250\setlength{\topmargin}{-0.45in}                                                 % move running title into header
    5351\setlength{\headsep}{0.25in}
     
    112110\renewcommand{\subsectionmark}[1]{\markboth{\thesubsection\quad #1}{\thesubsection\quad #1}}
    113111\pagenumbering{roman}
    114 \linenumbers                                            % comment out to turn off line numbering
     112%\linenumbers                                            % comment out to turn off line numbering
    115113
    116114\maketitle
     
    479477#endif // ! otype
    480478
    481 #®include_next® <bfd.h>                 §\C{// must have internal check for multiple expansion}§
     479#include_next <bfd.h>                   §\C{// must have internal check for multiple expansion}§
    482480
    483481#if defined( otype ) && defined( __CFA_BFD_H__ )        §\C{// reset only if set}§
     
    489487\label{f:InterpositionHeaderFile}
    490488\end{figure}
     489
     490
     491\section{Declarations}
     492\label{s:Declarations}
     493
     494C declaration syntax is notoriously confusing and error prone.
     495For example, many C programmers are confused by a declaration as simple as:
     496\begin{quote2}
     497\begin{tabular}{@{}ll@{}}
     498\begin{cfa}
     499int * x[5]
     500\end{cfa}
     501&
     502\raisebox{-0.75\totalheight}{\input{Cdecl}}
     503\end{tabular}
     504\end{quote2}
     505Is this an array of 5 pointers to integers or a \Index{pointer} to an array of 5 integers?
     506The fact this declaration is unclear to many C programmers means there are \Index{productivity} and \Index{safety} issues even for basic programs.
     507Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site.
     508For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
     509\begin{cfa}
     510int ®(*®f®())[®5®]® {...};                              §\C{definition}§
     511 ... ®(*®f®())[®3®]® += 1;                              §\C{usage}§
     512\end{cfa}
     513Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
     514While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
     515
     516\CFA provides its own type, variable and routine declarations, using a different syntax.
     517The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type.
     518In the following example, \R{red} is the base type and \B{blue} is qualifiers.
     519The \CFA declarations move the qualifiers to the left of the base type, \ie move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type.
     520\begin{quote2}
     521\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     522\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     523\begin{cfa}
     524ß[5] *ß ®int® x1;
     525ß* [5]ß ®int® x2;
     526ß[* [5] int]ß f®( int p )®;
     527\end{cfa}
     528&
     529\begin{cfa}
     530®int® ß*ß x1 ß[5]ß;
     531®int® ß(*ßx2ß)[5]ß;
     532ßint (*ßf®( int p )®ß)[5]ß;
     533\end{cfa}
     534\end{tabular}
     535\end{quote2}
     536The only exception is \Index{bit field} specification, which always appear to the right of the base type.
     537% Specifically, the character ©*© is used to indicate a pointer, square brackets ©[©\,©]© are used to represent an array or function return value, and parentheses ©()© are used to indicate a routine parameter.
     538However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
     539For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows:
     540\begin{quote2}
     541\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     542\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     543\begin{cfa}
     544®*® int x, y;
     545\end{cfa}
     546&
     547\begin{cfa}
     548int ®*®x, ®*®y;
     549\end{cfa}
     550\end{tabular}
     551\end{quote2}
     552The downside of this semantics is the need to separate regular and \Index{pointer} declarations:
     553\begin{quote2}
     554\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     555\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     556\begin{cfa}
     557®*® int x;
     558int y;
     559\end{cfa}
     560&
     561\begin{cfa}
     562int ®*®x, y;
     563
     564\end{cfa}
     565\end{tabular}
     566\end{quote2}
     567which is \Index{prescribing} a safety benefit.
     568Other examples are:
     569\begin{quote2}
     570\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
     571\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     572\begin{cfa}
     573[ 5 ] int z;
     574[ 5 ] * char w;
     575* [ 5 ] double v;
     576struct s {
     577        int f0:3;
     578        * int f1;
     579        [ 5 ] * int f2;
     580};
     581\end{cfa}
     582&
     583\begin{cfa}
     584int z[ 5 ];
     585char * w[ 5 ];
     586double (* v)[ 5 ];
     587struct s {
     588        int f0:3;
     589        int * f1;
     590        int * f2[ 5 ]
     591};
     592\end{cfa}
     593&
     594\begin{cfa}
     595// array of 5 integers
     596// array of 5 pointers to char
     597// pointer to array of 5 doubles
     598
     599// common bit field syntax
     600
     601
     602
     603\end{cfa}
     604\end{tabular}
     605\end{quote2}
     606
     607All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg:
     608\begin{quote2}
     609\begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
     610\multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
     611\begin{cfa}
     612const * const int x;
     613const * [ 5 ] const int y;
     614\end{cfa}
     615&
     616\begin{cfa}
     617int const * const x;
     618const int (* const y)[ 5 ]
     619\end{cfa}
     620&
     621\begin{cfa}
     622// const pointer to const integer
     623// const pointer to array of 5 const integers
     624\end{cfa}
     625\end{tabular}
     626\end{quote2}
     627All declaration qualifiers, \eg ©extern©, ©static©, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier}
     628The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg:
     629\begin{quote2}
     630\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
     631\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     632\begin{cfa}
     633extern [ 5 ] int x;
     634static * const int y;
     635\end{cfa}
     636&
     637\begin{cfa}
     638int extern x[ 5 ];
     639const int static * y;
     640\end{cfa}
     641&
     642\begin{cfa}
     643// externally visible array of 5 integers
     644// internally visible pointer to constant int
     645\end{cfa}
     646\end{tabular}
     647\end{quote2}
     648
     649The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©:
     650\begin{quote2}
     651\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     652\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     653\begin{cfa}
     654y = (®* int®)x;
     655i = sizeof(®[ 5 ] * int®);
     656\end{cfa}
     657&
     658\begin{cfa}
     659y = (®int *®)x;
     660i = sizeof(®int * [ 5 ]®);
     661\end{cfa}
     662\end{tabular}
     663\end{quote2}
     664
     665Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
     666Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
     667Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX systems.
     668
     669
     670\section{Pointer/Reference}
     671
     672C provides a \newterm{pointer type};
     673\CFA adds a \newterm{reference type}.
     674These types may be derived from an object or routine type, called the \newterm{referenced type}.
     675Objects of these types contain an \newterm{address}, which is normally a location in memory, but may also address memory-mapped registers in hardware devices.
     676An integer constant expression with the value 0, or such an expression cast to type ©void *©, is called a \newterm{null-pointer constant}.\footnote{
     677One way to conceptualize the null pointer is that no variable is placed at this address, so the null-pointer address can be used to denote an uninitialized pointer/reference object;
     678\ie the null pointer is guaranteed to compare unequal to a pointer to any object or routine.}
     679An address is \newterm{sound}, if it points to a valid memory location in scope, \ie within the program's execution-environment and has not been freed.
     680Dereferencing an \newterm{unsound} address, including the null pointer, is \Index{undefined}, often resulting in a \Index{memory fault}.
     681
     682A program \newterm{object} is a region of data storage in the execution environment, the contents of which can represent values.
     683In most cases, objects are located in memory at an address, and the variable name for an object is an implicit address to the object generated by the compiler and automatically dereferenced, as in:
     684\begin{quote2}
     685\begin{tabular}{@{}ll@{\hspace{2em}}l@{}}
     686\begin{cfa}
     687int x;
     688x = 3;
     689int y;
     690y = x;
     691\end{cfa}
     692&
     693\raisebox{-0.45\totalheight}{\input{pointer1}}
     694&
     695\begin{cfa}
     696int * ®const® x = (int *)100
     697*x = 3;                 // implicit dereference
     698int * ®const® y = (int *)104;
     699*y = *x;                // implicit dereference
     700\end{cfa}
     701\end{tabular}
     702\end{quote2}
     703where the right example is how the compiler logically interprets the variables in the left example.
     704Since a variable name only points to one address during its lifetime, it is an \Index{immutable} \Index{pointer};
     705hence, the implicit type of pointer variables ©x© and ©y© are constant pointers in the compiler interpretation.
     706In general, variable addresses are stored in instructions instead of loaded from memory, and hence may not occupy storage.
     707These approaches are contrasted in the following:
     708\begin{quote2}
     709\begin{tabular}{@{}l|l@{}}
     710\multicolumn{1}{c|}{explicit variable address} & \multicolumn{1}{c}{implicit variable address} \\
     711\hline
     712\begin{cfa}
     713lda             r1,100                  // load address of x
     714ld               r2,(r1)                  // load value of x
     715lda             r3,104                  // load address of y
     716st               r2,(r3)                  // store x into y
     717\end{cfa}
     718&
     719\begin{cfa}
     720
     721ld              r2,(100)                // load value of x
     722
     723st              r2,(104)                // store x into y
     724\end{cfa}
     725\end{tabular}
     726\end{quote2}
     727Finally, the immutable nature of a variable's address and the fact that there is no storage for the variable pointer means pointer assignment\index{pointer!assignment}\index{assignment!pointer} is impossible.
     728Therefore, the expression ©x = y© has only one meaning, ©*x = *y©, \ie manipulate values, which is why explicitly writing the dereferences is unnecessary even though it occurs implicitly as part of \Index{instruction decoding}.
     729
     730A \Index{pointer}/\Index{reference} object is a generalization of an object variable-name, \ie a mutable address that can point to more than one memory location during its lifetime.
     731(Similarly, an integer variable can contain multiple integer literals during its lifetime versus an integer constant representing a single literal during its lifetime, and like a variable name, may not occupy storage if the literal is embedded directly into instructions.)
     732Hence, a pointer occupies memory to store its current address, and the pointer's value is loaded by dereferencing, \eg:
     733\begin{quote2}
     734\begin{tabular}{@{}l@{\hspace{2em}}l@{}}
     735\begin{cfa}
     736int x, y, ®*® p1, ®*® p2, ®**® p3;
     737p1 = ®&®x;               // p1 points to x
     738p2 = p1;                 // p2 points to x
     739p1 = ®&®y;               // p1 points to y
     740p3 = &p2;               // p3 points to p2
     741\end{cfa}
     742&
     743\raisebox{-0.5\totalheight}{\input{pointer2.pstex_t}}
     744\end{tabular}
     745\end{quote2}
     746
     747Notice, an address has a \Index{duality}\index{address!duality}: a location in memory or the value at that location.
     748In many cases, a compiler might be able to infer the best meaning for these two cases.
     749For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage
     750\begin{cfa}
     751p2 = p1 + x;                                    §\C{// compiler infers *p2 = *p1 + x;}§
     752\end{cfa}
     753Algol68 infers the following dereferencing ©*p2 = *p1 + x©, because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation.
     754Unfortunately, automatic dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices.
     755
     756Rather than inferring dereference, most programming languages pick one implicit dereferencing semantics, and the programmer explicitly indicates the other to resolve address-duality.
     757In C, objects of pointer type always manipulate the pointer object's address:
     758\begin{cfa}
     759p1 = p2;                                                §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
     760p2 = p1 + x;                                    §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
     761\end{cfa}
     762even though the assignment to ©p2© is likely incorrect, and the programmer probably meant:
     763\begin{cfa}
     764p1 = p2;                                                §\C{// pointer address assignment}§
     765®*®p2 = ®*®p1 + x;                              §\C{// pointed-to value assignment / operation}§
     766\end{cfa}
     767The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©).
     768
     769However, in most other situations, the pointed-to value is requested more often than the pointer address.
     770\begin{cfa}
     771*p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);
     772\end{cfa}
     773In this case, it is tedious to explicitly write the dereferencing, and error prone when pointer arithmetic is allowed.
     774It is better to have the compiler generate the dereferencing and have no implicit pointer arithmetic:
     775\begin{cfa}
     776p2 = ((p1 + p2) * (p3 - p1)) / (p3 - 15);
     777\end{cfa}
     778
     779To support this common case, a reference type is introduced in \CFA, denoted by ©&©, which is the opposite dereference semantics to a pointer type, making the value at the pointed-to location the implicit semantics for dereferencing (similar but not the same as \CC \Index{reference type}s).
     780\begin{cfa}
     781int x, y, ®&® r1, ®&® r2, ®&&® r3;
     782®&®r1 = &x;                                             §\C{// r1 points to x}§
     783®&®r2 = &r1;                                    §\C{// r2 points to x}§
     784®&®r1 = &y;                                             §\C{// r1 points to y}§
     785®&&®r3 = ®&®&r2;                                §\C{// r3 points to r2}§
     786r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§
     787\end{cfa}
     788Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer example.
     789Hence, a reference behaves like the variable name for the current variable it is pointing-to.
     790One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in a declaration, so the previous example becomes:
     791\begin{cfa}
     792®*®r2 = ((®*®r1 + ®*®r2) ®*® (®**®r3 - ®*®r1)) / (®**®r3 - 15);
     793\end{cfa}
     794When a reference operation appears beside a dereference operation, \eg ©&*©, they cancel out.
     795However, in C, the cancellation always yields a value (\Index{rvalue}).\footnote{
     796The unary ©&© operator yields the address of its operand.
     797If the operand has type ``type'', the result has type ``pointer to type''.
     798If the operand is the result of a unary ©*© operator, neither that operator nor the ©&© operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.~\cite[\S~6.5.3.2--3]{C11}}
     799For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}):
     800\begin{cfa}
     801(&®*®)r1 = &x;                                  §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
     802\end{cfa}
     803Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}):
     804\begin{cfa}
     805(&(&®*®)®*®)r3 = &(&®*®)r2;             §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
     806\end{cfa}
     807Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth.
     808
     809Fundamentally, pointer and reference objects are functionally interchangeable because both contain addresses.
     810\begin{cfa}
     811int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
     812                 &r1 = x,    &&r2 = r1,   &&&r3 = r2;
     813***p3 = 3;                                              §\C{// change x}§
     814r3 = 3;                                                 §\C{// change x, ***r3}§
     815**p3 = ...;                                             §\C{// change p1}§
     816&r3 = ...;                                              §\C{// change r1, (\&*)**r3, 1 cancellation}§
     817*p3 = ...;                                              §\C{// change p2}§
     818&&r3 = ...;                                             §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§
     819&&&r3 = p3;                                             §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§
     820\end{cfa}
     821Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.
     822Therefore, the choice between them is based solely on whether the address is dereferenced frequently or infrequently, which dictates the amount of implicit dereferencing aid from the compiler.
     823
     824As for a pointer type, a reference type may have qualifiers:
     825\begin{cfa}
     826const int cx = 5;                                       §\C{// cannot change cx;}§
     827const int & cr = cx;                            §\C{// cannot change what cr points to}§
     828®&®cr = &cx;                                            §\C{// can change cr}§
     829cr = 7;                                                         §\C{// error, cannot change cx}§
     830int & const rc = x;                                     §\C{// must be initialized}§
     831®&®rc = &x;                                                     §\C{// error, cannot change rc}§
     832const int & const crc = cx;                     §\C{// must be initialized}§
     833crc = 7;                                                        §\C{// error, cannot change cx}§
     834®&®crc = &cx;                                           §\C{// error, cannot change crc}§
     835\end{cfa}
     836Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}:
     837\begin{cfa}
     838int & const cr = *0;                            §\C{// where 0 is the int * zero}§
     839\end{cfa}
     840Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management:
     841\begin{cfa}
     842int & const cr = *malloc();
     843cr = 5;
     844free( &cr );
     845cr = 7;                                                         §\C{// unsound pointer dereference}§
     846\end{cfa}
     847
     848The position of the ©const© qualifier \emph{after} the pointer/reference qualifier causes confuse for C programmers.
     849The ©const© qualifier cannot be moved before the pointer/reference qualifier for C style-declarations;
     850\CFA-style declarations (see \VRef{s:Declarations}) attempt to address this issue:
     851\begin{quote2}
     852\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     853\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     854\begin{cfa}
     855®const® * ®const® * const int ccp;
     856®const® & ®const® & const int ccr;
     857\end{cfa}
     858&
     859\begin{cfa}
     860const int * ®const® * ®const® ccp;
     861
     862\end{cfa}
     863\end{tabular}
     864\end{quote2}
     865where the \CFA declaration is read left-to-right.
     866
     867Finally, like pointers, references are usable and composable with other type operators and generators.
     868\begin{cfa}
     869int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§
     870&ar[1] = &w;                                            §\C{// change reference array element}§
     871typeof( ar[1] ) p;                                      §\C{// (gcc) is int, i.e., the type of referenced object}§
     872typeof( &ar[1] ) q;                                     §\C{// (gcc) is int \&, i.e., the type of reference}§
     873sizeof( ar[1] ) == sizeof( int );       §\C{// is true, i.e., the size of referenced object}§
     874sizeof( &ar[1] ) == sizeof( int *)      §\C{// is true, i.e., the size of a reference}§
     875\end{cfa}
     876
     877In contrast to \CFA reference types, \Index*[C++]{\CC{}}'s reference types are all ©const© references, preventing changes to the reference address, so only value assignment is possible, which eliminates half of the \Index{address duality}.
     878Also, \CC does not allow \Index{array}s\index{array!reference} of reference\footnote{
     879The reason for disallowing arrays of reference is unknown, but possibly comes from references being ethereal (like a textual macro), and hence, replaceable by the referant object.}
     880\Index*{Java}'s reference types to objects (all Java objects are on the heap) are like C pointers, which always manipulate the address, and there is no (bit-wise) object assignment, so objects are explicitly cloned by shallow or deep copying, which eliminates half of the address duality.
     881
     882
     883\subsection{Initialization}
     884
     885\Index{Initialization} is different than \Index{assignment} because initialization occurs on the empty (uninitialized) storage on an object, while assignment occurs on possibly initialized storage of an object.
     886There are three initialization contexts in \CFA: declaration initialization, argument/parameter binding, return/temporary binding.
     887Because the object being initialized has no value, there is only one meaningful semantics with respect to address duality: it must mean address as there is no pointed-to value.
     888In contrast, the left-hand side of assignment has an address that has a duality.
     889Therefore, for pointer/reference initialization, the initializing value must be an address not a value.
     890\begin{cfa}
     891int * p = &x;                                           §\C{// assign address of x}§
     892®int * p = x;®                                          §\C{// assign value of x}§
     893int & r = x;                                            §\C{// must have address of x}§
     894\end{cfa}
     895Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of ©x© into a pointer is meaningful (again, a warning is usually given).
     896Therefore, for safety, this context requires an address, so it is superfluous to require explicitly taking the address of the initialization object, even though the type is incorrect.
     897Note, this is strictly a convenience and safety feature for a programmer.
     898Hence, \CFA allows ©r© to be assigned ©x© because it infers a reference for ©x©, by implicitly inserting a address-of operator, ©&©, and it is an error to put an ©&© because the types no longer match due to the implicit dereference.
     899Unfortunately, C allows ©p© to be assigned with ©&x© (address) or ©x© (value), but most compilers warn about the latter assignment as being potentially incorrect.
     900Similarly, when a reference type is used for a parameter/return type, the call-site argument does not require a reference operator for the same reason.
     901\begin{cfa}
     902int & f( int & r );                                     §\C{// reference parameter and return}§
     903z = f( x ) + f( y );                            §\C{// reference operator added, temporaries needed for call results}§
     904\end{cfa}
     905Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©.
     906Since operator routine ©?+?© takes its arguments by value, the references returned from ©f© are used to initialize compiler generated temporaries with value semantics that copy from the references.
     907\begin{cfa}
     908int temp1 = f( x ), temp2 = f( y );
     909z = temp1 + temp2;
     910\end{cfa}
     911This \Index{implicit referencing} is crucial for reducing the syntactic burden for programmers when using references;
     912otherwise references have the same syntactic  burden as pointers in these contexts.
     913
     914When a pointer/reference parameter has a ©const© value (immutable), it is possible to pass literals and expressions.
     915\begin{cfa}
     916void f( ®const® int & cr );
     917void g( ®const® int * cp );
     918f( 3 );                   g( ®&®3 );
     919f( x + y );             g( ®&®(x + y) );
     920\end{cfa}
     921Here, the compiler passes the address to the literal 3 or the temporary for the expression ©x + y©, knowing the argument cannot be changed through the parameter.
     922The ©&© before the constant/expression for the pointer-type parameter (©g©) is a \CFA extension necessary to type match and is a common requirement before a variable in C (\eg ©scanf©).
     923Importantly, ©&3© may not be equal to ©&3©, where the references occur across calls because the temporaries maybe different on each call.
     924
     925\CFA \emph{extends} this semantics to a mutable pointer/reference parameter, and the compiler implicitly creates the necessary temporary (copying the argument), which is subsequently pointed-to by the reference parameter and can be changed.\footnote{
     926If whole program analysis is possible, and shows the parameter is not assigned, \ie it is ©const©, the temporary is unnecessary.}
     927\begin{cfa}
     928void f( int & r );
     929void g( int * p );
     930f( 3 );                   g( ®&®3 );            §\C{// compiler implicit generates temporaries}§
     931f( x + y );             g( ®&®(x + y) );        §\C{// compiler implicit generates temporaries}§
     932\end{cfa}
     933Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{
     934This conversion attempts to address the \newterm{const hell} problem, when the innocent addition of a ©const© qualifier causes a cascade of type failures, requiring an unknown number of additional ©const© qualifiers, until it is discovered a ©const© qualifier cannot be added and all the ©const© qualifiers must be removed.}
     935The implicit conversion allows seamless calls to any routine without having to explicitly name/copy the literal/expression to allow the call.
     936
     937%\CFA attempts to handle pointers and references in a uniform, symmetric manner.
     938Finally, C handles \Index{routine object}s in an inconsistent way.
     939A routine object is both a pointer and a reference (\Index{particle and wave}).
     940\begin{cfa}
     941void f( int i );
     942void (*fp)( int );                                      §\C{// routine pointer}§
     943fp = f;                                                         §\C{// reference initialization}§
     944fp = &f;                                                        §\C{// pointer initialization}§
     945fp = *f;                                                        §\C{// reference initialization}§
     946fp(3);                                                          §\C{// reference invocation}§
     947(*fp)(3);                                                       §\C{// pointer invocation}§
     948\end{cfa}
     949While C's treatment of routine objects has similarity to inferring a reference type in initialization contexts, the examples are assignment not initialization, and all possible forms of assignment are possible (©f©, ©&f©, ©*f©) without regard for type.
     950Instead, a routine object should be referenced by a ©const© reference:
     951\begin{cfa}
     952®const® void (®&® fr)( int ) = f;       §\C{// routine reference}§
     953fr = ...                                                        §\C{// error, cannot change code}§
     954&fr = ...;                                                      §\C{// changing routine reference}§
     955fr( 3 );                                                        §\C{// reference call to f}§
     956(*fr)(3);                                                       §\C{// error, incorrect type}§
     957\end{cfa}
     958because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{
     959Dynamic code rewriting is possible but only in special circumstances.}
     960\CFA allows this additional use of references for routine objects in an attempt to give a more consistent meaning for them.
     961
     962
     963\subsection{Address-of Semantics}
     964
     965In C, ©&E© is an rvalue for any expression ©E©.
     966\CFA extends the ©&© (address-of) operator as follows:
     967\begin{itemize}
     968\item
     969if ©R© is an \Index{rvalue} of type ©T &$_1$...&$_r$© where $r \ge 1$ references (©&© symbols) than ©&R© has type ©T ®*®&$_{\color{red}2}$...&$_{\color{red}r}$©, \ie ©T© pointer with $r-1$ references (©&© symbols).
     970
     971\item
     972if ©L© is an \Index{lvalue} of type ©T &$_1$...&$_l$© where $l \ge 0$ references (©&© symbols) then ©&L© has type ©T ®*®&$_{\color{red}1}$...&$_{\color{red}l}$©, \ie ©T© pointer with $l$ references (©&© symbols).
     973\end{itemize}
     974The following example shows the first rule applied to different \Index{rvalue} contexts:
     975\begin{cfa}
     976int x, * px, ** ppx, *** pppx, **** ppppx;
     977int & rx = x, && rrx = rx, &&& rrrx = rrx ;
     978x = rrrx;               // rrrx is an lvalue with type int &&& (equivalent to x)
     979px = &rrrx;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (&x)
     980ppx = &&rrrx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (&rx)
     981pppx = &&&rrrx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (&rrx)
     982ppppx = &&&&rrrx; // starting from &&&rrrx, &&&&rrrx is an rvalue with type int **** (&rrrx)
     983\end{cfa}
     984The following example shows the second rule applied to different \Index{lvalue} contexts:
     985\begin{cfa}
     986int x, * px, ** ppx, *** pppx;
     987int & rx = x, && rrx = rx, &&& rrrx = rrx ;
     988rrrx = 2;               // rrrx is an lvalue with type int &&& (equivalent to x)
     989&rrrx = px;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (rx)
     990&&rrrx = ppx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (rrx)
     991&&&rrrx = pppx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (rrrx)
     992\end{cfa}
     993
     994
     995\subsection{Conversions}
     996
     997C provides a basic implicit conversion to simplify variable usage:
     998\begin{enumerate}
     999\setcounter{enumi}{-1}
     1000\item
     1001lvalue to rvalue conversion: ©cv T© converts to ©T©, which allows implicit variable dereferencing.
     1002\begin{cfa}
     1003int x;
     1004x + 1;                  // lvalue variable (int) converts to rvalue for expression
     1005\end{cfa}
     1006An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped.
     1007\end{enumerate}
     1008\CFA provides three new implicit conversion for reference types to simplify reference usage.
     1009\begin{enumerate}
     1010\item
     1011reference to rvalue conversion: ©cv T &© converts to ©T©, which allows implicit reference dereferencing.
     1012\begin{cfa}
     1013int x, &r = x, f( int p );
     1014x = ®r® + f( ®r® );  // lvalue reference converts to rvalue
     1015\end{cfa}
     1016An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped.
     1017
     1018\item
     1019lvalue to reference conversion: \lstinline[deletekeywords={lvalue}]@lvalue-type cv1 T@ converts to ©cv2 T &©, which allows implicitly converting variables to references.
     1020\begin{cfa}
     1021int x, &r = ®x®, f( int & p ); // lvalue variable (int) convert to reference (int &)
     1022f( ®x® );               // lvalue variable (int) convert to reference (int &)
     1023\end{cfa}
     1024Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost.
     1025Conversion can expand a type, where ©cv1© $>$ ©cv2©, \eg passing a ©const volatile int© to an ©int &©, which has high cost (\Index{warning});
     1026furthermore, if ©cv1© has ©const© but not ©cv2©, a temporary variable is created to preserve the immutable lvalue.
     1027
     1028\item
     1029rvalue to reference conversion: ©T© converts to ©cv T &©, which allows binding references to temporaries.
     1030\begin{cfa}
     1031int x, & f( int & p );
     1032f( ®x + 3® );   // rvalue parameter (int) implicitly converts to lvalue temporary reference (int &)
     1033®&f®(...) = &x; // rvalue result (int &) implicitly converts to lvalue temporary reference (int &)
     1034\end{cfa}
     1035In both case, modifications to the temporary are inaccessible (\Index{warning}).
     1036Conversion expands the temporary-type with ©cv©, which is low cost since the temporary is inaccessible.
     1037\end{enumerate}
     1038
     1039
     1040\begin{comment}
     1041From: Richard Bilson <rcbilson@gmail.com>
     1042Date: Wed, 13 Jul 2016 01:58:58 +0000
     1043Subject: Re: pointers / references
     1044To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca>
     1045
     1046As a general comment I would say that I found the section confusing, as you move back and forth
     1047between various real and imagined programming languages. If it were me I would rewrite into two
     1048subsections, one that specifies precisely the syntax and semantics of reference variables and
     1049another that provides the rationale.
     1050
     1051I don't see any obvious problems with the syntax or semantics so far as I understand them. It's not
     1052obvious that the description you're giving is complete, but I'm sure you'll find the special cases
     1053as you do the implementation.
     1054
     1055My big gripes are mostly that you're not being as precise as you need to be in your terminology, and
     1056that you say a few things that aren't actually true even though I generally know what you mean.
     1057
     105820 C provides a pointer type; CFA adds a reference type. Both types contain an address, which is normally a
     105921 location in memory.
     1060
     1061An address is not a location in memory; an address refers to a location in memory. Furthermore it
     1062seems weird to me to say that a type "contains" an address; rather, objects of that type do.
     1063
     106421 Special addresses are used to denote certain states or access co-processor memory. By
     106522 convention, no variable is placed at address 0, so addresses like 0, 1, 2, 3 are often used to denote no-value
     106623 or other special states.
     1067
     1068This isn't standard C at all. There has to be one null pointer representation, but it doesn't have
     1069to be a literal zero representation and there doesn't have to be more than one such representation.
     1070
     107123 Often dereferencing a special state causes a memory fault, so checking is necessary
     107224 during execution.
     1073
     1074I don't see the connection between the two clauses here. I feel like if a bad pointer will not cause
     1075a memory fault then I need to do more checking, not less.
     1076
     107724 If the programming language assigns addresses, a program's execution is sound, \ie all
     107825 addresses are to valid memory locations.
     1079
     1080You haven't said what it means to "assign" an address, but if I use my intuitive understanding of
     1081the term I don't see how this can be true unless you're assuming automatic storage management.
     1082
     10831 Program variables are implicit pointers to memory locations generated by the compiler and automatically
     10842 dereferenced, as in:
     1085
     1086There is no reason why a variable needs to have a location in memory, and indeed in a typical
     1087program many variables will not. In standard terminology an object identifier refers to data in the
     1088execution environment, but not necessarily in memory.
     1089
     109013 A pointer/reference is a generalization of a variable name, \ie a mutable address that can point to more
     109114 than one memory location during its lifetime.
     1092
     1093I feel like you're off the reservation here. In my world there are objects of pointer type, which
     1094seem to be what you're describing here, but also pointer values, which can be stored in an object of
     1095pointer type but don't necessarily have to be. For example, how would you describe the value denoted
     1096by "&main" in a C program? I would call it a (function) pointer, but that doesn't satisfy your
     1097definition.
     1098
     109916 not occupy storage as the literal is embedded directly into instructions.) Hence, a pointer occupies memory
     110017 to store its current address, and the pointer's value is loaded by dereferencing, e.g.:
     1101
     1102As with my general objection regarding your definition of variables, there is no reason why a
     1103pointer variable (object of pointer type) needs to occupy memory.
     1104
     110521 p2 = p1 + x; // compiler infers *p2 = *p1 + x;
     1106
     1107What language are we in now?
     1108
     110924 pointer usage. However, in C, the following cases are ambiguous, especially with pointer arithmetic:
     111025 p1 = p2; // p1 = p2 or *p1 = *p2
     1111
     1112This isn't ambiguous. it's defined to be the first option.
     1113
     111426 p1 = p1 + 1; // p1 = p1 + 1 or *p1 = *p1 + 1
     1115
     1116Again, this statement is not ambiguous.
     1117
     111813 example. Hence, a reference behaves like the variable name for the current variable it is pointing-to. The
     111914 simplest way to understand a reference is to imagine the compiler inserting a dereference operator before
     112015 the reference variable for each reference qualifier in a declaration, e.g.:
     1121
     1122It's hard for me to understand who the audience for this part is. I think a practical programmer is
     1123likely to be satisfied with "a reference behaves like the variable name for the current variable it
     1124is pointing-to," maybe with some examples. Your "simplest way" doesn't strike me as simpler than
     1125that. It feels like you're trying to provide a more precise definition for the semantics of
     1126references, but it isn't actually precise enough to be a formal specification. If you want to
     1127express the semantics of references using rewrite rules that's a great way to do it, but lay the
     1128rules out clearly, and when you're showing an example of rewriting keep your
     1129references/pointers/values separate (right now, you use \eg "r3" to mean a reference, a pointer,
     1130and a value).
     1131
     113224 Cancellation works to arbitrary depth, and pointer and reference values are interchangeable because both
     113325 contain addresses.
     1134
     1135Except they're not interchangeable, because they have different and incompatible types.
     1136
     113740 Interestingly, C++ deals with the address duality by making the pointed-to value the default, and prevent-
     113841 ing changes to the reference address, which eliminates half of the duality. Java deals with the address duality
     113942 by making address assignment the default and requiring field assignment (direct or indirect via methods),
     114043 \ie there is no builtin bit-wise or method-wise assignment, which eliminates half of the duality.
     1141
     1142I can follow this but I think that's mostly because I already understand what you're trying to
     1143say. I don't think I've ever heard the term "method-wise assignment" and I don't see you defining
     1144it. Furthermore Java does have value assignment of basic (non-class) types, so your summary here
     1145feels incomplete. (If it were me I'd drop this paragraph rather than try to save it.)
     1146
     114711 Hence, for type & const, there is no pointer assignment, so &rc = &x is disallowed, and the address value
     114812 cannot be 0 unless an arbitrary pointer is assigned to the reference.
     1149
     1150Given the pains you've taken to motivate every little bit of the semantics up until now, this last
     1151clause ("the address value cannot be 0") comes out of the blue. It seems like you could have
     1152perfectly reasonable semantics that allowed the initialization of null references.
     1153
     115412 In effect, the compiler is managing the
     115513 addresses for type & const not the programmer, and by a programming discipline of only using references
     115614 with references, address errors can be prevented.
     1157
     1158Again, is this assuming automatic storage management?
     1159
     116018 rary binding. For reference initialization (like pointer), the initializing value must be an address (lvalue) not
     116119 a value (rvalue).
     1162
     1163This sentence appears to suggest that an address and an lvalue are the same thing.
     1164
     116520 int * p = &x; // both &x and x are possible interpretations
     1166
     1167Are you saying that we should be considering "x" as a possible interpretation of the initializer
     1168"&x"? It seems to me that this expression has only one legitimate interpretation in context.
     1169
     117021 int & r = x; // x unlikely interpretation, because of auto-dereferencing
     1171
     1172You mean, we can initialize a reference using an integer value? Surely we would need some sort of
     1173cast to induce that interpretation, no?
     1174
     117522 Hence, the compiler implicitly inserts a reference operator, &, before the initialization expression.
     1176
     1177But then the expression would have pointer type, which wouldn't be compatible with the type of r.
     1178
     117922 Similarly,
     118023 when a reference is used for a parameter/return type, the call-site argument does not require a reference
     118124 operator.
     1182
     1183Furthermore, it would not be correct to use a reference operator.
     1184
     118545 The implicit conversion allows
     11861 seamless calls to any routine without having to explicitly name/copy the literal/expression to allow the call.
     11872 While C' attempts to handle pointers and references in a uniform, symmetric manner, C handles routine
     11883 variables in an inconsistent way: a routine variable is both a pointer and a reference (particle and wave).
     1189
     1190After all this talk of how expressions can have both pointer and value interpretations, you're
     1191disparaging C because it has expressions that have both pointer and value interpretations?
     1192
     1193On Sat, Jul 9, 2016 at 4:18 PM Peter A. Buhr <pabuhr@plg.uwaterloo.ca> wrote:
     1194> Aaron discovered a few places where "&"s are missing and where there are too many "&", which are
     1195> corrected in the attached updated. None of the text has changed, if you have started reading
     1196> already.
     1197\end{comment}
     1198
     1199
     1200\section{Routine Definition}
     1201
     1202\CFA also supports a new syntax for routine definition, as well as \Celeven and K\&R routine syntax.
     1203The point of the new syntax is to allow returning multiple values from a routine~\cite{Galletly96,CLU}, \eg:
     1204\begin{cfa}
     1205®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) {
     1206        §\emph{routine body}§
     1207}
     1208\end{cfa}
     1209where routine ©f© has three output (return values) and three input parameters.
     1210Existing C syntax cannot be extended with multiple return types because it is impossible to embed a single routine name within multiple return type specifications.
     1211
     1212In detail, the brackets, ©[]©, enclose the result type, where each return value is named and that name is a local variable of the particular return type.\footnote{
     1213\Index*{Michael Tiemann}, with help from \Index*{Doug Lea}, provided named return values in g++, circa 1989.}
     1214The value of each local return variable is automatically returned at routine termination.
     1215Declaration qualifiers can only appear at the start of a routine definition, \eg:
     1216\begin{cfa}
     1217®extern® [ int x ] g( int y ) {§\,§}
     1218\end{cfa}
     1219Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified;
     1220in both cases the type is assumed to be void as opposed to old style C defaults of int return type and unknown parameter types, respectively, as in:
     1221\begin{cfa}
     1222[§\,§] g();                                                     §\C{// no input or output parameters}§
     1223[ void ] g( void );                                     §\C{// no input or output parameters}§
     1224\end{cfa}
     1225
     1226Routine f is called as follows:
     1227\begin{cfa}
     1228[ i, j, ch ] = f( 3, 'a', ch );
     1229\end{cfa}
     1230The list of return values from f and the grouping on the left-hand side of the assignment is called a \newterm{return list} and discussed in Section 12.
     1231
     1232\CFA style declarations cannot be used to declare parameters for K\&R style routine definitions because of the following ambiguity:
     1233\begin{cfa}
     1234int (*f(x))[ 5 ] int x; {}
     1235\end{cfa}
     1236The string ``©int (*f(x))[ 5 ]©'' declares a K\&R style routine of type returning a pointer to an array of 5 integers, while the string ``©[ 5 ] int x©'' declares a \CFA style parameter x of type array of 5 integers.
     1237Since the strings overlap starting with the open bracket, ©[©, there is an ambiguous interpretation for the string.
     1238As well, \CFA-style declarations cannot be used to declare parameters for C-style routine-definitions because of the following ambiguity:
     1239\begin{cfa}
     1240typedef int foo;
     1241int f( int (* foo) );                           §\C{// foo is redefined as a parameter name}§
     1242\end{cfa}
     1243The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo.
     1244The redefinition of a type name in a parameter list is the only context in C where the character ©*© can appear to the left of a type name, and \CFA relies on all type qualifier characters appearing to the right of the type name.
     1245The inability to use \CFA declarations in these two contexts is probably a blessing because it precludes programmers from arbitrarily switching between declarations forms within a declaration contexts.
     1246
     1247C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg:
     1248\begin{cfa}
     1249[ int ] f( * int, int * );                      §\C{// returns an integer, accepts 2 pointers to integers}§
     1250[ * int, int * ] f( int );                      §\C{// returns 2 pointers to integers, accepts an integer}§
     1251\end{cfa}
     1252The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in:
     1253\begin{cfa}
     1254#define ptoa( n, d ) int (*n)[ d ]
     1255int f( ptoa( p, 5 ) ) ...                       §\C{// expands to int f( int (*p)[ 5 ] )}§
     1256[ int ] f( ptoa( p, 5 ) ) ...           §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§
     1257\end{cfa}
     1258Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms.
     1259
     1260
     1261\subsection{Named Return Values}
     1262
     1263\Index{Named return values} handle the case where it is necessary to define a local variable whose value is then returned in a ©return© statement, as in:
     1264\begin{cfa}
     1265int f() {
     1266        int x;
     1267        ... x = 0; ... x = y; ...
     1268        return x;
     1269}
     1270\end{cfa}
     1271Because the value in the return variable is automatically returned when a \CFA routine terminates, the ©return© statement \emph{does not} contain an expression, as in:
     1272\newline
     1273\begin{minipage}{\linewidth}
     1274\begin{cfa}
     1275®[ int x, int y ]® f() {
     1276        int z;
     1277        ... x = 0; ... y = z; ...
     1278        ®return;®                                                       §\C{// implicitly return x, y}§
     1279}
     1280\end{cfa}
     1281\end{minipage}
     1282\newline
     1283When the return is encountered, the current values of ©x© and ©y© are returned to the calling routine.
     1284As well, ``falling off the end'' of a routine without a ©return© statement is permitted, as in:
     1285\begin{cfa}
     1286[ int x, int y ] f() {
     1287        ...
     1288}                                                                               §\C{// implicitly return x, y}§
     1289\end{cfa}
     1290In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered.
     1291
     1292Named return values may be used in conjunction with named parameter values;
     1293specifically, a return and parameter can have the same name.
     1294\begin{cfa}
     1295[ int x, int y ] f( int, x, int y ) {
     1296        ...
     1297}                                                                               §\C{// implicitly return x, y}§
     1298\end{cfa}
     1299This notation allows the compiler to eliminate temporary variables in nested routine calls.
     1300\begin{cfa}
     1301[ int x, int y ] f( int, x, int y );    §\C{// prototype declaration}§
     1302int a, b;
     1303[a, b] = f( f( f( a, b ) ) );
     1304\end{cfa}
     1305While the compiler normally ignores parameters names in prototype declarations, here they are used to eliminate temporary return-values by inferring that the results of each call are the inputs of the next call, and ultimately, the left-hand side of the assignment.
     1306Hence, even without the body of routine ©f© (separate compilation), it is possible to perform a global optimization across routine calls.
     1307The compiler warns about naming inconsistencies between routine prototype and definition in this case, and behaviour is \Index{undefined} if the programmer is inconsistent.
     1308
     1309
     1310\subsection{Routine Prototype}
     1311
     1312The syntax of the new routine prototype declaration follows directly from the new routine definition syntax;
     1313as well, parameter names are optional, \eg:
     1314\begin{cfa}
     1315[ int x ] f ();                                                 §\C{// returning int with no parameters}§
     1316[ * int ] g (int y);                                    §\C{// returning pointer to int with int parameter}§
     1317[ ] h ( int, char );                                    §\C{// returning no result with int and char parameters}§
     1318[ * int, int ] j ( int );                               §\C{// returning pointer to int and int, with int parameter}§
     1319\end{cfa}
     1320This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
     1321It is possible to declare multiple routine-prototypes in a single declaration, but the entire type specification is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
     1322\begin{quote2}
     1323\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1324\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     1325\begin{cfa}
     1326[ int ] f( int ), g;
     1327\end{cfa}
     1328&
     1329\begin{cfa}
     1330int f( int ), g( int );
     1331\end{cfa}
     1332\end{tabular}
     1333\end{quote2}
     1334Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg:
     1335\begin{cfa}
     1336extern [ int ] f ( int );
     1337static [ int ] g ( int );
     1338\end{cfa}
     1339
     1340
     1341\section{Routine Pointers}
     1342
     1343The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
     1344\begin{cfa}
     1345* [ int x ] () fp;                                              §\C{// pointer to routine returning int with no parameters}§
     1346* [ * int ] (int y) gp;                                 §\C{// pointer to routine returning pointer to int with int parameter}§
     1347* [ ] (int,char) hp;                                    §\C{// pointer to routine returning no result with int and char parameters}§
     1348* [ * int,int ] ( int ) jp;                             §\C{// pointer to routine returning pointer to int and int, with int parameter}§
     1349\end{cfa}
     1350While parameter names are optional, \emph{a routine name cannot be specified};
     1351for example, the following is incorrect:
     1352\begin{cfa}
     1353* [ int x ] f () fp;                                    §\C{// routine name "f" is not allowed}§
     1354\end{cfa}
     1355
     1356
     1357\section{Named and Default Arguments}
     1358
     1359Named\index{named arguments}\index{arguments!named} and default\index{default arguments}\index{arguments!default} arguments~\cite{Hardgrave76}\footnote{
     1360Francez~\cite{Francez77} proposed a further extension to the named-parameter passing style, which specifies what type of communication (by value, by reference, by name) the argument is passed to the routine.}
     1361are two mechanisms to simplify routine call.
     1362Both mechanisms are discussed with respect to \CFA.
     1363\begin{description}
     1364\item[Named (or Keyword) Arguments:]
     1365provide the ability to specify an argument to a routine call using the parameter name rather than the position of the parameter.
     1366For example, given the routine:
     1367\begin{cfa}
     1368void p( int x, int y, int z ) {...}
     1369\end{cfa}
     1370a positional call is:
     1371\begin{cfa}
     1372p( 4, 7, 3 );
     1373\end{cfa}
     1374whereas a named (keyword) call may be:
     1375\begin{cfa}
     1376p( z : 3, x : 4, y : 7 );       §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§
     1377\end{cfa}
     1378Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters.
     1379The compiler rewrites a named call into a positional call.
     1380The advantages of named parameters are:
     1381\begin{itemize}
     1382\item
     1383Remembering the names of the parameters may be easier than the order in the routine definition.
     1384\item
     1385Parameter names provide documentation at the call site (assuming the names are descriptive).
     1386\item
     1387Changes can be made to the order or number of parameters without affecting the call (although the call must still be recompiled).
     1388\end{itemize}
     1389
     1390Unfortunately, named arguments do not work in C-style programming-languages because a routine prototype is not required to specify parameter names, nor do the names in the prototype have to match with the actual definition.
     1391For example, the following routine prototypes and definition are all valid.
     1392\begin{cfa}
     1393void p( int, int, int );                        §\C{// equivalent prototypes}§
     1394void p( int x, int y, int z );
     1395void p( int y, int x, int z );
     1396void p( int z, int y, int x );
     1397void p( int q, int r, int s ) {}        §\C{// match with this definition}§
     1398\end{cfa}
     1399Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming.
     1400Alternatively, prototype definitions can be eliminated by using a two-pass compilation, and implicitly creating header files for exports.
     1401The former is easy to do, while the latter is more complex.
     1402
     1403Furthermore, named arguments do not work well in a \CFA-style programming-languages because they potentially introduces a new criteria for type matching.
     1404For example, it is technically possible to disambiguate between these two overloaded definitions of ©f© based on named arguments at the call site:
     1405\begin{cfa}
     1406int f( int i, int j );
     1407int f( int x, double y );
     1408
     1409f( j : 3, i : 4 );                              §\C{// 1st f}§
     1410f( x : 7, y : 8.1 );                    §\C{// 2nd f}§
     1411f( 4, 5 );                                              §\C{// ambiguous call}§
     1412\end{cfa}
     1413However, named arguments compound routine resolution in conjunction with conversions:
     1414\begin{cfa}
     1415f( i : 3, 5.7 );                                §\C{// ambiguous call ?}§
     1416\end{cfa}
     1417Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.
     1418Adding named argument into the routine resolution algorithm does not seem worth the complexity.
     1419Therefore, \CFA does \emph{not} attempt to support named arguments.
     1420
     1421\item[Default Arguments]
     1422provide the ability to associate a default value with a parameter so it can be optionally specified in the argument list.
     1423For example, given the routine:
     1424\begin{cfa}
     1425void p( int x = 1, int y = 2, int z = 3 ) {...}
     1426\end{cfa}
     1427the allowable positional calls are:
     1428\begin{cfa}
     1429p();                                                    §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
     1430p( 4 );                                                 §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
     1431p( 4, 4 );                                              §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
     1432p( 4, 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§
     1433// empty arguments
     1434p(  , 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§
     1435p( 4,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§
     1436p( 4, 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
     1437p( 4,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
     1438p(  , 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§
     1439p(  ,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§
     1440p(  ,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
     1441\end{cfa}
     1442Here the missing arguments are inserted from the default values in the parameter list.
     1443The compiler rewrites missing default values into explicit positional arguments.
     1444The advantages of default values are:
     1445\begin{itemize}
     1446\item
     1447Routines with a large number of parameters are often very generalized, giving a programmer a number of different options on how a computation is performed.
     1448For many of these kinds of routines, there are standard or default settings that work for the majority of computations.
     1449Without default values for parameters, a programmer is forced to specify these common values all the time, resulting in long argument lists that are error prone.
     1450\item
     1451When a routine's interface is augmented with new parameters, it extends the interface providing generalizability\footnote{
     1452``It should be possible for the implementor of an abstraction to increase its generality.
     1453So long as the modified abstraction is a generalization of the original, existing uses of the abstraction will not require change.
     1454It might be possible to modify an abstraction in a manner which is not a generalization without affecting existing uses, but, without inspecting the modules in which the uses occur, this possibility cannot be determined.
     1455This criterion precludes the addition of parameters, unless these parameters have default or inferred values that are valid for all possible existing applications.''~\cite[p.~128]{Cormack90}}
     1456(somewhat like the generalization provided by inheritance for classes).
     1457That is, all existing calls are still valid, although the call must still be recompiled.
     1458\end{itemize}
     1459The only disadvantage of default arguments is that unintentional omission of an argument may not result in a compiler-time error.
     1460Instead, a default value is used, which may not be the programmer's intent.
     1461
     1462Default values may only appear in a prototype versus definition context:
     1463\begin{cfa}
     1464void p( int x, int y = 2, int z = 3 );          §\C{// prototype: allowed}§
     1465void p( int, int = 2, int = 3 );                        §\C{// prototype: allowed}§
     1466void p( int x, int y = 2, int z = 3 ) {}        §\C{// definition: not allowed}§
     1467\end{cfa}
     1468The reason for this restriction is to allow separate compilation.
     1469Multiple prototypes with different default values is an error.
     1470\end{description}
     1471
     1472Ellipse (``...'') arguments present problems when used with default arguments.
     1473The conflict occurs because both named and ellipse arguments must appear after positional arguments, giving two possibilities:
     1474\begin{cfa}
     1475p( /* positional */, ... , /* named */ );
     1476p( /* positional */, /* named */, ... );
     1477\end{cfa}
     1478While it is possible to implement both approaches, the first possibly is more complex than the second, \eg:
     1479\begin{cfa}
     1480p( int x, int y, int z, ... );
     1481p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§
     1482p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§
     1483\end{cfa}
     1484In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin.
     1485Hence, this approach seems significantly more difficult, and hence, confusing and error prone.
     1486In the second call, the named arguments separate the positional and ellipse arguments, making it trivial to read the call.
     1487
     1488The problem is exacerbated with default arguments, \eg:
     1489\begin{cfa}
     1490void p( int x, int y = 2, int z = 3... );
     1491p( 1, 4, 5, 6, z : 3 );         §\C{// assume p( /* positional */, ... , /* named */ );}§
     1492p( 1, z : 3, 4, 5, 6 );         §\C{// assume p( /* positional */, /* named */, ... );}§
     1493\end{cfa}
     1494The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments;
     1495therefore, argument 5 subsequently conflicts with the named argument z : 3.
     1496In the second call, the default value for y is implicitly inserted after argument 1 and the named arguments separate the positional and ellipse arguments, making it trivial to read the call.
     1497For these reasons, \CFA requires named arguments before ellipse arguments.
     1498Finally, while ellipse arguments are needed for a small set of existing C routines, like printf, the extended \CFA type system largely eliminates the need for ellipse arguments (see Section 24), making much of this discussion moot.
     1499
     1500Default arguments and overloading (see Section 24) are complementary.
     1501While in theory default arguments can be simulated with overloading, as in:
     1502\begin{quote2}
     1503\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1504\multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}}   & \multicolumn{1}{c}{\textbf{overloading}}      \\
     1505\begin{cfa}
     1506void p( int x, int y = 2, int z = 3 ) {...}
     1507
     1508
     1509\end{cfa}
     1510&
     1511\begin{cfa}
     1512void p( int x, int y, int z ) {...}
     1513void p( int x ) { p( x, 2, 3 ); }
     1514void p( int x, int y ) { p( x, y, 3 ); }
     1515\end{cfa}
     1516\end{tabular}
     1517\end{quote2}
     1518the number of required overloaded routines is linear in the number of default values, which is unacceptable growth.
     1519In general, overloading should only be used over default arguments if the body of the routine is significantly different.
     1520Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as:
     1521\begin{cfa}
     1522p( 1, /* default */, 5 );               §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§
     1523\end{cfa}
     1524
     1525Given the \CFA restrictions above, both named and default arguments are backwards compatible.
     1526\Index*[C++]{\CC{}} only supports default arguments;
     1527\Index*{Ada} supports both named and default arguments.
     1528
     1529
     1530\section{Unnamed Structure Fields}
     1531
     1532C requires each field of a structure to have a name, except for a bit field associated with a basic type, \eg:
     1533\begin{cfa}
     1534struct {
     1535        int f1;                                 §\C{// named field}§
     1536        int f2 : 4;                             §\C{// named field with bit field size}§
     1537        int : 3;                                §\C{// unnamed field for basic type with bit field size}§
     1538        int ;                                   §\C{// disallowed, unnamed field}§
     1539        int *;                                  §\C{// disallowed, unnamed field}§
     1540        int (*)( int );                 §\C{// disallowed, unnamed field}§
     1541};
     1542\end{cfa}
     1543This requirement is relaxed by making the field name optional for all field declarations; therefore, all the field declarations in the example are allowed.
     1544As for unnamed bit fields, an unnamed field is used for padding a structure to a particular size.
     1545A list of unnamed fields is also supported, \eg:
     1546\begin{cfa}
     1547struct {
     1548        int , , ;                               §\C{// 3 unnamed fields}§
     1549}
     1550\end{cfa}
     1551
     1552
     1553\section{Nesting}
     1554
     1555Nesting of types and routines is useful for controlling name visibility (\newterm{name hiding}).
     1556
     1557
     1558\subsection{Type Nesting}
     1559
     1560\CFA allows \Index{type nesting}, and type qualification of the nested types (see \VRef[Figure]{f:TypeNestingQualification}), where as C hoists\index{type hoisting} (refactors) nested types into the enclosing scope and has no type qualification.
     1561\begin{figure}
     1562\centering
     1563\begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
     1564\multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}}      & \multicolumn{1}{c}{\textbf{C Implicit Hoisting}}      & \multicolumn{1}{|c}{\textbf{\CFA}}    \\
     1565\hline
     1566\begin{cfa}
     1567struct S {
     1568        enum C { R, G, B };
     1569        struct T {
     1570                union U { int i, j; };
     1571                enum C c;
     1572                short int i, j;
     1573        };
     1574        struct T t;
     1575} s;
     1576
     1577int fred() {
     1578        s.t.c = R;
     1579        struct T t = { R, 1, 2 };
     1580        enum C c;
     1581        union U u;
     1582}
     1583\end{cfa}
     1584&
     1585\begin{cfa}
     1586enum C { R, G, B };
     1587union U { int i, j; };
     1588struct T {
     1589        enum C c;
     1590        short int i, j;
     1591};
     1592struct S {
     1593        struct T t;
     1594} s;
     1595       
     1596
     1597
     1598
     1599
     1600
     1601
     1602\end{cfa}
     1603&
     1604\begin{cfa}
     1605struct S {
     1606        enum C { R, G, B };
     1607        struct T {
     1608                union U { int i, j; };
     1609                enum C c;
     1610                short int i, j;
     1611        };
     1612        struct T t;
     1613} s;
     1614
     1615int fred() {
     1616        s.t.c = ®S.®R;  // type qualification
     1617        struct ®S.®T t = { ®S.®R, 1, 2 };
     1618        enum ®S.®C c;
     1619        union ®S.T.®U u;
     1620}
     1621\end{cfa}
     1622\end{tabular}
     1623\caption{Type Nesting / Qualification}
     1624\label{f:TypeNestingQualification}
     1625\end{figure}
     1626In the left example in C, types ©C©, ©U© and ©T© are implicitly hoisted outside of type ©S© into the containing block scope.
     1627In the right example in \CFA, the types are not hoisted and accessed using the field-selection operator ``©.©'' for type qualification, as does \Index*{Java}, rather than the \CC type-selection operator ``©::©''.
     1628
     1629
     1630\subsection{Routine Nesting}
     1631
     1632While \CFA does not provide object programming by putting routines into structures, it does rely heavily on locally nested routines to redefine operations at or close to a call site.
     1633For example, the C quick-sort is wrapped into the following polymorphic \CFA routine:
     1634\begin{cfa}
     1635forall( otype T | { int ?<?( T, T ); } )
     1636void qsort( const T * arr, size_t dimension );
     1637\end{cfa}
     1638which can be used to sort in ascending and descending order by locally redefining the less-than operator into greater-than.
     1639\begin{cfa}
     1640const unsigned int size = 5;
     1641int ia[size];
     1642...                                             §\C{// assign values to array ia}§
     1643qsort( ia, size );              §\C{// sort ascending order using builtin ?<?}§
     1644{
     1645        ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§
     1646        qsort( ia, size );      §\C{// sort descending order by local redefinition}§
     1647}
     1648\end{cfa}
     1649
     1650Nested routines are not first-class, meaning a nested routine cannot be returned if it has references to variables in its enclosing blocks;
     1651the only exception is references to the external block of the translation unit, as these variables persist for the duration of the program.
     1652The following program in undefined in \CFA (and Indexc{gcc})
     1653\begin{cfa}
     1654[* [int]( int )] foo() {                §\C{// int (*foo())( int )}§
     1655        int ®i® = 7;
     1656        int bar( int p ) {
     1657                ®i® += 1;                               §\C{// dependent on local variable}§
     1658                sout | ®i® | endl;
     1659        }
     1660        return bar;                                     §\C{// undefined because of local dependence}§
     1661}
     1662int main() {
     1663        * [int]( int ) fp = foo();      §\C{// int (*fp)( int )}§
     1664        sout | fp( 3 ) | endl;
     1665}
     1666\end{cfa}
     1667because
     1668
     1669Currently, there are no \Index{lambda} expressions, \ie unnamed routines because routine names are very important to properly select the correct routine.
     1670
     1671
     1672\section{Tuples}
     1673
     1674In C and \CFA, lists of elements appear in several contexts, such as the parameter list for a routine call.
     1675(More contexts are added shortly.)
     1676A list of such elements is called a \newterm{lexical list}.
     1677The general syntax of a lexical list is:
     1678\begin{cfa}
     1679[ §\emph{exprlist}§ ]
     1680\end{cfa}
     1681where ©$\emph{exprlist}$© is a list of one or more expressions separated by commas.
     1682The brackets, ©[]©, allow differentiating between lexical lists and expressions containing the C comma operator.
     1683The following are examples of lexical lists:
     1684\begin{cfa}
     1685[ x, y, z ]
     1686[ 2 ]
     1687[ v+w, x*y, 3.14159, f() ]
     1688\end{cfa}
     1689Tuples are permitted to contain sub-tuples (\ie nesting), such as ©[ [ 14, 21 ], 9 ]©, which is a 2-element tuple whose first element is itself a tuple.
     1690Note, a tuple is not a record (structure);
     1691a record denotes a single value with substructure, whereas a tuple is multiple values with no substructure (see flattening coercion in Section 12.1).
     1692In essence, tuples are largely a compile time phenomenon, having little or no runtime presence.
     1693
     1694Tuples can be organized into compile-time tuple variables;
     1695these variables are of \newterm{tuple type}.
     1696Tuple variables and types can be used anywhere lists of conventional variables and types can be used.
     1697The general syntax of a tuple type is:
     1698\begin{cfa}
     1699[ §\emph{typelist}§ ]
     1700\end{cfa}
     1701where ©$\emph{typelist}$© is a list of one or more legal \CFA or C type specifications separated by commas, which may include other tuple type specifications.
     1702Examples of tuple types include:
     1703\begin{cfa}
     1704[ unsigned int, char ]
     1705[ double, double, double ]
     1706[ * int, int * ]                §\C{// mix of CFA and ANSI}§
     1707[ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]
     1708\end{cfa}
     1709Like tuples, tuple types may be nested, such as ©[ [ int, int ], int ]©, which is a 2-element tuple type whose first element is itself a tuple type.
     1710
     1711Examples of declarations using tuple types are:
     1712\begin{cfa}
     1713[ int, int ] x;                 §\C{// 2 element tuple, each element of type int}§
     1714* [ char, char ] y;             §\C{// pointer to a 2 element tuple}§
     1715[ [ int, int ] ] z ([ int, int ]);
     1716\end{cfa}
     1717The last example declares an external routine that expects a 2 element tuple as an input parameter and returns a 2 element tuple as its result.
     1718
     1719As mentioned, tuples can appear in contexts requiring a list of value, such as an argument list of a routine call.
     1720In unambiguous situations, the tuple brackets may be omitted, \eg a tuple that appears as an argument may have its
     1721square brackets omitted for convenience; therefore, the following routine invocations are equivalent:
     1722\begin{cfa}
     1723f( [ 1, x+2, fred() ] );
     1724f( 1, x+2, fred() );
     1725\end{cfa}
     1726Also, a tuple or a tuple variable may be used to supply all or part of an argument list for a routine expecting multiple input parameters or for a routine expecting a tuple as an input parameter.
     1727For example, the following are all legal:
     1728\begin{cfa}
     1729[ int, int ] w1;
     1730[ int, int, int ] w2;
     1731[ void ] f (int, int, int); /* three input parameters of type int */
     1732[ void ] g ([ int, int, int ]); /* 3 element tuple as input */
     1733f( [ 1, 2, 3 ] );
     1734f( w1, 3 );
     1735f( 1, w1 );
     1736f( w2 );
     1737g( [ 1, 2, 3 ] );
     1738g( w1, 3 );
     1739g( 1, w1 );
     1740g( w2 );
     1741\end{cfa}
     1742Note, in all cases 3 arguments are supplied even though the syntax may appear to supply less than 3. As mentioned, a
     1743tuple does not have structure like a record; a tuple is simply converted into a list of components.
     1744\begin{rationale}
     1745The present implementation of \CFA does not support nested routine calls when the inner routine returns multiple values; \ie a statement such as ©g( f() )© is not supported.
     1746Using a temporary variable to store the  results of the inner routine and then passing this variable to the outer routine works, however.
     1747\end{rationale}
     1748
     1749A tuple can contain a C comma expression, provided the expression containing the comma operator is enclosed in parentheses.
     1750For instance, the following tuples are equivalent:
     1751\begin{cfa}
     1752[ 1, 3, 5 ]
     1753[ 1, (2, 3), 5 ]
     1754\end{cfa}
     1755The second element of the second tuple is the expression (2, 3), which yields the result 3.
     1756This requirement is the same as for comma expressions in argument lists.
     1757
     1758Type qualifiers, \ie const and volatile, may modify a tuple type.
     1759The meaning is the same as for a type qualifier modifying an aggregate type [Int99, x 6.5.2.3(7),x 6.7.3(11)], \ie the qualifier is distributed across all of the types in the tuple, \eg:
     1760\begin{cfa}
     1761const volatile [ int, float, const int ] x;
     1762\end{cfa}
     1763is equivalent to:
     1764\begin{cfa}
     1765[ const volatile int, const volatile float, const volatile int ] x;
     1766\end{cfa}
     1767Declaration qualifiers can only appear at the start of a \CFA tuple declaration4, \eg:
     1768\begin{cfa}
     1769extern [ int, int ] w1;
     1770static [ int, int, int ] w2;
     1771\end{cfa}
     1772\begin{rationale}
     1773Unfortunately, C's syntax for subscripts precluded treating them as tuples.
     1774The C subscript list has the form ©[i][j]...© and not ©[i, j, ...]©.
     1775Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[g()]© always means a single subscript value because there is only one set of brackets.
     1776Fixing this requires a major change to C because the syntactic form ©M[i, j, k]© already has a particular meaning: ©i, j, k© is a comma expression.
     1777\end{rationale}
     1778
     1779
     1780\subsection{Tuple Coercions}
     1781
     1782There are four coercions that can be performed on tuples and tuple variables: closing, opening, flattening and structuring.
     1783In addition, the coercion of dereferencing can be performed on a tuple variable to yield its value(s), as for other variables.
     1784A \newterm{closing coercion} takes a set of values and converts it into a tuple value, which is a contiguous set of values, as in:
     1785\begin{cfa}
     1786[ int, int, int, int ] w;
     1787w = [ 1, 2, 3, 4 ];
     1788\end{cfa}
     1789First the right-hand tuple is closed into a tuple value and then the tuple value is assigned.
     1790
     1791An \newterm{opening coercion} is the opposite of closing; a tuple value is converted into a tuple of values, as in:
     1792\begin{cfa}
     1793[ a, b, c, d ] = w
     1794\end{cfa}
     1795©w© is implicitly opened to yield a tuple of four values, which are then assigned individually.
     1796
     1797A \newterm{flattening coercion} coerces a nested tuple, \ie a tuple with one or more components, which are themselves tuples, into a flattened tuple, which is a tuple whose components are not tuples, as in:
     1798\begin{cfa}
     1799[ a, b, c, d ] = [ 1, [ 2, 3 ], 4 ];
     1800\end{cfa}
     1801First the right-hand tuple is flattened and then the values are assigned individually.
     1802Flattening is also performed on tuple types.
     1803For example, the type ©[ int, [ int, int ], int ]© can be coerced, using flattening, into the type ©[ int, int, int, int ]©.
     1804
     1805A \newterm{structuring coercion} is the opposite of flattening;
     1806a tuple is structured into a more complex nested tuple.
     1807For example, structuring the tuple ©[ 1, 2, 3, 4 ]© into the tuple ©[ 1, [ 2, 3 ], 4 ]© or the tuple type ©[ int, int, int, int ]© into the tuple type ©[ int, [ int, int ], int ]©.
     1808In the following example, the last assignment illustrates all the tuple coercions:
     1809\begin{cfa}
     1810[ int, int, int, int ] w = [ 1, 2, 3, 4 ];
     1811int x = 5;
     1812[ x, w ] = [ w, x ];            §\C{// all four tuple coercions}§
     1813\end{cfa}
     1814Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values;
     1815therefore, the right-hand tuple is now the tuple ©[ [ 1, 2, 3, 4 ], 5 ]©.
     1816This tuple is then flattened, yielding ©[ 1, 2, 3, 4, 5 ]©, which is structured into ©[ 1, [ 2, 3, 4, 5 ] ]© to match the tuple type of the left-hand side.
     1817The tuple ©[ 2, 3, 4, 5 ]© is then closed to create a tuple value.
     1818Finally, ©x© is assigned ©1© and ©w© is assigned the tuple value using multiple assignment (see Section 14).
     1819\begin{rationale}
     1820A possible additional language extension is to use the structuring coercion for tuples to initialize a complex record with a tuple.
     1821\end{rationale}
     1822
     1823
     1824\section{Mass Assignment}
     1825
     1826\CFA permits assignment to several variables at once using mass assignment~\cite{CLU}.
     1827Mass assignment has the following form:
     1828\begin{cfa}
     1829[ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = §\emph{expr}§;
     1830\end{cfa}
     1831\index{lvalue}
     1832The left-hand side is a tuple of \emph{lvalues}, which is a list of expressions each yielding an address, \ie any data object that can appear on the left-hand side of a conventional assignment statement.
     1833©$\emph{expr}$© is any standard arithmetic expression.
     1834Clearly, the types of the entities being assigned must be type compatible with the value of the expression.
     1835
     1836Mass assignment has parallel semantics, \eg the statement:
     1837\begin{cfa}
     1838[ x, y, z ] = 1.5;
     1839\end{cfa}
     1840is equivalent to:
     1841\begin{cfa}
     1842x = 1.5; y = 1.5; z = 1.5;
     1843\end{cfa}
     1844This semantics is not the same as the following in C:
     1845\begin{cfa}
     1846x = y = z = 1.5;
     1847\end{cfa}
     1848as conversions between intermediate assignments may lose information.
     1849A more complex example is:
     1850\begin{cfa}
     1851[ i, y[i], z ] = a + b;
     1852\end{cfa}
     1853which is equivalent to:
     1854\begin{cfa}
     1855t = a + b;
     1856a1 = &i; a2 = &y[i]; a3 = &z;
     1857*a1 = t; *a2 = t; *a3 = t;
     1858\end{cfa}
     1859The temporary ©t© is necessary to store the value of the expression to eliminate conversion issues.
     1860The temporaries for the addresses are needed so that locations on the left-hand side do not change as the values are assigned.
     1861In this case, ©y[i]© uses the previous value of ©i© and not the new value set at the beginning of the mass assignment.
     1862
     1863
     1864\section{Multiple Assignment}
     1865
     1866\CFA also supports the assignment of several values at once, known as multiple assignment~\cite{CLU,Galletly96}.
     1867Multiple assignment has the following form:
     1868\begin{cfa}
     1869[ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = [ §\emph{expr}§, ... , §\emph{expr}§ ];
     1870\end{cfa}
     1871\index{lvalue}
     1872The left-hand side is a tuple of \emph{lvalues}, and the right-hand side is a tuple of \emph{expr}s.
     1873Each \emph{expr} appearing on the right-hand side of a multiple assignment statement is assigned to the corresponding \emph{lvalues} on the left-hand side of the statement using parallel semantics for each assignment.
     1874An example of multiple assignment is:
     1875\begin{cfa}
     1876[ x, y, z ] = [ 1, 2, 3 ];
     1877\end{cfa}
     1878Here, the values ©1©, ©2© and ©3© are assigned, respectively, to the variables ©x©, ©y© and ©z©.
     1879 A more complex example is:
     1880\begin{cfa}
     1881[ i, y[ i ], z ] = [ 1, i, a + b ];
     1882\end{cfa}
     1883Here, the values ©1©, ©i© and ©a + b© are assigned to the variables ©i©, ©y[i]© and ©z©, respectively.
     1884 Note, the parallel semantics of
     1885multiple assignment ensures:
     1886\begin{cfa}
     1887[ x, y ] = [ y, x ];
     1888\end{cfa}
     1889correctly interchanges (swaps) the values stored in ©x© and ©y©.
     1890The following cases are errors:
     1891\begin{cfa}
     1892[ a, b, c ] = [ 1, 2, 3, 4 ];
     1893[ a, b, c ] = [ 1, 2 ];
     1894\end{cfa}
     1895because the number of entities in the left-hand tuple is unequal with the right-hand tuple.
     1896
     1897As for all tuple contexts in C, side effects should not be used because C does not define an ordering for the evaluation of the elements of a tuple;
     1898both these examples produce indeterminate results:
     1899\begin{cfa}
     1900f( x++, x++ );                          §\C{// C routine call with side effects in arguments}§
     1901[ v1, v2 ] = [ x++, x++ ];      §\C{// side effects in righthand side of multiple assignment}§
     1902\end{cfa}
     1903
     1904
     1905\section{Cascade Assignment}
     1906
     1907As in C, \CFA mass and multiple assignments can be cascaded, producing cascade assignment.
     1908Cascade assignment has the following form:
     1909\begin{cfa}
     1910§\emph{tuple}§ = §\emph{tuple}§ = ... = §\emph{tuple}§;
     1911\end{cfa}
     1912and it has the same parallel semantics as for mass and multiple assignment.
     1913Some examples of cascade assignment are:
     1914\begin{cfa}
     1915x1 = y1 = x2 = y2 = 0;
     1916[ x1, y1 ] = [ x2, y2 ] = [ x3, y3 ];
     1917[ x1, y1 ] = [ x2, y2 ] = 0;
     1918[ x1, y1 ] = z = 0;
     1919\end{cfa}
     1920As in C, the rightmost assignment is performed first, \ie assignment parses right to left.
     1921
     1922
     1923\section{Field Tuples}
     1924
     1925Tuples may be used to select multiple fields of a record by field name.
     1926Its general form is:
     1927\begin{cfa}
     1928§\emph{expr}§ . [ §\emph{fieldlist}§ ]
     1929§\emph{expr}§ -> [ §\emph{fieldlist}§ ]
     1930\end{cfa}
     1931\emph{expr} is any expression yielding a value of type record, \eg ©struct©, ©union©.
     1932Each element of \emph{ fieldlist} is an element of the record specified by \emph{expr}.
     1933A record-field tuple may be used anywhere a tuple can be used. An example of the use of a record-field tuple is
     1934the following:
     1935\begin{cfa}
     1936struct s {
     1937        int f1, f2;
     1938        char f3;
     1939        double f4;
     1940} v;
     1941v.[ f3, f1, f2 ] = ['x', 11, 17 ];      §\C{// equivalent to v.f3 = 'x', v.f1 = 11, v.f2 = 17}§
     1942f( v.[ f3, f1, f2 ] );                          §\C{// equivalent to f( v.f3, v.f1, v.f2 )}§
     1943\end{cfa}
     1944Note, the fields appearing in a record-field tuple may be specified in any order;
     1945also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple.
     1946
     1947If a field of a ©struct© is itself another ©struct©, multiple fields of this subrecord can be specified using a nested record-field tuple, as in the following example:
     1948\begin{cfa}
     1949struct inner {
     1950        int f2, f3;
     1951};
     1952struct outer {
     1953        int f1;
     1954        struct inner i;
     1955        double f4;
     1956} o;
     1957
     1958o.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ];
     1959\end{cfa}
    4911960
    4921961
     
    7802249still works.
    7812250Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments.
    782 Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, \eg:
     2251Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, e.g.:
    7832252\begin{cfa}
    7842253®choose® ( i ) {
     
    9282397
    9292398
    930 \subsection{Exception Hierarchy}
    931 
    932 An exception type can be derived from another exception type, just like deriving a subclass from a class, providing a kind of polymorphism among exception types.
    933 The exception-type hierarchy that is created is used to organize exception types, similar to a class hierarchy in object-oriented languages, \eg:
    934 \begin{center}
    935 \input{EHMHierarchy}
    936 \end{center}
    937 A programmer can then choose to handle an exception at different degrees of specificity along the hierarchy;
    938 derived exception-types support a more flexible programming style.
    939 For example, higher-level code should catch general exceptions to reduce coupling to the specific implementation at the lower levels;
    940 unnecessary coupling may force changes in higher-level code when low-level code changes.
    941 A consequence of derived exception-types is that multiple exceptions may match, \eg:
    942 \begin{cfa}
    943 catch( Arithmetic )
    944 \end{cfa}
    945 matches all three derived exception-types: ©DivideByZero©, ©Overflow©, and ©Underflow©.
    946 Because the propagation mechanisms perform a simple linear search of the handler clause for a guarded block, and selects the first matching handler, the order of catch clauses in the handler clause becomes important, \eg:
    947 \begin{cfa}
    948 try {
    949         ...
    950 } catch( Overflow ) {   // must appear first
    951         // handle overflow
    952 } catch( Arithmetic )
    953         // handle other arithmetic issues
    954 }
    955 \end{cfa}
    956 \newterm{Multiple derivation} among exception is not supported.
    957 
    958 
    959 \section{Declarations}
    960 \label{s:Declarations}
    961 
    962 C declaration syntax is notoriously confusing and error prone.
    963 For example, many C programmers are confused by a declaration as simple as:
    964 \begin{quote2}
    965 \begin{tabular}{@{}ll@{}}
    966 \begin{cfa}
    967 int * x[5]
    968 \end{cfa}
    969 &
    970 \raisebox{-0.75\totalheight}{\input{Cdecl}}
    971 \end{tabular}
    972 \end{quote2}
    973 Is this an array of 5 pointers to integers or a \Index{pointer} to an array of 5 integers?
    974 The fact this declaration is unclear to many C programmers means there are \Index{productivity} and \Index{safety} issues even for basic programs.
    975 Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site.
    976 For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    977 \begin{cfa}
    978 int ®(*®f®())[®5®]® {...};                              §\C{definition}§
    979  ... ®(*®f®())[®3®]® += 1;                              §\C{usage}§
    980 \end{cfa}
    981 Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
    982 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    983 
    984 \CFA provides its own type, variable and routine declarations, using a different syntax.
    985 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type.
    986 In the following example, \R{red} is the base type and \B{blue} is qualifiers.
    987 The \CFA declarations move the qualifiers to the left of the base type, \ie move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type.
    988 \begin{quote2}
    989 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    990 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    991 \begin{cfa}
    992 ß[5] *ß ®int® x1;
    993 ß* [5]ß ®int® x2;
    994 ß[* [5] int]ß f®( int p )®;
    995 \end{cfa}
    996 &
    997 \begin{cfa}
    998 ®int® ß*ß x1 ß[5]ß;
    999 ®int® ß(*ßx2ß)[5]ß;
    1000 ßint (*ßf®( int p )®ß)[5]ß;
    1001 \end{cfa}
    1002 \end{tabular}
    1003 \end{quote2}
    1004 The only exception is \Index{bit field} specification, which always appear to the right of the base type.
    1005 % Specifically, the character ©*© is used to indicate a pointer, square brackets ©[©\,©]© are used to represent an array or function return value, and parentheses ©()© are used to indicate a routine parameter.
    1006 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    1007 For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows:
    1008 \begin{quote2}
    1009 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1010 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1011 \begin{cfa}
    1012 ®*® int x, y;
    1013 \end{cfa}
    1014 &
    1015 \begin{cfa}
    1016 int ®*®x, ®*®y;
    1017 \end{cfa}
    1018 \end{tabular}
    1019 \end{quote2}
    1020 The downside of this semantics is the need to separate regular and \Index{pointer} declarations:
    1021 \begin{quote2}
    1022 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1023 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1024 \begin{cfa}
    1025 ®*® int x;
    1026 int y;
    1027 \end{cfa}
    1028 &
    1029 \begin{cfa}
    1030 int ®*®x, y;
    1031 
    1032 \end{cfa}
    1033 \end{tabular}
    1034 \end{quote2}
    1035 which is \Index{prescribing} a safety benefit.
    1036 Other examples are:
    1037 \begin{quote2}
    1038 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    1039 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    1040 \begin{cfa}
    1041 [ 5 ] int z;
    1042 [ 5 ] * char w;
    1043 * [ 5 ] double v;
    1044 struct s {
    1045         int f0:3;
    1046         * int f1;
    1047         [ 5 ] * int f2;
    1048 };
    1049 \end{cfa}
    1050 &
    1051 \begin{cfa}
    1052 int z[ 5 ];
    1053 char * w[ 5 ];
    1054 double (* v)[ 5 ];
    1055 struct s {
    1056         int f0:3;
    1057         int * f1;
    1058         int * f2[ 5 ]
    1059 };
    1060 \end{cfa}
    1061 &
    1062 \begin{cfa}
    1063 // array of 5 integers
    1064 // array of 5 pointers to char
    1065 // pointer to array of 5 doubles
    1066 
    1067 // common bit field syntax
    1068 
    1069 
    1070 
    1071 \end{cfa}
    1072 \end{tabular}
    1073 \end{quote2}
    1074 
    1075 All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg:
    1076 \begin{quote2}
    1077 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
    1078 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
    1079 \begin{cfa}
    1080 const * const int x;
    1081 const * [ 5 ] const int y;
    1082 \end{cfa}
    1083 &
    1084 \begin{cfa}
    1085 int const * const x;
    1086 const int (* const y)[ 5 ]
    1087 \end{cfa}
    1088 &
    1089 \begin{cfa}
    1090 // const pointer to const integer
    1091 // const pointer to array of 5 const integers
    1092 \end{cfa}
    1093 \end{tabular}
    1094 \end{quote2}
    1095 All declaration qualifiers, \eg ©extern©, ©static©, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier}
    1096 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg:
    1097 \begin{quote2}
    1098 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    1099 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    1100 \begin{cfa}
    1101 extern [ 5 ] int x;
    1102 static * const int y;
    1103 \end{cfa}
    1104 &
    1105 \begin{cfa}
    1106 int extern x[ 5 ];
    1107 const int static * y;
    1108 \end{cfa}
    1109 &
    1110 \begin{cfa}
    1111 // externally visible array of 5 integers
    1112 // internally visible pointer to constant int
    1113 \end{cfa}
    1114 \end{tabular}
    1115 \end{quote2}
    1116 
    1117 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©:
    1118 \begin{quote2}
    1119 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1120 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1121 \begin{cfa}
    1122 y = (®* int®)x;
    1123 i = sizeof(®[ 5 ] * int®);
    1124 \end{cfa}
    1125 &
    1126 \begin{cfa}
    1127 y = (®int *®)x;
    1128 i = sizeof(®int * [ 5 ]®);
    1129 \end{cfa}
    1130 \end{tabular}
    1131 \end{quote2}
    1132 
    1133 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
    1134 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    1135 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX systems.
    1136 
    1137 
    1138 \section{Pointer/Reference}
    1139 
    1140 C provides a \newterm{pointer type};
    1141 \CFA adds a \newterm{reference type}.
    1142 These types may be derived from an object or routine type, called the \newterm{referenced type}.
    1143 Objects of these types contain an \newterm{address}, which is normally a location in memory, but may also address memory-mapped registers in hardware devices.
    1144 An integer constant expression with the value 0, or such an expression cast to type ©void *©, is called a \newterm{null-pointer constant}.\footnote{
    1145 One way to conceptualize the null pointer is that no variable is placed at this address, so the null-pointer address can be used to denote an uninitialized pointer/reference object;
    1146 \ie the null pointer is guaranteed to compare unequal to a pointer to any object or routine.}
    1147 An address is \newterm{sound}, if it points to a valid memory location in scope, \ie within the program's execution-environment and has not been freed.
    1148 Dereferencing an \newterm{unsound} address, including the null pointer, is \Index{undefined}, often resulting in a \Index{memory fault}.
    1149 
    1150 A program \newterm{object} is a region of data storage in the execution environment, the contents of which can represent values.
    1151 In most cases, objects are located in memory at an address, and the variable name for an object is an implicit address to the object generated by the compiler and automatically dereferenced, as in:
    1152 \begin{quote2}
    1153 \begin{tabular}{@{}ll@{\hspace{2em}}l@{}}
    1154 \begin{cfa}
    1155 int x;
    1156 x = 3;
    1157 int y;
    1158 y = x;
    1159 \end{cfa}
    1160 &
    1161 \raisebox{-0.45\totalheight}{\input{pointer1}}
    1162 &
    1163 \begin{cfa}
    1164 int * ®const® x = (int *)100
    1165 *x = 3;                 // implicit dereference
    1166 int * ®const® y = (int *)104;
    1167 *y = *x;                // implicit dereference
    1168 \end{cfa}
    1169 \end{tabular}
    1170 \end{quote2}
    1171 where the right example is how the compiler logically interprets the variables in the left example.
    1172 Since a variable name only points to one address during its lifetime, it is an \Index{immutable} \Index{pointer};
    1173 hence, the implicit type of pointer variables ©x© and ©y© are constant pointers in the compiler interpretation.
    1174 In general, variable addresses are stored in instructions instead of loaded from memory, and hence may not occupy storage.
    1175 These approaches are contrasted in the following:
    1176 \begin{quote2}
    1177 \begin{tabular}{@{}l|l@{}}
    1178 \multicolumn{1}{c|}{explicit variable address} & \multicolumn{1}{c}{implicit variable address} \\
    1179 \hline
    1180 \begin{cfa}
    1181 lda             r1,100                  // load address of x
    1182 ld               r2,(r1)                  // load value of x
    1183 lda             r3,104                  // load address of y
    1184 st               r2,(r3)                  // store x into y
    1185 \end{cfa}
    1186 &
    1187 \begin{cfa}
    1188 
    1189 ld              r2,(100)                // load value of x
    1190 
    1191 st              r2,(104)                // store x into y
    1192 \end{cfa}
    1193 \end{tabular}
    1194 \end{quote2}
    1195 Finally, the immutable nature of a variable's address and the fact that there is no storage for the variable pointer means pointer assignment\index{pointer!assignment}\index{assignment!pointer} is impossible.
    1196 Therefore, the expression ©x = y© has only one meaning, ©*x = *y©, \ie manipulate values, which is why explicitly writing the dereferences is unnecessary even though it occurs implicitly as part of \Index{instruction decoding}.
    1197 
    1198 A \Index{pointer}/\Index{reference} object is a generalization of an object variable-name, \ie a mutable address that can point to more than one memory location during its lifetime.
    1199 (Similarly, an integer variable can contain multiple integer literals during its lifetime versus an integer constant representing a single literal during its lifetime, and like a variable name, may not occupy storage if the literal is embedded directly into instructions.)
    1200 Hence, a pointer occupies memory to store its current address, and the pointer's value is loaded by dereferencing, \eg:
    1201 \begin{quote2}
    1202 \begin{tabular}{@{}l@{\hspace{2em}}l@{}}
    1203 \begin{cfa}
    1204 int x, y, ®*® p1, ®*® p2, ®**® p3;
    1205 p1 = ®&®x;               // p1 points to x
    1206 p2 = p1;                 // p2 points to x
    1207 p1 = ®&®y;               // p1 points to y
    1208 p3 = &p2;               // p3 points to p2
    1209 \end{cfa}
    1210 &
    1211 \raisebox{-0.5\totalheight}{\input{pointer2.pstex_t}}
    1212 \end{tabular}
    1213 \end{quote2}
    1214 
    1215 Notice, an address has a \Index{duality}\index{address!duality}: a location in memory or the value at that location.
    1216 In many cases, a compiler might be able to infer the best meaning for these two cases.
    1217 For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage
    1218 \begin{cfa}
    1219 p2 = p1 + x;                                    §\C{// compiler infers *p2 = *p1 + x;}§
    1220 \end{cfa}
    1221 Algol68 infers the following dereferencing ©*p2 = *p1 + x©, because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation.
    1222 Unfortunately, automatic dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices.
    1223 
    1224 Rather than inferring dereference, most programming languages pick one implicit dereferencing semantics, and the programmer explicitly indicates the other to resolve address-duality.
    1225 In C, objects of pointer type always manipulate the pointer object's address:
    1226 \begin{cfa}
    1227 p1 = p2;                                                §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
    1228 p2 = p1 + x;                                    §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
    1229 \end{cfa}
    1230 even though the assignment to ©p2© is likely incorrect, and the programmer probably meant:
    1231 \begin{cfa}
    1232 p1 = p2;                                                §\C{// pointer address assignment}§
    1233 ®*®p2 = ®*®p1 + x;                              §\C{// pointed-to value assignment / operation}§
    1234 \end{cfa}
    1235 The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©).
    1236 
    1237 However, in most other situations, the pointed-to value is requested more often than the pointer address.
    1238 \begin{cfa}
    1239 *p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);
    1240 \end{cfa}
    1241 In this case, it is tedious to explicitly write the dereferencing, and error prone when pointer arithmetic is allowed.
    1242 It is better to have the compiler generate the dereferencing and have no implicit pointer arithmetic:
    1243 \begin{cfa}
    1244 p2 = ((p1 + p2) * (p3 - p1)) / (p3 - 15);
    1245 \end{cfa}
    1246 
    1247 To support this common case, a reference type is introduced in \CFA, denoted by ©&©, which is the opposite dereference semantics to a pointer type, making the value at the pointed-to location the implicit semantics for dereferencing (similar but not the same as \CC \Index{reference type}s).
    1248 \begin{cfa}
    1249 int x, y, ®&® r1, ®&® r2, ®&&® r3;
    1250 ®&®r1 = &x;                                             §\C{// r1 points to x}§
    1251 ®&®r2 = &r1;                                    §\C{// r2 points to x}§
    1252 ®&®r1 = &y;                                             §\C{// r1 points to y}§
    1253 ®&&®r3 = ®&®&r2;                                §\C{// r3 points to r2}§
    1254 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§
    1255 \end{cfa}
    1256 Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer example.
    1257 Hence, a reference behaves like the variable name for the current variable it is pointing-to.
    1258 One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in a declaration, so the previous example becomes:
    1259 \begin{cfa}
    1260 ®*®r2 = ((®*®r1 + ®*®r2) ®*® (®**®r3 - ®*®r1)) / (®**®r3 - 15);
    1261 \end{cfa}
    1262 When a reference operation appears beside a dereference operation, \eg ©&*©, they cancel out.
    1263 However, in C, the cancellation always yields a value (\Index{rvalue}).\footnote{
    1264 The unary ©&© operator yields the address of its operand.
    1265 If the operand has type ``type'', the result has type ``pointer to type''.
    1266 If the operand is the result of a unary ©*© operator, neither that operator nor the ©&© operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.~\cite[\S~6.5.3.2--3]{C11}}
    1267 For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}):
    1268 \begin{cfa}
    1269 (&®*®)r1 = &x;                                  §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
    1270 \end{cfa}
    1271 Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}):
    1272 \begin{cfa}
    1273 (&(&®*®)®*®)r3 = &(&®*®)r2;             §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
    1274 \end{cfa}
    1275 Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth.
    1276 
    1277 Fundamentally, pointer and reference objects are functionally interchangeable because both contain addresses.
    1278 \begin{cfa}
    1279 int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    1280                  &r1 = x,    &&r2 = r1,   &&&r3 = r2;
    1281 ***p3 = 3;                                              §\C{// change x}§
    1282 r3 = 3;                                                 §\C{// change x, ***r3}§
    1283 **p3 = ...;                                             §\C{// change p1}§
    1284 &r3 = ...;                                              §\C{// change r1, (\&*)**r3, 1 cancellation}§
    1285 *p3 = ...;                                              §\C{// change p2}§
    1286 &&r3 = ...;                                             §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§
    1287 &&&r3 = p3;                                             §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§
    1288 \end{cfa}
    1289 Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.
    1290 Therefore, the choice between them is based solely on whether the address is dereferenced frequently or infrequently, which dictates the amount of implicit dereferencing aid from the compiler.
    1291 
    1292 As for a pointer type, a reference type may have qualifiers:
    1293 \begin{cfa}
    1294 const int cx = 5;                                       §\C{// cannot change cx;}§
    1295 const int & cr = cx;                            §\C{// cannot change what cr points to}§
    1296 ®&®cr = &cx;                                            §\C{// can change cr}§
    1297 cr = 7;                                                         §\C{// error, cannot change cx}§
    1298 int & const rc = x;                                     §\C{// must be initialized}§
    1299 ®&®rc = &x;                                                     §\C{// error, cannot change rc}§
    1300 const int & const crc = cx;                     §\C{// must be initialized}§
    1301 crc = 7;                                                        §\C{// error, cannot change cx}§
    1302 ®&®crc = &cx;                                           §\C{// error, cannot change crc}§
    1303 \end{cfa}
    1304 Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}:
    1305 \begin{cfa}
    1306 int & const cr = *0;                            §\C{// where 0 is the int * zero}§
    1307 \end{cfa}
    1308 Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management:
    1309 \begin{cfa}
    1310 int & const cr = *malloc();
    1311 cr = 5;
    1312 free( &cr );
    1313 cr = 7;                                                         §\C{// unsound pointer dereference}§
    1314 \end{cfa}
    1315 
    1316 The position of the ©const© qualifier \emph{after} the pointer/reference qualifier causes confuse for C programmers.
    1317 The ©const© qualifier cannot be moved before the pointer/reference qualifier for C style-declarations;
    1318 \CFA-style declarations (see \VRef{s:Declarations}) attempt to address this issue:
    1319 \begin{quote2}
    1320 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1321 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1322 \begin{cfa}
    1323 ®const® * ®const® * const int ccp;
    1324 ®const® & ®const® & const int ccr;
    1325 \end{cfa}
    1326 &
    1327 \begin{cfa}
    1328 const int * ®const® * ®const® ccp;
    1329 
    1330 \end{cfa}
    1331 \end{tabular}
    1332 \end{quote2}
    1333 where the \CFA declaration is read left-to-right.
    1334 
    1335 Finally, like pointers, references are usable and composable with other type operators and generators.
    1336 \begin{cfa}
    1337 int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§
    1338 &ar[1] = &w;                                            §\C{// change reference array element}§
    1339 typeof( ar[1] ) p;                                      §\C{// (gcc) is int, i.e., the type of referenced object}§
    1340 typeof( &ar[1] ) q;                                     §\C{// (gcc) is int \&, i.e., the type of reference}§
    1341 sizeof( ar[1] ) == sizeof( int );       §\C{// is true, i.e., the size of referenced object}§
    1342 sizeof( &ar[1] ) == sizeof( int *)      §\C{// is true, i.e., the size of a reference}§
    1343 \end{cfa}
    1344 
    1345 In contrast to \CFA reference types, \Index*[C++]{\CC{}}'s reference types are all ©const© references, preventing changes to the reference address, so only value assignment is possible, which eliminates half of the \Index{address duality}.
    1346 Also, \CC does not allow \Index{array}s\index{array!reference} of reference\footnote{
    1347 The reason for disallowing arrays of reference is unknown, but possibly comes from references being ethereal (like a textual macro), and hence, replaceable by the referant object.}
    1348 \Index*{Java}'s reference types to objects (all Java objects are on the heap) are like C pointers, which always manipulate the address, and there is no (bit-wise) object assignment, so objects are explicitly cloned by shallow or deep copying, which eliminates half of the address duality.
    1349 
    1350 
    1351 \subsection{Initialization}
    1352 
    1353 \Index{Initialization} is different than \Index{assignment} because initialization occurs on the empty (uninitialized) storage on an object, while assignment occurs on possibly initialized storage of an object.
    1354 There are three initialization contexts in \CFA: declaration initialization, argument/parameter binding, return/temporary binding.
    1355 Because the object being initialized has no value, there is only one meaningful semantics with respect to address duality: it must mean address as there is no pointed-to value.
    1356 In contrast, the left-hand side of assignment has an address that has a duality.
    1357 Therefore, for pointer/reference initialization, the initializing value must be an address not a value.
    1358 \begin{cfa}
    1359 int * p = &x;                                           §\C{// assign address of x}§
    1360 ®int * p = x;®                                          §\C{// assign value of x}§
    1361 int & r = x;                                            §\C{// must have address of x}§
    1362 \end{cfa}
    1363 Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of ©x© into a pointer is meaningful (again, a warning is usually given).
    1364 Therefore, for safety, this context requires an address, so it is superfluous to require explicitly taking the address of the initialization object, even though the type is incorrect.
    1365 Note, this is strictly a convenience and safety feature for a programmer.
    1366 Hence, \CFA allows ©r© to be assigned ©x© because it infers a reference for ©x©, by implicitly inserting a address-of operator, ©&©, and it is an error to put an ©&© because the types no longer match due to the implicit dereference.
    1367 Unfortunately, C allows ©p© to be assigned with ©&x© (address) or ©x© (value), but most compilers warn about the latter assignment as being potentially incorrect.
    1368 Similarly, when a reference type is used for a parameter/return type, the call-site argument does not require a reference operator for the same reason.
    1369 \begin{cfa}
    1370 int & f( int & r );                                     §\C{// reference parameter and return}§
    1371 z = f( x ) + f( y );                            §\C{// reference operator added, temporaries needed for call results}§
    1372 \end{cfa}
    1373 Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©.
    1374 Since operator routine ©?+?© takes its arguments by value, the references returned from ©f© are used to initialize compiler generated temporaries with value semantics that copy from the references.
    1375 \begin{cfa}
    1376 int temp1 = f( x ), temp2 = f( y );
    1377 z = temp1 + temp2;
    1378 \end{cfa}
    1379 This \Index{implicit referencing} is crucial for reducing the syntactic burden for programmers when using references;
    1380 otherwise references have the same syntactic  burden as pointers in these contexts.
    1381 
    1382 When a pointer/reference parameter has a ©const© value (immutable), it is possible to pass literals and expressions.
    1383 \begin{cfa}
    1384 void f( ®const® int & cr );
    1385 void g( ®const® int * cp );
    1386 f( 3 );                   g( ®&®3 );
    1387 f( x + y );             g( ®&®(x + y) );
    1388 \end{cfa}
    1389 Here, the compiler passes the address to the literal 3 or the temporary for the expression ©x + y©, knowing the argument cannot be changed through the parameter.
    1390 The ©&© before the constant/expression for the pointer-type parameter (©g©) is a \CFA extension necessary to type match and is a common requirement before a variable in C (\eg ©scanf©).
    1391 Importantly, ©&3© may not be equal to ©&3©, where the references occur across calls because the temporaries maybe different on each call.
    1392 
    1393 \CFA \emph{extends} this semantics to a mutable pointer/reference parameter, and the compiler implicitly creates the necessary temporary (copying the argument), which is subsequently pointed-to by the reference parameter and can be changed.\footnote{
    1394 If whole program analysis is possible, and shows the parameter is not assigned, \ie it is ©const©, the temporary is unnecessary.}
    1395 \begin{cfa}
    1396 void f( int & r );
    1397 void g( int * p );
    1398 f( 3 );                   g( ®&®3 );            §\C{// compiler implicit generates temporaries}§
    1399 f( x + y );             g( ®&®(x + y) );        §\C{// compiler implicit generates temporaries}§
    1400 \end{cfa}
    1401 Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{
    1402 This conversion attempts to address the \newterm{const hell} problem, when the innocent addition of a ©const© qualifier causes a cascade of type failures, requiring an unknown number of additional ©const© qualifiers, until it is discovered a ©const© qualifier cannot be added and all the ©const© qualifiers must be removed.}
    1403 The implicit conversion allows seamless calls to any routine without having to explicitly name/copy the literal/expression to allow the call.
    1404 
    1405 %\CFA attempts to handle pointers and references in a uniform, symmetric manner.
    1406 Finally, C handles \Index{routine object}s in an inconsistent way.
    1407 A routine object is both a pointer and a reference (\Index{particle and wave}).
    1408 \begin{cfa}
    1409 void f( int i );
    1410 void (*fp)( int );                                      §\C{// routine pointer}§
    1411 fp = f;                                                         §\C{// reference initialization}§
    1412 fp = &f;                                                        §\C{// pointer initialization}§
    1413 fp = *f;                                                        §\C{// reference initialization}§
    1414 fp(3);                                                          §\C{// reference invocation}§
    1415 (*fp)(3);                                                       §\C{// pointer invocation}§
    1416 \end{cfa}
    1417 While C's treatment of routine objects has similarity to inferring a reference type in initialization contexts, the examples are assignment not initialization, and all possible forms of assignment are possible (©f©, ©&f©, ©*f©) without regard for type.
    1418 Instead, a routine object should be referenced by a ©const© reference:
    1419 \begin{cfa}
    1420 ®const® void (®&® fr)( int ) = f;       §\C{// routine reference}§
    1421 fr = ...                                                        §\C{// error, cannot change code}§
    1422 &fr = ...;                                                      §\C{// changing routine reference}§
    1423 fr( 3 );                                                        §\C{// reference call to f}§
    1424 (*fr)(3);                                                       §\C{// error, incorrect type}§
    1425 \end{cfa}
    1426 because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{
    1427 Dynamic code rewriting is possible but only in special circumstances.}
    1428 \CFA allows this additional use of references for routine objects in an attempt to give a more consistent meaning for them.
    1429 
    1430 
    1431 \subsection{Address-of Semantics}
    1432 
    1433 In C, ©&E© is an rvalue for any expression ©E©.
    1434 \CFA extends the ©&© (address-of) operator as follows:
    1435 \begin{itemize}
    1436 \item
    1437 if ©R© is an \Index{rvalue} of type ©T &$_1$...&$_r$© where $r \ge 1$ references (©&© symbols) than ©&R© has type ©T ®*®&$_{\color{red}2}$...&$_{\color{red}r}$©, \ie ©T© pointer with $r-1$ references (©&© symbols).
    1438 
    1439 \item
    1440 if ©L© is an \Index{lvalue} of type ©T &$_1$...&$_l$© where $l \ge 0$ references (©&© symbols) then ©&L© has type ©T ®*®&$_{\color{red}1}$...&$_{\color{red}l}$©, \ie ©T© pointer with $l$ references (©&© symbols).
    1441 \end{itemize}
    1442 The following example shows the first rule applied to different \Index{rvalue} contexts:
    1443 \begin{cfa}
    1444 int x, * px, ** ppx, *** pppx, **** ppppx;
    1445 int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    1446 x = rrrx;               // rrrx is an lvalue with type int &&& (equivalent to x)
    1447 px = &rrrx;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (&x)
    1448 ppx = &&rrrx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (&rx)
    1449 pppx = &&&rrrx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (&rrx)
    1450 ppppx = &&&&rrrx; // starting from &&&rrrx, &&&&rrrx is an rvalue with type int **** (&rrrx)
    1451 \end{cfa}
    1452 The following example shows the second rule applied to different \Index{lvalue} contexts:
    1453 \begin{cfa}
    1454 int x, * px, ** ppx, *** pppx;
    1455 int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    1456 rrrx = 2;               // rrrx is an lvalue with type int &&& (equivalent to x)
    1457 &rrrx = px;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (rx)
    1458 &&rrrx = ppx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (rrx)
    1459 &&&rrrx = pppx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (rrrx)
    1460 \end{cfa}
    1461 
    1462 
    1463 \subsection{Conversions}
    1464 
    1465 C provides a basic implicit conversion to simplify variable usage:
    1466 \begin{enumerate}
    1467 \setcounter{enumi}{-1}
    1468 \item
    1469 lvalue to rvalue conversion: ©cv T© converts to ©T©, which allows implicit variable dereferencing.
    1470 \begin{cfa}
    1471 int x;
    1472 x + 1;                  // lvalue variable (int) converts to rvalue for expression
    1473 \end{cfa}
    1474 An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped.
    1475 \end{enumerate}
    1476 \CFA provides three new implicit conversion for reference types to simplify reference usage.
    1477 \begin{enumerate}
    1478 \item
    1479 reference to rvalue conversion: ©cv T &© converts to ©T©, which allows implicit reference dereferencing.
    1480 \begin{cfa}
    1481 int x, &r = x, f( int p );
    1482 x = ®r® + f( ®r® );  // lvalue reference converts to rvalue
    1483 \end{cfa}
    1484 An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped.
    1485 
    1486 \item
    1487 lvalue to reference conversion: \lstinline[deletekeywords={lvalue}]@lvalue-type cv1 T@ converts to ©cv2 T &©, which allows implicitly converting variables to references.
    1488 \begin{cfa}
    1489 int x, &r = ®x®, f( int & p ); // lvalue variable (int) convert to reference (int &)
    1490 f( ®x® );               // lvalue variable (int) convert to reference (int &)
    1491 \end{cfa}
    1492 Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost.
    1493 Conversion can expand a type, where ©cv1© $>$ ©cv2©, \eg passing a ©const volatile int© to an ©int &©, which has high cost (\Index{warning});
    1494 furthermore, if ©cv1© has ©const© but not ©cv2©, a temporary variable is created to preserve the immutable lvalue.
    1495 
    1496 \item
    1497 rvalue to reference conversion: ©T© converts to ©cv T &©, which allows binding references to temporaries.
    1498 \begin{cfa}
    1499 int x, & f( int & p );
    1500 f( ®x + 3® );   // rvalue parameter (int) implicitly converts to lvalue temporary reference (int &)
    1501 ®&f®(...) = &x; // rvalue result (int &) implicitly converts to lvalue temporary reference (int &)
    1502 \end{cfa}
    1503 In both case, modifications to the temporary are inaccessible (\Index{warning}).
    1504 Conversion expands the temporary-type with ©cv©, which is low cost since the temporary is inaccessible.
    1505 \end{enumerate}
    1506 
    1507 
    1508 \begin{comment}
    1509 From: Richard Bilson <rcbilson@gmail.com>
    1510 Date: Wed, 13 Jul 2016 01:58:58 +0000
    1511 Subject: Re: pointers / references
    1512 To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca>
    1513 
    1514 As a general comment I would say that I found the section confusing, as you move back and forth
    1515 between various real and imagined programming languages. If it were me I would rewrite into two
    1516 subsections, one that specifies precisely the syntax and semantics of reference variables and
    1517 another that provides the rationale.
    1518 
    1519 I don't see any obvious problems with the syntax or semantics so far as I understand them. It's not
    1520 obvious that the description you're giving is complete, but I'm sure you'll find the special cases
    1521 as you do the implementation.
    1522 
    1523 My big gripes are mostly that you're not being as precise as you need to be in your terminology, and
    1524 that you say a few things that aren't actually true even though I generally know what you mean.
    1525 
    1526 20 C provides a pointer type; CFA adds a reference type. Both types contain an address, which is normally a
    1527 21 location in memory.
    1528 
    1529 An address is not a location in memory; an address refers to a location in memory. Furthermore it
    1530 seems weird to me to say that a type "contains" an address; rather, objects of that type do.
    1531 
    1532 21 Special addresses are used to denote certain states or access co-processor memory. By
    1533 22 convention, no variable is placed at address 0, so addresses like 0, 1, 2, 3 are often used to denote no-value
    1534 23 or other special states.
    1535 
    1536 This isn't standard C at all. There has to be one null pointer representation, but it doesn't have
    1537 to be a literal zero representation and there doesn't have to be more than one such representation.
    1538 
    1539 23 Often dereferencing a special state causes a memory fault, so checking is necessary
    1540 24 during execution.
    1541 
    1542 I don't see the connection between the two clauses here. I feel like if a bad pointer will not cause
    1543 a memory fault then I need to do more checking, not less.
    1544 
    1545 24 If the programming language assigns addresses, a program's execution is sound, \ie all
    1546 25 addresses are to valid memory locations.
    1547 
    1548 You haven't said what it means to "assign" an address, but if I use my intuitive understanding of
    1549 the term I don't see how this can be true unless you're assuming automatic storage management.
    1550 
    1551 1 Program variables are implicit pointers to memory locations generated by the compiler and automatically
    1552 2 dereferenced, as in:
    1553 
    1554 There is no reason why a variable needs to have a location in memory, and indeed in a typical
    1555 program many variables will not. In standard terminology an object identifier refers to data in the
    1556 execution environment, but not necessarily in memory.
    1557 
    1558 13 A pointer/reference is a generalization of a variable name, \ie a mutable address that can point to more
    1559 14 than one memory location during its lifetime.
    1560 
    1561 I feel like you're off the reservation here. In my world there are objects of pointer type, which
    1562 seem to be what you're describing here, but also pointer values, which can be stored in an object of
    1563 pointer type but don't necessarily have to be. For example, how would you describe the value denoted
    1564 by "&main" in a C program? I would call it a (function) pointer, but that doesn't satisfy your
    1565 definition.
    1566 
    1567 16 not occupy storage as the literal is embedded directly into instructions.) Hence, a pointer occupies memory
    1568 17 to store its current address, and the pointer's value is loaded by dereferencing, \eg:
    1569 
    1570 As with my general objection regarding your definition of variables, there is no reason why a
    1571 pointer variable (object of pointer type) needs to occupy memory.
    1572 
    1573 21 p2 = p1 + x; // compiler infers *p2 = *p1 + x;
    1574 
    1575 What language are we in now?
    1576 
    1577 24 pointer usage. However, in C, the following cases are ambiguous, especially with pointer arithmetic:
    1578 25 p1 = p2; // p1 = p2 or *p1 = *p2
    1579 
    1580 This isn't ambiguous. it's defined to be the first option.
    1581 
    1582 26 p1 = p1 + 1; // p1 = p1 + 1 or *p1 = *p1 + 1
    1583 
    1584 Again, this statement is not ambiguous.
    1585 
    1586 13 example. Hence, a reference behaves like the variable name for the current variable it is pointing-to. The
    1587 14 simplest way to understand a reference is to imagine the compiler inserting a dereference operator before
    1588 15 the reference variable for each reference qualifier in a declaration, \eg:
    1589 
    1590 It's hard for me to understand who the audience for this part is. I think a practical programmer is
    1591 likely to be satisfied with "a reference behaves like the variable name for the current variable it
    1592 is pointing-to," maybe with some examples. Your "simplest way" doesn't strike me as simpler than
    1593 that. It feels like you're trying to provide a more precise definition for the semantics of
    1594 references, but it isn't actually precise enough to be a formal specification. If you want to
    1595 express the semantics of references using rewrite rules that's a great way to do it, but lay the
    1596 rules out clearly, and when you're showing an example of rewriting keep your
    1597 references/pointers/values separate (right now, you use \eg "r3" to mean a reference, a pointer,
    1598 and a value).
    1599 
    1600 24 Cancellation works to arbitrary depth, and pointer and reference values are interchangeable because both
    1601 25 contain addresses.
    1602 
    1603 Except they're not interchangeable, because they have different and incompatible types.
    1604 
    1605 40 Interestingly, C++ deals with the address duality by making the pointed-to value the default, and prevent-
    1606 41 ing changes to the reference address, which eliminates half of the duality. Java deals with the address duality
    1607 42 by making address assignment the default and requiring field assignment (direct or indirect via methods),
    1608 43 \ie there is no builtin bit-wise or method-wise assignment, which eliminates half of the duality.
    1609 
    1610 I can follow this but I think that's mostly because I already understand what you're trying to
    1611 say. I don't think I've ever heard the term "method-wise assignment" and I don't see you defining
    1612 it. Furthermore Java does have value assignment of basic (non-class) types, so your summary here
    1613 feels incomplete. (If it were me I'd drop this paragraph rather than try to save it.)
    1614 
    1615 11 Hence, for type & const, there is no pointer assignment, so &rc = &x is disallowed, and the address value
    1616 12 cannot be 0 unless an arbitrary pointer is assigned to the reference.
    1617 
    1618 Given the pains you've taken to motivate every little bit of the semantics up until now, this last
    1619 clause ("the address value cannot be 0") comes out of the blue. It seems like you could have
    1620 perfectly reasonable semantics that allowed the initialization of null references.
    1621 
    1622 12 In effect, the compiler is managing the
    1623 13 addresses for type & const not the programmer, and by a programming discipline of only using references
    1624 14 with references, address errors can be prevented.
    1625 
    1626 Again, is this assuming automatic storage management?
    1627 
    1628 18 rary binding. For reference initialization (like pointer), the initializing value must be an address (lvalue) not
    1629 19 a value (rvalue).
    1630 
    1631 This sentence appears to suggest that an address and an lvalue are the same thing.
    1632 
    1633 20 int * p = &x; // both &x and x are possible interpretations
    1634 
    1635 Are you saying that we should be considering "x" as a possible interpretation of the initializer
    1636 "&x"? It seems to me that this expression has only one legitimate interpretation in context.
    1637 
    1638 21 int & r = x; // x unlikely interpretation, because of auto-dereferencing
    1639 
    1640 You mean, we can initialize a reference using an integer value? Surely we would need some sort of
    1641 cast to induce that interpretation, no?
    1642 
    1643 22 Hence, the compiler implicitly inserts a reference operator, &, before the initialization expression.
    1644 
    1645 But then the expression would have pointer type, which wouldn't be compatible with the type of r.
    1646 
    1647 22 Similarly,
    1648 23 when a reference is used for a parameter/return type, the call-site argument does not require a reference
    1649 24 operator.
    1650 
    1651 Furthermore, it would not be correct to use a reference operator.
    1652 
    1653 45 The implicit conversion allows
    1654 1 seamless calls to any routine without having to explicitly name/copy the literal/expression to allow the call.
    1655 2 While C' attempts to handle pointers and references in a uniform, symmetric manner, C handles routine
    1656 3 variables in an inconsistent way: a routine variable is both a pointer and a reference (particle and wave).
    1657 
    1658 After all this talk of how expressions can have both pointer and value interpretations, you're
    1659 disparaging C because it has expressions that have both pointer and value interpretations?
    1660 
    1661 On Sat, Jul 9, 2016 at 4:18 PM Peter A. Buhr <pabuhr@plg.uwaterloo.ca> wrote:
    1662 > Aaron discovered a few places where "&"s are missing and where there are too many "&", which are
    1663 > corrected in the attached updated. None of the text has changed, if you have started reading
    1664 > already.
    1665 \end{comment}
    1666 
    1667 
    1668 \section{Routine Definition}
    1669 
    1670 \CFA also supports a new syntax for routine definition, as well as \Celeven and K\&R routine syntax.
    1671 The point of the new syntax is to allow returning multiple values from a routine~\cite{Galletly96,CLU}, \eg:
    1672 \begin{cfa}
    1673 ®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) {
    1674         §\emph{routine body}§
    1675 }
    1676 \end{cfa}
    1677 where routine ©f© has three output (return values) and three input parameters.
    1678 Existing C syntax cannot be extended with multiple return types because it is impossible to embed a single routine name within multiple return type specifications.
    1679 
    1680 In detail, the brackets, ©[]©, enclose the result type, where each return value is named and that name is a local variable of the particular return type.\footnote{
    1681 \Index*{Michael Tiemann}, with help from \Index*{Doug Lea}, provided named return values in g++, circa 1989.}
    1682 The value of each local return variable is automatically returned at routine termination.
    1683 Declaration qualifiers can only appear at the start of a routine definition, \eg:
    1684 \begin{cfa}
    1685 ®extern® [ int x ] g( int y ) {§\,§}
    1686 \end{cfa}
    1687 Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified;
    1688 in both cases the type is assumed to be void as opposed to old style C defaults of int return type and unknown parameter types, respectively, as in:
    1689 \begin{cfa}
    1690 [§\,§] g();                                                     §\C{// no input or output parameters}§
    1691 [ void ] g( void );                                     §\C{// no input or output parameters}§
    1692 \end{cfa}
    1693 
    1694 Routine f is called as follows:
    1695 \begin{cfa}
    1696 [ i, j, ch ] = f( 3, 'a', ch );
    1697 \end{cfa}
    1698 The list of return values from f and the grouping on the left-hand side of the assignment is called a \newterm{return list} and discussed in Section 12.
    1699 
    1700 \CFA style declarations cannot be used to declare parameters for K\&R style routine definitions because of the following ambiguity:
    1701 \begin{cfa}
    1702 int (*f(x))[ 5 ] int x; {}
    1703 \end{cfa}
    1704 The string ``©int (*f(x))[ 5 ]©'' declares a K\&R style routine of type returning a pointer to an array of 5 integers, while the string ``©[ 5 ] int x©'' declares a \CFA style parameter x of type array of 5 integers.
    1705 Since the strings overlap starting with the open bracket, ©[©, there is an ambiguous interpretation for the string.
    1706 As well, \CFA-style declarations cannot be used to declare parameters for C-style routine-definitions because of the following ambiguity:
    1707 \begin{cfa}
    1708 typedef int foo;
    1709 int f( int (* foo) );                           §\C{// foo is redefined as a parameter name}§
    1710 \end{cfa}
    1711 The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo.
    1712 The redefinition of a type name in a parameter list is the only context in C where the character ©*© can appear to the left of a type name, and \CFA relies on all type qualifier characters appearing to the right of the type name.
    1713 The inability to use \CFA declarations in these two contexts is probably a blessing because it precludes programmers from arbitrarily switching between declarations forms within a declaration contexts.
    1714 
    1715 C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg:
    1716 \begin{cfa}
    1717 [ int ] f( * int, int * );                      §\C{// returns an integer, accepts 2 pointers to integers}§
    1718 [ * int, int * ] f( int );                      §\C{// returns 2 pointers to integers, accepts an integer}§
    1719 \end{cfa}
    1720 The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in:
    1721 \begin{cfa}
    1722 #define ptoa( n, d ) int (*n)[ d ]
    1723 int f( ptoa( p, 5 ) ) ...                       §\C{// expands to int f( int (*p)[ 5 ] )}§
    1724 [ int ] f( ptoa( p, 5 ) ) ...           §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§
    1725 \end{cfa}
    1726 Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms.
    1727 
    1728 
    1729 \subsection{Named Return Values}
    1730 
    1731 \Index{Named return values} handle the case where it is necessary to define a local variable whose value is then returned in a ©return© statement, as in:
    1732 \begin{cfa}
    1733 int f() {
    1734         int x;
    1735         ... x = 0; ... x = y; ...
    1736         return x;
    1737 }
    1738 \end{cfa}
    1739 Because the value in the return variable is automatically returned when a \CFA routine terminates, the ©return© statement \emph{does not} contain an expression, as in:
    1740 \newline
    1741 \begin{minipage}{\linewidth}
    1742 \begin{cfa}
    1743 ®[ int x, int y ]® f() {
    1744         int z;
    1745         ... x = 0; ... y = z; ...
    1746         ®return;®                                                       §\C{// implicitly return x, y}§
    1747 }
    1748 \end{cfa}
    1749 \end{minipage}
    1750 \newline
    1751 When the return is encountered, the current values of ©x© and ©y© are returned to the calling routine.
    1752 As well, ``falling off the end'' of a routine without a ©return© statement is permitted, as in:
    1753 \begin{cfa}
    1754 [ int x, int y ] f() {
    1755         ...
    1756 }                                                                               §\C{// implicitly return x, y}§
    1757 \end{cfa}
    1758 In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered.
    1759 
    1760 Named return values may be used in conjunction with named parameter values;
    1761 specifically, a return and parameter can have the same name.
    1762 \begin{cfa}
    1763 [ int x, int y ] f( int, x, int y ) {
    1764         ...
    1765 }                                                                               §\C{// implicitly return x, y}§
    1766 \end{cfa}
    1767 This notation allows the compiler to eliminate temporary variables in nested routine calls.
    1768 \begin{cfa}
    1769 [ int x, int y ] f( int, x, int y );    §\C{// prototype declaration}§
    1770 int a, b;
    1771 [a, b] = f( f( f( a, b ) ) );
    1772 \end{cfa}
    1773 While the compiler normally ignores parameters names in prototype declarations, here they are used to eliminate temporary return-values by inferring that the results of each call are the inputs of the next call, and ultimately, the left-hand side of the assignment.
    1774 Hence, even without the body of routine ©f© (separate compilation), it is possible to perform a global optimization across routine calls.
    1775 The compiler warns about naming inconsistencies between routine prototype and definition in this case, and behaviour is \Index{undefined} if the programmer is inconsistent.
    1776 
    1777 
    1778 \subsection{Routine Prototype}
    1779 
    1780 The syntax of the new routine prototype declaration follows directly from the new routine definition syntax;
    1781 as well, parameter names are optional, \eg:
    1782 \begin{cfa}
    1783 [ int x ] f ();                                                 §\C{// returning int with no parameters}§
    1784 [ * int ] g (int y);                                    §\C{// returning pointer to int with int parameter}§
    1785 [ ] h ( int, char );                                    §\C{// returning no result with int and char parameters}§
    1786 [ * int, int ] j ( int );                               §\C{// returning pointer to int and int, with int parameter}§
    1787 \end{cfa}
    1788 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
    1789 It is possible to declare multiple routine-prototypes in a single declaration, but the entire type specification is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
    1790 \begin{quote2}
    1791 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1792 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1793 \begin{cfa}
    1794 [ int ] f( int ), g;
    1795 \end{cfa}
    1796 &
    1797 \begin{cfa}
    1798 int f( int ), g( int );
    1799 \end{cfa}
    1800 \end{tabular}
    1801 \end{quote2}
    1802 Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg:
    1803 \begin{cfa}
    1804 extern [ int ] f ( int );
    1805 static [ int ] g ( int );
    1806 \end{cfa}
    1807 
    1808 
    1809 \section{Routine Pointers}
    1810 
    1811 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    1812 \begin{cfa}
    1813 * [ int x ] () fp;                                              §\C{// pointer to routine returning int with no parameters}§
    1814 * [ * int ] (int y) gp;                                 §\C{// pointer to routine returning pointer to int with int parameter}§
    1815 * [ ] (int,char) hp;                                    §\C{// pointer to routine returning no result with int and char parameters}§
    1816 * [ * int,int ] ( int ) jp;                             §\C{// pointer to routine returning pointer to int and int, with int parameter}§
    1817 \end{cfa}
    1818 While parameter names are optional, \emph{a routine name cannot be specified};
    1819 for example, the following is incorrect:
    1820 \begin{cfa}
    1821 * [ int x ] f () fp;                                    §\C{// routine name "f" is not allowed}§
    1822 \end{cfa}
    1823 
    1824 
    1825 \section{Named and Default Arguments}
    1826 
    1827 Named\index{named arguments}\index{arguments!named} and default\index{default arguments}\index{arguments!default} arguments~\cite{Hardgrave76}\footnote{
    1828 Francez~\cite{Francez77} proposed a further extension to the named-parameter passing style, which specifies what type of communication (by value, by reference, by name) the argument is passed to the routine.}
    1829 are two mechanisms to simplify routine call.
    1830 Both mechanisms are discussed with respect to \CFA.
    1831 \begin{description}
    1832 \item[Named (or Keyword) Arguments:]
    1833 provide the ability to specify an argument to a routine call using the parameter name rather than the position of the parameter.
    1834 For example, given the routine:
    1835 \begin{cfa}
    1836 void p( int x, int y, int z ) {...}
    1837 \end{cfa}
    1838 a positional call is:
    1839 \begin{cfa}
    1840 p( 4, 7, 3 );
    1841 \end{cfa}
    1842 whereas a named (keyword) call may be:
    1843 \begin{cfa}
    1844 p( z : 3, x : 4, y : 7 );       §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§
    1845 \end{cfa}
    1846 Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters.
    1847 The compiler rewrites a named call into a positional call.
    1848 The advantages of named parameters are:
    1849 \begin{itemize}
    1850 \item
    1851 Remembering the names of the parameters may be easier than the order in the routine definition.
    1852 \item
    1853 Parameter names provide documentation at the call site (assuming the names are descriptive).
    1854 \item
    1855 Changes can be made to the order or number of parameters without affecting the call (although the call must still be recompiled).
    1856 \end{itemize}
    1857 
    1858 Unfortunately, named arguments do not work in C-style programming-languages because a routine prototype is not required to specify parameter names, nor do the names in the prototype have to match with the actual definition.
    1859 For example, the following routine prototypes and definition are all valid.
    1860 \begin{cfa}
    1861 void p( int, int, int );                        §\C{// equivalent prototypes}§
    1862 void p( int x, int y, int z );
    1863 void p( int y, int x, int z );
    1864 void p( int z, int y, int x );
    1865 void p( int q, int r, int s ) {}        §\C{// match with this definition}§
    1866 \end{cfa}
    1867 Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming.
    1868 Alternatively, prototype definitions can be eliminated by using a two-pass compilation, and implicitly creating header files for exports.
    1869 The former is easy to do, while the latter is more complex.
    1870 
    1871 Furthermore, named arguments do not work well in a \CFA-style programming-languages because they potentially introduces a new criteria for type matching.
    1872 For example, it is technically possible to disambiguate between these two overloaded definitions of ©f© based on named arguments at the call site:
    1873 \begin{cfa}
    1874 int f( int i, int j );
    1875 int f( int x, double y );
    1876 
    1877 f( j : 3, i : 4 );                              §\C{// 1st f}§
    1878 f( x : 7, y : 8.1 );                    §\C{// 2nd f}§
    1879 f( 4, 5 );                                              §\C{// ambiguous call}§
    1880 \end{cfa}
    1881 However, named arguments compound routine resolution in conjunction with conversions:
    1882 \begin{cfa}
    1883 f( i : 3, 5.7 );                                §\C{// ambiguous call ?}§
    1884 \end{cfa}
    1885 Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.
    1886 Adding named argument into the routine resolution algorithm does not seem worth the complexity.
    1887 Therefore, \CFA does \emph{not} attempt to support named arguments.
    1888 
    1889 \item[Default Arguments]
    1890 provide the ability to associate a default value with a parameter so it can be optionally specified in the argument list.
    1891 For example, given the routine:
    1892 \begin{cfa}
    1893 void p( int x = 1, int y = 2, int z = 3 ) {...}
    1894 \end{cfa}
    1895 the allowable positional calls are:
    1896 \begin{cfa}
    1897 p();                                                    §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
    1898 p( 4 );                                                 §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
    1899 p( 4, 4 );                                              §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
    1900 p( 4, 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§
    1901 // empty arguments
    1902 p(  , 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§
    1903 p( 4,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§
    1904 p( 4, 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
    1905 p( 4,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
    1906 p(  , 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§
    1907 p(  ,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§
    1908 p(  ,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
    1909 \end{cfa}
    1910 Here the missing arguments are inserted from the default values in the parameter list.
    1911 The compiler rewrites missing default values into explicit positional arguments.
    1912 The advantages of default values are:
    1913 \begin{itemize}
    1914 \item
    1915 Routines with a large number of parameters are often very generalized, giving a programmer a number of different options on how a computation is performed.
    1916 For many of these kinds of routines, there are standard or default settings that work for the majority of computations.
    1917 Without default values for parameters, a programmer is forced to specify these common values all the time, resulting in long argument lists that are error prone.
    1918 \item
    1919 When a routine's interface is augmented with new parameters, it extends the interface providing generalizability\footnote{
    1920 ``It should be possible for the implementor of an abstraction to increase its generality.
    1921 So long as the modified abstraction is a generalization of the original, existing uses of the abstraction will not require change.
    1922 It might be possible to modify an abstraction in a manner which is not a generalization without affecting existing uses, but, without inspecting the modules in which the uses occur, this possibility cannot be determined.
    1923 This criterion precludes the addition of parameters, unless these parameters have default or inferred values that are valid for all possible existing applications.''~\cite[p.~128]{Cormack90}}
    1924 (somewhat like the generalization provided by inheritance for classes).
    1925 That is, all existing calls are still valid, although the call must still be recompiled.
    1926 \end{itemize}
    1927 The only disadvantage of default arguments is that unintentional omission of an argument may not result in a compiler-time error.
    1928 Instead, a default value is used, which may not be the programmer's intent.
    1929 
    1930 Default values may only appear in a prototype versus definition context:
    1931 \begin{cfa}
    1932 void p( int x, int y = 2, int z = 3 );          §\C{// prototype: allowed}§
    1933 void p( int, int = 2, int = 3 );                        §\C{// prototype: allowed}§
    1934 void p( int x, int y = 2, int z = 3 ) {}        §\C{// definition: not allowed}§
    1935 \end{cfa}
    1936 The reason for this restriction is to allow separate compilation.
    1937 Multiple prototypes with different default values is an error.
    1938 \end{description}
    1939 
    1940 Ellipse (``...'') arguments present problems when used with default arguments.
    1941 The conflict occurs because both named and ellipse arguments must appear after positional arguments, giving two possibilities:
    1942 \begin{cfa}
    1943 p( /* positional */, ... , /* named */ );
    1944 p( /* positional */, /* named */, ... );
    1945 \end{cfa}
    1946 While it is possible to implement both approaches, the first possibly is more complex than the second, \eg:
    1947 \begin{cfa}
    1948 p( int x, int y, int z, ... );
    1949 p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§
    1950 p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§
    1951 \end{cfa}
    1952 In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin.
    1953 Hence, this approach seems significantly more difficult, and hence, confusing and error prone.
    1954 In the second call, the named arguments separate the positional and ellipse arguments, making it trivial to read the call.
    1955 
    1956 The problem is exacerbated with default arguments, \eg:
    1957 \begin{cfa}
    1958 void p( int x, int y = 2, int z = 3... );
    1959 p( 1, 4, 5, 6, z : 3 );         §\C{// assume p( /* positional */, ... , /* named */ );}§
    1960 p( 1, z : 3, 4, 5, 6 );         §\C{// assume p( /* positional */, /* named */, ... );}§
    1961 \end{cfa}
    1962 The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments;
    1963 therefore, argument 5 subsequently conflicts with the named argument z : 3.
    1964 In the second call, the default value for y is implicitly inserted after argument 1 and the named arguments separate the positional and ellipse arguments, making it trivial to read the call.
    1965 For these reasons, \CFA requires named arguments before ellipse arguments.
    1966 Finally, while ellipse arguments are needed for a small set of existing C routines, like printf, the extended \CFA type system largely eliminates the need for ellipse arguments (see Section 24), making much of this discussion moot.
    1967 
    1968 Default arguments and overloading (see Section 24) are complementary.
    1969 While in theory default arguments can be simulated with overloading, as in:
    1970 \begin{quote2}
    1971 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1972 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}}   & \multicolumn{1}{c}{\textbf{overloading}}      \\
    1973 \begin{cfa}
    1974 void p( int x, int y = 2, int z = 3 ) {...}
    1975 
    1976 
    1977 \end{cfa}
    1978 &
    1979 \begin{cfa}
    1980 void p( int x, int y, int z ) {...}
    1981 void p( int x ) { p( x, 2, 3 ); }
    1982 void p( int x, int y ) { p( x, y, 3 ); }
    1983 \end{cfa}
    1984 \end{tabular}
    1985 \end{quote2}
    1986 the number of required overloaded routines is linear in the number of default values, which is unacceptable growth.
    1987 In general, overloading should only be used over default arguments if the body of the routine is significantly different.
    1988 Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as:
    1989 \begin{cfa}
    1990 p( 1, /* default */, 5 );               §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§
    1991 \end{cfa}
    1992 
    1993 Given the \CFA restrictions above, both named and default arguments are backwards compatible.
    1994 \Index*[C++]{\CC{}} only supports default arguments;
    1995 \Index*{Ada} supports both named and default arguments.
    1996 
    1997 
    1998 \section{Unnamed Structure Fields}
    1999 
    2000 C requires each field of a structure to have a name, except for a bit field associated with a basic type, \eg:
    2001 \begin{cfa}
    2002 struct {
    2003         int f1;                                 §\C{// named field}§
    2004         int f2 : 4;                             §\C{// named field with bit field size}§
    2005         int : 3;                                §\C{// unnamed field for basic type with bit field size}§
    2006         int ;                                   §\C{// disallowed, unnamed field}§
    2007         int *;                                  §\C{// disallowed, unnamed field}§
    2008         int (*)( int );                 §\C{// disallowed, unnamed field}§
    2009 };
    2010 \end{cfa}
    2011 This requirement is relaxed by making the field name optional for all field declarations; therefore, all the field declarations in the example are allowed.
    2012 As for unnamed bit fields, an unnamed field is used for padding a structure to a particular size.
    2013 A list of unnamed fields is also supported, \eg:
    2014 \begin{cfa}
    2015 struct {
    2016         int , , ;                               §\C{// 3 unnamed fields}§
    2017 }
    2018 \end{cfa}
    2019 
    2020 
    2021 \section{Nesting}
    2022 
    2023 Nesting of types and routines is useful for controlling name visibility (\newterm{name hiding}).
    2024 
    2025 
    2026 \subsection{Type Nesting}
    2027 
    2028 \CFA allows \Index{type nesting}, and type qualification of the nested types (see \VRef[Figure]{f:TypeNestingQualification}), where as C hoists\index{type hoisting} (refactors) nested types into the enclosing scope and has no type qualification.
    2029 \begin{figure}
    2030 \centering
    2031 \begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
    2032 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}}      & \multicolumn{1}{c}{\textbf{C Implicit Hoisting}}      & \multicolumn{1}{|c}{\textbf{\CFA}}    \\
    2033 \hline
    2034 \begin{cfa}
    2035 struct S {
    2036         enum C { R, G, B };
    2037         struct T {
    2038                 union U { int i, j; };
    2039                 enum C c;
    2040                 short int i, j;
    2041         };
    2042         struct T t;
    2043 } s;
    2044 
    2045 int fred() {
    2046         s.t.c = R;
    2047         struct T t = { R, 1, 2 };
    2048         enum C c;
    2049         union U u;
    2050 }
    2051 \end{cfa}
    2052 &
    2053 \begin{cfa}
    2054 enum C { R, G, B };
    2055 union U { int i, j; };
    2056 struct T {
    2057         enum C c;
    2058         short int i, j;
    2059 };
    2060 struct S {
    2061         struct T t;
    2062 } s;
    2063        
    2064 
    2065 
    2066 
    2067 
    2068 
    2069 
    2070 \end{cfa}
    2071 &
    2072 \begin{cfa}
    2073 struct S {
    2074         enum C { R, G, B };
    2075         struct T {
    2076                 union U { int i, j; };
    2077                 enum C c;
    2078                 short int i, j;
    2079         };
    2080         struct T t;
    2081 } s;
    2082 
    2083 int fred() {
    2084         s.t.c = ®S.®R;  // type qualification
    2085         struct ®S.®T t = { ®S.®R, 1, 2 };
    2086         enum ®S.®C c;
    2087         union ®S.T.®U u;
    2088 }
    2089 \end{cfa}
    2090 \end{tabular}
    2091 \caption{Type Nesting / Qualification}
    2092 \label{f:TypeNestingQualification}
    2093 \end{figure}
    2094 In the left example in C, types ©C©, ©U© and ©T© are implicitly hoisted outside of type ©S© into the containing block scope.
    2095 In the right example in \CFA, the types are not hoisted and accessed using the field-selection operator ``©.©'' for type qualification, as does \Index*{Java}, rather than the \CC type-selection operator ``©::©''.
    2096 
    2097 
    2098 \subsection{Routine Nesting}
    2099 
    2100 While \CFA does not provide object programming by putting routines into structures, it does rely heavily on locally nested routines to redefine operations at or close to a call site.
    2101 For example, the C quick-sort is wrapped into the following polymorphic \CFA routine:
    2102 \begin{cfa}
    2103 forall( otype T | { int ?<?( T, T ); } )
    2104 void qsort( const T * arr, size_t dimension );
    2105 \end{cfa}
    2106 which can be used to sort in ascending and descending order by locally redefining the less-than operator into greater-than.
    2107 \begin{cfa}
    2108 const unsigned int size = 5;
    2109 int ia[size];
    2110 ...                                             §\C{// assign values to array ia}§
    2111 qsort( ia, size );              §\C{// sort ascending order using builtin ?<?}§
    2112 {
    2113         ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§
    2114         qsort( ia, size );      §\C{// sort descending order by local redefinition}§
    2115 }
    2116 \end{cfa}
    2117 
    2118 Nested routines are not first-class, meaning a nested routine cannot be returned if it has references to variables in its enclosing blocks;
    2119 the only exception is references to the external block of the translation unit, as these variables persist for the duration of the program.
    2120 The following program in undefined in \CFA (and Indexc{gcc})
    2121 \begin{cfa}
    2122 [* [int]( int )] foo() {                §\C{// int (*foo())( int )}§
    2123         int ®i® = 7;
    2124         int bar( int p ) {
    2125                 ®i® += 1;                               §\C{// dependent on local variable}§
    2126                 sout | ®i® | endl;
    2127         }
    2128         return bar;                                     §\C{// undefined because of local dependence}§
    2129 }
    2130 int main() {
    2131         * [int]( int ) fp = foo();      §\C{// int (*fp)( int )}§
    2132         sout | fp( 3 ) | endl;
    2133 }
    2134 \end{cfa}
    2135 because
    2136 
    2137 Currently, there are no \Index{lambda} expressions, \ie unnamed routines because routine names are very important to properly select the correct routine.
    2138 
    2139 
    2140 \section{Tuples}
    2141 
    2142 In C and \CFA, lists of elements appear in several contexts, such as the parameter list for a routine call.
    2143 (More contexts are added shortly.)
    2144 A list of such elements is called a \newterm{lexical list}.
    2145 The general syntax of a lexical list is:
    2146 \begin{cfa}
    2147 [ §\emph{exprlist}§ ]
    2148 \end{cfa}
    2149 where ©$\emph{exprlist}$© is a list of one or more expressions separated by commas.
    2150 The brackets, ©[]©, allow differentiating between lexical lists and expressions containing the C comma operator.
    2151 The following are examples of lexical lists:
    2152 \begin{cfa}
    2153 [ x, y, z ]
    2154 [ 2 ]
    2155 [ v+w, x*y, 3.14159, f() ]
    2156 \end{cfa}
    2157 Tuples are permitted to contain sub-tuples (\ie nesting), such as ©[ [ 14, 21 ], 9 ]©, which is a 2-element tuple whose first element is itself a tuple.
    2158 Note, a tuple is not a record (structure);
    2159 a record denotes a single value with substructure, whereas a tuple is multiple values with no substructure (see flattening coercion in Section 12.1).
    2160 In essence, tuples are largely a compile time phenomenon, having little or no runtime presence.
    2161 
    2162 Tuples can be organized into compile-time tuple variables;
    2163 these variables are of \newterm{tuple type}.
    2164 Tuple variables and types can be used anywhere lists of conventional variables and types can be used.
    2165 The general syntax of a tuple type is:
    2166 \begin{cfa}
    2167 [ §\emph{typelist}§ ]
    2168 \end{cfa}
    2169 where ©$\emph{typelist}$© is a list of one or more legal \CFA or C type specifications separated by commas, which may include other tuple type specifications.
    2170 Examples of tuple types include:
    2171 \begin{cfa}
    2172 [ unsigned int, char ]
    2173 [ double, double, double ]
    2174 [ * int, int * ]                §\C{// mix of CFA and ANSI}§
    2175 [ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]
    2176 \end{cfa}
    2177 Like tuples, tuple types may be nested, such as ©[ [ int, int ], int ]©, which is a 2-element tuple type whose first element is itself a tuple type.
    2178 
    2179 Examples of declarations using tuple types are:
    2180 \begin{cfa}
    2181 [ int, int ] x;                 §\C{// 2 element tuple, each element of type int}§
    2182 * [ char, char ] y;             §\C{// pointer to a 2 element tuple}§
    2183 [ [ int, int ] ] z ([ int, int ]);
    2184 \end{cfa}
    2185 The last example declares an external routine that expects a 2 element tuple as an input parameter and returns a 2 element tuple as its result.
    2186 
    2187 As mentioned, tuples can appear in contexts requiring a list of value, such as an argument list of a routine call.
    2188 In unambiguous situations, the tuple brackets may be omitted, \eg a tuple that appears as an argument may have its
    2189 square brackets omitted for convenience; therefore, the following routine invocations are equivalent:
    2190 \begin{cfa}
    2191 f( [ 1, x+2, fred() ] );
    2192 f( 1, x+2, fred() );
    2193 \end{cfa}
    2194 Also, a tuple or a tuple variable may be used to supply all or part of an argument list for a routine expecting multiple input parameters or for a routine expecting a tuple as an input parameter.
    2195 For example, the following are all legal:
    2196 \begin{cfa}
    2197 [ int, int ] w1;
    2198 [ int, int, int ] w2;
    2199 [ void ] f (int, int, int); /* three input parameters of type int */
    2200 [ void ] g ([ int, int, int ]); /* 3 element tuple as input */
    2201 f( [ 1, 2, 3 ] );
    2202 f( w1, 3 );
    2203 f( 1, w1 );
    2204 f( w2 );
    2205 g( [ 1, 2, 3 ] );
    2206 g( w1, 3 );
    2207 g( 1, w1 );
    2208 g( w2 );
    2209 \end{cfa}
    2210 Note, in all cases 3 arguments are supplied even though the syntax may appear to supply less than 3. As mentioned, a
    2211 tuple does not have structure like a record; a tuple is simply converted into a list of components.
    2212 \begin{rationale}
    2213 The present implementation of \CFA does not support nested routine calls when the inner routine returns multiple values; \ie a statement such as ©g( f() )© is not supported.
    2214 Using a temporary variable to store the  results of the inner routine and then passing this variable to the outer routine works, however.
    2215 \end{rationale}
    2216 
    2217 A tuple can contain a C comma expression, provided the expression containing the comma operator is enclosed in parentheses.
    2218 For instance, the following tuples are equivalent:
    2219 \begin{cfa}
    2220 [ 1, 3, 5 ]
    2221 [ 1, (2, 3), 5 ]
    2222 \end{cfa}
    2223 The second element of the second tuple is the expression (2, 3), which yields the result 3.
    2224 This requirement is the same as for comma expressions in argument lists.
    2225 
    2226 Type qualifiers, \ie const and volatile, may modify a tuple type.
    2227 The meaning is the same as for a type qualifier modifying an aggregate type [Int99, x 6.5.2.3(7),x 6.7.3(11)], \ie the qualifier is distributed across all of the types in the tuple, \eg:
    2228 \begin{cfa}
    2229 const volatile [ int, float, const int ] x;
    2230 \end{cfa}
    2231 is equivalent to:
    2232 \begin{cfa}
    2233 [ const volatile int, const volatile float, const volatile int ] x;
    2234 \end{cfa}
    2235 Declaration qualifiers can only appear at the start of a \CFA tuple declaration4, \eg:
    2236 \begin{cfa}
    2237 extern [ int, int ] w1;
    2238 static [ int, int, int ] w2;
    2239 \end{cfa}
    2240 \begin{rationale}
    2241 Unfortunately, C's syntax for subscripts precluded treating them as tuples.
    2242 The C subscript list has the form ©[i][j]...© and not ©[i, j, ...]©.
    2243 Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[g()]© always means a single subscript value because there is only one set of brackets.
    2244 Fixing this requires a major change to C because the syntactic form ©M[i, j, k]© already has a particular meaning: ©i, j, k© is a comma expression.
    2245 \end{rationale}
    2246 
    2247 
    2248 \subsection{Tuple Coercions}
    2249 
    2250 There are four coercions that can be performed on tuples and tuple variables: closing, opening, flattening and structuring.
    2251 In addition, the coercion of dereferencing can be performed on a tuple variable to yield its value(s), as for other variables.
    2252 A \newterm{closing coercion} takes a set of values and converts it into a tuple value, which is a contiguous set of values, as in:
    2253 \begin{cfa}
    2254 [ int, int, int, int ] w;
    2255 w = [ 1, 2, 3, 4 ];
    2256 \end{cfa}
    2257 First the right-hand tuple is closed into a tuple value and then the tuple value is assigned.
    2258 
    2259 An \newterm{opening coercion} is the opposite of closing; a tuple value is converted into a tuple of values, as in:
    2260 \begin{cfa}
    2261 [ a, b, c, d ] = w
    2262 \end{cfa}
    2263 ©w© is implicitly opened to yield a tuple of four values, which are then assigned individually.
    2264 
    2265 A \newterm{flattening coercion} coerces a nested tuple, \ie a tuple with one or more components, which are themselves tuples, into a flattened tuple, which is a tuple whose components are not tuples, as in:
    2266 \begin{cfa}
    2267 [ a, b, c, d ] = [ 1, [ 2, 3 ], 4 ];
    2268 \end{cfa}
    2269 First the right-hand tuple is flattened and then the values are assigned individually.
    2270 Flattening is also performed on tuple types.
    2271 For example, the type ©[ int, [ int, int ], int ]© can be coerced, using flattening, into the type ©[ int, int, int, int ]©.
    2272 
    2273 A \newterm{structuring coercion} is the opposite of flattening;
    2274 a tuple is structured into a more complex nested tuple.
    2275 For example, structuring the tuple ©[ 1, 2, 3, 4 ]© into the tuple ©[ 1, [ 2, 3 ], 4 ]© or the tuple type ©[ int, int, int, int ]© into the tuple type ©[ int, [ int, int ], int ]©.
    2276 In the following example, the last assignment illustrates all the tuple coercions:
    2277 \begin{cfa}
    2278 [ int, int, int, int ] w = [ 1, 2, 3, 4 ];
    2279 int x = 5;
    2280 [ x, w ] = [ w, x ];            §\C{// all four tuple coercions}§
    2281 \end{cfa}
    2282 Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values;
    2283 therefore, the right-hand tuple is now the tuple ©[ [ 1, 2, 3, 4 ], 5 ]©.
    2284 This tuple is then flattened, yielding ©[ 1, 2, 3, 4, 5 ]©, which is structured into ©[ 1, [ 2, 3, 4, 5 ] ]© to match the tuple type of the left-hand side.
    2285 The tuple ©[ 2, 3, 4, 5 ]© is then closed to create a tuple value.
    2286 Finally, ©x© is assigned ©1© and ©w© is assigned the tuple value using multiple assignment (see Section 14).
    2287 \begin{rationale}
    2288 A possible additional language extension is to use the structuring coercion for tuples to initialize a complex record with a tuple.
    2289 \end{rationale}
    2290 
    2291 
    2292 \section{Mass Assignment}
    2293 
    2294 \CFA permits assignment to several variables at once using mass assignment~\cite{CLU}.
    2295 Mass assignment has the following form:
    2296 \begin{cfa}
    2297 [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = §\emph{expr}§;
    2298 \end{cfa}
    2299 \index{lvalue}
    2300 The left-hand side is a tuple of \emph{lvalues}, which is a list of expressions each yielding an address, \ie any data object that can appear on the left-hand side of a conventional assignment statement.
    2301 ©$\emph{expr}$© is any standard arithmetic expression.
    2302 Clearly, the types of the entities being assigned must be type compatible with the value of the expression.
    2303 
    2304 Mass assignment has parallel semantics, \eg the statement:
    2305 \begin{cfa}
    2306 [ x, y, z ] = 1.5;
    2307 \end{cfa}
    2308 is equivalent to:
    2309 \begin{cfa}
    2310 x = 1.5; y = 1.5; z = 1.5;
    2311 \end{cfa}
    2312 This semantics is not the same as the following in C:
    2313 \begin{cfa}
    2314 x = y = z = 1.5;
    2315 \end{cfa}
    2316 as conversions between intermediate assignments may lose information.
    2317 A more complex example is:
    2318 \begin{cfa}
    2319 [ i, y[i], z ] = a + b;
    2320 \end{cfa}
    2321 which is equivalent to:
    2322 \begin{cfa}
    2323 t = a + b;
    2324 a1 = &i; a2 = &y[i]; a3 = &z;
    2325 *a1 = t; *a2 = t; *a3 = t;
    2326 \end{cfa}
    2327 The temporary ©t© is necessary to store the value of the expression to eliminate conversion issues.
    2328 The temporaries for the addresses are needed so that locations on the left-hand side do not change as the values are assigned.
    2329 In this case, ©y[i]© uses the previous value of ©i© and not the new value set at the beginning of the mass assignment.
    2330 
    2331 
    2332 \section{Multiple Assignment}
    2333 
    2334 \CFA also supports the assignment of several values at once, known as multiple assignment~\cite{CLU,Galletly96}.
    2335 Multiple assignment has the following form:
    2336 \begin{cfa}
    2337 [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = [ §\emph{expr}§, ... , §\emph{expr}§ ];
    2338 \end{cfa}
    2339 \index{lvalue}
    2340 The left-hand side is a tuple of \emph{lvalues}, and the right-hand side is a tuple of \emph{expr}s.
    2341 Each \emph{expr} appearing on the right-hand side of a multiple assignment statement is assigned to the corresponding \emph{lvalues} on the left-hand side of the statement using parallel semantics for each assignment.
    2342 An example of multiple assignment is:
    2343 \begin{cfa}
    2344 [ x, y, z ] = [ 1, 2, 3 ];
    2345 \end{cfa}
    2346 Here, the values ©1©, ©2© and ©3© are assigned, respectively, to the variables ©x©, ©y© and ©z©.
    2347  A more complex example is:
    2348 \begin{cfa}
    2349 [ i, y[ i ], z ] = [ 1, i, a + b ];
    2350 \end{cfa}
    2351 Here, the values ©1©, ©i© and ©a + b© are assigned to the variables ©i©, ©y[i]© and ©z©, respectively.
    2352  Note, the parallel semantics of
    2353 multiple assignment ensures:
    2354 \begin{cfa}
    2355 [ x, y ] = [ y, x ];
    2356 \end{cfa}
    2357 correctly interchanges (swaps) the values stored in ©x© and ©y©.
    2358 The following cases are errors:
    2359 \begin{cfa}
    2360 [ a, b, c ] = [ 1, 2, 3, 4 ];
    2361 [ a, b, c ] = [ 1, 2 ];
    2362 \end{cfa}
    2363 because the number of entities in the left-hand tuple is unequal with the right-hand tuple.
    2364 
    2365 As for all tuple contexts in C, side effects should not be used because C does not define an ordering for the evaluation of the elements of a tuple;
    2366 both these examples produce indeterminate results:
    2367 \begin{cfa}
    2368 f( x++, x++ );                          §\C{// C routine call with side effects in arguments}§
    2369 [ v1, v2 ] = [ x++, x++ ];      §\C{// side effects in righthand side of multiple assignment}§
    2370 \end{cfa}
    2371 
    2372 
    2373 \section{Cascade Assignment}
    2374 
    2375 As in C, \CFA mass and multiple assignments can be cascaded, producing cascade assignment.
    2376 Cascade assignment has the following form:
    2377 \begin{cfa}
    2378 §\emph{tuple}§ = §\emph{tuple}§ = ... = §\emph{tuple}§;
    2379 \end{cfa}
    2380 and it has the same parallel semantics as for mass and multiple assignment.
    2381 Some examples of cascade assignment are:
    2382 \begin{cfa}
    2383 x1 = y1 = x2 = y2 = 0;
    2384 [ x1, y1 ] = [ x2, y2 ] = [ x3, y3 ];
    2385 [ x1, y1 ] = [ x2, y2 ] = 0;
    2386 [ x1, y1 ] = z = 0;
    2387 \end{cfa}
    2388 As in C, the rightmost assignment is performed first, \ie assignment parses right to left.
    2389 
    2390 
    2391 \section{Field Tuples}
    2392 
    2393 Tuples may be used to select multiple fields of a record by field name.
    2394 Its general form is:
    2395 \begin{cfa}
    2396 §\emph{expr}§ . [ §\emph{fieldlist}§ ]
    2397 §\emph{expr}§ -> [ §\emph{fieldlist}§ ]
    2398 \end{cfa}
    2399 \emph{expr} is any expression yielding a value of type record, \eg ©struct©, ©union©.
    2400 Each element of \emph{ fieldlist} is an element of the record specified by \emph{expr}.
    2401 A record-field tuple may be used anywhere a tuple can be used. An example of the use of a record-field tuple is
    2402 the following:
    2403 \begin{cfa}
    2404 struct s {
    2405         int f1, f2;
    2406         char f3;
    2407         double f4;
    2408 } v;
    2409 v.[ f3, f1, f2 ] = ['x', 11, 17 ];      §\C{// equivalent to v.f3 = 'x', v.f1 = 11, v.f2 = 17}§
    2410 f( v.[ f3, f1, f2 ] );                          §\C{// equivalent to f( v.f3, v.f1, v.f2 )}§
    2411 \end{cfa}
    2412 Note, the fields appearing in a record-field tuple may be specified in any order;
    2413 also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple.
    2414 
    2415 If a field of a ©struct© is itself another ©struct©, multiple fields of this subrecord can be specified using a nested record-field tuple, as in the following example:
    2416 \begin{cfa}
    2417 struct inner {
    2418         int f2, f3;
    2419 };
    2420 struct outer {
    2421         int f1;
    2422         struct inner i;
    2423         double f4;
    2424 } o;
    2425 
    2426 o.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ];
    2427 \end{cfa}
    2428 
    2429 
    24302399\section{I/O Library}
    24312400\label{s:IOLibrary}
     
    24332402
    24342403The goal of \CFA I/O is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way.
    2435 The approach combines ideas from \CC and Python.
    24362404The \CFA header file for the I/O library is \Indexc{fstream}.
    24372405
     
    24512419\\
    24522420\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
    2453 1® ®2® ®3
     24211 2 3
    24542422\end{cfa}
    24552423&
     
    24592427\end{tabular}
    24602428\end{quote2}
    2461 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
    2462 Similar simplification occurs for \Index{tuple} I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
     2429The \CFA form has half as many characters as the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
     2430A tuple prints all the tuple's values, each separated by ©", "©.
    24632431\begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
    2464 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 3, [ 4, 5 ] ];
     2432[int, int] t1 = [1, 2], t2 = [3, 4];
    24652433sout | t1 | t2 | endl;                                  §\C{// print tuples}§
    24662434\end{cfa}
    24672435\begin{cfa}[mathescape=off,showspaces=true,belowskip=0pt]
    2468 1®, ®2®, ®3 3®, ®4®, ®5
    2469 \end{cfa}
    2470 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
     24361, 2, 3, 4
     2437\end{cfa}
     2438\CFA uses the logical-or operator for I/O because it is the lowest-priority overloadable operator, other than assignment.
    24712439Therefore, fewer output expressions require parenthesis.
    24722440\begin{quote2}
     
    24902458\end{tabular}
    24912459\end{quote2}
    2492 There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    2493 
    2494 
    2495 \subsection{Implicit Separator}
    2496 
    2497 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator.
     2460Finally, the logical-or operator has a link with the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
     2461
     2462
     2463The implicit separator\index{I/O!separator} character (space/blank) is a separator not a terminator.
    24982464The rules for implicitly adding the separator are:
    24992465\begin{enumerate}
     
    25672533\end{enumerate}
    25682534
    2569 
    2570 \subsection{Manipulator}
    2571 
    25722535The following routines and \CC-style \Index{manipulator}s control implicit seperation.
    25732536\begin{enumerate}
     
    25812544%$
    25822545\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt]
    2583 1®, $®2®, $®3 ®", $"®
     25461, $2, $3 ®", $"®
    25842547\end{cfa}
    25852548%$
     
    25892552\end{cfa}
    25902553\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt]
    2591 1® ®2® ®3 ®" "®
     25541 2 3 ®" "®
     2555\end{cfa}
     2556
     2557\item
     2558Manipulators \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} and \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} \emph{locally} toggle printing the separator, \ie the seperator is adjusted only with respect to the next printed item.
     2559\begin{cfa}[mathescape=off,belowskip=0pt]
     2560sout | sepOn | 1 | 2 | 3 | sepOn | endl;        §\C{// separator at start of line}§
     2561\end{cfa}
     2562\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     2563 1 2 3
     2564\end{cfa}
     2565\begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
     2566sout | 1 | sepOff | 2 | 3 | endl;                       §\C{// locally turn off implicit separator}§
     2567\end{cfa}
     2568\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     256912 3
     2570\end{cfa}
     2571
     2572\item
     2573Manipulators \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} \emph{globally} toggle printing the separator, \ie the seperator is adjusted with respect to all subsequent printed items, unless locally adjusted.
     2574\begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
     2575sout | sepDisable | 1 | 2 | 3 | endl;           §\C{// globally turn off implicit separation}§
     2576\end{cfa}
     2577\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     2578123
     2579\end{cfa}
     2580\begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
     2581sout | 1 | sepOn | 2 | 3 | endl;                        §\C{// locally turn on implicit separator}§
     2582\end{cfa}
     2583\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     25841 23
     2585\end{cfa}
     2586\begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
     2587sout | sepEnable | 1 | 2 | 3 | endl;            §\C{// globally turn on implicit separation}§
     2588\end{cfa}
     2589\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     25901 2 3
    25922591\end{cfa}
    25932592
     
    26112610
    26122611\item
    2613 Manipulators \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} and \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} \emph{locally} toggle printing the separator, \ie the seperator is adjusted only with respect to the next printed item.
    2614 \begin{cfa}[mathescape=off,belowskip=0pt]
    2615 sout | sepOn | 1 | 2 | 3 | sepOn | endl;        §\C{// separator at start/end of line}§
    2616 \end{cfa}
    2617 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
    2618 ® ®1 2 3® ®
    2619 \end{cfa}
    2620 \begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
    2621 sout | 1 | sepOff | 2 | 3 | endl;                       §\C{// locally turn off implicit separator}§
    2622 \end{cfa}
    2623 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
    2624 12 3
    2625 \end{cfa}
    2626 The tuple separator also responses to being turned on and off.
     2612The tuple separator can also be turned on and off.
    26272613\begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
    26282614sout | sepOn | t1 | sepOff | t2 | endl;         §\C{// locally turn on/off implicit separation}§
     
    26322618\end{cfa}
    26332619Notice a tuple seperator starts the line because the next item is a tuple.
    2634 
    2635 \item
    2636 Manipulators \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} \emph{globally} toggle printing the separator, \ie the seperator is adjusted with respect to all subsequent printed items, unless locally adjusted.
    2637 \begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
    2638 sout | sepDisable | 1 | 2 | 3 | endl;           §\C{// globally turn off implicit separation}§
    2639 \end{cfa}
    2640 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
    2641 123
    2642 \end{cfa}
    2643 \begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
    2644 sout | 1 | ®sepOn® | 2 | 3 | endl;                      §\C{// locally turn on implicit separator}§
    2645 \end{cfa}
    2646 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
    2647 1® ®23
    2648 \end{cfa}
    2649 \begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
    2650 sout | sepEnable | 1 | 2 | 3 | endl;            §\C{// globally turn on implicit separation}§
    2651 \end{cfa}
    2652 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
    2653 1 2 3
    2654 \end{cfa}
    26552620\end{enumerate}
    26562621
     
    26612626        int x = 1, y = 2, z = 3;
    26622627        sout | x | y | z | endl;
    2663         [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 3, [ 4, 5 ] ];
    2664         sout | t1 | t2 | endl;                                          // print tuples
     2628        [int, int] t1 = [1, 2], t2 = [3, 4];
     2629        sout | t1 | t2 | endl;                                          // print tuple
    26652630        sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;
    26662631        sout | 1 | 2 | 3 | endl;
     
    52245189
    52255190
    5226 \section{\CFA Keywords}
     5191\section{\protect\CFA Keywords}
    52275192\label{s:CFAKeywords}
    52285193
     
    55225487For an increase in storage size, new storage after the copied data may be filled.
    55235488\item[alignment]
    5524 an allocation starts on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
     5489an allocation starts on a specified memory boundary, e.g., an address multiple of 64 or 128 for cache-line purposes.
    55255490\item[array]
    55265491the allocation size is scaled to the specified number of array elements.
  • src/CodeGen/CodeGenerator.cc

    r67fa9f9 r11dbfe1  
    288288        }
    289289
    290         void CodeGenerator::visit( Designation * designation ) {
    291                 std::list< Expression * > designators = designation->get_designators();
     290        void CodeGenerator::printDesignators( std::list< Expression * > & designators ) {
     291                typedef std::list< Expression * > DesignatorList;
    292292                if ( designators.size() == 0 ) return;
    293                 for ( Expression * des : designators ) {
    294                         if ( dynamic_cast< NameExpr * >( des ) || dynamic_cast< VariableExpr * >( des ) ) {
    295                                 // if expression is a NameExpr or VariableExpr, then initializing aggregate member
     293                for ( DesignatorList::iterator iter = designators.begin(); iter != designators.end(); ++iter ) {
     294                        if ( dynamic_cast< NameExpr * >( *iter ) ) {
     295                                // if expression is a name, then initializing aggregate member
    296296                                output << ".";
    297                                 des->accept( *this );
     297                                (*iter)->accept( *this );
    298298                        } else {
    299                                 // otherwise, it has to be a ConstantExpr or CastExpr, initializing array eleemnt
     299                                // if not a simple name, it has to be a constant expression, i.e. an array designator
    300300                                output << "[";
    301                                 des->accept( *this );
     301                                (*iter)->accept( *this );
    302302                                output << "]";
    303303                        } // if
     
    307307
    308308        void CodeGenerator::visit( SingleInit * init ) {
     309                printDesignators( init->get_designators() );
    309310                init->get_value()->accept( *this );
    310311        }
    311312
    312313        void CodeGenerator::visit( ListInit * init ) {
    313                 auto initBegin = init->begin();
    314                 auto initEnd = init->end();
    315                 auto desigBegin = init->get_designations().begin();
    316                 auto desigEnd = init->get_designations().end();
    317 
     314                printDesignators( init->get_designators() );
    318315                output << "{ ";
    319                 for ( ; initBegin != initEnd && desigBegin != desigEnd; ) {
    320                         (*desigBegin)->accept( *this );
    321                         (*initBegin)->accept( *this );
    322                         ++initBegin, ++desigBegin;
    323                         if ( initBegin != initEnd ) {
    324                                 output << ", ";
    325                         }
    326                 }
     316                genCommaList( init->begin(), init->end() );
    327317                output << " }";
    328                 assertf( initBegin == initEnd && desigBegin == desigEnd, "Initializers and designators not the same length. %s", toString( init ).c_str() );
    329318        }
    330319
     
    727716
    728717        void CodeGenerator::visit( TypeExpr * typeExpr ) {
    729                 // if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
    730                 // assertf( ! genC, "TypeExpr should not reach code generation." );
    731                 if ( ! genC ) {
    732                         output<< genType( typeExpr->get_type(), "", pretty, genC );
    733                 }
     718                assertf( ! genC, "TypeExpr should not reach code generation." );
     719                output<< genType( typeExpr->get_type(), "", pretty, genC );
    734720        }
    735721
  • src/CodeGen/CodeGenerator.h

    r67fa9f9 r11dbfe1  
    4747
    4848                //*** Initializer
    49                 virtual void visit( Designation * );
    5049                virtual void visit( SingleInit * );
    5150                virtual void visit( ListInit * );
     
    138137                bool lineMarks = false;
    139138
     139                void printDesignators( std::list< Expression * > & );
    140140                void handleStorageClass( DeclarationWithType *decl );
    141141                void handleAggregate( AggregateDecl *aggDecl, const std::string & kind );
  • src/Common/PassVisitor.h

    r67fa9f9 r11dbfe1  
    1212#include "SynTree/Expression.h"
    1313#include "SynTree/Constant.h"
    14 #include "SynTree/TypeSubstitution.h"
    1514
    1615#include "PassVisitor.proto.h"
     
    2726//                          stmtsToAddBefore or stmtsToAddAfter respectively.
    2827// | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children to false in pre{visit,mutate} to skip visiting children
    29 // | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save, call GuardValue with the variable to save, the variable
     28// | WithScopes           - provides the ability to save/restore data like a LIFO stack; to save, call GuardValue with the variable to save, the variable
    3029//                          will automatically be restored to its previous value after the corresponding postvisit/postmutate teminates.
    3130//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    3332class PassVisitor final : public Visitor, public Mutator {
    3433public:
     34        PassVisitor() = default;
    3535
    3636        template< typename... Args >
     
    257257
    258258        void set_visit_children( bool& ref ) { bool_ref * ptr = visit_children_impl(pass, 0); if(ptr) ptr->set( ref ); }
     259
     260        guard_value_impl init_guard() {
     261                guard_value_impl guard;
     262                auto at_cleanup = at_cleanup_impl(pass, 0);
     263                if( at_cleanup ) {
     264                        *at_cleanup = [&guard]( cleanup_func_t && func, void* val ) {
     265                                guard.push( std::move( func ), val );
     266                        };
     267                }
     268                return guard;
     269        }
    259270};
    260271
     
    272283
    273284public:
    274         TypeSubstitution * env = nullptr;
     285        TypeSubstitution * env;
    275286};
    276287
     
    284295        std::list< Statement* > stmtsToAddAfter;
    285296};
    286 
    287 class WithDeclsToAdd {
    288 protected:
    289         WithDeclsToAdd() = default;
    290         ~WithDeclsToAdd() = default;
    291 
    292 public:
    293         std::list< Declaration* > declsToAddBefore;
    294         std::list< Declaration* > declsToAddAfter;
    295 };
    296 
    297297class WithShortCircuiting {
    298298protected:
     
    304304};
    305305
    306 class WithGuards {
    307 protected:
    308         WithGuards() = default;
    309         ~WithGuards() = default;
     306class WithScopes {
     307protected:
     308        WithScopes() = default;
     309        ~WithScopes() = default;
    310310
    311311public:
     
    318318                }, static_cast< void * >( & val ) );
    319319        }
    320 
    321         template< typename T >
    322         void GuardScope( T& val ) {
    323                 val.beginScope();
    324                 at_cleanup( []( void * val ) {
    325                         static_cast< T * >( val )->endScope();
    326                 }, static_cast< void * >( & val ) );
    327         }
    328 
    329         template< typename Func >
    330         void GuardAction( Func func ) {
    331                 at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr );
    332         }
    333320};
    334321
     
    336323class WithVisitorRef {
    337324protected:
    338         WithVisitorRef() {}
    339         ~WithVisitorRef() {}
    340 
    341 public:
    342         PassVisitor<pass_type> * const visitor = nullptr;
     325        WithVisitorRef() = default;
     326        ~WithVisitorRef() = default;
     327
     328public:
     329        PassVisitor<pass_type> * const visitor;
    343330};
    344331
  • src/Common/PassVisitor.impl.h

    r67fa9f9 r11dbfe1  
    33#define VISIT_START( node )                     \
    44        __attribute__((unused))                   \
    5         guard_value_impl guard( at_cleanup_impl(pass, 0) );       \
     5        const auto & guard = init_guard();        \
    66        bool visit_children = true;               \
    77        set_visit_children( visit_children );   \
     
    1515#define MUTATE_START( node )                    \
    1616        __attribute__((unused))                   \
    17         guard_value_impl guard( at_cleanup_impl(pass, 0) );       \
     17        const auto & guard = init_guard();        \
    1818        bool visit_children = true;               \
    1919        set_visit_children( visit_children );   \
     
    6868        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
    6969                // splice in new declarations after previous decl
    70                 if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
     70                if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); } 
    7171
    7272                if ( i == decls.end() ) break;
     
    8888        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
    8989                // splice in new declarations after previous decl
    90                 if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
     90                if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); } 
    9191
    9292                if ( i == decls.end() ) break;
     
    104104void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
    105105        SemanticError errors;
    106 
    107         // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    108         ValueGuardPtr< StmtList_t > oldBeforeStmts( get_beforeStmts() );
    109         ValueGuardPtr< StmtList_t > oldAfterStmts ( get_afterStmts () );
    110         ValueGuardPtr< DeclList_t > oldBeforeDecls( get_beforeDecls() );
    111         ValueGuardPtr< DeclList_t > oldAfterDecls ( get_afterDecls () );
    112106
    113107        StmtList_t* beforeStmts = get_beforeStmts();
     
    187181Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
    188182        return handleStatement( stmt, [this]( Statement * stmt ) {
    189                 maybeAccept( stmt, *this );
     183                maybeAccept( stmt, *this ); 
    190184                return stmt;
    191185        });
     
    218212                expr->accept( *this );
    219213                return expr;
    220         });
     214        });             
    221215}
    222216
     
    571565        VISIT_START( node );
    572566
    573         // maybeAccept( node->get_env(), *this );
    574         maybeAccept( node->get_result(), *this );
    575 
    576567        for ( auto expr : node->get_args() ) {
    577568                visitExpression( expr );
     
    584575Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
    585576        MUTATE_START( node );
    586 
    587         node->set_env( maybeMutate( node->get_env(), *this ) );
    588         node->set_result( maybeMutate( node->get_result(), *this ) );
    589577
    590578        for ( auto& expr : node->get_args() ) {
  • src/Common/PassVisitor.proto.h

    r67fa9f9 r11dbfe1  
    55
    66typedef std::function<void( void * )> cleanup_func_t;
    7 typedef std::function< void( cleanup_func_t, void * ) > at_cleanup_t;
    87
    98class guard_value_impl {
    109public:
    11         guard_value_impl( at_cleanup_t * at_cleanup ) {
    12                 if( at_cleanup ) {
    13                         *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
    14                                 push( std::move( func ), val );
    15                         };
    16                 }
    17         }
     10        guard_value_impl() = default;
    1811
    1912        ~guard_value_impl() {
     
    4033};
    4134
     35typedef std::function< void( cleanup_func_t, void * ) > at_cleanup_t;
    4236
    4337class bool_ref {
     
    6256// Deep magic (a.k.a template meta programming) to make the templated visitor work
    6357// Basically the goal is to make 2 previsit_impl
    64 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
     58// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 
    6559//     'pass.previsit( node )' that compiles will be used for that node for that type
    6660//     This requires that this option only compile for passes that actually define an appropriate visit.
  • src/Common/utility.h

    r67fa9f9 r11dbfe1  
    305305// for ( val : group_iterate( container1, container2, ... ) ) {}
    306306// syntax to have a for each that iterates multiple containers of the same length
    307 // TODO: update to use variadic arguments, perfect forwarding
     307// TODO: update to use variadic arguments
    308308
    309309template< typename T1, typename T2 >
  • src/ControlStruct/ExceptTranslate.cc

    r67fa9f9 r11dbfe1  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 30 13:30:00 2017
    13 // Update Count     : 1
     12// Last Modified On : Thr Jun 22 15:57:00 2017
     13// Update Count     : 0
    1414//
    1515
    1616#include "ExceptTranslate.h"
    1717#include "Common/PassVisitor.h"
    18 #include "SynTree/Statement.h"
    19 #include "SynTree/Declaration.h"
    20 #include "SynTree/Expression.h"
    21 #include "SynTree/Type.h"
    22 #include "SynTree/Attribute.h"
    23 
    24 namespace ControlStruct {
     18
     19namespace ControlFlow {
    2520
    2621        // This (large) section could probably be moved out of the class
     
    2924        // Type(Qualifiers &, false, std::list<Attribute *> &)
    3025
    31         // void (*function)();
    32         static FunctionType try_func_t(Type::Qualifiers(), false);
     26        // void (*function)()
     27        static FunctionType void_func_t(Type::Qualifiers(), false);
    3328        // void (*function)(int, exception);
    3429        static FunctionType catch_func_t(Type::Qualifiers(), false);
     
    3732        // bool (*function)(exception);
    3833        static FunctionType handle_func_t(Type::Qualifiers(), false);
    39         // void (*function)(__attribute__((unused)) void *);
    40         static FunctionType finally_func_t(Type::Qualifiers(), false);
    4134
    4235        static void init_func_types() {
    43                 static bool init_complete = false;
     36                static init_complete = false;
    4437                if (init_complete) {
    4538                        return;
    4639                }
    4740                ObjectDecl index_obj(
    48                         "__handler_index",
     41                        "index_t",
    4942                        Type::StorageClasses(),
    5043                        LinkageSpec::Cforall,
    5144                        /*bitfieldWidth*/ NULL,
    52                         new BasicType( emptyQualifiers, BasicType::SignedInt ),
     45                        new BasicType(emptyQualifiers, BasicType::UnsignedInt),
    5346                        /*init*/ NULL
    54                         );
     47                );
    5548                ObjectDecl exception_obj(
    56                         "__exception_inst",
     49                        "exception_t",
    5750                        Type::StorageClasses(),
    5851                        LinkageSpec::Cforall,
    5952                        /*bitfieldWidth*/ NULL,
    60                         new PointerType(
    61                                 emptyQualifiers,
    62                                 new BasicType( emptyQualifiers, BasicType::SignedInt )
    63                                 ),
     53                        new BasicType(emptyQualifiers, BasicType::UnsignedInt),
    6454                        /*init*/ NULL
    65                         );
     55                );
    6656                ObjectDecl bool_obj(
    67                         "__ret_bool",
     57                        "bool_t",
    6858                        Type::StorageClasses(),
    6959                        LinkageSpec::Cforall,
     
    7161                        new BasicType(emptyQualifiers, BasicType::Bool),
    7262                        /*init*/ NULL
    73                         );
    74                 ObjectDecl voidptr_obj(
    75                         "__hook",
    76                         Type::StorageClasses(),
    77                         LinkageSpec::Cforall,
    78                         NULL,
    79                         new PointerType(
    80                                 emptyQualifiers,
    81                                 new VoidType(
    82                                         emptyQualifiers
    83                                         ),
    84                                 std::list<Attribute *>{new Attribute("unused")}
    85                                 ),
    86                         NULL
    87                         );
    88 
    89                 catch_func_t.get_parameters().push_back( index_obj.clone() );
    90                 catch_func_t.get_parameters().push_back( exception_obj.clone() );
    91                 match_func_t.get_returnVals().push_back( index_obj.clone() );
    92                 match_func_t.get_parameters().push_back( exception_obj.clone() );
    93                 handle_func_t.get_returnVals().push_back( bool_obj.clone() );
    94                 handle_func_t.get_parameters().push_back( exception_obj.clone() );
    95                 finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
     63                );
     64
     65                catch_func_t.get_parameters().push_back(index_obj.clone());
     66                catch_func_t.get_parameters().push_back(exception_obj.clone());
     67                match_func_t.get_returnVals().push_back(index_obj.clone());
     68                match_func_t.get_parameters().push_back(exception_obj.clone());
     69                handle_func_t.get_returnVals().push_back(bool_obj.clone());
     70                handle_func_t.get_parameters().push_back(exception_obj.clone());
    9671
    9772                init_complete = true;
     
    10378
    10479        void split( CatchList& allHandlers, CatchList& terHandlers,
    105                                 CatchList& resHandlers ) {
     80                    CatchList& resHandlers ) {
    10681                while ( !allHandlers.empty() ) {
    107                         CatchStmt * stmt = allHandlers.front();
     82                        Statement * stmt = allHandlers.front();
    10883                        allHandlers.pop_front();
    109                         if (CatchStmt::Terminate == stmt->get_kind()) {
     84                        if (CaseStmt::Terminate == stmt->get_kind()) {
    11085                                terHandlers.push_back(stmt);
    11186                        } else {
     
    11792        template<typename T>
    11893        void free_all( std::list<T *> &list ) {
    119                 typename std::list<T *>::iterator it;
     94                std::list<T *>::iterator it;
    12095                for ( it = list.begin() ; it != list.end() ; ++it ) {
    12196                        delete *it;
     
    125100
    126101        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
    127                 block->push_back(new DeclStmt(noLabels, item));
    128         }
    129 
    130         Expression * nameOf( DeclarationWithType * decl ) {
    131                 return new VariableExpr( decl );
     102                block->push_back(new DeclStmt(no_labels, item));
     103        }
     104
     105        Expression * nameOf( FunctionDecl * function ) {
     106                return new VariableExpr( function );
    132107        }
    133108
    134109        // ThrowStmt Mutation Helpers
    135110
    136         Statement * create_given_throw(
    137                         const char * throwFunc, ThrowStmt * throwStmt ) {
    138                 // { int NAME = EXPR; throwFunc( &NAME ); }
    139                 CompoundStmt * result = new CompoundStmt( noLabels );
    140                 ObjectDecl * local = new ObjectDecl(
    141                         "__local_exception_copy",
    142                         Type::StorageClasses(),
    143                         LinkageSpec::Cforall,
    144                         NULL,
    145                         new BasicType( emptyQualifiers, BasicType::SignedInt ),
    146                         new SingleInit( throwStmt->get_expr() )
    147                         );
    148                 appendDeclStmt( result, local );
    149                 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
    150                 call->get_args().push_back( new AddressExpr( nameOf( local ) ) );
    151                 result->push_back( new ExprStmt( throwStmt->get_labels(), call ) );
     111        Statement * create_terminate_throw( ThrowStmt *throwStmt ) {
     112                // __throw_terminate( EXPR );
     113                ApplicationExpr * call = new ApplicationExpr( /* ... */ );
     114                call->get_args.push_back( throwStmt->get_expr() );
     115                Statement * result = new ExprStmt( throwStmt->get_labels(), call );
    152116                throwStmt->set_expr( nullptr );
    153117                delete throwStmt;
    154118                return result;
    155119        }
    156 
    157         Statement * create_terminate_throw( ThrowStmt *throwStmt ) {
    158                 // { int NAME = EXPR; __throw_terminate( &NAME ); }
    159                 return create_given_throw( "__cfaehm__throw_termination", throwStmt );
    160         }
    161120        Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
    162121                // __rethrow_terminate();
    163                 assert( nullptr == throwStmt->get_expr() );
    164122                Statement * result = new ExprStmt(
    165123                        throwStmt->get_labels(),
    166                         new UntypedExpr( new NameExpr( "__cfaehm__rethrow_termination" ) )
     124                        new ApplicationExpr( /* ... */ );
    167125                        );
    168126                delete throwStmt;
     
    171129        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
    172130                // __throw_resume( EXPR );
    173                 return create_given_throw( "__cfaehm__throw_resumption", throwStmt );
     131                ApplicationExpr * call = new ApplicationExpr( /* ... */ );
     132                call->get_args.push_back( throwStmt->get_expr() );
     133                Statement * result = new ExprStmt( throwStmt->get_labels(), call );
     134                throwStmt->set_expr( nullptr );
     135                delete throwStmt;
     136                return result;
    174137        }
    175138        Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
     
    177140                Statement * result = new ReturnStmt(
    178141                        throwStmt->get_labels(),
    179                         new ConstantExpr( Constant::from_bool( false ) )
     142                        new ConstantExpr(
     143                                Constant(
     144                                        new BasicType(
     145                                                Type::Qualifiers(),
     146                                                BasicType::Bool
     147                                                ),
     148                                        "0")
     149                                )
    180150                        );
    181151                delete throwStmt;
     
    190160                return block;
    191161        }
    192         FunctionDecl * create_try_wrapper( CompoundStmt *body ) {
    193 
    194                 return new FunctionDecl( "try", Type::StorageClasses(),
    195                         LinkageSpec::Cforall, try_func_t.clone(), body );
     162        FunctionDecl * create_try_wrapper( TryStmt *tryStmt ) {
     163                CompoundStmt * body = base_try->get_block();
     164                base_try->set_block(nullptr);
     165
     166                return new FunctionDecl("try", Type::StorageClasses(),
     167                        LinkageSpec::Cforall, void_func_t, body);
    196168        }
    197169
    198170        FunctionDecl * create_terminate_catch( CatchList &handlers ) {
    199171                std::list<CaseStmt *> handler_wrappers;
    200 
    201                 FunctionType *func_type = catch_func_t.clone();
    202                 DeclarationWithType * index_obj = func_type->get_parameters().front();
    203         //      DeclarationWithType * except_obj = func_type->get_parameters().back();
    204172
    205173                // Index 1..{number of handlers}
     
    210178                        CatchStmt * handler = *it;
    211179
    212                         // INTEGERconstant Version
    213                         // case `index`:
    214                         // {
    215                         //     `handler.body`
    216                         // }
    217                         // return;
    218                         std::list<Statement *> caseBody;
    219                         caseBody.push_back( handler->get_body() );
    220                         handler->set_body( nullptr );
    221                         caseBody.push_back( new ReturnStmt( noLabels, nullptr ) );
    222 
    223                         handler_wrappers.push_back( new CaseStmt(
     180                        std::list<Statement *> core;
     181                        if ( /*the exception is named*/ ) {
     182                                ObjectDecl * local_except = /* Dynamic case, same */;
     183                                core->push_back( new DeclStmt( noLabel, local_except ) );
     184                        }
     185                        // Append the provided statement to the handler.
     186                        core->push_back( cur_handler->get_body() );
     187                        // Append return onto the inner block? case stmt list?
     188                        CaseStmt * wrapper = new CaseStmt(
    224189                                noLabels,
    225190                                new ConstantExpr( Constant::from_int( index ) ),
    226                                 caseBody
    227                                 ) );
     191                                core
     192                                );
     193                        handler_wrappers.push_back(wrapper);
    228194                }
    229195                // TODO: Some sort of meaningful error on default perhaps?
    230 
    231                 std::list<Statement*> stmt_handlers;
    232                 while ( !handler_wrappers.empty() ) {
    233                         stmt_handlers.push_back( handler_wrappers.front() );
    234                         handler_wrappers.pop_front();
    235                 }
    236196
    237197                SwitchStmt * handler_lookup = new SwitchStmt(
    238198                        noLabels,
    239                         nameOf( index_obj ),
    240                         stmt_handlers
     199                        /*parameter 0: index*/,
     200                        handler_wrappers,
     201                        false
    241202                        );
    242203                CompoundStmt * body = new CompoundStmt( noLabels );
     
    244205
    245206                return new FunctionDecl("catch", Type::StorageClasses(),
    246                         LinkageSpec::Cforall, func_type, body);
     207                        LinkageSpec::Cforall, catch_func_t, body);
    247208        }
    248209
    249210        // Create a single check from a moddified handler.
    250         // except_obj is referenced, modded_handler will be freed.
    251         CompoundStmt *create_single_matcher(
    252                         DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    253                 CompoundStmt * block = new CompoundStmt( noLabels );
    254 
    255                 // INTEGERconstant Version
    256                 assert( nullptr == modded_handler->get_decl() );
    257                 ConstantExpr * number =
    258                         dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
    259                 assert( number );
    260                 modded_handler->set_cond( nullptr );
    261 
    262                 Expression * cond;
    263                 {
    264                         std::list<Expression *> args;
    265                         args.push_back( number );
    266 
    267                         std::list<Expression *> rhs_args;
    268                         rhs_args.push_back( nameOf( except_obj ) );
    269                         Expression * rhs = new UntypedExpr(
    270                                 new NameExpr( "*?" ), rhs_args );
    271                         args.push_back( rhs );
    272 
    273                         cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args );
    274                 }
     211        CompoundStmt *create_single_matcher( CatchStmt * modded_handler ) {
     212                CompoundStmt * block = new CompoundStmt( noLables );
     213
     214                appendDeclStmt( block, modded_handler->get_decl() );
     215
     216                // TODO: This is not the actual check.
     217                LogicalExpr * cond = new ConstantExpr( Constant::from_bool( false ) );
    275218
    276219                if ( modded_handler->get_cond() ) {
    277                         cond = new LogicalExpr( cond, modded_handler->get_cond() );
     220                        cond = new LogicalExpr( cond, modded_handler->get_cond() )q
    278221                }
    279222                block->push_back( new IfStmt( noLabels,
    280                         cond, modded_handler->get_body(), nullptr ) );
     223                        cond, modded_handler->get_body() );
    281224
    282225                modded_handler->set_decl( nullptr );
     
    289232        FunctionDecl * create_terminate_match( CatchList &handlers ) {
    290233                CompoundStmt * body = new CompoundStmt( noLabels );
    291 
    292                 FunctionType * func_type = match_func_t.clone();
    293                 DeclarationWithType * except_obj = func_type->get_parameters().back();
    294234
    295235                // Index 1..{number of handlers}
     
    300240                        CatchStmt * handler = *it;
    301241
    302                         // Body should have been taken by create_terminate_catch.
    303                         assert( nullptr == handler->get_body() );
    304 
    305                         // Create new body.
     242                        // body should have been taken by create_terminate_catch.
     243                        // assert( nullptr == handler->get_body() );
    306244                        handler->set_body( new ReturnStmt( noLabels,
    307245                                new ConstantExpr( Constant::from_int( index ) ) ) );
    308246
    309                         // Create the handler.
    310                         body->push_back( create_single_matcher( except_obj, handler ) );
    311                         *it = nullptr;
    312                 }
    313 
    314                 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
    315                         Constant::from_int( 0 ) ) ) );
     247                        body->push_back( create_single_matcher( handler ) );
     248                }
    316249
    317250                return new FunctionDecl("match", Type::StorageClasses(),
    318                         LinkageSpec::Cforall, func_type, body);
    319         }
    320 
    321         CompoundStmt * create_terminate_caller(
     251                        LinkageSpec::Cforall, match_func_t, body);
     252        }
     253
     254        Statement * create_terminate_caller(
    322255                        FunctionDecl * try_wrapper,
    323256                        FunctionDecl * terminate_catch,
    324257                        FunctionDecl * terminate_match) {
    325258
    326                 UntypedExpr * caller = new UntypedExpr( new NameExpr(
    327                         "__cfaehm__try_terminate" ) );
    328                 std::list<Expression *>& args = caller->get_args();
     259                ApplicationExpr * caller = new ApplicationExpr( /* ... */ );
     260                std::list<Expression *>& args = caller.get_args();
    329261                args.push_back( nameOf( try_wrapper ) );
    330262                args.push_back( nameOf( terminate_catch ) );
    331263                args.push_back( nameOf( terminate_match ) );
    332264
    333                 CompoundStmt * callStmt = new CompoundStmt( noLabels );
    334                 callStmt->push_back( new ExprStmt( noLabels, caller ) );
    335                 return callStmt;
     265                return new ExprStmt( noLabels, caller );
    336266        }
    337267
    338268        FunctionDecl * create_resume_handler( CatchList &handlers ) {
    339                 CompoundStmt * body = new CompoundStmt( noLabels );
    340 
    341                 FunctionType * func_type = match_func_t.clone();
    342                 DeclarationWithType * except_obj = func_type->get_parameters().back();
     269                CompoundStmt * body = new CompountStmt( noLabels );
    343270
    344271                CatchList::iterator it;
     
    353280                                handling_code->push_back( handler->get_body() );
    354281                        }
    355                         handling_code->push_back( new ReturnStmt( noLabels,
     282                        handling_code->push_back( new ReturnStmt( noLabel,
    356283                                new ConstantExpr( Constant::from_bool( false ) ) ) );
    357284                        handler->set_body( handling_code );
    358285
    359286                        // Create the handler.
    360                         body->push_back( create_single_matcher( except_obj, handler ) );
    361                         *it = nullptr;
     287                        body->push_back( create_single_matcher( handler ) );
    362288                }
    363289
    364290                return new FunctionDecl("handle", Type::StorageClasses(),
    365                         LinkageSpec::Cforall, func_type, body);
    366         }
    367 
    368         CompoundStmt * create_resume_wrapper(
    369                         StructDecl * node_decl,
     291                        LinkageSpec::Cforall, handle_func_t, body);
     292        }
     293
     294        Statement * create_resume_wrapper(
    370295                        Statement * wraps,
    371296                        FunctionDecl * resume_handler ) {
    372297                CompoundStmt * body = new CompoundStmt( noLabels );
    373298
    374                 // struct __try_resume_node __resume_node
    375                 //      __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
    376                 // ** unwinding of the stack here could cause problems **
    377                 // ** however I don't think that can happen currently **
    378                 // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
     299                // struct node = {current top resume handler, call to resume_handler};
     300                // __attribute__((cleanup( ... )));
     301                // set top resume handler to node.
     302                // The wrapped statement.
     303
     304                ListInit * node_init;
     305                {
     306                        std::list<Initializer*> field_inits;
     307                        field_inits.push_back( new SingleInit( /* ... */ ) );
     308                        field_inits.push_back( new SingleInit( nameOf( resume_handler ) ) );
     309                        node_init = new ListInit( field_inits );
     310                }
    379311
    380312                std::list< Attribute * > attributes;
    381313                {
    382314                        std::list< Expression * > attr_params;
    383                         attr_params.push_back( new NameExpr(
    384                                 "__cfaehm__try_resume_cleanup" ) );
    385                         attributes.push_back( new Attribute( "cleanup", attr_params ) );
    386                 }
    387 
    388                 ObjectDecl * obj = new ObjectDecl(
    389                         "__resume_node",
     315                        attr_params.push_back( nameOf( /* ... deconstructor ... */ ) );
     316                        attrributes.push_back( new Attribute( "cleanup", attr_params ) );
     317                }
     318
     319                appendDeclStmt( body,
     320                /**/ ObjectDecl(
     321                        "resume_node",
    390322                        Type::StorageClasses(),
    391323                        LinkageSpec::Cforall,
    392324                        nullptr,
    393                         new StructInstType(
    394                                 Type::Qualifiers(),
    395                                 node_decl
    396                                 ),
    397                         nullptr,
     325                        /* Type* = resume_node */,
     326                        node_init,
    398327                        attributes
    399                         );
    400                 appendDeclStmt( body, obj );
    401 
    402                 UntypedExpr *setup = new UntypedExpr( new NameExpr(
    403                         "__cfaehm__try_resume_setup" ) );
    404                 setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
    405                 setup->get_args().push_back( nameOf( resume_handler ) );
    406 
    407                 body->push_back( new ExprStmt( noLabels, setup ) );
    408 
     328                        )
     329                );
    409330                body->push_back( wraps );
    410331                return body;
     
    412333
    413334        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
    414                 FinallyStmt * finally = tryStmt->get_finally();
    415                 CompoundStmt * body = finally->get_block();
    416                 finally->set_block( nullptr );
    417                 delete finally;
     335                CompoundStmt * body = tryStmt->get_finally();
    418336                tryStmt->set_finally( nullptr );
    419337
    420338                return new FunctionDecl("finally", Type::StorageClasses(),
    421                         LinkageSpec::Cforall, finally_func_t.clone(), body);
    422         }
    423 
    424         ObjectDecl * create_finally_hook(
    425                         StructDecl * hook_decl, FunctionDecl * finally_wrapper ) {
    426                 // struct __cfaehm__cleanup_hook __finally_hook
    427                 //      __attribute__((cleanup( finally_wrapper )));
     339                        LinkageSpec::Cforall, void_func_t, body);
     340        }
     341
     342        ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ) {
     343                // struct _cleanup_hook NAME __attribute__((cleanup( ... )));
    428344
    429345                // Make Cleanup Attribute.
     
    432348                        std::list< Expression * > attr_params;
    433349                        attr_params.push_back( nameOf( finally_wrapper ) );
    434                         attributes.push_back( new Attribute( "cleanup", attr_params ) );
    435                 }
    436 
    437                 return new ObjectDecl(
    438                         "__finally_hook",
     350                        attrributes.push_back( new Attribute( "cleanup", attr_params ) );
     351                }
     352
     353                return ObjectDecl( /* ... */
     354                        const std::string &name "finally_hook",
    439355                        Type::StorageClasses(),
    440356                        LinkageSpec::Cforall,
    441357                        nullptr,
    442                         new StructInstType(
    443                                 emptyQualifiers,
    444                                 hook_decl
    445                                 ),
     358                        /* ... Type * ... */,
    446359                        nullptr,
    447360                        attributes
     
    450363
    451364
    452         class ExceptionMutatorCore : public WithGuards {
     365        class ExceptionMutatorCore : public WithScoping {
    453366                enum Context { NoHandler, TerHandler, ResHandler };
    454367
     
    457370                // loop, switch or the goto stays within the function.
    458371
    459                 Context cur_context;
     372                Context curContext;
    460373
    461374                // We might not need this, but a unique base for each try block's
     
    464377                //unsigned int try_count = 0;
    465378
    466                 StructDecl *node_decl;
    467                 StructDecl *hook_decl;
    468379
    469380        public:
    470381                ExceptionMutatorCore() :
    471                         cur_context(NoHandler),
    472                         node_decl(nullptr), hook_decl(nullptr)
     382                        curContext(NoHandler)
    473383                {}
    474384
    475                 void premutate( CatchStmt *catchStmt );
    476                 void premutate( StructDecl *structDecl );
     385                void premutate( CatchStmt *tryStmt );
    477386                Statement * postmutate( ThrowStmt *throwStmt );
    478387                Statement * postmutate( TryStmt *tryStmt );
     
    484393                        if ( throwStmt->get_expr() ) {
    485394                                return create_terminate_throw( throwStmt );
    486                         } else if ( TerHandler == cur_context ) {
     395                        } else if ( TerHandler == curContext ) {
    487396                                return create_terminate_rethrow( throwStmt );
    488397                        } else {
    489398                                assertf(false, "Invalid throw in %s at %i\n",
    490                                         throwStmt->location.filename.c_str(),
     399                                        throwStmt->location.filename,
    491400                                        throwStmt->location.linenumber);
    492401                                return nullptr;
     
    495404                        if ( throwStmt->get_expr() ) {
    496405                                return create_resume_throw( throwStmt );
    497                         } else if ( ResHandler == cur_context ) {
     406                        } else if ( ResHandler == curContext ) {
    498407                                return create_resume_rethrow( throwStmt );
    499408                        } else {
    500409                                assertf(false, "Invalid throwResume in %s at %i\n",
    501                                         throwStmt->location.filename.c_str(),
     410                                        throwStmt->location.filename,
    502411                                        throwStmt->location.linenumber);
    503412                                return nullptr;
     
    507416
    508417        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
    509                 assert( node_decl );
    510                 assert( hook_decl );
    511 
    512418                // Generate a prefix for the function names?
    513419
    514                 CompoundStmt * block = new CompoundStmt( noLabels );
    515                 CompoundStmt * inner = take_try_block( tryStmt );
     420                CompoundStmt * block = new CompoundStmt();
     421                Statement * inner = take_try_block( tryStmt );
    516422
    517423                if ( tryStmt->get_finally() ) {
     
    521427                        appendDeclStmt( block, finally_block );
    522428                        // Create and add the finally cleanup hook.
    523                         appendDeclStmt( block,
    524                                 create_finally_hook( hook_decl, finally_block ) );
    525                 }
    526 
    527                 CatchList termination_handlers;
    528                 CatchList resumption_handlers;
    529                 split( tryStmt->get_catchers(),
    530                            termination_handlers, resumption_handlers );
    531 
    532                 if ( resumption_handlers.size() ) {
     429                        appendDeclStmt( block, create_finally_hook( finally_block ) );
     430                }
     431
     432                StatementList termination_handlers;
     433                StatementList resumption_handlers;
     434                split( tryStmt->get_handlers(),
     435                       termination_handlers, resumption_handlers );
     436
     437                if ( resumeption_handlers.size() ) {
    533438                        // Define the helper function.
    534439                        FunctionDecl * resume_handler =
     
    536441                        appendDeclStmt( block, resume_handler );
    537442                        // Prepare hooks
    538                         inner = create_resume_wrapper( node_decl, inner, resume_handler );
     443                        inner = create_resume_wrapper( inner, resume_handler );
    539444                }
    540445
     
    557462                block->push_back( inner );
    558463
    559                 //free_all( termination_handlers );
    560                 //free_all( resumption_handlers );
     464                free_all( termination_handlers );
     465                free_all( resumption_handlers );
    561466
    562467                return block;
     
    564469
    565470        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    566                 GuardValue( cur_context );
    567                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    568                         cur_context = TerHandler;
     471                GuardValue( curContext );
     472                if ( CatchStmt::Termination == catchStmt->get_kind() ) {
     473                        curContext = TerHandler;
    569474                } else {
    570                         cur_context = ResHandler;
    571                 }
    572         }
    573 
    574         void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
    575                 if ( !structDecl->has_body() ) {
    576                         // Skip children?
    577                         return;
    578                 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
    579                         assert( nullptr == node_decl );
    580                         node_decl = structDecl;
    581                 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
    582                         assert( nullptr == hook_decl );
    583                         hook_decl = structDecl;
    584                 }
    585                 // Later we might get the exception type as well.
    586         }
    587 
    588         void translateEHM( std::list< Declaration *> & translationUnit ) {
    589                 init_func_types();
    590 
     475                        curContext = ResHandler;
     476                }
     477        }
     478
     479    void translateEHM( std::list< Declaration *> & translationUnit ) {
    591480                PassVisitor<ExceptionMutatorCore> translator;
    592481                for ( Declaration * decl : translationUnit ) {
    593                         decl->acceptMutator( translator );
     482                        decl->mutate( translator );
    594483                }
    595484        }
  • src/ControlStruct/ExceptTranslate.h

    r67fa9f9 r11dbfe1  
    1010// Created On       : Tus Jun 06 10:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 30 10:20:00 2017
    13 // Update Count     : 2
     12// Last Modified On : Thr Jun 22 15:57:00 2017
     13// Update Count     : 0
    1414//
    1515
     
    1717#define EXCEPT_TRANSLATE_H
    1818
    19 #include <list>
    20 #include "SynTree/SynTree.h"
    21 
    22 namespace ControlStruct {
     19namespace ControlFlow {
    2320        void translateEHM( std::list< Declaration *> & translationUnit );
    2421        /* Converts exception handling structures into their underlying C code.
  • src/ControlStruct/module.mk

    r67fa9f9 r11dbfe1  
    1010## Author           : Richard C. Bilson
    1111## Created On       : Mon Jun  1 17:49:17 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Wed Jun 28 16:15:00 2017
    14 ## Update Count     : 4
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Thu Aug  4 11:38:06 2016
     14## Update Count     : 3
    1515###############################################################################
    1616
    1717SRC +=  ControlStruct/LabelGenerator.cc \
    1818        ControlStruct/LabelFixer.cc \
    19         ControlStruct/MLEMutator.cc \
     19        ControlStruct/MLEMutator.cc \
    2020        ControlStruct/Mutate.cc \
    21         ControlStruct/ForExprMutator.cc \
    22         ControlStruct/ExceptTranslate.cc
     21        ControlStruct/ForExprMutator.cc
     22
  • src/GenPoly/Box.cc

    r67fa9f9 r11dbfe1  
    504504                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    505505                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    506                                 // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
    507506                                doBeginScope();
    508507                                scopeTyVars.beginScope();
     
    549548                                retval = oldRetval;
    550549                                doEndScope();
    551                                 // std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl;
    552550                        } // if
    553551                        return functionDecl;
     
    11181116
    11191117                Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
    1120                         // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
     1118                        // std::cerr << "mutate appExpr: ";
    11211119                        // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    11221120                        //      std::cerr << i->first << " ";
     
    11431141                        ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
    11441142
    1145                         // std::cerr << function << std::endl;
    1146                         // std::cerr << "scopeTyVars: ";
    1147                         // printTyVarMap( std::cerr, scopeTyVars );
    1148                         // std::cerr << "exprTyVars: ";
    1149                         // printTyVarMap( std::cerr, exprTyVars );
    1150                         // std::cerr << "env: " << *env << std::endl;
    1151                         // std::cerr << needsAdapter( function, scopeTyVars ) << ! needsAdapter( function, exprTyVars) << std::endl;
    1152 
    11531143                        // NOTE: addDynRetParam needs to know the actual (generated) return type so it can make a temp variable, so pass the result type from the appExpr
    11541144                        // passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
    11551145                        // concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
    11561146                        if ( dynRetType ) {
    1157                                 // std::cerr << "dynRetType: " << dynRetType << std::endl;
    11581147                                Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
    11591148                                ret = addDynRetParam( appExpr, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
  • src/GenPoly/InstantiateGeneric.cc

    r67fa9f9 r11dbfe1  
    2222#include "InstantiateGeneric.h"
    2323
     24#include "DeclMutator.h"
    2425#include "GenPoly.h"
    2526#include "ScopedSet.h"
    2627#include "ScrubTyVars.h"
    27 
    28 #include "Common/PassVisitor.h"
     28#include "PolyMutator.h"
     29
     30#include "ResolvExpr/typeops.h"
     31
     32#include "SynTree/Declaration.h"
     33#include "SynTree/Expression.h"
     34#include "SynTree/Type.h"
     35
    2936#include "Common/ScopedMap.h"
    3037#include "Common/UniqueName.h"
    3138#include "Common/utility.h"
    32 
    33 #include "ResolvExpr/typeops.h"
    34 
    35 #include "SynTree/Declaration.h"
    36 #include "SynTree/Expression.h"
    37 #include "SynTree/Type.h"
    38 
    39 
    40 #include "InitTweak/InitTweak.h"
    41 
    4239
    4340namespace GenPoly {
     
    156153        }
    157154
     155        // collect the environments of each TypeInstType so that type variables can be replaced
     156        // xxx - possibly temporary solution. Access to type environments is required in GenericInstantiator, but it needs to be a DeclMutator which does not provide easy access to the type environments.
     157        class EnvFinder final : public GenPoly::PolyMutator {
     158        public:
     159                using GenPoly::PolyMutator::mutate;
     160                virtual Type * mutate( TypeInstType * inst ) override {
     161                        if ( env ) envMap[inst] = env;
     162                        return inst;
     163                }
     164
     165                // don't want to associate an environment with TypeInstTypes that occur in function types - this may actually only apply to function types belonging to DeclarationWithTypes (or even just FunctionDecl)?
     166                virtual Type * mutate( FunctionType * ftype ) override {
     167                        return ftype;
     168                }
     169                std::unordered_map< ReferenceToType *, TypeSubstitution * > envMap;
     170        };
     171
    158172        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
    159         struct GenericInstantiator final : public WithTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {
     173        class GenericInstantiator final : public DeclMutator {
    160174                /// Map of (generic type, parameter list) pairs to concrete type instantiations
    161175                InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
     
    164178                /// Namer for concrete types
    165179                UniqueName typeNamer;
    166                 /// Should not make use of type environment to replace types of function parameter and return values.
    167                 bool inFunctionType = false;
    168                 GenericInstantiator() : instantiations(), dtypeStatics(), typeNamer("_conc_") {}
    169 
    170                 Type* postmutate( StructInstType *inst );
    171                 Type* postmutate( UnionInstType *inst );
    172 
    173                 void premutate( FunctionType * ftype ) {
    174                         GuardValue( inFunctionType );
    175                         inFunctionType = true;
    176                 }
    177 
    178                 void beginScope();
    179                 void endScope();
     180                /// Reference to mapping of environments
     181                const std::unordered_map< ReferenceToType *, TypeSubstitution * > & envMap;
     182        public:
     183                GenericInstantiator( const std::unordered_map< ReferenceToType *, TypeSubstitution * > & envMap ) : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_"), envMap( envMap ) {}
     184
     185                using DeclMutator::mutate;
     186                virtual Type* mutate( StructInstType *inst ) override;
     187                virtual Type* mutate( UnionInstType *inst ) override;
     188
     189                virtual void doBeginScope() override;
     190                virtual void doEndScope() override;
    180191        private:
    181192                /// Wrap instantiation lookup for structs
     
    196207
    197208        void instantiateGeneric( std::list< Declaration* > &translationUnit ) {
    198                 PassVisitor<GenericInstantiator> instantiator;
    199                 mutateAll( translationUnit, instantiator );
     209                EnvFinder finder;
     210                mutateAll( translationUnit, finder );
     211                GenericInstantiator instantiator( finder.envMap );
     212                instantiator.mutateDeclarationList( translationUnit );
    200213        }
    201214
     
    293306        Type *GenericInstantiator::replaceWithConcrete( Type *type, bool doClone ) {
    294307                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    295                         if ( env && ! inFunctionType ) {
     308                        if ( envMap.count( typeInst ) ) {
     309                                TypeSubstitution * env = envMap.at( typeInst );
    296310                                Type *concrete = env->lookup( typeInst->get_name() );
    297311                                if ( concrete ) {
     
    317331
    318332
    319         Type* GenericInstantiator::postmutate( StructInstType *inst ) {
     333        Type* GenericInstantiator::mutate( StructInstType *inst ) {
     334                // mutate subtypes
     335                Type *mutated = Mutator::mutate( inst );
     336                inst = dynamic_cast< StructInstType* >( mutated );
     337                if ( ! inst ) return mutated;
     338
    320339                // exit early if no need for further mutation
    321340                if ( inst->get_parameters().empty() ) return inst;
     
    349368                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
    350369                                insert( inst, typeSubs, concDecl ); // must insert before recursion
    351                                 concDecl->acceptMutator( *visitor ); // recursively instantiate members
    352                                 declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
     370                                concDecl->acceptMutator( *this ); // recursively instantiate members
     371                                DeclMutator::addDeclaration( concDecl ); // must occur before declaration is added so that member instantiations appear first
    353372                        }
    354373                        StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
     
    369388        }
    370389
    371         Type* GenericInstantiator::postmutate( UnionInstType *inst ) {
     390        Type* GenericInstantiator::mutate( UnionInstType *inst ) {
     391                // mutate subtypes
     392                Type *mutated = Mutator::mutate( inst );
     393                inst = dynamic_cast< UnionInstType* >( mutated );
     394                if ( ! inst ) return mutated;
     395
    372396                // exit early if no need for further mutation
    373397                if ( inst->get_parameters().empty() ) return inst;
     
    399423                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
    400424                                insert( inst, typeSubs, concDecl ); // must insert before recursion
    401                                 concDecl->acceptMutator( *visitor ); // recursively instantiate members
    402                                 declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
     425                                concDecl->acceptMutator( *this ); // recursively instantiate members
     426                                DeclMutator::addDeclaration( concDecl ); // must occur before declaration is added so that member instantiations appear first
    403427                        }
    404428                        UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
     
    418442        }
    419443
    420         void GenericInstantiator::beginScope() {
     444        void GenericInstantiator::doBeginScope() {
     445                DeclMutator::doBeginScope();
    421446                instantiations.beginScope();
    422447                dtypeStatics.beginScope();
    423448        }
    424449
    425         void GenericInstantiator::endScope() {
     450        void GenericInstantiator::doEndScope() {
     451                DeclMutator::doEndScope();
    426452                instantiations.endScope();
    427453                dtypeStatics.endScope();
  • src/InitTweak/FixInit.cc

    r67fa9f9 r11dbfe1  
    104104                        typedef AddStmtVisitor Parent;
    105105                        using Parent::visit;
    106                         // use ordered data structure to maintain ordering for set_difference and for consistent error messages
    107                         typedef std::list< ObjectDecl * > ObjectSet;
     106                        typedef std::set< ObjectDecl * > ObjectSet;
    108107                        virtual void visit( CompoundStmt *compoundStmt ) override;
    109108                        virtual void visit( DeclStmt *stmt ) override;
     
    117116
    118117                // debug
    119                 template<typename ObjectSet>
    120                 struct PrintSet {
    121                         PrintSet( const ObjectSet & objs ) : objs( objs ) {}
     118                struct printSet {
     119                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     120                        printSet( const ObjectSet & objs ) : objs( objs ) {}
    122121                        const ObjectSet & objs;
    123122                };
    124                 template<typename ObjectSet>
    125                 PrintSet<ObjectSet> printSet( const ObjectSet & objs ) { return PrintSet<ObjectSet>( objs ); }
    126                 template<typename ObjectSet>
    127                 std::ostream & operator<<( std::ostream & out, const PrintSet<ObjectSet> & set) {
     123                std::ostream & operator<<( std::ostream & out, const printSet & set) {
    128124                        out << "{ ";
    129125                        for ( ObjectDecl * obj : set.objs ) {
     
    728724                                                // static bool __objName_uninitialized = true
    729725                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    730                                                 SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant::from_int( 1 ) ) );
     726                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant::from_int( 1 ) ), noDesignators );
    731727                                                ObjectDecl * isUninitializedVar = new ObjectDecl( objDecl->get_mangleName() + "_uninitialized", Type::StorageClasses( Type::Static ), LinkageSpec::Cforall, 0, boolType, boolInitExpr );
    732728                                                isUninitializedVar->fixUniqueId();
     
    749745
    750746                                                Statement * dtor = ctorInit->get_dtor();
    751                                                 objDecl->set_init( nullptr );
    752                                                 ctorInit->set_ctor( nullptr );
     747                                                objDecl->set_init( NULL );
     748                                                ctorInit->set_ctor( NULL );
    753749                                                ctorInit->set_dtor( nullptr );
    754750                                                if ( dtor ) {
     
    803799                                                } else {
    804800                                                        stmtsToAddAfter.push_back( ctor );
    805                                                         objDecl->set_init( nullptr );
    806                                                         ctorInit->set_ctor( nullptr );
     801                                                        objDecl->set_init( NULL );
     802                                                        ctorInit->set_ctor( NULL );
    807803                                                }
    808804                                        } // if
    809805                                } else if ( Initializer * init = ctorInit->get_init() ) {
    810806                                        objDecl->set_init( init );
    811                                         ctorInit->set_init( nullptr );
     807                                        ctorInit->set_init( NULL );
    812808                                } else {
    813809                                        // no constructor and no initializer, which is okay
    814                                         objDecl->set_init( nullptr );
     810                                        objDecl->set_init( NULL );
    815811                                } // if
    816812                                delete ctorInit;
     
    820816
    821817                void ObjDeclCollector::visit( CompoundStmt * compoundStmt ) {
    822                         ObjectSet prevVars = curVars;
     818                        std::set< ObjectDecl * > prevVars = curVars;
    823819                        Parent::visit( compoundStmt );
    824820                        curVars = prevVars;
     
    828824                        // keep track of all variables currently in scope
    829825                        if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) {
    830                                 curVars.push_back( objDecl );
     826                                curVars.insert( objDecl );
    831827                        } // if
    832828                        Parent::visit( stmt );
     
    943939                        )
    944940                        if ( ! diff.empty() ) {
    945                                 // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.
    946                                 std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );
    947 
    948941                                // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor
    949942                                OrderedDecls ordered;
    950943                                for ( OrderedDecls & rdo : reverseDeclOrder ) {
    951944                                        // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.
    952                                         copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
     945                                        copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return diff.count( objDecl ); } );
    953946                                } // for
    954947                                insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) );
  • src/InitTweak/GenInit.cc

    r67fa9f9 r11dbfe1  
    4444        }
    4545
    46         struct ReturnFixer : public WithStmtsToAdd, public WithGuards {
     46        class ReturnFixer : public WithStmtsToAdd, public WithScopes {
     47          public:
    4748                /// consistently allocates a temporary variable for the return value
    4849                /// of a function so that anything which the resolver decides can be constructed
     
    5859        };
    5960
    60         struct CtorDtor : public WithGuards, public WithShortCircuiting  {
     61        class CtorDtor final : public GenPoly::PolyMutator {
     62          public:
     63                typedef GenPoly::PolyMutator Parent;
     64                using Parent::mutate;
    6165                /// create constructor and destructor statements for object declarations.
    6266                /// the actual call statements will be added in after the resolver has run
     
    6569                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
    6670
    67                 void previsit( ObjectDecl * );
    68                 void previsit( FunctionDecl *functionDecl );
    69 
     71                virtual DeclarationWithType * mutate( ObjectDecl * ) override;
     72                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
    7073                // should not traverse into any of these declarations to find objects
    7174                // that need to be constructed or destructed
    72                 void previsit( StructDecl *aggregateDecl );
    73                 void previsit( UnionDecl *aggregateDecl ) { visit_children = false; }
    74                 void previsit( EnumDecl *aggregateDecl ) { visit_children = false; }
    75                 void previsit( TraitDecl *aggregateDecl ) { visit_children = false; }
    76                 void previsit( TypeDecl *typeDecl ) { visit_children = false; }
    77                 void previsit( TypedefDecl *typeDecl ) { visit_children = false; }
    78 
    79                 void previsit( FunctionType *funcType ) { visit_children = false; }
    80 
    81                 void previsit( CompoundStmt * compoundStmt );
     75                virtual Declaration* mutate( StructDecl *aggregateDecl ) override;
     76                virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
     77                virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
     78                virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
     79                virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
     80                virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
     81
     82                virtual Type * mutate( FunctionType *funcType ) override { return funcType; }
     83
     84                virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override;
    8285
    8386          private:
     
    208211
    209212        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
    210                 PassVisitor<CtorDtor> ctordtor;
    211                 acceptAll( translationUnit, ctordtor );
     213                CtorDtor ctordtor;
     214                mutateAll( translationUnit, ctordtor );
    212215        }
    213216
     
    286289        }
    287290
    288         void CtorDtor::previsit( ObjectDecl * objDecl ) {
     291        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    289292                handleDWT( objDecl );
    290293                // hands off if @=, extern, builtin, etc.
     
    298301                        objDecl->set_init( genCtorInit( objDecl ) );
    299302                }
    300         }
    301 
    302         void CtorDtor::previsit( FunctionDecl *functionDecl ) {
    303                 GuardValue( inFunction );
     303                return Parent::mutate( objDecl );
     304        }
     305
     306        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
     307                ValueGuard< bool > oldInFunc = inFunction;
    304308                inFunction = true;
    305309
    306310                handleDWT( functionDecl );
    307311
    308                 GuardScope( managedTypes );
     312                managedTypes.beginScope();
    309313                // go through assertions and recursively add seen ctor/dtors
    310314                for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
     
    313317                        }
    314318                }
    315 
    316                 PassVisitor<CtorDtor> newCtorDtor;
    317                 newCtorDtor.pass = *this;
    318                 maybeAccept( functionDecl->get_statements(), newCtorDtor );
    319                 visit_children = false;  // do not try and construct parameters or forall parameters - must happen after maybeAccept
    320         }
    321 
    322         void CtorDtor::previsit( StructDecl *aggregateDecl ) {
    323                 visit_children = false; // do not try to construct and destruct aggregate members
    324 
     319                // parameters should not be constructed and destructed, so don't mutate FunctionType
     320                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     321
     322                managedTypes.endScope();
     323                return functionDecl;
     324        }
     325
     326        Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) {
    325327                // don't construct members, but need to take note if there is a managed member,
    326328                // because that means that this type is also managed
     
    334336                        }
    335337                }
    336         }
    337 
    338         void CtorDtor::previsit( CompoundStmt * compoundStmt ) {
    339                 GuardScope( managedTypes );
    340         }
     338                return aggregateDecl;
     339        }
     340
     341        CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
     342                managedTypes.beginScope();
     343                CompoundStmt * stmt = Parent::mutate( compoundStmt );
     344                managedTypes.endScope();
     345                return stmt;
     346        }
     347
    341348} // namespace InitTweak
    342349
  • src/InitTweak/InitTweak.cc

    r67fa9f9 r11dbfe1  
    1414                public:
    1515                        bool hasDesignations = false;
    16                         virtual void visit( Designation * des ) {
    17                                 if ( ! des->get_designators().empty() ) hasDesignations = true;
    18                                 else Visitor::visit( des );
    19                         }
     16                        template<typename Init>
     17                        void handleInit( Init * init ) {
     18                                if ( ! init->get_designators().empty() ) hasDesignations = true;
     19                                else Visitor::visit( init );
     20                        }
     21                        virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
     22                        virtual void visit( ListInit * listInit ) { handleInit( listInit); }
    2023                };
    2124
  • src/MakeLibCfa.cc

    r67fa9f9 r11dbfe1  
    9292                assert( ! objDecl->get_init() );
    9393                std::list< Expression* > noDesignators;
    94                 objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), false ) ); // cannot be constructed
     94                objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators, false ) ); // cannot be constructed
    9595                newDecls.push_back( objDecl );
    9696        }
  • src/Makefile.in

    r67fa9f9 r11dbfe1  
    119119        ControlStruct/driver_cfa_cpp-Mutate.$(OBJEXT) \
    120120        ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT) \
    121         ControlStruct/driver_cfa_cpp-ExceptTranslate.$(OBJEXT) \
    122121        GenPoly/driver_cfa_cpp-Box.$(OBJEXT) \
    123122        GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT) \
     
    162161        ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT) \
    163162        ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) \
    164         ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT) \
    165163        SymTab/driver_cfa_cpp-Indexer.$(OBJEXT) \
    166164        SymTab/driver_cfa_cpp-Mangler.$(OBJEXT) \
     
    396394        ControlStruct/LabelGenerator.cc ControlStruct/LabelFixer.cc \
    397395        ControlStruct/MLEMutator.cc ControlStruct/Mutate.cc \
    398         ControlStruct/ForExprMutator.cc \
    399         ControlStruct/ExceptTranslate.cc GenPoly/Box.cc \
     396        ControlStruct/ForExprMutator.cc GenPoly/Box.cc \
    400397        GenPoly/GenPoly.cc GenPoly/PolyMutator.cc \
    401398        GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
     
    417414        ResolvExpr/RenameVars.cc ResolvExpr/FindOpenVars.cc \
    418415        ResolvExpr/PolyCost.cc ResolvExpr/Occurs.cc \
    419         ResolvExpr/TypeEnvironment.cc ResolvExpr/CurrentObject.cc \
    420         SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \
    421         SymTab/FixFunction.cc SymTab/ImplementationType.cc \
    422         SymTab/TypeEquality.cc SymTab/Autogen.cc SynTree/Type.cc \
    423         SynTree/VoidType.cc SynTree/BasicType.cc \
    424         SynTree/PointerType.cc SynTree/ArrayType.cc \
    425         SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
    426         SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
     416        ResolvExpr/TypeEnvironment.cc SymTab/Indexer.cc \
     417        SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \
     418        SymTab/ImplementationType.cc SymTab/TypeEquality.cc \
     419        SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \
     420        SynTree/BasicType.cc SynTree/PointerType.cc \
     421        SynTree/ArrayType.cc SynTree/FunctionType.cc \
     422        SynTree/ReferenceToType.cc SynTree/TupleType.cc \
     423        SynTree/TypeofType.cc SynTree/AttrType.cc \
    427424        SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \
    428425        SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \
     
    595592        ControlStruct/$(DEPDIR)/$(am__dirstamp)
    596593ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT):  \
    597         ControlStruct/$(am__dirstamp) \
    598         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    599 ControlStruct/driver_cfa_cpp-ExceptTranslate.$(OBJEXT):  \
    600594        ControlStruct/$(am__dirstamp) \
    601595        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     
    727721        ResolvExpr/$(am__dirstamp) \
    728722        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    729 ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT):  \
    730         ResolvExpr/$(am__dirstamp) \
    731         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    732723SymTab/$(am__dirstamp):
    733724        @$(MKDIR_P) SymTab
     
    862853        -rm -f Common/driver_cfa_cpp-UniqueName.$(OBJEXT)
    863854        -rm -f Concurrency/driver_cfa_cpp-Keywords.$(OBJEXT)
    864         -rm -f ControlStruct/driver_cfa_cpp-ExceptTranslate.$(OBJEXT)
    865855        -rm -f ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT)
    866856        -rm -f ControlStruct/driver_cfa_cpp-LabelFixer.$(OBJEXT)
     
    900890        -rm -f ResolvExpr/driver_cfa_cpp-CommonType.$(OBJEXT)
    901891        -rm -f ResolvExpr/driver_cfa_cpp-ConversionCost.$(OBJEXT)
    902         -rm -f ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT)
    903892        -rm -f ResolvExpr/driver_cfa_cpp-FindOpenVars.$(OBJEXT)
    904893        -rm -f ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT)
     
    976965@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Po@am__quote@
    977966@AMDEP_TRUE@@am__include@ @am__quote@Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Po@am__quote@
    978 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Po@am__quote@
    979967@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Po@am__quote@
    980968@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Po@am__quote@
     
    10141002@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Po@am__quote@
    10151003@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Po@am__quote@
    1016 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po@am__quote@
    10171004@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Po@am__quote@
    10181005@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Po@am__quote@
     
    13681355@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ForExprMutator.obj `if test -f 'ControlStruct/ForExprMutator.cc'; then $(CYGPATH_W) 'ControlStruct/ForExprMutator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ForExprMutator.cc'; fi`
    13691356
    1370 ControlStruct/driver_cfa_cpp-ExceptTranslate.o: ControlStruct/ExceptTranslate.cc
    1371 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-ExceptTranslate.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.o `test -f 'ControlStruct/ExceptTranslate.cc' || echo '$(srcdir)/'`ControlStruct/ExceptTranslate.cc
    1372 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Po
    1373 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/ExceptTranslate.cc' object='ControlStruct/driver_cfa_cpp-ExceptTranslate.o' libtool=no @AMDEPBACKSLASH@
    1374 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1375 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.o `test -f 'ControlStruct/ExceptTranslate.cc' || echo '$(srcdir)/'`ControlStruct/ExceptTranslate.cc
    1376 
    1377 ControlStruct/driver_cfa_cpp-ExceptTranslate.obj: ControlStruct/ExceptTranslate.cc
    1378 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-ExceptTranslate.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.obj `if test -f 'ControlStruct/ExceptTranslate.cc'; then $(CYGPATH_W) 'ControlStruct/ExceptTranslate.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ExceptTranslate.cc'; fi`
    1379 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Po
    1380 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/ExceptTranslate.cc' object='ControlStruct/driver_cfa_cpp-ExceptTranslate.obj' libtool=no @AMDEPBACKSLASH@
    1381 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1382 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.obj `if test -f 'ControlStruct/ExceptTranslate.cc'; then $(CYGPATH_W) 'ControlStruct/ExceptTranslate.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ExceptTranslate.cc'; fi`
    1383 
    13841357GenPoly/driver_cfa_cpp-Box.o: GenPoly/Box.cc
    13851358@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Box.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Tpo -c -o GenPoly/driver_cfa_cpp-Box.o `test -f 'GenPoly/Box.cc' || echo '$(srcdir)/'`GenPoly/Box.cc
     
    19691942@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    19701943@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj `if test -f 'ResolvExpr/TypeEnvironment.cc'; then $(CYGPATH_W) 'ResolvExpr/TypeEnvironment.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/TypeEnvironment.cc'; fi`
    1971 
    1972 ResolvExpr/driver_cfa_cpp-CurrentObject.o: ResolvExpr/CurrentObject.cc
    1973 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CurrentObject.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.o `test -f 'ResolvExpr/CurrentObject.cc' || echo '$(srcdir)/'`ResolvExpr/CurrentObject.cc
    1974 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po
    1975 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CurrentObject.cc' object='ResolvExpr/driver_cfa_cpp-CurrentObject.o' libtool=no @AMDEPBACKSLASH@
    1976 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1977 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.o `test -f 'ResolvExpr/CurrentObject.cc' || echo '$(srcdir)/'`ResolvExpr/CurrentObject.cc
    1978 
    1979 ResolvExpr/driver_cfa_cpp-CurrentObject.obj: ResolvExpr/CurrentObject.cc
    1980 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CurrentObject.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.obj `if test -f 'ResolvExpr/CurrentObject.cc'; then $(CYGPATH_W) 'ResolvExpr/CurrentObject.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CurrentObject.cc'; fi`
    1981 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po
    1982 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CurrentObject.cc' object='ResolvExpr/driver_cfa_cpp-CurrentObject.obj' libtool=no @AMDEPBACKSLASH@
    1983 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1984 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.obj `if test -f 'ResolvExpr/CurrentObject.cc'; then $(CYGPATH_W) 'ResolvExpr/CurrentObject.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CurrentObject.cc'; fi`
    19851944
    19861945SymTab/driver_cfa_cpp-Indexer.o: SymTab/Indexer.cc
  • src/Parser/InitializerNode.cc

    r67fa9f9 r11dbfe1  
    7474
    7575        InitializerNode *moreInit;
    76         if ( (moreInit = dynamic_cast< InitializerNode * >( get_next() ) ) ) {
     76        if  ( get_next() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_next() ) ) != 0) )
    7777                moreInit->printOneLine( os );
    78         }
    7978}
    8079
    8180Initializer *InitializerNode::build() const {
    8281        if ( aggregate ) {
    83                 // steal designators from children
    84                 std::list< Designation * > designlist;
    85                 InitializerNode * child = next_init();
    86                 for ( ; child != nullptr; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
    87                         std::list< Expression * > desList;
    88                         buildList< Expression, ExpressionNode >( child->designator, desList );
    89                         designlist.push_back( new Designation( desList ) );
    90                 } // for
    9182                std::list< Initializer * > initlist;
    9283                buildList< Initializer, InitializerNode >( next_init(), initlist );
     84
     85                std::list< Expression * > designlist;
     86
     87                if ( designator != 0 ) {
     88                        buildList< Expression, ExpressionNode >( designator, designlist );
     89                } // if
     90
    9391                return new ListInit( initlist, designlist, maybeConstructed );
    9492        } else {
    95                 if ( get_expression() != 0) {
    96                         return new SingleInit( maybeBuild< Expression >( get_expression() ), maybeConstructed );
    97                 }
     93                std::list< Expression * > designators;
     94
     95                if ( designator != 0 )
     96                        buildList< Expression, ExpressionNode >( designator, designators );
     97
     98                if ( get_expression() != 0)
     99                        return new SingleInit( maybeBuild< Expression >( get_expression() ), designators, maybeConstructed );
    98100        } // if
     101
    99102        return 0;
    100103}
  • src/Parser/TypeData.cc

    r67fa9f9 r11dbfe1  
    760760                if ( cur->has_enumeratorValue() ) {
    761761                        ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members);
    762                         member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) );
     762                        member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ), list< Expression * >() ) );
    763763                } // if
    764764        } // for
     
    777777TupleType * buildTuple( const TypeData * td ) {
    778778        assert( td->kind == TypeData::Tuple );
    779         std::list< Type * > types;
    780         buildTypeList( td->tuple, types );
    781         TupleType * ret = new TupleType( buildQualifiers( td ), types );
     779        TupleType * ret = new TupleType( buildQualifiers( td ) );
     780        buildTypeList( td->tuple, ret->get_types() );
    782781        buildForall( td->forall, ret->get_forall() );
    783782        return ret;
  • src/Parser/parser.yy

    r67fa9f9 r11dbfe1  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Sep  1 20:22:55 2001
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 30 15:38:00 2017
    13 // Update Count     : 2415
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jun 28 22:11:22 2017
     13// Update Count     : 2414
    1414//
    1515
     
    104104        std::string * str;
    105105        bool flag;
    106         CatchStmt::Kind catch_kind;
    107106}
    108107
     
    193192%type<sn> switch_clause_list_opt                switch_clause_list                      choose_clause_list_opt          choose_clause_list
    194193%type<sn> /* handler_list */                    handler_clause                          finally_clause
    195 %type<catch_kind> handler_key
    196194
    197195// declarations
     
    960958handler_clause:
    961959        // TEMPORARY, TEST EXCEPTIONS
    962         handler_key '(' push push INTEGERconstant pop ')' compound_statement pop
    963                 { $$ = new StatementNode( build_catch( $1, nullptr, new ExpressionNode( build_constantInteger( *$5 ) ), $8 ) ); }
    964         | handler_clause handler_key '(' push push INTEGERconstant pop ')' compound_statement pop
    965                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, nullptr, new ExpressionNode( build_constantInteger( *$6 ) ), $9 ) ) ); }
    966 
    967         | handler_key '(' push push exception_declaration pop ')' compound_statement pop
    968                 { $$ = new StatementNode( build_catch( $1, $5, nullptr, $8 ) ); }
    969         | handler_clause handler_key '(' push push exception_declaration pop ')' compound_statement pop
    970                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $6, nullptr, $9 ) ) ); }
    971         ;
    972 
    973 handler_key:
    974         CATCH
    975                 { $$ = CatchStmt::Terminate; }
    976         | CATCHRESUME
    977                 { $$ = CatchStmt::Resume; }
     960        CATCH '(' push push INTEGERconstant pop ')' compound_statement pop
     961                { $$ = new StatementNode( build_catch( CatchStmt::Terminate, nullptr, new ExpressionNode( build_constantInteger( *$5 ) ), $8 ) ); }
     962        | handler_clause CATCH '(' push push INTEGERconstant pop ')' compound_statement pop
     963                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( CatchStmt::Terminate, nullptr, new ExpressionNode( build_constantInteger( *$6 ) ), $9 ) ) ); }
     964
     965        | CATCH '(' push push exception_declaration pop ')' compound_statement pop
     966                { $$ = new StatementNode( build_catch( CatchStmt::Terminate, $5, nullptr, $8 ) ); }
     967        | handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop
     968                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( CatchStmt::Terminate, $6, nullptr, $9 ) ) ); }
     969        | CATCHRESUME '(' push push exception_declaration pop ')' compound_statement pop
     970                { $$ = new StatementNode( build_catch( CatchStmt::Resume, $5, nullptr, $8 ) ); }
     971        | handler_clause CATCHRESUME '(' push push exception_declaration pop ')' compound_statement pop
     972                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( CatchStmt::Resume, $6, nullptr, $9 ) ) ); }
    978973        ;
    979974
  • src/ResolvExpr/AlternativeFinder.cc

    r67fa9f9 r11dbfe1  
    604604//          )
    605605                SymTab::Indexer decls( indexer );
    606                 // PRINT(
    607                 //      std::cerr << "============= original indexer" << std::endl;
    608                 //      indexer.print( std::cerr );
    609                 //      std::cerr << "============= new indexer" << std::endl;
    610                 //      decls.print( std::cerr );
    611                 // )
     606                PRINT(
     607                        std::cerr << "============= original indexer" << std::endl;
     608                        indexer.print( std::cerr );
     609                        std::cerr << "============= new indexer" << std::endl;
     610                        decls.print( std::cerr );
     611                )
    612612                addToIndexer( have, decls );
    613613                AssertionSet newNeed;
     
    809809        }
    810810
    811         Expression * restructureCast( Expression * argExpr, Type * toType ) {
    812                 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) {
    813                         // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
    814                         // to its corresponding target type, producing the tuple of those cast expressions. If there are
    815                         // more components of the tuple than components in the target type, then excess components do not
    816                         // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
    817                         if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
    818                                 // expressions which may contain side effects require a single unique instance of the expression.
    819                                 argExpr = new UniqueExpr( argExpr );
    820                         }
    821                         std::list< Expression * > componentExprs;
    822                         for ( unsigned int i = 0; i < toType->size(); i++ ) {
    823                                 // cast each component
    824                                 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
    825                                 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) );
    826                         }
    827                         delete argExpr;
    828                         assert( componentExprs.size() > 0 );
    829                         // produce the tuple of casts
    830                         return new TupleExpr( componentExprs );
    831                 } else {
    832                         // handle normally
    833                         return new CastExpr( argExpr, toType->clone() );
    834                 }
    835         }
    836 
    837811        void AlternativeFinder::visit( CastExpr *castExpr ) {
    838812                Type *& toType = castExpr->get_result();
     
    866840                                thisCost += Cost( 0, 0, discardedValues );
    867841
    868                                 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     842                                Expression * argExpr = i->expr->clone();
     843                                if ( argExpr->get_result()->size() > 1 && ! castExpr->get_result()->isVoid() ) {
     844                                        // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
     845                                        // to its corresponding target type, producing the tuple of those cast expressions. If there are
     846                                        // more components of the tuple than components in the target type, then excess components do not
     847                                        // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
     848                                        if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
     849                                                // expressions which may contain side effects require a single unique instance of the expression.
     850                                                argExpr = new UniqueExpr( argExpr );
     851                                        }
     852                                        std::list< Expression * > componentExprs;
     853                                        for ( unsigned int i = 0; i < castExpr->get_result()->size(); i++ ) {
     854                                                // cast each component
     855                                                TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
     856                                                componentExprs.push_back( new CastExpr( idx, castExpr->get_result()->getComponent( i )->clone() ) );
     857                                        }
     858                                        delete argExpr;
     859                                        assert( componentExprs.size() > 0 );
     860                                        // produce the tuple of casts
     861                                        candidates.push_back( Alternative( new TupleExpr( componentExprs ), i->env, i->cost, thisCost ) );
     862                                } else {
     863                                        // handle normally
     864                                        candidates.push_back( Alternative( new CastExpr( argExpr->clone(), toType->clone() ), i->env, i->cost, thisCost ) );
     865                                }
    869866                        } // if
    870867                } // for
     
    11851182        }
    11861183
    1187         void AlternativeFinder::visit( UntypedInitExpr *initExpr ) {
    1188                 // handle each option like a cast
    1189                 AltList candidates;
    1190                 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; )
    1191                 // O(N^2) checks of d-types with e-types
    1192                 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
    1193                         Type * toType = resolveTypeof( initAlt.type, indexer );
    1194                         SymTab::validateType( toType, &indexer );
    1195                         adjustExprType( toType, env, indexer );
    1196                         // Ideally the call to findWithAdjustment could be moved out of the loop, but unfortunately it currently has to occur inside or else
    1197                         // polymorphic return types are not properly bound to the initialization type, since return type variables are only open for the duration of resolving
    1198                         // the UntypedExpr. This is only actually an issue in initialization contexts that allow more than one possible initialization type, but it is still suboptimal.
    1199                         AlternativeFinder finder( indexer, env );
    1200                         finder.targetType = toType;
    1201                         finder.findWithAdjustment( initExpr->get_expr() );
    1202                         for ( Alternative & alt : finder.get_alternatives() ) {
    1203                                 TypeEnvironment newEnv( alt.env );
    1204                                 AssertionSet needAssertions, haveAssertions;
    1205                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    1206                                 PRINT( std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl; )
    1207                                 // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    1208                                 // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    1209                                 // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    1210                                 // to.
    1211                                 int discardedValues = alt.expr->get_result()->size() - toType->size();
    1212                                 if ( discardedValues < 0 ) continue;
    1213                                 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    1214                                 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    1215                                 // unification run for side-effects
    1216                                 unify( toType, alt.expr->get_result(), newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
    1217 
    1218                                 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv );
    1219                                 if ( thisCost != Cost::infinity ) {
    1220                                         // count one safe conversion for each value that is thrown away
    1221                                         thisCost += Cost( 0, 0, discardedValues );
    1222                                         candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    1223                                 }
    1224                         }
    1225                 }
    1226 
    1227                 // findMinCost selects the alternatives with the lowest "cost" members, but has the side effect of copying the
    1228                 // cvtCost member to the cost member (since the old cost is now irrelevant).  Thus, calling findMinCost twice
    1229                 // selects first based on argument cost, then on conversion cost.
    1230                 AltList minArgCost;
    1231                 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) );
    1232                 findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
    1233         }
    12341184} // namespace ResolvExpr
    12351185
  • src/ResolvExpr/AlternativeFinder.h

    r67fa9f9 r11dbfe1  
    7373                virtual void visit( UniqueExpr *unqExpr );
    7474                virtual void visit( StmtExpr *stmtExpr );
    75                 virtual void visit( UntypedInitExpr *initExpr );
    7675                /// Runs a new alternative finder on each element in [begin, end)
    7776                /// and writes each alternative finder to out.
  • src/ResolvExpr/Resolver.cc

    r67fa9f9 r11dbfe1  
    1414//
    1515
    16 #include <iostream>
    17 
     16#include "Resolver.h"
     17#include "AlternativeFinder.h"
    1818#include "Alternative.h"
    19 #include "AlternativeFinder.h"
    20 #include "CurrentObject.h"
    2119#include "RenameVars.h"
    22 #include "Resolver.h"
    2320#include "ResolveTypeof.h"
    2421#include "typeops.h"
    25 
     22#include "SynTree/Statement.h"
     23#include "SynTree/Type.h"
    2624#include "SynTree/Expression.h"
    2725#include "SynTree/Initializer.h"
    28 #include "SynTree/Statement.h"
    29 #include "SynTree/Type.h"
    30 
     26#include "SymTab/Indexer.h"
    3127#include "SymTab/Autogen.h"
    32 #include "SymTab/Indexer.h"
    33 
    3428#include "Common/utility.h"
    35 
    3629#include "InitTweak/InitTweak.h"
    3730
     31#include <iostream>
    3832using namespace std;
    3933
     
    4539                        if ( const Resolver * res = dynamic_cast< const Resolver * >( &other ) ) {
    4640                                functionReturn = res->functionReturn;
    47                                 currentObject = res->currentObject;
     41                                initContext = res->initContext;
    4842                                inEnumDecl = res->inEnumDecl;
    4943                        }
     
    7064                virtual void visit( BranchStmt *branchStmt ) override;
    7165                virtual void visit( ReturnStmt *returnStmt ) override;
    72                 virtual void visit( ThrowStmt *throwStmt ) override;
    7366
    7467                virtual void visit( SingleInit *singleInit ) override;
     
    8679
    8780                Type * functionReturn = nullptr;
    88                 CurrentObject currentObject = nullptr;
     81                Type *initContext = nullptr;
    8982                bool inEnumDecl = false;
    9083        };
     
    193186                // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
    194187                // the RHS.
    195                 ValueGuard<CurrentObject> temp( currentObject );
    196                 currentObject = CurrentObject( objectDecl->get_type() );
    197                 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
     188                Type *temp = initContext;
     189                initContext = new_type;
     190                if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) {
    198191                        // enumerator initializers should not use the enum type to initialize, since
    199192                        // the enum type is still incomplete at this point. Use signed int instead.
    200                         currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     193                        initContext = new BasicType( Type::Qualifiers(), BasicType::SignedInt );
    201194                }
    202195                Parent::visit( objectDecl );
    203                 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
     196                if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) {
    204197                        // delete newly created signed int type
    205                         // delete currentObject.getType();
    206                 }
     198                        delete initContext;
     199                }
     200                initContext = temp;
    207201        }
    208202
     
    321315
    322316        void Resolver::visit( SwitchStmt *switchStmt ) {
    323                 ValueGuard< CurrentObject > oldCurrentObject( currentObject );
     317                ValueGuard< Type * > oldInitContext( initContext );
    324318                Expression *newExpr;
    325319                newExpr = findIntegralExpression( switchStmt->get_condition(), *this );
     
    327321                switchStmt->set_condition( newExpr );
    328322
    329                 currentObject = CurrentObject( newExpr->get_result() );
     323                initContext = newExpr->get_result();
    330324                Parent::visit( switchStmt );
    331325        }
     
    333327        void Resolver::visit( CaseStmt *caseStmt ) {
    334328                if ( caseStmt->get_condition() ) {
    335                         std::list< InitAlternative > initAlts = currentObject.getOptions();
    336                         assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
    337                         CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initAlts.front().type->clone() );
     329                        assert( initContext );
     330                        CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initContext->clone() );
    338331                        Expression * newExpr = findSingleExpression( castExpr, *this );
    339332                        castExpr = safe_dynamic_cast< CastExpr * >( newExpr );
     
    367360        }
    368361
    369         void Resolver::visit( ThrowStmt *throwStmt ) {
    370                 if ( throwStmt->get_expr() ) {
    371                         Expression * wrapped = new CastExpr( throwStmt->get_expr(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    372                         Expression * newExpr = findSingleExpression( wrapped, *this );
    373                         throwStmt->set_expr( newExpr );
    374                 }
    375         }
    376 
    377362        template< typename T >
    378363        bool isCharType( T t ) {
     
    385370
    386371        void Resolver::visit( SingleInit *singleInit ) {
    387                 // resolve initialization using the possibilities as determined by the currentObject cursor
    388                 UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() );
    389                 Expression * newExpr = findSingleExpression( untyped, *this );
    390                 InitExpr * initExpr = safe_dynamic_cast< InitExpr * >( newExpr );
    391 
    392                 // move cursor to the object that is actually initialized
    393                 currentObject.setNext( initExpr->get_designation() );
    394 
    395                 // discard InitExpr wrapper and retain relevant pieces
    396                 newExpr = initExpr->get_expr();
    397                 newExpr->set_env( initExpr->get_env() );
    398                 initExpr->set_expr( nullptr );
    399                 initExpr->set_env( nullptr );
    400                 delete initExpr;
    401 
    402                 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
    403                 Type * initContext = currentObject.getCurrentType();
    404 
    405                 // check if actual object's type is char[]
    406                 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
    407                         if ( isCharType( at->get_base() ) ) {
    408                                 // check if the resolved type is char *
    409                                 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    410                                         if ( isCharType( pt->get_base() ) ) {
    411                                                 // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
    412                                                 CastExpr *ce = safe_dynamic_cast< CastExpr * >( newExpr );
    413                                                 newExpr = ce->get_arg();
    414                                                 ce->set_arg( nullptr );
    415                                                 delete ce;
     372                if ( singleInit->get_value() ) {
     373                        // // find all the d's
     374                        // std::list<Expression *> &designators = singleInit->get_designators();
     375                        // std::list<Type *> types1{ initContext }, types2;
     376                        // for ( Expression * expr: designators ) {
     377                        //      cerr << expr << endl;
     378                        //      if ( NameExpr * nexpr = dynamic_cast<NameExpr *>( expr ) ) {
     379                        //              for ( Type * type: types1 ) {
     380                        //                      cerr << type << endl;
     381                        //                      ReferenceToType * fred = dynamic_cast<ReferenceToType *>(type);
     382                        //                      std::list<Declaration *> members;
     383                        //                      if ( fred ) {
     384                        //                              fred->lookup( nexpr->get_name(), members ); // concatenate identical field name
     385                        //                              for ( Declaration * mem: members ) {
     386                        //                                      if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>(mem) ) {
     387                        //                                              types2.push_back( dwt->get_type() );
     388                        //                                      } // if
     389                        //                              } // for
     390                        //                      } // if
     391                        //              } // for
     392                        //              types1 = types2;
     393                        //              types2.clear();
     394                        //      } // if
     395                        // } // for
     396                        // // for ( Type * type: types1 ) {
     397                        // //   cerr << type << endl;
     398                        // // } // for
     399
     400                        // // O(N^2) checks of d-types with f-types
     401                        // // find the minimum cost
     402                        CastExpr *castExpr = new CastExpr( singleInit->get_value(), initContext->clone() );
     403                        Expression *newExpr = findSingleExpression( castExpr, *this );
     404                        delete castExpr;
     405                        singleInit->set_value( newExpr );
     406
     407                        // check if initializing type is char[]
     408                        if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     409                                if ( isCharType( at->get_base() ) ) {
     410                                        // check if the resolved type is char *
     411                                        if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
     412                                                if ( isCharType( pt->get_base() ) ) {
     413                                                        // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
     414                                                        CastExpr *ce = dynamic_cast< CastExpr * >( newExpr );
     415                                                        singleInit->set_value( ce->get_arg() );
     416                                                        ce->set_arg( NULL );
     417                                                        delete ce;
     418                                                }
    416419                                        }
    417420                                }
    418421                        }
    419                 }
    420 
    421                 // set initializer expr to resolved express
    422                 singleInit->set_value( newExpr );
    423 
    424                 // move cursor to next object in preparation for next initializer
    425                 currentObject.increment();
     422                } // if
     423        }
     424
     425        template< typename AggrInst >
     426        TypeSubstitution makeGenericSubstitutuion( AggrInst * inst ) {
     427                assert( inst );
     428                assert( inst->get_baseParameters() );
     429                std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
     430                std::list< Expression * > typeSubs = inst->get_parameters();
     431                TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
     432                return subs;
     433        }
     434
     435        ReferenceToType * isStructOrUnion( Type * type ) {
     436                if ( StructInstType * sit = dynamic_cast< StructInstType * >( type ) ) {
     437                        return sit;
     438                } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( type ) ) {
     439                        return uit;
     440                }
     441                return nullptr;
     442        }
     443
     444        void Resolver::resolveSingleAggrInit( Declaration * dcl, InitIterator & init, InitIterator & initEnd, TypeSubstitution sub ) {
     445                DeclarationWithType * dt = dynamic_cast< DeclarationWithType * >( dcl );
     446                assert( dt );
     447                // need to substitute for generic types, so that casts are to concrete types
     448                initContext = dt->get_type()->clone();
     449                sub.apply( initContext );
     450
     451                try {
     452                        if ( init == initEnd ) return; // stop when there are no more initializers
     453                        (*init)->accept( *this );
     454                        ++init; // made it past an initializer
     455                } catch( SemanticError & ) {
     456                        // need to delve deeper, if you can
     457                        if ( ReferenceToType * type = isStructOrUnion( initContext ) ) {
     458                                resolveAggrInit( type, init, initEnd );
     459                        } else {
     460                                // member is not an aggregate type, so can't go any deeper
     461
     462                                // might need to rethink what is being thrown
     463                                throw;
     464                        } // if
     465                }
     466        }
     467
     468        void Resolver::resolveAggrInit( ReferenceToType * inst, InitIterator & init, InitIterator & initEnd ) {
     469                if ( StructInstType * sit = dynamic_cast< StructInstType * >( inst ) ) {
     470                        TypeSubstitution sub = makeGenericSubstitutuion( sit );
     471                        StructDecl * st = sit->get_baseStruct();
     472                        if(st->get_members().empty()) return;
     473                        // want to resolve each initializer to the members of the struct,
     474                        // but if there are more initializers than members we should stop
     475                        list< Declaration * >::iterator it = st->get_members().begin();
     476                        for ( ; it != st->get_members().end(); ++it) {
     477                                resolveSingleAggrInit( *it, init, initEnd, sub );
     478                        }
     479                } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( inst ) ) {
     480                        TypeSubstitution sub = makeGenericSubstitutuion( uit );
     481                        UnionDecl * un = uit->get_baseUnion();
     482                        if(un->get_members().empty()) return;
     483                        // only resolve to the first member of a union
     484                        resolveSingleAggrInit( *un->get_members().begin(), init, initEnd, sub );
     485                } // if
    426486        }
    427487
    428488        void Resolver::visit( ListInit * listInit ) {
    429                 // move cursor into brace-enclosed initializer-list
    430                 currentObject.enterListInit();
    431                 // xxx - fix this so that the list isn't copied, iterator should be used to change current element
    432                 std::list<Designation *> newDesignations;
    433                 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    434                         // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
    435                         // the initializer against that object.
    436                         Designation * des = std::get<0>(p);
    437                         Initializer * init = std::get<1>(p);
    438                         newDesignations.push_back( currentObject.findNext( des ) );
    439                         init->accept( *this );
    440                 }
    441                 // set the set of 'resolved' designations and leave the brace-enclosed initializer-list
    442                 listInit->get_designations() = newDesignations; // xxx - memory management
    443                 currentObject.exitListInit();
    444 
    445                 // xxx - this part has not be folded into CurrentObject yet
    446                 // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
    447                 //      Type * base = tt->get_baseType()->get_base();
    448                 //      if ( base ) {
    449                 //              // know the implementation type, so try using that as the initContext
    450                 //              ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr );
    451                 //              currentObject = &tmpObj;
    452                 //              visit( listInit );
    453                 //      } else {
    454                 //              // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
    455                 //              Parent::visit( listInit );
    456                 //      }
    457                 // } else {
     489                InitIterator iter = listInit->begin();
     490                InitIterator end = listInit->end();
     491
     492                if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
     493                        // resolve each member to the base type of the array
     494                        for ( ; iter != end; ++iter ) {
     495                                initContext = at->get_base();
     496                                (*iter)->accept( *this );
     497                        } // for
     498                } else if ( TupleType * tt = dynamic_cast< TupleType * > ( initContext ) ) {
     499                        for ( Type * t : *tt ) {
     500                                if ( iter == end ) break;
     501                                initContext = t;
     502                                (*iter++)->accept( *this );
     503                        }
     504                } else if ( ReferenceToType * type = isStructOrUnion( initContext ) ) {
     505                        resolveAggrInit( type, iter, end );
     506                } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
     507                        Type * base = tt->get_baseType()->get_base();
     508                        if ( base ) {
     509                                // know the implementation type, so try using that as the initContext
     510                                initContext = base;
     511                                visit( listInit );
     512                        } else {
     513                                // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
     514                                Parent::visit( listInit );
     515                        }
     516                } else {
     517                        assert( dynamic_cast< BasicType * >( initContext ) || dynamic_cast< PointerType * >( initContext )
     518                                || dynamic_cast< ZeroType * >( initContext ) || dynamic_cast< OneType * >( initContext ) || dynamic_cast < EnumInstType * > ( initContext ) );
     519                        // basic types are handled here
     520                        Parent::visit( listInit );
     521                }
     522
     523#if 0
     524                if ( ArrayType *at = dynamic_cast<ArrayType*>(initContext) ) {
     525                        std::list<Initializer *>::iterator iter( listInit->begin_initializers() );
     526                        for ( ; iter != listInit->end_initializers(); ++iter ) {
     527                                initContext = at->get_base();
     528                                (*iter)->accept( *this );
     529                        } // for
     530                } else if ( StructInstType *st = dynamic_cast<StructInstType*>(initContext) ) {
     531                        StructDecl *baseStruct = st->get_baseStruct();
     532                        std::list<Declaration *>::iterator iter1( baseStruct->get_members().begin() );
     533                        std::list<Initializer *>::iterator iter2( listInit->begin_initializers() );
     534                        for ( ; iter1 != baseStruct->get_members().end() && iter2 != listInit->end_initializers(); ++iter2 ) {
     535                                if ( (*iter2)->get_designators().empty() ) {
     536                                        DeclarationWithType *dt = dynamic_cast<DeclarationWithType *>( *iter1 );
     537                                        initContext = dt->get_type();
     538                                        (*iter2)->accept( *this );
     539                                        ++iter1;
     540                                } else {
     541                                        StructDecl *st = baseStruct;
     542                                        iter1 = st->get_members().begin();
     543                                        std::list<Expression *>::iterator iter3( (*iter2)->get_designators().begin() );
     544                                        for ( ; iter3 != (*iter2)->get_designators().end(); ++iter3 ) {
     545                                                NameExpr *key = dynamic_cast<NameExpr *>( *iter3 );
     546                                                assert( key );
     547                                                for ( ; iter1 != st->get_members().end(); ++iter1 ) {
     548                                                        if ( key->get_name() == (*iter1)->get_name() ) {
     549                                                                (*iter1)->print( cout );
     550                                                                cout << key->get_name() << endl;
     551                                                                ObjectDecl *fred = dynamic_cast<ObjectDecl *>( *iter1 );
     552                                                                assert( fred );
     553                                                                StructInstType *mary = dynamic_cast<StructInstType*>( fred->get_type() );
     554                                                                assert( mary );
     555                                                                st = mary->get_baseStruct();
     556                                                                iter1 = st->get_members().begin();
     557                                                                break;
     558                                                        } // if
     559                                                }  // for
     560                                        } // for
     561                                        ObjectDecl *fred = dynamic_cast<ObjectDecl *>( *iter1 );
     562                                        assert( fred );
     563                                        initContext = fred->get_type();
     564                                        (*listInit->begin_initializers())->accept( *this );
     565                                } // if
     566                        } // for
     567                } else if ( UnionInstType *st = dynamic_cast<UnionInstType*>(initContext) ) {
     568                        DeclarationWithType *dt = dynamic_cast<DeclarationWithType *>( *st->get_baseUnion()->get_members().begin() );
     569                        initContext = dt->get_type();
     570                        (*listInit->begin_initializers())->accept( *this );
     571                } // if
     572#endif
    458573        }
    459574
  • src/ResolvExpr/Unify.cc

    r67fa9f9 r11dbfe1  
    606606                        } else if ( tupleParam ) {
    607607                                // bundle other parameters into tuple to match
    608                                 std::list< Type * > binderTypes;
     608                                TupleType* binder = new TupleType{ paramTy->get_qualifiers() };
    609609
    610610                                do {
    611                                         binderTypes.push_back( otherParam->get_type()->clone() );
     611                                        binder->get_types().push_back( otherParam->get_type()->clone() );
    612612                                        ++jt;
    613613
     
    618618                                } while (true);
    619619
    620                                 otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes };
     620                                otherParamTy = binder;
    621621                                ++it;  // skip ttype parameter for break
    622622                        } else if ( otherTupleParam ) {
    623623                                // bundle parameters into tuple to match other
    624                                 std::list< Type * > binderTypes;
     624                                TupleType* binder = new TupleType{ otherParamTy->get_qualifiers() };
    625625
    626626                                do {
    627                                         binderTypes.push_back( param->get_type()->clone() );
     627                                        binder->get_types().push_back( param->get_type()->clone() );
    628628                                        ++it;
    629629
     
    634634                                } while (true);
    635635
    636                                 paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes };
     636                                paramTy = binder;
    637637                                ++jt;  // skip ttype parameter for break
    638638                        }
     
    756756                        return function->get_returnVals().front()->get_type()->clone();
    757757                } else {
    758                         std::list< Type * > types;
     758                        TupleType * tupleType = new TupleType( Type::Qualifiers() );
    759759                        for ( DeclarationWithType * decl : function->get_returnVals() ) {
    760                                 types.push_back( decl->get_type()->clone() );
     760                                tupleType->get_types().push_back( decl->get_type()->clone() );
    761761                        } // for
    762                         return new TupleType( Type::Qualifiers(), types );
     762                        return tupleType;
    763763                }
    764764        }
  • src/ResolvExpr/module.mk

    r67fa9f9 r11dbfe1  
    66## file "LICENCE" distributed with Cforall.
    77##
    8 ## module.mk --
     8## module.mk -- 
    99##
    1010## Author           : Richard C. Bilson
     
    3131       ResolvExpr/PolyCost.cc \
    3232       ResolvExpr/Occurs.cc \
    33        ResolvExpr/TypeEnvironment.cc \
    34        ResolvExpr/CurrentObject.cc
     33       ResolvExpr/TypeEnvironment.cc
  • src/SymTab/Autogen.h

    r67fa9f9 r11dbfe1  
    2525
    2626namespace SymTab {
    27         /// Generates assignment operators, constructors, and destructor for aggregate types as required
    28         void autogenerateRoutines( std::list< Declaration * > &translationUnit );
     27    /// Generates assignment operators, constructors, and destructor for aggregate types as required
     28    void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    2929
    30         /// returns true if obj's name is the empty string and it has a bitfield width
    31         bool isUnnamedBitfield( ObjectDecl * obj );
     30    /// returns true if obj's name is the empty string and it has a bitfield width
     31    bool isUnnamedBitfield( ObjectDecl * obj );
    3232
    33         /// size_t type - set when size_t typedef is seen. Useful in a few places,
    34         /// such as in determining array dimension type
    35         extern Type * SizeType;
     33    /// size_t type - set when size_t typedef is seen. Useful in a few places,
     34    /// such as in determining array dimension type
     35    extern Type * SizeType;
    3636
    37         /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    38         template< typename OutputIterator >
     37    /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
     38    template< typename OutputIterator >
    3939        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
    4040
    41         /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    42         /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    43         template< typename OutputIterator >
     41    /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     42    /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
     43    template< typename OutputIterator >
    4444        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    4545        // want to be able to generate assignment, ctor, and dtor generically,
     
    5050        dstParam = new AddressExpr( dstParam );
    5151        if ( addCast ) {
    52                 // cast to T* with qualifiers removed, so that qualified objects can be constructed
    53                 // and destructed with the same functions as non-qualified objects.
    54                 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    55                 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    56                 // remove lvalue as a qualifier, this can change to
    57                 //   type->get_qualifiers() = Type::Qualifiers();
    58                 assert( type );
    59                 Type * castType = type->clone();
    60                 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    61                 castType->set_lvalue( true ); // xxx - might not need this
    62                 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
     52            // cast to T* with qualifiers removed, so that qualified objects can be constructed
     53            // and destructed with the same functions as non-qualified objects.
     54            // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     55            // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     56            // remove lvalue as a qualifier, this can change to
     57            //   type->get_qualifiers() = Type::Qualifiers();
     58            assert( type );
     59            Type * castType = type->clone();
     60//                      castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, false);
     61            castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     62            castType->set_lvalue( true ); // xxx - might not need this
     63            dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
    6364        }
    6465        fExpr->get_args().push_back( dstParam );
     
    7475
    7576        return listInit;
     77    }
     78
     79    /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
     80    /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
     81    template< typename OutputIterator >
     82        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
     83        static UniqueName indexName( "_index" );
     84
     85        // for a flexible array member nothing is done -- user must define own assignment
     86        if ( ! array->get_dimension() ) return ;
     87
     88        Expression * begin, * end, * update, * cmp;
     89        if ( forward ) {
     90            // generate: for ( int i = 0; i < N; ++i )
     91            begin = new ConstantExpr( Constant::from_int( 0 ) );
     92            end = array->get_dimension()->clone();
     93            cmp = new NameExpr( "?<?" );
     94            update = new NameExpr( "++?" );
     95        } else {
     96            // generate: for ( int i = N-1; i >= 0; --i )
     97            begin = new UntypedExpr( new NameExpr( "?-?" ) );
     98            ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
     99            ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
     100            end = new ConstantExpr( Constant::from_int( 0 ) );
     101            cmp = new NameExpr( "?>=?" );
     102            update = new NameExpr( "--?" );
    76103        }
    77104
    78         /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    79         /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    80         template< typename OutputIterator >
    81         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
    82                 static UniqueName indexName( "_index" );
     105        ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
    83106
    84                 // for a flexible array member nothing is done -- user must define own assignment
    85                 if ( ! array->get_dimension() ) return ;
     107        UntypedExpr *cond = new UntypedExpr( cmp );
     108        cond->get_args().push_back( new VariableExpr( index ) );
     109        cond->get_args().push_back( end );
    86110
    87                 Expression * begin, * end, * update, * cmp;
    88                 if ( forward ) {
    89                         // generate: for ( int i = 0; i < N; ++i )
    90                         begin = new ConstantExpr( Constant::from_int( 0 ) );
    91                         end = array->get_dimension()->clone();
    92                         cmp = new NameExpr( "?<?" );
    93                         update = new NameExpr( "++?" );
    94                 } else {
    95                         // generate: for ( int i = N-1; i >= 0; --i )
    96                         begin = new UntypedExpr( new NameExpr( "?-?" ) );
    97                         ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    98                         ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
    99                         end = new ConstantExpr( Constant::from_int( 0 ) );
    100                         cmp = new NameExpr( "?>=?" );
    101                         update = new NameExpr( "--?" );
    102                 }
     111        UntypedExpr *inc = new UntypedExpr( update );
     112        inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    103113
    104                 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
     114        UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     115        dstIndex->get_args().push_back( dstParam );
     116        dstIndex->get_args().push_back( new VariableExpr( index ) );
     117        dstParam = dstIndex;
    105118
    106                 UntypedExpr *cond = new UntypedExpr( cmp );
    107                 cond->get_args().push_back( new VariableExpr( index ) );
    108                 cond->get_args().push_back( end );
     119        // srcParam must keep track of the array indices to build the
     120        // source parameter and/or array list initializer
     121        srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
    109122
    110                 UntypedExpr *inc = new UntypedExpr( update );
    111                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     123        // for stmt's body, eventually containing call
     124        CompoundStmt * body = new CompoundStmt( noLabels );
     125        Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
    112126
    113                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    114                 dstIndex->get_args().push_back( dstParam );
    115                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    116                 dstParam = dstIndex;
     127        // block containing for stmt and index variable
     128        std::list<Statement *> initList;
     129        CompoundStmt * block = new CompoundStmt( noLabels );
     130        block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     131        if ( listInit ) block->get_kids().push_back( listInit );
     132        block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
    117133
    118                 // srcParam must keep track of the array indices to build the
    119                 // source parameter and/or array list initializer
    120                 srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
     134        *out++ = block;
     135    }
    121136
    122                 // for stmt's body, eventually containing call
    123                 CompoundStmt * body = new CompoundStmt( noLabels );
    124                 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
     137    template< typename OutputIterator >
     138        Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
     139        if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     140            genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     141            return 0;
     142        } else {
     143            return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
     144        }
     145    }
    125146
    126                 // block containing for stmt and index variable
    127                 std::list<Statement *> initList;
    128                 CompoundStmt * block = new CompoundStmt( noLabels );
    129                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
    130                 if ( listInit ) block->get_kids().push_back( listInit );
    131                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     147    /// inserts into out a generated call expression to function fname with arguments dstParam
     148    /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     149    /// object being constructed. The function wraps constructor and destructor calls in an
     150    /// ImplicitCtorDtorStmt node.
     151    template< typename OutputIterator >
     152        void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     153        ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
     154        assert( obj );
     155        // unnamed bit fields are not copied as they cannot be accessed
     156        if ( isUnnamedBitfield( obj ) ) return;
    132157
    133                 *out++ = block;
     158        bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
     159        std::list< Statement * > stmts;
     160        genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
     161
     162        // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
     163        assert( stmts.size() <= 1 );
     164        if ( stmts.size() == 1 ) {
     165            Statement * callStmt = stmts.front();
     166            if ( addCast ) {
     167                // implicitly generated ctor/dtor calls should be wrapped
     168                // so that later passes are aware they were generated.
     169                // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
     170                // because this causes the address to be taken at codegen, which is illegal in C.
     171                callStmt = new ImplicitCtorDtorStmt( callStmt );
     172            }
     173            *out++ = callStmt;
    134174        }
    135 
    136         template< typename OutputIterator >
    137         Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    138                 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    139                         genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
    140                         return 0;
    141                 } else {
    142                         return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    143                 }
    144         }
    145 
    146         /// inserts into out a generated call expression to function fname with arguments dstParam
    147         /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
    148         /// object being constructed. The function wraps constructor and destructor calls in an
    149         /// ImplicitCtorDtorStmt node.
    150         template< typename OutputIterator >
    151         void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    152                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    153                 assert( obj );
    154                 // unnamed bit fields are not copied as they cannot be accessed
    155                 if ( isUnnamedBitfield( obj ) ) return;
    156 
    157                 bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
    158                 std::list< Statement * > stmts;
    159                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
    160 
    161                 // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
    162                 assert( stmts.size() <= 1 );
    163                 if ( stmts.size() == 1 ) {
    164                         Statement * callStmt = stmts.front();
    165                         if ( addCast ) {
    166                                 // implicitly generated ctor/dtor calls should be wrapped
    167                                 // so that later passes are aware they were generated.
    168                                 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
    169                                 // because this causes the address to be taken at codegen, which is illegal in C.
    170                                 callStmt = new ImplicitCtorDtorStmt( callStmt );
    171                         }
    172                         *out++ = callStmt;
    173                 }
    174         }
     175    }
    175176} // namespace SymTab
    176177#endif // AUTOGEN_H
  • src/SymTab/ImplementationType.cc

    r67fa9f9 r11dbfe1  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ImplementationType.cc --
     7// ImplementationType.cc -- 
    88//
    99// Author           : Richard C. Bilson
     
    9292
    9393        void ImplementationType::visit(TupleType *tupleType) {
    94                 std::list< Type * > types;
     94                TupleType *newType = new TupleType( Type::Qualifiers() );
    9595                for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
    9696                        Type *implType = implementationType( *i, indexer );
    9797                        implType->get_qualifiers() |= tupleType->get_qualifiers();
    98                         types.push_back( implType );
     98                        newType->get_types().push_back( implType );
    9999                } // for
    100                 result = new TupleType( Type::Qualifiers(), types );
     100                result = newType;
    101101        }
    102102
  • src/SymTab/Indexer.cc

    r67fa9f9 r11dbfe1  
    652652                        for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    653653                                // check for C decls with the same name, skipping those with a compatible type (by mangleName)
    654                                 if ( ! LinkageSpec::isMangled( decl->second->get_linkage() ) && decl->first != mangleName ) return true;
     654                                if ( decl->second->get_linkage() == LinkageSpec::C && decl->first != mangleName ) return true;
    655655                        }
    656656                }
     
    669669                                // check for C decls with the same name, skipping
    670670                                // those with an incompatible type (by mangleName)
    671                                 if ( ! LinkageSpec::isMangled( decl->second->get_linkage() ) && decl->first == mangleName ) return true;
     671                                if ( decl->second->get_linkage() == LinkageSpec::C && decl->first == mangleName ) return true;
    672672                        }
    673673                }
     
    724724                        // new definition shadows the autogenerated one, even at the same scope
    725725                        return false;
    726                 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
     726                } else if ( added->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
    727727                        // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
    728728                        // we should ignore outermost pointer qualifiers, except _Atomic?
     
    765765
    766766                // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage
    767                 if ( ! LinkageSpec::isMangled( decl->get_linkage() ) ) {
     767                if ( decl->get_linkage() == LinkageSpec::C ) {
    768768                        // NOTE this is broken in Richard's original code in such a way that it never triggers (it
    769769                        // doesn't check decls that have the same manglename, and all C-linkage decls are defined to
  • src/SymTab/Validate.cc

    r67fa9f9 r11dbfe1  
    106106
    107107        /// Fix return types so that every function returns exactly one value
    108         struct ReturnTypeFixer {
     108        class ReturnTypeFixer {
     109          public:
    109110                static void fix( std::list< Declaration * > &translationUnit );
    110111
     
    114115
    115116        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    116         struct EnumAndPointerDecay {
     117        class EnumAndPointerDecay {
     118        public:
    117119                void previsit( EnumDecl *aggregateDecl );
    118120                void previsit( FunctionType *func );
     
    157159        };
    158160
    159         struct ReturnChecker : public WithGuards {
     161        class ReturnChecker : public WithScopes {
     162          public:
    160163                /// Checks that return statements return nothing if their return type is void
    161164                /// and return something if the return type is non-void.
    162165                static void checkFunctionReturns( std::list< Declaration * > & translationUnit );
    163 
     166          private:
    164167                void previsit( FunctionDecl * functionDecl );
    165168                void previsit( ReturnStmt * returnStmt );
     
    202205        };
    203206
    204         struct VerifyCtorDtorAssign {
     207        class VerifyCtorDtorAssign {
     208        public:
    205209                /// ensure that constructors, destructors, and assignment have at least one
    206210                /// parameter, the first of which must be a pointer, and that ctor/dtors have no
     
    212216
    213217        /// ensure that generic types have the correct number of type arguments
    214         struct ValidateGenericParameters {
     218        class ValidateGenericParameters {
     219        public:
    215220                void previsit( StructInstType * inst );
    216221                void previsit( UnionInstType * inst );
    217222        };
    218223
    219         struct ArrayLength {
     224        class ArrayLength {
     225        public:
    220226                /// for array types without an explicit length, compute the length and store it so that it
    221227                /// is known to the rest of the phases. For example,
     
    230236        };
    231237
    232         struct CompoundLiteral final : public WithDeclsToAdd, public WithVisitorRef<CompoundLiteral> {
     238        class CompoundLiteral final : public GenPoly::DeclMutator {
    233239                Type::StorageClasses storageClasses;
    234240
    235                 void premutate( ObjectDecl *objectDecl );
    236                 Expression * postmutate( CompoundLiteralExpr *compLitExpr );
     241                using GenPoly::DeclMutator::mutate;
     242                DeclarationWithType * mutate( ObjectDecl *objectDecl ) final;
     243                Expression *mutate( CompoundLiteralExpr *compLitExpr ) final;
    237244        };
    238245
     
    241248                LinkReferenceToTypes lrt( doDebug, 0 );
    242249                ForallPointerDecay fpd( 0 );
    243                 PassVisitor<CompoundLiteral> compoundliteral;
     250                CompoundLiteral compoundliteral;
    244251                PassVisitor<ValidateGenericParameters> genericParams;
    245252
     
    256263                Concurrency::implementThreadStarter( translationUnit );
    257264                ReturnChecker::checkFunctionReturns( translationUnit );
    258                 mutateAll( translationUnit, compoundliteral );
     265                compoundliteral.mutateDeclarationList( translationUnit );
    259266                acceptAll( translationUnit, fpd );
    260267                ArrayLength::computeLength( translationUnit );
     
    876883        }
    877884
    878         void CompoundLiteral::premutate( ObjectDecl *objectDecl ) {
     885        DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) {
    879886                storageClasses = objectDecl->get_storageClasses();
    880         }
    881 
    882         Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {
     887                DeclarationWithType * temp = Mutator::mutate( objectDecl );
     888                return temp;
     889        }
     890
     891        Expression *CompoundLiteral::mutate( CompoundLiteralExpr *compLitExpr ) {
    883892                // transform [storage_class] ... (struct S){ 3, ... };
    884893                // into [storage_class] struct S temp =  { 3, ... };
    885894                static UniqueName indexName( "_compLit" );
    886895
    887                 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
    888                 compLitExpr->set_result( nullptr );
    889                 compLitExpr->set_initializer( nullptr );
     896                ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, 0, compLitExpr->get_result(), compLitExpr->get_initializer() );
     897                compLitExpr->set_result( 0 );
     898                compLitExpr->set_initializer( 0 );
    890899                delete compLitExpr;
    891                 declsToAddBefore.push_back( tempvar );                                  // add modified temporary to current block
    892                 return new VariableExpr( tempvar );
     900                DeclarationWithType * newtempvar = mutate( tempvar );
     901                addDeclaration( newtempvar );                                   // add modified temporary to current block
     902                return new VariableExpr( newtempvar );
    893903        }
    894904
  • src/SynTree/Constant.cc

    r67fa9f9 r11dbfe1  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Constant.cc --
     7// Constant.cc -- 
    88//
    99// Author           : Richard C. Bilson
     
    4646}
    4747
    48 unsigned long long Constant::get_ival() const {
    49         assertf( safe_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." );
    50         return val.ival;
    51 }
    52 
    53 double Constant::get_dval() const {
    54         assertf( ! safe_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." );
    55         return val.dval;
    56 }
    57 
    5848void Constant::print( std::ostream &os ) const {
    5949        os << "(" << rep << " " << val.ival;
  • src/SynTree/Constant.h

    r67fa9f9 r11dbfe1  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Constant.h --
     7// Constant.h -- 
    88//
    99// Author           : Richard C. Bilson
     
    3232        std::string & get_value() { return rep; }
    3333        void set_value( std::string newValue ) { rep = newValue; }
    34         unsigned long long get_ival() const;
    35         double get_dval() const;
    3634
    3735        /// generates a boolean constant of the given bool
  • src/SynTree/Expression.cc

    r67fa9f9 r11dbfe1  
    2121#include <iterator>
    2222
     23#include "Type.h"
     24#include "Initializer.h"
     25#include "Expression.h"
    2326#include "Declaration.h"
    24 #include "Expression.h"
    25 #include "Initializer.h"
    2627#include "Statement.h"
    27 #include "Type.h"
    2828#include "TypeSubstitution.h"
    29 #include "VarExprReplacer.h"
    30 
    3129#include "Common/utility.h"
    32 #include "Common/PassVisitor.h"
    33 
    3430#include "InitTweak/InitTweak.h"
    3531
     
    9692
    9793        Declaration *decl = get_var();
     94        // if ( decl != 0) decl->print(os, indent + 2);
    9895        if ( decl != 0) decl->printShort(os, indent + 2);
    9996        os << std::endl;
     
    660657}
    661658
    662 InitAlternative::InitAlternative( Type * type, Designation * designation ) : type( type ), designation( designation ) {}
    663 InitAlternative::InitAlternative( const InitAlternative & other ) : type( maybeClone( other.type ) ), designation( maybeClone( other.designation ) ) {}
    664 InitAlternative::~InitAlternative() {
    665         delete type;
    666         delete designation;
    667 }
    668 
    669 UntypedInitExpr::UntypedInitExpr( Expression * expr, const std::list<InitAlternative> & initAlts ) : expr( expr ), initAlts( initAlts ) {}
    670 UntypedInitExpr::UntypedInitExpr( const UntypedInitExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), initAlts( other.initAlts ) {}
    671 UntypedInitExpr::~UntypedInitExpr() {
    672         delete expr;
    673 }
    674 
    675 void UntypedInitExpr::print( std::ostream & os, int indent ) const {
    676         os << "Untyped Init Expression" << std::endl << std::string( indent+2, ' ' );
    677         expr->print( os, indent+2 );
    678         if ( ! initAlts.empty() ) {
    679                 for ( const InitAlternative & alt : initAlts ) {
    680                         os << std::string( indent+2, ' ' ) <<  "InitAlternative: ";
    681                         alt.type->print( os, indent+2 );
    682                         alt.designation->print( os, indent+2 );
    683                 }
    684         }
    685 }
    686 
    687 InitExpr::InitExpr( Expression * expr, Designation * designation ) : expr( expr ), designation( designation ) {
    688         set_result( expr->get_result()->clone() );
    689 }
    690 InitExpr::InitExpr( const InitExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), designation( maybeClone( other.designation) ) {}
    691 InitExpr::~InitExpr() {
    692         delete expr;
    693         delete designation;
    694 }
    695 
    696 void InitExpr::print( std::ostream & os, int indent ) const {
    697         os << "Init Expression" << std::endl << std::string( indent+2, ' ' );
    698         expr->print( os, indent+2 );
    699         os << std::string( indent+2, ' ' ) << "with designation: ";
    700         designation->print( os, indent+2 );
    701 }
    702 
    703 
    704659std::ostream & operator<<( std::ostream & out, const Expression * expr ) {
    705660        if ( expr ) {
  • src/SynTree/Expression.h

    r67fa9f9 r11dbfe1  
    744744};
    745745
    746 struct InitAlternative {
    747 public:
    748         Type * type = nullptr;
    749         Designation * designation = nullptr;
    750         InitAlternative( Type * type, Designation * designation );
    751         InitAlternative( const InitAlternative & other );
    752         InitAlternative & operator=( const Initializer & other ) = delete; // at the moment this isn't used, and I don't want to implement it
    753         ~InitAlternative();
    754 };
    755 
    756 class UntypedInitExpr : public Expression {
    757 public:
    758         UntypedInitExpr( Expression * expr, const std::list<InitAlternative> & initAlts );
    759         UntypedInitExpr( const UntypedInitExpr & other );
    760         ~UntypedInitExpr();
    761 
    762         Expression * get_expr() const { return expr; }
    763         UntypedInitExpr * set_expr( Expression * newValue ) { expr = newValue; return this; }
    764 
    765         std::list<InitAlternative> & get_initAlts() { return initAlts; }
    766 
    767         virtual UntypedInitExpr * clone() const { return new UntypedInitExpr( * this ); }
    768         virtual void accept( Visitor & v ) { v.visit( this ); }
    769         virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    770         virtual void print( std::ostream & os, int indent = 0 ) const;
    771 private:
    772         Expression * expr;
    773         std::list<InitAlternative> initAlts;
    774 };
    775 
    776 class InitExpr : public Expression {
    777 public:
    778         InitExpr( Expression * expr, Designation * designation );
    779         InitExpr( const InitExpr & other );
    780         ~InitExpr();
    781 
    782         Expression * get_expr() const { return expr; }
    783         InitExpr * set_expr( Expression * newValue ) { expr = newValue; return this; }
    784 
    785         Designation * get_designation() const { return designation; }
    786         InitExpr * set_designation( Designation * newValue ) { designation = newValue; return this; }
    787 
    788         virtual InitExpr * clone() const { return new InitExpr( * this ); }
    789         virtual void accept( Visitor & v ) { v.visit( this ); }
    790         virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    791         virtual void print( std::ostream & os, int indent = 0 ) const;
    792 private:
    793         Expression * expr;
    794         Designation * designation;
    795 };
    796 
    797 
    798746std::ostream & operator<<( std::ostream & out, const Expression * expr );
    799747
  • src/SynTree/Initializer.cc

    r67fa9f9 r11dbfe1  
    1919#include "Common/utility.h"
    2020
    21 Designation::Designation( const std::list< Expression * > & designators ) : designators( designators ) {}
    22 Designation::Designation( const Designation & other ) : BaseSyntaxNode( other ) {
    23         // std::cerr << "cloning designation" << std::endl;
    24         cloneAll( other.designators, designators );
    25         // std::cerr << "finished cloning designation" << std::endl;
    26 }
    27 
    28 Designation::~Designation() {
    29         // std::cerr << "destroying designation" << std::endl;
    30         deleteAll( designators );
    31         // std::cerr << "finished destroying designation" << std::endl;
    32 }
    33 
    34 void Designation::print( std::ostream &os, int indent ) const {
    35         if ( ! designators.empty() ) {
    36                 os << std::string(indent + 2, ' ' ) << "designated by: " << std::endl;
    37                 for ( std::list < Expression * >::const_iterator i = designators.begin(); i != designators.end(); i++ ) {
    38                         os << std::string(indent + 4, ' ' );
    39                         ( *i )->print(os, indent + 4 );
    40                 }
    41                 os << std::endl;
    42         } // if
    43 }
    44 
    4521Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
    4622Initializer::Initializer( const Initializer & other ) : BaseSyntaxNode( other ), maybeConstructed( other.maybeConstructed ) {
    4723}
     24
     25
    4826Initializer::~Initializer() {}
    4927
    50 SingleInit::SingleInit( Expression *v, bool maybeConstructed ) : Initializer( maybeConstructed ), value ( v ) {
     28std::string Initializer::designator_name( Expression *des ) {
     29        if ( NameExpr *n = dynamic_cast<NameExpr *>(des) )
     30                return n->get_name();
     31        else
     32                throw 0;
     33}
     34
     35// void Initializer::print( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent ) {}
     36
     37SingleInit::SingleInit( Expression *v, const std::list< Expression *> &_designators, bool maybeConstructed ) : Initializer( maybeConstructed ), value ( v ), designators( _designators ) {
    5138}
    5239
    5340SingleInit::SingleInit( const SingleInit &other ) : Initializer(other), value ( maybeClone( other.value ) ) {
     41        cloneAll(other.designators, designators );
    5442}
    5543
    5644SingleInit::~SingleInit() {
    5745        delete value;
     46        deleteAll(designators);
    5847}
    5948
    60 void SingleInit::print( std::ostream &os, int indent ) const {
    61         os << std::string(indent, ' ' ) << "Simple Initializer: " << std::endl;
     49void SingleInit::print( std::ostream &os, int indent ) {
     50        os << std::endl << std::string(indent, ' ' ) << "Simple Initializer: " << std::endl;
    6251        os << std::string(indent+4, ' ' );
    6352        value->print( os, indent+4 );
     53
     54        if ( ! designators.empty() ) {
     55                os << std::endl << std::string(indent + 2, ' ' ) << "designated by: " << std::endl;
     56                for ( std::list < Expression * >::iterator i = designators.begin(); i != designators.end(); i++ ) {
     57                        os << std::string(indent + 4, ' ' );
     58                        ( *i )->print(os, indent + 4 );
     59                }
     60        } // if
    6461}
    6562
    66 
    67 ListInit::ListInit( const std::list<Initializer*> &inits, const std::list<Designation *> &des, bool maybeConstructed )
    68         : Initializer( maybeConstructed ), initializers( inits ), designations( des ) {
    69                 // handle the common case where a ListInit is created without designations by making a list of empty designations with the same length as the initializer
    70                 if ( designations.empty() ) {
    71                         for ( auto & i : initializers ) {
    72                                 (void)i;
    73                                 designations.push_back( new Designation( {} ) );
    74                         }
    75                 }
    76                 assertf( initializers.size() == designations.size(), "Created ListInit with mismatching initializers (%d) and designations (%d)", initializers.size(), designations.size() );
     63ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed )
     64        : Initializer( maybeConstructed ), initializers( _initializers ), designators( _designators ) {
    7765}
    7866
    7967ListInit::ListInit( const ListInit & other ) : Initializer( other ) {
    8068        cloneAll( other.initializers, initializers );
    81         cloneAll( other.designations, designations );
     69        cloneAll( other.designators, designators );
    8270}
     71
    8372
    8473ListInit::~ListInit() {
    8574        deleteAll( initializers );
    86         deleteAll( designations );
     75        deleteAll( designators );
    8776}
    8877
    89 void ListInit::print( std::ostream &os, int indent ) const {
    90         os << std::string(indent, ' ') << "Compound initializer:  " << std::endl;
    91         for ( Designation * d : designations ) {
    92                 d->print( os, indent + 2 );
    93         }
     78void ListInit::print( std::ostream &os, int indent ) {
     79        os << std::endl << std::string(indent, ' ') << "Compound initializer:  ";
     80        if ( ! designators.empty() ) {
     81                os << std::string(indent + 2, ' ' ) << "designated by: [";
     82                for ( std::list < Expression * >::iterator i = designators.begin();
     83                          i != designators.end(); i++ ) {
     84                        ( *i )->print(os, indent + 4 );
     85                } // for
    9486
    95         for ( const Initializer * init : initializers ) {
    96                 init->print( os, indent + 2 );
    97                 os << std::endl;
    98         }
     87                os << std::string(indent + 2, ' ' ) << "]";
     88        } // if
     89
     90        for ( std::list<Initializer *>::iterator i = initializers.begin(); i != initializers.end(); i++ )
     91                (*i)->print( os, indent + 2 );
    9992}
    10093
     
    110103}
    111104
    112 void ConstructorInit::print( std::ostream &os, int indent ) const {
     105void ConstructorInit::print( std::ostream &os, int indent ) {
    113106        os << std::endl << std::string(indent, ' ') << "Constructor initializer: " << std::endl;
    114107        if ( ctor ) {
     
    131124}
    132125
    133 std::ostream & operator<<( std::ostream & out, const Initializer * init ) {
    134         if ( init ) {
    135                 init->print( out );
    136         } else {
    137                 out << "nullptr";
    138         }
    139         return out;
    140 }
    141 
    142 std::ostream & operator<<( std::ostream & out, const Designation * des ) {
    143         if ( des ) {
    144                 des->print( out );
    145         } else {
    146                 out << "nullptr";
    147         }
     126std::ostream & operator<<( std::ostream & out, Initializer * init ) {
     127        init->print( out );
    148128        return out;
    149129}
  • src/SynTree/Initializer.h

    r67fa9f9 r11dbfe1  
    2525#include "Visitor.h"
    2626
    27 // Designation: list of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an object being initialized.
    28 class Designation : public BaseSyntaxNode {
    29 public:
    30         Designation( const std::list< Expression * > & designators );
    31         Designation( const Designation & other );
    32         virtual ~Designation();
    33 
    34         std::list< Expression * > & get_designators() { return designators; }
    35 
    36         virtual Designation * clone() const { return new Designation( *this ); };
    37         virtual void accept( Visitor &v ) { v.visit( this ); }
    38         virtual Designation * acceptMutator( Mutator &m ) { return m.mutate( this ); }
    39         virtual void print( std::ostream &os, int indent = 0 ) const;
    40 private:
    41         std::list< Expression * > designators;
    42 };
    43 
    44 const std::list<Designation *> noDesignators;
     27const std::list<Expression*> noDesignators;
    4528
    4629// Initializer: base class for object initializers (provide default values)
    4730class Initializer : public BaseSyntaxNode {
    4831  public:
     32        //      Initializer( std::string _name = std::string(""), int _pos = 0 );
    4933        Initializer( bool maybeConstructed );
    5034        Initializer( const Initializer & other );
    5135        virtual ~Initializer();
     36
     37        static std::string designator_name( Expression *designator );
     38
     39        //      void set_name( std::string newValue ) { name = newValue; }
     40        //      std::string get_name() const { return name; }
     41
     42        //      void set_pos( int newValue ) { pos = newValue; }
     43        //      int get_pos() const { return pos; }
     44        virtual void set_designators( std::list<Expression *> & ) { assert(false); }
     45        virtual std::list<Expression *> &get_designators() {
     46                assert(false);
     47                std::list<Expression *> *ret = 0; return *ret;  // never reached
     48        }
    5249
    5350        bool get_maybeConstructed() { return maybeConstructed; }
     
    5653        virtual void accept( Visitor &v ) = 0;
    5754        virtual Initializer *acceptMutator( Mutator &m ) = 0;
    58         virtual void print( std::ostream &os, int indent = 0 ) const = 0;
     55        virtual void print( std::ostream &os, int indent = 0 ) = 0;
    5956  private:
     57        //      std::string name;
     58        //      int pos;
    6059        bool maybeConstructed;
    6160};
     
    6463class SingleInit : public Initializer {
    6564  public:
    66         SingleInit( Expression *value, bool maybeConstructed = false );
     65        SingleInit( Expression *value, const std::list< Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false );
    6766        SingleInit( const SingleInit &other );
    6867        virtual ~SingleInit();
     
    7170        void set_value( Expression *newValue ) { value = newValue; }
    7271
     72        std::list<Expression *> &get_designators() { return designators; }
     73        void set_designators( std::list<Expression *> &newValue ) { designators = newValue; }
     74
    7375        virtual SingleInit *clone() const { return new SingleInit( *this); }
    7476        virtual void accept( Visitor &v ) { v.visit( this ); }
    7577        virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    76         virtual void print( std::ostream &os, int indent = 0 ) const;
     78        virtual void print( std::ostream &os, int indent = 0 );
    7779  private:
    7880        //Constant *value;
    7981        Expression *value;      // has to be a compile-time constant
     82        std::list< Expression * > designators;
    8083};
    8184
     
    8588  public:
    8689        ListInit( const std::list<Initializer*> &initializers,
    87                           const std::list<Designation *> &designators = {}, bool maybeConstructed = false );
     90                          const std::list<Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false );
    8891        ListInit( const ListInit & other );
    8992        virtual ~ListInit();
    9093
    91         std::list<Designation *> & get_designations() { return designations; }
    92         std::list<Initializer *> & get_initializers() { return initializers; }
     94        void set_designators( std::list<Expression *> &newValue ) { designators = newValue; }
     95        std::list<Expression *> &get_designators() { return designators; }
     96        void set_initializers( std::list<Initializer*> &newValue ) { initializers = newValue; }
     97        std::list<Initializer*> &get_initializers() { return initializers; }
    9398
    9499        typedef std::list<Initializer*>::iterator iterator;
    95         typedef std::list<Initializer*>::const_iterator const_iterator;
    96100        iterator begin() { return initializers.begin(); }
    97101        iterator end() { return initializers.end(); }
    98         const_iterator begin() const { return initializers.begin(); }
    99         const_iterator end() const { return initializers.end(); }
    100102
    101103        virtual ListInit *clone() const { return new ListInit( *this ); }
    102104        virtual void accept( Visitor &v ) { v.visit( this ); }
    103105        virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    104         virtual void print( std::ostream &os, int indent = 0 ) const;
     106        virtual void print( std::ostream &os, int indent = 0 );
    105107  private:
    106         std::list<Initializer *> initializers;  // order *is* important
    107         std::list<Designation *> designations;  // order/length is consistent with initializers
     108        std::list<Initializer*> initializers;  // order *is* important
     109        std::list<Expression *> designators;
    108110};
    109111
     
    128130        virtual void accept( Visitor &v ) { v.visit( this ); }
    129131        virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    130         virtual void print( std::ostream &os, int indent = 0 ) const;
     132        virtual void print( std::ostream &os, int indent = 0 );
    131133
    132134  private:
     
    138140};
    139141
    140 std::ostream & operator<<( std::ostream & out, const Initializer * init );
    141 std::ostream & operator<<( std::ostream & out, const Designation * des );
     142std::ostream & operator<<( std::ostream & out, Initializer * init );
    142143
    143144#endif // INITIALIZER_H
  • src/SynTree/Mutator.cc

    r67fa9f9 r11dbfe1  
    433433}
    434434
    435 Expression *Mutator::mutate( UntypedInitExpr * initExpr ) {
    436         initExpr->set_env( maybeMutate( initExpr->get_env(), *this ) );
    437         initExpr->set_result( maybeMutate( initExpr->get_result(), *this ) );
    438         initExpr->set_expr( maybeMutate( initExpr->get_expr(), *this ) );
    439         // not currently mutating initAlts, but this doesn't matter since this node is only used in the resolver.
    440         return initExpr;
    441 }
    442 
    443 Expression *Mutator::mutate( InitExpr * initExpr ) {
    444         initExpr->set_env( maybeMutate( initExpr->get_env(), *this ) );
    445         initExpr->set_result( maybeMutate( initExpr->get_result(), *this ) );
    446         initExpr->set_expr( maybeMutate( initExpr->get_expr(), *this ) );
    447         initExpr->set_designation( maybeMutate( initExpr->get_designation(), *this ) );
    448         return initExpr;
    449 }
    450 
    451435
    452436Type *Mutator::mutate( VoidType *voidType ) {
     
    515499        mutateAll( tupleType->get_forall(), *this );
    516500        mutateAll( tupleType->get_types(), *this );
    517         mutateAll( tupleType->get_members(), *this );
    518501        return tupleType;
    519502}
     
    552535
    553536
    554 Designation *Mutator::mutate( Designation * designation ) {
    555         mutateAll( designation->get_designators(), *this );
    556         return designation;
    557 }
    558 
    559537Initializer *Mutator::mutate( SingleInit *singleInit ) {
    560538        singleInit->set_value( singleInit->get_value()->acceptMutator( *this ) );
     
    563541
    564542Initializer *Mutator::mutate( ListInit *listInit ) {
    565         mutateAll( listInit->get_designations(), *this );
     543        mutateAll( listInit->get_designators(), *this );
    566544        mutateAll( listInit->get_initializers(), *this );
    567545        return listInit;
  • src/SynTree/Mutator.h

    r67fa9f9 r11dbfe1  
    8585        virtual Expression* mutate( StmtExpr * stmtExpr );
    8686        virtual Expression* mutate( UniqueExpr * uniqueExpr );
    87         virtual Expression* mutate( UntypedInitExpr * initExpr );
    88         virtual Expression* mutate( InitExpr * initExpr );
    8987
    9088        virtual Type* mutate( VoidType *basicType );
     
    105103        virtual Type* mutate( OneType *oneType );
    106104
    107         virtual Designation* mutate( Designation *designation );
    108105        virtual Initializer* mutate( SingleInit *singleInit );
    109106        virtual Initializer* mutate( ListInit *listInit );
  • src/SynTree/SynTree.h

    r67fa9f9 r11dbfe1  
    9393class StmtExpr;
    9494class UniqueExpr;
    95 class UntypedInitExpr;
    96 class InitExpr;
    9795
    9896class Type;
     
    115113class OneType;
    116114
    117 class Designation;
    118115class Initializer;
    119116class SingleInit;
  • src/SynTree/TupleType.cc

    r67fa9f9 r11dbfe1  
    1414//
    1515
    16 #include "Declaration.h"
    17 #include "Initializer.h"
    1816#include "Type.h"
    1917#include "Common/utility.h"
    20 #include "Parser/LinkageSpec.h"
    2118
    2219TupleType::TupleType( const Type::Qualifiers &tq, const std::list< Type * > & types, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), types( types ) {
    23         for ( Type * t : *this ) {
    24                 // xxx - this is very awkward. TupleTypes should contain objects so that members can be named, but if they don't have an initializer node then
    25                 // they end up getting constructors, which end up being inserted causing problems. This happens because the object decls have to be visited so that
    26                 // their types are kept in sync with the types list here. Ultimately, the types list here should be eliminated and perhaps replaced with a list-view
    27                 // of the object types list, but I digress. The temporary solution here is to make a ListInit with maybeConstructed = false, that way even when the
    28                 // object is visited, it is never constructed. Ultimately, a better solution might be either:
    29                 // a) to separate TupleType from its declarations, into TupleDecl and Tuple{Inst?}Type, ala StructDecl and StructInstType
    30                 // b) separate initializer nodes better, e.g. add a MaybeConstructed node that is replaced by genInit, rather than what currently exists in a bool
    31                 members.push_back( new ObjectDecl( "" , Type::StorageClasses(), LinkageSpec::Cforall, nullptr, t->clone(), new ListInit( {}, {}, false ) ) );
    32         }
    3320}
    3421
    3522TupleType::TupleType( const TupleType& other ) : Type( other ) {
    3623        cloneAll( other.types, types );
    37         cloneAll( other.members, members );
    3824}
    3925
    4026TupleType::~TupleType() {
    4127        deleteAll( types );
    42         deleteAll( members );
    4328}
    4429
  • src/SynTree/Type.h

    r67fa9f9 r11dbfe1  
    481481class TupleType : public Type {
    482482  public:
    483         TupleType( const Type::Qualifiers & tq, const std::list< Type * > & types, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     483        TupleType( const Type::Qualifiers & tq, const std::list< Type * > & types = std::list< Type * >(), const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    484484        TupleType( const TupleType& );
    485485        virtual ~TupleType();
     
    488488        typedef value_type::iterator iterator;
    489489
    490         std::list<Type *> & get_types() { return types; }
     490        std::list<Type*>& get_types() { return types; }
    491491        virtual unsigned size() const { return types.size(); };
    492 
    493         // For now, this is entirely synthetic -- tuple types always have unnamed members.
    494         // Eventually, we may allow named tuples, in which case members should subsume types
    495         std::list<Declaration *> & get_members() { return members; }
    496492
    497493        iterator begin() { return types.begin(); }
     
    510506        virtual void print( std::ostream & os, int indent = 0 ) const;
    511507  private:
    512         std::list<Type *> types;
    513         std::list<Declaration *> members;
     508        std::list<Type*> types;
    514509};
    515510
  • src/SynTree/VarExprReplacer.cc

    r67fa9f9 r11dbfe1  
    1414//
    1515
    16 #include "Declaration.h"
    1716#include "Expression.h"
    1817#include "VarExprReplacer.h"
    1918
    20 VarExprReplacer::VarExprReplacer( const DeclMap & declMap, bool debug ) : declMap( declMap ), debug( debug ) {}
     19VarExprReplacer::VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}
    2120
    2221// replace variable with new node from decl map
    2322void VarExprReplacer::visit( VariableExpr * varExpr ) {
    24         // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
    25         if ( declMap.count( varExpr->get_var() ) ) {
    26                 if ( debug ) {
    27                         std::cerr << "replacing variable reference: " << (void*)varExpr->get_var() << " " << varExpr->get_var() << " with " << (void*)declMap.at( varExpr->get_var() ) << " " << declMap.at( varExpr->get_var() ) << std::endl;
    28                 }
    29                 varExpr->set_var( declMap.at( varExpr->get_var() ) );
    30         }
     23  // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
     24  if ( declMap.count( varExpr->get_var() ) ) {
     25    varExpr->set_var( declMap.at( varExpr->get_var() ) );
     26  }
    3127}
  • src/SynTree/VarExprReplacer.h

    r67fa9f9 r11dbfe1  
    2727private:
    2828        const DeclMap & declMap;
    29   bool debug;
    3029public:
    31         VarExprReplacer( const DeclMap & declMap, bool debug = false );
     30        VarExprReplacer( const DeclMap & declMap );
    3231
    3332        // replace variable with new node from decl map
  • src/SynTree/Visitor.cc

    r67fa9f9 r11dbfe1  
    340340}
    341341
    342 void Visitor::visit( UntypedInitExpr * initExpr ) {
    343         maybeAccept( initExpr->get_result(), *this );
    344         maybeAccept( initExpr->get_expr(), *this );
    345         // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
    346 }
    347 
    348 void Visitor::visit( InitExpr * initExpr ) {
    349         maybeAccept( initExpr->get_result(), *this );
    350         maybeAccept( initExpr->get_expr(), *this );
    351         maybeAccept( initExpr->get_designation(), *this );
    352 }
    353 
    354342
    355343void Visitor::visit( VoidType *voidType ) {
     
    407395        acceptAll( tupleType->get_forall(), *this );
    408396        acceptAll( tupleType->get_types(), *this );
    409         acceptAll( tupleType->get_members(), *this );
    410397}
    411398
     
    437424}
    438425
    439 void Visitor::visit( Designation * designation ) {
    440         acceptAll( designation->get_designators(), *this );
    441 }
    442426
    443427void Visitor::visit( SingleInit *singleInit ) {
     
    446430
    447431void Visitor::visit( ListInit *listInit ) {
    448         acceptAll( listInit->get_designations(), *this );
     432        acceptAll( listInit->get_designators(), *this );
    449433        acceptAll( listInit->get_initializers(), *this );
    450434}
  • src/SynTree/Visitor.h

    r67fa9f9 r11dbfe1  
    8888        virtual void visit( StmtExpr * stmtExpr );
    8989        virtual void visit( UniqueExpr * uniqueExpr );
    90         virtual void visit( UntypedInitExpr * initExpr );
    91         virtual void visit( InitExpr * initExpr );
    9290
    9391        virtual void visit( VoidType *basicType );
     
    108106        virtual void visit( OneType *oneType );
    109107
    110         virtual void visit( Designation *designation );
    111108        virtual void visit( SingleInit *singleInit );
    112109        virtual void visit( ListInit *listInit );
  • src/Tuples/TupleExpansion.cc

    r67fa9f9 r11dbfe1  
    192192                        }
    193193                        ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ),
    194                                                                                                         new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) );
     194                                                                                                        new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ), noDesignators ) );
    195195                        addDeclaration( finished );
    196196                        // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
     
    310310        Type * makeTupleType( const std::list< Expression * > & exprs ) {
    311311                // produce the TupleType which aggregates the types of the exprs
    312                 std::list< Type * > types;
    313                 Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex );
     312                TupleType *tupleType = new TupleType( Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex ) );
     313                Type::Qualifiers &qualifiers = tupleType->get_qualifiers();
    314314                for ( Expression * expr : exprs ) {
    315315                        assert( expr->get_result() );
    316316                        if ( expr->get_result()->isVoid() ) {
    317317                                // if the type of any expr is void, the type of the entire tuple is void
     318                                delete tupleType;
    318319                                return new VoidType( Type::Qualifiers() );
    319320                        }
    320321                        Type * type = expr->get_result()->clone();
    321                         types.push_back( type );
     322                        tupleType->get_types().push_back( type );
    322323                        // the qualifiers on the tuple type are the qualifiers that exist on all component types
    323324                        qualifiers &= type->get_qualifiers();
    324325                } // for
    325326                if ( exprs.empty() ) qualifiers = Type::Qualifiers();
    326                 return new TupleType( qualifiers, types );
     327                return tupleType;
    327328        }
    328329
  • src/libcfa/Makefile.am

    r67fa9f9 r11dbfe1  
    5050
    5151libobjs = ${headers:=.o}
    52 libsrc = libcfa-prelude.c interpose.c libhdr/libdebug.c ${headers:=.c} exception.c
     52libsrc = libcfa-prelude.c interpose.c libhdr/libdebug.c ${headers:=.c}
    5353
    5454# not all platforms support concurrency, add option do disable it
  • src/libcfa/Makefile.in

    r67fa9f9 r11dbfe1  
    102102        containers/pair.c containers/result.c containers/vector.c \
    103103        concurrency/coroutine.c concurrency/thread.c \
    104         concurrency/kernel.c concurrency/monitor.c exception.c \
     104        concurrency/kernel.c concurrency/monitor.c \
    105105        concurrency/CtxSwitch-@MACHINE_TYPE@.S concurrency/alarm.c \
    106106        concurrency/invoke.c concurrency/preemption.c
     
    126126        libcfa_d_a-interpose.$(OBJEXT) \
    127127        libhdr/libcfa_d_a-libdebug.$(OBJEXT) $(am__objects_2) \
    128         libcfa_d_a-exception.$(OBJEXT) $(am__objects_3)
     128        $(am__objects_3)
    129129am_libcfa_d_a_OBJECTS = $(am__objects_4)
    130130libcfa_d_a_OBJECTS = $(am_libcfa_d_a_OBJECTS)
     
    136136        containers/pair.c containers/result.c containers/vector.c \
    137137        concurrency/coroutine.c concurrency/thread.c \
    138         concurrency/kernel.c concurrency/monitor.c exception.c \
     138        concurrency/kernel.c concurrency/monitor.c \
    139139        concurrency/CtxSwitch-@MACHINE_TYPE@.S concurrency/alarm.c \
    140140        concurrency/invoke.c concurrency/preemption.c
     
    158158        libcfa_a-interpose.$(OBJEXT) \
    159159        libhdr/libcfa_a-libdebug.$(OBJEXT) $(am__objects_6) \
    160         libcfa_a-exception.$(OBJEXT) $(am__objects_7)
     160        $(am__objects_7)
    161161am_libcfa_a_OBJECTS = $(am__objects_8)
    162162libcfa_a_OBJECTS = $(am_libcfa_a_OBJECTS)
     
    328328libobjs = ${headers:=.o}
    329329libsrc = libcfa-prelude.c interpose.c libhdr/libdebug.c ${headers:=.c} \
    330         exception.c $(am__append_4)
     330        $(am__append_4)
    331331libcfa_a_SOURCES = ${libsrc}
    332332libcfa_a_CFLAGS = -nodebug -O2
     
    514514
    515515@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_a-assert.Po@am__quote@
    516 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_a-exception.Po@am__quote@
    517516@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_a-fstream.Po@am__quote@
    518517@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_a-interpose.Po@am__quote@
     
    525524@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_a-stdlib.Po@am__quote@
    526525@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_d_a-assert.Po@am__quote@
    527 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_d_a-exception.Po@am__quote@
    528526@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_d_a-fstream.Po@am__quote@
    529527@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfa_d_a-interpose.Po@am__quote@
     
    852850@am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-monitor.obj `if test -f 'concurrency/monitor.c'; then $(CYGPATH_W) 'concurrency/monitor.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/monitor.c'; fi`
    853851
    854 libcfa_d_a-exception.obj: exception.c
    855 @am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT libcfa_d_a-exception.obj -MD -MP -MF $(DEPDIR)/libcfa_d_a-exception.Tpo -c -o libcfa_d_a-exception.obj `if test -f 'exception.c'; then $(CYGPATH_W) 'exception.c'; else $(CYGPATH_W) '$(srcdir)/exception.c'; fi`
    856 @am__fastdepCC_TRUE@    $(AM_V_at)$(am__mv) $(DEPDIR)/libcfa_d_a-exception.Tpo $(DEPDIR)/libcfa_d_a-exception.Po
    857 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='exception.c' object='libcfa_d_a-exception.obj' libtool=no @AMDEPBACKSLASH@
    858 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    859 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o libcfa_d_a-exception.obj `if test -f 'exception.c'; then $(CYGPATH_W) 'exception.c'; else $(CYGPATH_W) '$(srcdir)/exception.c'; fi`
    860 
    861852concurrency/libcfa_d_a-alarm.o: concurrency/alarm.c
    862853@am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_d_a-alarm.o -MD -MP -MF concurrency/$(DEPDIR)/libcfa_d_a-alarm.Tpo -c -o concurrency/libcfa_d_a-alarm.o `test -f 'concurrency/alarm.c' || echo '$(srcdir)/'`concurrency/alarm.c
     
    11521143@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    11531144@am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-monitor.obj `if test -f 'concurrency/monitor.c'; then $(CYGPATH_W) 'concurrency/monitor.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/monitor.c'; fi`
    1154 
    1155 libcfa_a-exception.obj: exception.c
    1156 @am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -MT libcfa_a-exception.obj -MD -MP -MF $(DEPDIR)/libcfa_a-exception.Tpo -c -o libcfa_a-exception.obj `if test -f 'exception.c'; then $(CYGPATH_W) 'exception.c'; else $(CYGPATH_W) '$(srcdir)/exception.c'; fi`
    1157 @am__fastdepCC_TRUE@    $(AM_V_at)$(am__mv) $(DEPDIR)/libcfa_a-exception.Tpo $(DEPDIR)/libcfa_a-exception.Po
    1158 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='exception.c' object='libcfa_a-exception.obj' libtool=no @AMDEPBACKSLASH@
    1159 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1160 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o libcfa_a-exception.obj `if test -f 'exception.c'; then $(CYGPATH_W) 'exception.c'; else $(CYGPATH_W) '$(srcdir)/exception.c'; fi`
    11611145
    11621146concurrency/libcfa_a-alarm.o: concurrency/alarm.c
  • src/libcfa/exception.c

    r67fa9f9 r11dbfe1  
    4444// RESUMPTION ================================================================
    4545
    46 void __cfaehm__throw_resumption(exception * except) {
    47 
    48         // DEBUG
    49         printf("Throwing resumption exception %d\n", *except);
    50 
    51         struct __cfaehm__try_resume_node * original_head = shared_stack.current_resume;
    52         struct __cfaehm__try_resume_node * current =
     46void __cfaehm__throw_resume(exception except) {
     47
     48        // DEBUG
     49        printf("Throwing resumption exception %d\n", except);
     50
     51        struct __try_resume_node * original_head = shared_stack.current_resume;
     52        struct __try_resume_node * current =
    5353                (original_head) ? original_head->next : shared_stack.top_resume;
    5454
    5555        for ( ; current ; current = current->next) {
    5656                shared_stack.current_resume = current;
    57                 if (current->handler(except)) {
     57                if (current->try_to_handle(except)) {
    5858                        shared_stack.current_resume = original_head;
    5959                        return;
     
    6161        }
    6262
    63         printf("Unhandled exception %d\n", *except);
     63        printf("Unhandled exception %d\n", except);
    6464        shared_stack.current_resume = original_head;
    6565
    6666        // Fall back to termination:
    67         __cfaehm__throw_termination(except);
     67        __cfaehm__throw_terminate(except);
    6868        // TODO: Default handler for resumption.
    6969}
     
    7373 * after the node is built but before it is made the top node.
    7474 */
    75 void __cfaehm__try_resume_setup(struct __cfaehm__try_resume_node * node,
    76                         int (*handler)(exception * except)) {
     75void __try_resume_setup(struct __try_resume_node * node,
     76                        bool (*handler)(exception except)) {
    7777        node->next = shared_stack.top_resume;
    78         node->handler = handler;
     78        node->try_to_handle = handler;
    7979        shared_stack.top_resume = node;
    8080}
    8181
    82 void __cfaehm__try_resume_cleanup(struct __cfaehm__try_resume_node * node) {
     82void __try_resume_cleanup(struct __try_resume_node * node) {
    8383        shared_stack.top_resume = node->next;
    8484}
     
    111111}
    112112
    113 void __cfaehm__throw_termination( exception * val ) {
     113void __cfaehm__throw_terminate( int val ) {
    114114        // Store the current exception
    115         shared_stack.current_exception = *val;
    116 
    117         // DEBUG
    118         printf("Throwing termination exception %d\n", *val);
     115        shared_stack.current_exception = val;
     116
     117        // DEBUG
     118        printf("Throwing termination exception %d\n", val);
    119119
    120120        // Call stdlibc to raise the exception
     
    147147
    148148// Nesting this the other way would probably be faster.
    149 void __cfaehm__rethrow_termination(void) {
     149void __cfaehm__rethrow_terminate(void) {
    150150        // DEBUG
    151151        printf("Rethrowing termination exception\n");
    152152
    153         __cfaehm__throw_termination(&shared_stack.current_exception);
     153        __cfaehm__throw_terminate(shared_stack.current_exception);
    154154}
    155155
     
    322322// for details
    323323__attribute__((noinline))
    324 void __cfaehm__try_terminate(void (*try_block)(),
    325                 void (*catch_block)(int index, exception * except),
    326                 __attribute__((unused)) int (*match_block)(exception * except)) {
     324void __try_terminate(void (*try_block)(),
     325                void (*catch_block)(int index, exception except),
     326                __attribute__((unused)) int (*match_block)(exception except)) {
    327327        //! volatile int xy = 0;
    328328        //! printf("%p %p %p %p\n", &try_block, &catch_block, &match_block, &xy);
     
    364364        // Exception handler
    365365        catch_block(shared_stack.current_handler_index,
    366                     &shared_stack.current_exception);
     366                    shared_stack.current_exception);
    367367}
    368368
     
    384384        // Body uses language specific data and therefore could be modified arbitrarily
    385385        ".LLSDACSBCFA2:\n"                                              // BODY start
    386         "       .uleb128 .TRYSTART-__cfaehm__try_terminate\n"           // Handled area start  (relative to start of function)
     386        "       .uleb128 .TRYSTART-__try_terminate\n"           // Handled area start  (relative to start of function)
    387387        "       .uleb128 .TRYEND-.TRYSTART\n"                           // Handled area length
    388         "       .uleb128 .CATCH-__cfaehm__try_terminate\n"                              // Hanlder landing pad adress  (relative to start of function)
     388        "       .uleb128 .CATCH-__try_terminate\n"                              // Hanlder landing pad adress  (relative to start of function)
    389389        "       .uleb128 1\n"                                           // Action code, gcc seems to use always 0
    390390        ".LLSDACSECFA2:\n"                                              // BODY end
    391391        "       .text\n"                                                        // TABLE footer
    392         "       .size   __cfaehm__try_terminate, .-__cfaehm__try_terminate\n"
     392        "       .size   __try_terminate, .-__try_terminate\n"
    393393        "       .ident  \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n"
    394394//      "       .section        .note.GNU-stack,\"x\",@progbits\n"
  • src/libcfa/exception.h

    r67fa9f9 r11dbfe1  
    3838// Data structure creates a list of resume handlers.
    3939struct __cfaehm__try_resume_node {
    40     struct __cfaehm__try_resume_node * next;
     40    __cfaehm__try_resume_node * next;
    4141    int (*handler)(exception * except);
    4242};
    4343
    4444void __cfaehm__try_resume_setup(
    45     struct __cfaehm__try_resume_node * node,
     45    __cfaehm__try_resume_node * node,
    4646    int (*handler)(exception * except));
    4747void __cfaehm__try_resume_cleanup(
    48     struct __cfaehm__try_resume_node * node);
     48    __cfaehm__try_resume_node * node);
    4949
    5050// Check for a standard way to call fake deconstructors.
  • src/libcfa/fstream

    r67fa9f9 r11dbfe1  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul  1 16:37:53 2017
    13 // Update Count     : 112
     12// Last Modified On : Mon May 15 18:11:09 2017
     13// Update Count     : 104
    1414//
    1515
     
    2424        _Bool sepDefault;
    2525        _Bool sepOnOff;
    26         _Bool lastSepOn;
    2726        const char * sepCur;
    2827        char separator[separateSize];
     
    3635const char * sepGetCur( ofstream * );
    3736void sepSetCur( ofstream *, const char * );
    38 _Bool lastSepOn( ofstream * );
    3937
    4038// public
  • src/libcfa/fstream.c

    r67fa9f9 r11dbfe1  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul  1 16:37:54 2017
    13 // Update Count     : 242
     12// Last Modified On : Mon May 15 18:11:11 2017
     13// Update Count     : 234
    1414//
    1515
     
    3333        this->sepDefault = sepDefault;
    3434        this->sepOnOff = sepOnOff;
    35         this->lastSepOn = false;
    3635        sepSet( this, separator );
    3736        sepSetCur( this, sepGet( this ) );
     
    4039
    4140// private
    42 _Bool lastSepOn( ofstream * os ) { return os->lastSepOn; }
    43 _Bool sepPrt( ofstream * os ) { os->lastSepOn = false; return os->sepOnOff; }
     41_Bool sepPrt( ofstream * os ) { return os->sepOnOff; }
    4442void sepReset( ofstream * os ) { os->sepOnOff = os->sepDefault; }
    4543void sepReset( ofstream * os, _Bool reset ) { os->sepDefault = reset; os->sepOnOff = os->sepDefault; }
     
    4846
    4947// public
    50 void sepOn( ofstream * os ) { os->lastSepOn = true; os->sepOnOff = true; }
    51 void sepOff( ofstream * os ) { os->lastSepOn = false; os->sepOnOff = 0; }
     48void sepOn( ofstream * os ) { os->sepOnOff = 1; }
     49void sepOff( ofstream * os ) { os->sepOnOff = 0; }
    5250
    5351_Bool sepDisable( ofstream *os ) {
    5452        _Bool temp = os->sepDefault;
    5553        os->sepDefault = false;
    56         os->lastSepOn = false;
    5754        sepReset( os );
    5855        return temp;
     
    9592                exit( EXIT_FAILURE );
    9693        } // if
    97         ?{}( os, file, true, false, " ", ", " );
     94        ?{}( os, file, 1, 0, " ", ", " );
    9895} // open
    9996
     
    135132} // fmt
    136133
    137 static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_), true, false, " ", ", " };
     134static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_), 1, 0, " ", ", " };
    138135ofstream *sout = &soutFile;
    139 static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_), true, false, " ", ", " };
     136static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_), 1, 0, " ", ", " };
    140137ofstream *serr = &serrFile;
    141138
  • src/libcfa/iostream

    r67fa9f9 r11dbfe1  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul  2 08:42:56 2017
    13 // Update Count     : 110
     12// Last Modified On : Mon May 15 18:08:44 2017
     13// Update Count     : 105
    1414//
    1515
     
    2626        const char * sepGetCur( ostype * );                                     // get current separator string
    2727        void sepSetCur( ostype *, const char * );                       // set current separator string
    28         _Bool lastSepOn( ostype * );                                            // last manipulator is setOn (context sensitive)
    2928        // public
    3029        void sepOn( ostype * );                                                         // turn separator state on
     
    4443        ostype * write( ostype *, const char *, unsigned long int );
    4544        int fmt( ostype *, const char fmt[], ... );
    46 }; // ostream
     45};
    4746
    4847trait writeable( otype T ) {
    4948        forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, T );
    50 }; // writeable
     49};
    5150
    5251// implement writable for intrinsic types
     
    104103        istype * ungetc( istype *, char );
    105104        int fmt( istype *, const char fmt[], ... );
    106 }; // istream
     105};
    107106
    108107trait readable( otype T ) {
    109108        forall( dtype istype | istream( istype ) ) istype * ?|?( istype *, T );
    110 }; // readable
     109};
    111110
    112111forall( dtype istype | istream( istype ) ) istype * ?|?( istype *, char * );
  • src/libcfa/iostream.c

    r67fa9f9 r11dbfe1  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul  2 08:54:02 2017
    13 // Update Count     : 375
     12// Last Modified On : Mon May  8 18:24:23 2017
     13// Update Count     : 369
    1414//
    1515
     
    201201forall( dtype ostype, otype T, ttype Params | ostream( ostype ) | writeable( T ) | { ostype * ?|?( ostype *, Params ); } )
    202202ostype * ?|?( ostype * os, T arg, Params rest ) {
     203        sepSetCur( os, sepGetTuple( os ) );                                     // switch to tuple separator
    203204        os | arg;                                                                                       // print first argument
    204         sepSetCur( os, sepGetTuple( os ) );                                     // switch to tuple separator
    205205        os | rest;                                                                                      // print remaining arguments
    206206        sepSetCur( os, sepGet( os ) );                                          // switch to regular separator
     
    217217forall( dtype ostype | ostream( ostype ) )
    218218ostype * endl( ostype * os ) {
    219         if ( lastSepOn( os ) ) fmt( os, "%s", sepGetCur( os ) );
    220219        os | '\n';
    221220        flush( os );
  • src/main.cc

    r67fa9f9 r11dbfe1  
    1111// Created On       : Fri May 15 23:12:02 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Thu Jun 29 12:46:50 2017
    14 // Update Count     : 441
     13// Last Modified On : Wed Jun 28 21:56:47 2017
     14// Update Count     : 440
    1515//
    1616
     
    3939#include "CodeTools/TrackLoc.h"
    4040#include "ControlStruct/Mutate.h"
    41 #include "ControlStruct/ExceptTranslate.h"
    4241#include "SymTab/Validate.h"
    4342#include "ResolvExpr/AlternativePrinter.h"
     
    291290                Tuples::expandUniqueExpr( translationUnit );
    292291
    293                 OPTPRINT( "translateEHM" );
    294                 ControlStruct::translateEHM( translationUnit );
    295 
    296292                OPTPRINT( "convertSpecializations" ) // needs to happen before tuple types are expanded
    297293                GenPoly::convertSpecializations( translationUnit );
     
    485481                        break;
    486482                  case '?':
    487                         if ( optopt ) {                                                         // short option ?
    488                                 assertf( false, "Unknown option: -%c\n", (char)optopt );
    489                         } else {
    490                                 assertf( false, "Unknown option: %s\n", argv[optind - 1] );
    491                         } // if
     483                        assertf( false, "Unknown option: '%c'\n", (char)optopt );
    492484                  default:
    493485                        abort();
  • src/prelude/Makefile.am

    r67fa9f9 r11dbfe1  
    2323noinst_DATA = ../libcfa/libcfa-prelude.c
    2424
    25 CC = ${abs_top_srcdir}/src/driver/cfa
    26 
    2725$(DEPDIR) :
    2826        mkdir $(DEPDIR)
     
    4745
    4846# create forward declarations for cfa builtins
    49 builtins.cf : builtins.c ${CC}
    50         ${AM_V_GEN}${CC} -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po
     47builtins.cf : builtins.c
     48        ${AM_V_GEN}@BACKEND_CC@ -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po
    5149        ${AM_V_at}sed -i 's/builtins.o/builtins.cf/g' $(DEPDIR)/builtins.Po
    5250
  • src/prelude/Makefile.in

    r67fa9f9 r11dbfe1  
    9595AWK = @AWK@
    9696BACKEND_CC = @BACKEND_CC@
    97 CC = ${abs_top_srcdir}/src/driver/cfa
     97CC = @CC@
    9898CCAS = @CCAS@
    9999CCASDEPMODE = @CCASDEPMODE@
     
    444444
    445445# create forward declarations for cfa builtins
    446 builtins.cf : builtins.c ${CC}
    447         ${AM_V_GEN}${CC} -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po
     446builtins.cf : builtins.c
     447        ${AM_V_GEN}@BACKEND_CC@ -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po
    448448        ${AM_V_at}sed -i 's/builtins.o/builtins.cf/g' $(DEPDIR)/builtins.Po
    449449
  • src/tests/.expect/io.txt

    r67fa9f9 r11dbfe1  
    44123
    55
    6 opening delimiters
    76x (1 x [2 x {3 x =4 x $5 x £6 x ¥7 x ¡8 x ¿9 x «10
    8 
    9 closing delimiters
    10 1, x 2. x 3; x 4! x 5? x 6% x 7¢ x 8» x 9) x 10] x 11} x
    11 
    12 opening/closing delimiters
     71, x 2. x 3; x 4! x 5? x 6% x 7¢ x 8» x 9) x 10] x 11} x
    138x`1`x'2'x"3"x:4:x 5 x   6       x
    1497
     
    1914x
    201510
    21 x
    22 
    23 override opening/closing delimiters
     16x
    2417x ( 1 ) x 2 , x 3 :x: 4
    25 
    26 input bacis types
    27 
    28 output basic types
    2918A
    30191 2 3 4 5 6 7 8
     
    32211.1+2.3i 1.1-2.3i 1.1-2.3i
    3322
    34 tuples
    35 1, 2, 3 3, 4, 5
    36 
    37 toggle separator
    38231.11.21.3
    39241.1+2.3i1.1-2.3i1.1-2.3i
    40  abcxyz 
    41 abcxyz 
     25 abcxyz
     26abcxyz
    4227
    43 change separator
    44 from "  "to " , $"
    45281.1, $1.2, $1.3
    46291.1+2.3i, $1.1-2.3i, $1.1-2.3i
    47 abc, $xyz, $
    48 1, 2, 3, $3, 4, 5
     30abc, $xyz
    4931
    50 from ", $"to " "
    51 1.1 1.2 1.3
    52 1.1+2.3i 1.1-2.3i 1.1-2.3i
    53 abc xyz
    54 1, 2, 3 3, 4, 5
    55 
    56  1 2 3
     321, 2, 3, 4
     331, $2, $3 ", $"
     341 2 3 " "
     35 1 2 3
    573612 3
    58  1 2 3
    59 1 2 3
    60  1 2 3
    61 
    6237123
    63381 23
    64391 2 3
    65 123
    66 1 2 3
    67 123
    68 1 2 3
    69 
    70 1 2 3 3 4 5 " "
    71 1, 2, 3 3, 4, 5 ", "
    72 1, 2, 3 3, 4, 5
    73 
     401 2 3 4 " "
     411, 2, 3, 4 ", "
     421, 2, 3, 4
    74433, 4, a, 7.2
    75443, 4, a, 7.2
    76453 4 a 7.2
    7746 3 4 a 7.234a7.23 4 a 7.2
    78 3-4-a-7.2^3^4^3-4-a-7.2
     473-4-a-7.2^3^4-3-4-a-7.2
  • src/tests/io.c

    r67fa9f9 r11dbfe1  
    1010// Created On       : Wed Mar  2 16:56:02 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul  2 09:40:58 2017
    13 // Update Count     : 68
     12// Last Modified On : Thu Jun  8 09:52:10 2017
     13// Update Count     : 51
    1414//
    1515
     
    4242        sout | endl;
    4343
    44         sout | "opening delimiters" | endl;
    4544        sout
     45                // opening delimiters
    4646                | "x (" | 1
    4747                | "x [" | 2
     
    5454                | "x ¿" | 9
    5555                | "x «" | 10
    56                 | endl | endl;
    57 
    58         sout | "closing delimiters" | endl;
     56                | endl;
    5957        sout
     58                // closing delimiters
    6059                | 1 | ", x"
    6160                | 2 | ". x"
     
    6968                | 10 | "] x"
    7069                | 11 | "} x"
    71                 | endl | endl;
    72 
    73         sout | "opening/closing delimiters" | endl;
     70                | endl;
    7471        sout
     72                // opening-closing delimiters
    7573                | "x`" | 1 | "`x'" | 2
    7674                | "'x\"" | 3 | "\"x:" | 4
     
    7876                | "\tx\f" | 7 | "\fx\v" | 8
    7977                | "\vx\n" | 9 | "\nx\r" | 10
    80                 | "\rx"
    81                 | endl | endl;
    82 
    83         sout | "override opening/closing delimiters" | endl;
     78                | "\rx" |
     79                endl;
    8480        sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4 | endl;
    85         sout | endl;
    8681
    8782        ifstream in;                                                                            // create / open file
    8883        open( &in, "io.data", "r" );
    8984
    90         sout | "input bacis types" | endl;
    9185        &in | &c                                                                                        // character
    9286                | &si | &usi | &i | &ui | &li | &uli | &lli | &ulli     // integral
     
    9488                | &fc | &dc | &ldc                                                              // floating-point complex
    9589                | cstr( s1 ) | cstr( s2, size );                                // C string, length unchecked and checked
    96         sout | endl;
    9790
    98         sout | "output basic types" | endl;
    9991        sout | c | ' ' | endl                                                           // character
    10092                | si | usi | i | ui | li | uli | lli | ulli | endl // integral
     
    10294                | fc | dc | ldc | endl;                                                 // complex
    10395        sout | endl;
    104 
    105         sout | "tuples" | endl;
    106         [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 3, [ 4, 5 ] ];
    107         sout | t1 | t2 | endl;                                                          // print tuple
    108         sout | endl;
    109 
    110         sout | "toggle separator" | endl;
    11196        sout | f | "" | d | "" | ld | endl                                      // floating point without separator
    11297                | sepDisable | fc | dc | ldc | sepEnable | endl // complex without separator
     
    115100        sout | endl;
    116101
    117         sout | "change separator" | endl;
    118         sout | "from \" " | sepGet( sout ) | "\"";
    119102        sepSet( sout, ", $" );                                                          // change separator, maximum of 15 characters
    120         sout | "to \" " | sepGet( sout ) | "\"" | endl;
    121103        sout | f | d | ld | endl
    122104                | fc | dc | ldc | endl
    123                 | s1 | s2 | endl
    124                 | t1 | t2 | endl;                                                               // print tuple
    125         sout | endl;
    126         sout | "from \"" | sepGet( sout ) | "\"";
    127         sepSet( sout, " " );                                                            // restore separator
    128         sout | "to \"" | sepGet( sout ) | "\"" | endl;
    129         sout | f | d | ld | endl
    130                 | fc | dc | ldc | endl
    131                 | s1 | s2 | endl
    132                 | t1 | t2 | endl;                                                               // print tuple
     105                | s1 | s2 | endl;
    133106        sout | endl;
    134107
    135         sout | sepOn | 1 | 2 | 3 | sepOn | endl;                        // separator at start/end of line
     108        [int, int] t1 = [1, 2], t2 = [3, 4];
     109        sout | t1 | t2 | endl;                                                          // print tuple
     110
     111        sepSet( sout, " " );
     112        sepSet( sout, ", $" );                                                          // set separator from " " to ", $"
     113        sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"" | endl;
     114        sepSet( sout, " " );                                                            // reset separator to " "
     115        sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"" | endl;
     116
     117        sout | sepOn | 1 | 2 | 3 | sepOn | endl;                        // separator at start of line
    136118        sout | 1 | sepOff | 2 | 3 | endl;                                       // locally turn off implicit separator
    137         sout | sepOn | 1 | 2 | 3 | sepOn | sepOff | endl;       // separator at start of line
    138         sout | 1 | 2 | 3 | endl | sepOn;                                        // separator at start of next line
    139         sout | 1 | 2 | 3 | endl;
    140         sout | endl;
    141119
    142120        sout | sepDisable | 1 | 2 | 3 | endl;                           // globally turn off implicit separation
    143121        sout | 1 | sepOn | 2 | 3 | endl;                                        // locally turn on implicit separator
    144         sout | sepEnable | 1 | 2 | 3 | endl | sepDisable;       // globally turn on/off implicit separation
    145         sout | 1 | 2 | 3 | endl | sepEnable;                            // globally turn on implicit separation
    146         sout | 1 | 2 | 3 | sepOn | sepDisable | endl;           // ignore seperate at end of line
    147         sout | 1 | 2 | 3 | sepOn | sepEnable | endl;            // separator at end of line
    148         sout | 1 | 2 | 3 | endl;
    149         sout | endl;
     122        sout | sepEnable | 1 | 2 | 3 | endl;                            // globally turn on implicit separation
    150123
    151124        sepSetTuple( sout, " " );                                                       // set tuple separator from ", " to " "
     
    153126        sepSetTuple( sout, ", " );                                                      // reset tuple separator to ", "
    154127        sout | t1 | t2 | " \"" | sepGetTuple( sout ) | "\"" | endl;
     128
    155129        sout | t1 | t2 | endl;                                                          // print tuple
    156         sout | endl;
    157130
    158131        [int, int, const char *, double] t3 = { 3, 4, "a", 7.2 };
  • tools/cfa.nanorc

    r67fa9f9 r11dbfe1  
    22## WIP
    33
    4 syntax "cfa" "\.cfa"
     4syntax "cfa" "\.cfa$"
     5## No magic
    56
    67# Macros
     
    1819# Control Flow Structures
    1920color brightyellow "\<(if|else|while|do|for|switch|choose|case|default)\>"
    20 color brightyellow "\<(try|catch(Resume)?|finally)\>"
     21##color brightyellow "\<(try|catch|catchResume|finally)\>"
    2122
    2223# Control Flow Statements
    23 color magenta "\<(goto|return|break|continue|fallthr(u|ough)|throw(Resume)?)\>"
     24color magenta "\<(return|break|continue|fallthru|throw)\>"
    2425
    2526# Operator Names
     
    4546color brightmagenta "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
    4647# Strings and Angle Strings
    47 color yellow ""([^"]|\\")*"" "<[^[:blank:]=]*>"
     48color brightyellow ""([^"]|\\")*"" "<[^[:blank:]=]*>"
    4849# Multiline Strings: This regex is VERY expencive and often too strong.
    4950###color brightyellow start=""(\\.|[^"])*\\[[:space:]]*$" end="^(\\.|[^"])*""
  • tools/prettyprinter/main.cc

    r67fa9f9 r11dbfe1  
    11//
    2 // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
     
    1010// Created On       : Wed Jun 28 22:57:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun 29 13:09:32 2017
    13 // Update Count     : 58
     12// Last Modified On : Thu Jun 29 09:02:37 2017
     13// Update Count     : 15
    1414//
    1515
     
    1919using namespace std;
    2020#include <unistd.h>                                                                             // close
    21 #include <getopt.h>                                                                             // getopt
    2221#include "filter.h"
    2322
    2423extern FILE * yyin;
     24extern int yylineno;
    2525extern int yydebug;
    2626extern int yyparse( void );
    2727
    28 bool parse_cmdline( int argc, char * argv[] ) {
    29         enum { Html, Identity, Latex, Nocode, ParseTree, };
    30 
    31         static struct option long_opts[] = {
    32                 { "html", no_argument, nullptr, Html },
    33                 { "identity", no_argument, nullptr, Identity },
    34                 { "latex", no_argument, nullptr, Latex },
    35                 { "nocode", no_argument, nullptr, Nocode },
    36                 { "parse-tree", no_argument, nullptr, ParseTree },
    37                 { nullptr, 0, nullptr, 0 }
    38         }; // long_opts
    39         int long_index;
    40 
    41         opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
    42 
    43         int c;
    44         while ( (c = getopt_long( argc, argv, "hilnp", long_opts, &long_index )) != -1 ) {
    45                 switch ( c ) {
    46                   case Html:
    47                   case 'h':
    48                         filter = HTML;
    49                         break;
    50                   case Identity:
    51                   case 'i':
    52                         filter = ::Identity;
    53                         break;
    54                   case Latex:
    55                   case 'l':
    56                         filter = LaTeX;
    57                         break;
    58                   case Nocode:
    59                   case 'n':
    60                         filter = ::Nocode;
    61                         break;
    62                   case ParseTree:
    63                   case 'p':
    64                         filter = Parse_Tree;
    65                   case '?':
    66                         if ( optopt ) {                                                         // short option ?
    67                                 cerr << "Unknown option: -" << (char)optopt << endl;
    68                         } else {                                                                        // long option
    69                                 cerr << "Unknown option: " << argv[optind - 1] << endl;
    70                         } // if
    71                         return false;
    72                   default:
    73                         abort();
    74                 } // switch
    75         } // while
    76 
    77         if ( optind != argc ) {                                                         // input files ?
    78                 if ( optind == argc - 1 ) {                                             // any commands after the flags ? => input file name
    79                         yyin = fopen( argv[ optind ], "r" );
    80                         if ( yyin == nullptr ) {
    81                                 cerr << "Open failure for input file \"" << argv[ optind ] << "\"" << endl;
    82                                 return false;
    83                         } // if
    84                 } else {
    85                         cerr << "Too many input files " << argv[ optind + 1 ] << endl;
    86                         return false;
    87                 } // if
    88         } // if
    89         return true;
    90 } // parse_cmdline
    91 
    9228int main( int argc, char *argv[] ) {
    93         yyin = stdin;                                                                           // defaults
     29        yyin = stdin;
    9430        filter = Nocode;
    9531
    96         if ( ! parse_cmdline( argc, argv ) ) {
    97                 cerr << "Usage: " << argv[0]
    98                          << " ["
    99                          << "-h/--html | "
    100                          << "-i/--identity | "
    101                          << "-l/--latex | "
    102                          << "-n/--nocode | "
    103                          << "-p/--parse-tree"
     32        try {
     33                switch ( argc ) {
     34                  case 3:
     35                        yyin = fopen( argv[ 2 ], "r" );
     36                        if ( yyin == nullptr ) {
     37                                throw ios_base::failure( "unknown printer option arguments" );
     38                        } // if
     39                        // FALL THROUGH
     40                  case 2: {
     41                          string arg( argv[1] );
     42
     43                          if ( arg == "-identity" ) {
     44                                  filter = Identity;
     45                          } else if ( arg == "-parse_tree" ) {
     46                                  filter = Parse_Tree;
     47                          } else if ( arg == "-nocode" ) {
     48                                  filter = Nocode;
     49                          } else if ( arg == "-latex" ) {
     50                                  filter = LaTeX;
     51                          } else if ( arg == "-html" ) {
     52                                  filter = HTML;
     53                          } else {
     54                                  throw ios_base::failure( "unknown printer option arguments" );
     55                          } // if
     56                          break;
     57                  }
     58                  default:
     59                        throw ios_base::failure( "wrong number of arguments" );
     60                } // switch
     61        } catch( ios_base::failure err ) {
     62                cerr << err.what() << endl;
     63                cerr << "Usage: [" << argv[0]
     64                         << "-identity |"
     65                         << "-parse_tree |"
     66                         << "-nocode |"
     67                         << "-latex |"
     68                         << "-html"
    10469                         << "] [input-file]"
    10570                         << endl;
    10671                exit( EXIT_FAILURE );                                                   // TERMINATE
    107         } // if
     72        } // try
    10873
    10974        //yydebug = 1;
Note: See TracChangeset for help on using the changeset viewer.