Changes in / [7cc6bd6:9243a501]
- Files:
-
- 2 added
- 6 deleted
- 61 edited
-
doc/LaTeXmacros/common.tex (modified) (8 diffs)
-
doc/refrat/refrat.tex (modified) (159 diffs)
-
doc/user/user.tex (modified) (48 diffs)
-
src/CodeGen/CodeGenerator.cc (modified) (36 diffs)
-
src/CodeGen/FixNames.cc (modified) (4 diffs)
-
src/CodeGen/OperatorTable.cc (modified) (2 diffs)
-
src/CodeGen/OperatorTable.h (modified) (2 diffs)
-
src/GenPoly/Box.cc (modified) (32 diffs)
-
src/GenPoly/CopyParams.cc (modified) (4 diffs)
-
src/GenPoly/GenPoly.cc (modified) (6 diffs)
-
src/GenPoly/PolyMutator.cc (modified) (3 diffs)
-
src/GenPoly/Specialize.cc (modified) (4 diffs)
-
src/InitTweak/FixInit.cc (deleted)
-
src/InitTweak/FixInit.h (deleted)
-
src/InitTweak/GenInit.cc (deleted)
-
src/InitTweak/GenInit.h (deleted)
-
src/InitTweak/InitModel.cc (modified) (3 diffs)
-
src/InitTweak/RemoveInit.cc (added)
-
src/InitTweak/RemoveInit.h (added)
-
src/InitTweak/module.mk (modified) (1 diff)
-
src/MakeLibCfa.cc (modified) (6 diffs)
-
src/Makefile.in (modified) (12 diffs)
-
src/Parser/DeclarationNode.cc (modified) (7 diffs)
-
src/Parser/InitializerNode.cc (modified) (5 diffs)
-
src/Parser/ParseNode.h (modified) (4 diffs)
-
src/Parser/TypeData.cc (modified) (3 diffs)
-
src/Parser/parser.cc (modified) (1 diff)
-
src/Parser/parser.yy (modified) (3 diffs)
-
src/ResolvExpr/AlternativeFinder.cc (modified) (2 diffs)
-
src/ResolvExpr/AlternativeFinder.h (modified) (3 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (15 diffs)
-
src/ResolvExpr/Resolver.h (modified) (2 diffs)
-
src/SymTab/AddVisit.h (modified) (2 diffs)
-
src/SymTab/Autogen.cc (deleted)
-
src/SymTab/Autogen.h (deleted)
-
src/SymTab/Validate.cc (modified) (9 diffs)
-
src/SymTab/module.mk (modified) (2 diffs)
-
src/SynTree/CommaExpr.cc (modified) (1 diff)
-
src/SynTree/CompoundStmt.cc (modified) (3 diffs)
-
src/SynTree/Declaration.h (modified) (4 diffs)
-
src/SynTree/DeclarationWithType.cc (modified) (2 diffs)
-
src/SynTree/Expression.cc (modified) (3 diffs)
-
src/SynTree/Expression.h (modified) (3 diffs)
-
src/SynTree/Initializer.cc (modified) (5 diffs)
-
src/SynTree/Initializer.h (modified) (7 diffs)
-
src/SynTree/Mutator.cc (modified) (3 diffs)
-
src/SynTree/Mutator.h (modified) (4 diffs)
-
src/SynTree/ObjectDecl.cc (modified) (3 diffs)
-
src/SynTree/SynTree.h (modified) (3 diffs)
-
src/SynTree/TypeSubstitution.cc (modified) (3 diffs)
-
src/SynTree/TypeSubstitution.h (modified) (8 diffs)
-
src/SynTree/Visitor.cc (modified) (3 diffs)
-
src/SynTree/Visitor.h (modified) (4 diffs)
-
src/examples/array.c (modified) (3 diffs)
-
src/examples/array.h (modified) (3 diffs)
-
src/examples/io.c (modified) (3 diffs)
-
src/examples/vector_int.c (modified) (3 diffs)
-
src/examples/vector_int.h (modified) (3 diffs)
-
src/examples/vector_test.c (modified) (3 diffs)
-
src/initialization.txt (modified) (1 diff)
-
src/libcfa/Makefile.am (modified) (3 diffs)
-
src/libcfa/Makefile.in (modified) (3 diffs)
-
src/libcfa/fstream (modified) (2 diffs)
-
src/libcfa/fstream.c (modified) (6 diffs)
-
src/libcfa/iostream.c (modified) (23 diffs)
-
src/libcfa/prelude.cf (modified) (3 diffs)
-
src/libcfa/stdlib (modified) (2 diffs)
-
src/libcfa/stdlib.c (modified) (2 diffs)
-
src/main.cc (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.tex
r7cc6bd6 r9243a501 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sat Apr 30 13:52:12201614 %% Update Count : 4113 %% Last Modified On : Sat Apr 9 10:06:39 2016 14 %% Update Count : 1 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 19 19 % Names used in the document. 20 20 21 \newcommand{\CFA}{C$\mathbf\forall$\xspace} % set language symbolic name22 \newcommand{\CFL}{Cforall\xspace} % set language text name21 \newcommand{\CFA}{C$\mathbf\forall$\xspace} % set language symbolic name 22 \newcommand{\CFL}{Cforall\xspace} % set language text name 23 23 \newcommand{\CC}{C\kern-.1em\hbox{+\kern-.25em+}\xspace} % CC symbolic name 24 24 \def\c11{ISO/IEC C} % C11 name (cannot have numbers in latex command name) … … 43 43 \belowdisplayskip \abovedisplayskip 44 44 } 45 \usepackage{relsize} % must be after change to small or selects old size45 \usepackage{relsize} % must be after change to small or selects old size 46 46 47 47 % reduce size of chapter/section titles … … 66 66 \vskip 50\p@ 67 67 }} 68 \renewcommand\section{\@startsection{section}{1}{\z@}{-3. 5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont\large\bfseries}}69 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{- 3.25ex \@plus -1ex \@minus -.2ex}{1.5ex \@plus .2ex}{\normalfont\normalsize\bfseries}}68 \renewcommand\section{\@startsection{section}{1}{\z@}{-3.0ex \@plus -1ex \@minus -.2ex}{1.0ex \@plus .2ex}{\normalfont\large\bfseries}} 69 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-2.5ex \@plus -1ex \@minus -.2ex}{1.0ex \@plus .2ex}{\normalfont\normalsize\bfseries}} 70 70 \renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{-2.5ex \@plus -1ex \@minus -.2ex}{1.0ex \@plus .2ex}{\normalfont\normalsize\bfseries}} 71 71 \renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}{-2.0ex \@plus -1ex \@minus -.2ex}{-1em}{\normalfont\normalsize\bfseries}} … … 109 109 \newcommand{\@sIndex}[2][\@empty]{#2\ifx#1\@empty\index{#2}\else\index{#1@{\protect#2}}\fi} 110 110 111 \newcommand{\Indexc}[1]{\lstinline$#1$\index{#1@\lstinline$#1$}}112 \newcommand{\indexc}[1]{\index{#1@\lstinline$#1$}}113 114 111 \newcommand{\newtermFontInline}{\emph} 115 112 \newcommand{\newterm}{\@ifstar\@snewterm\@newterm} … … 182 179 fallthru,finally,forall,ftype,_Generic,_Imaginary,inline,__label__,lvalue,_Noreturn,otype,restrict,_Static_assert, 183 180 _Thread_local,throw,throwResume,trait,try,typeof,__typeof,__typeof__,}, 181 moredelim=**[is][\color{red}]{`}{`}, % red highlighting of program text 184 182 }% 185 183 … … 188 186 columns=flexible, 189 187 basicstyle=\sf\relsize{-1}, 190 stringstyle=\tt,191 188 tabsize=4, 192 189 xleftmargin=\parindent, 193 extendedchars=true, 194 escapechar=§, 190 escapechar=@, 195 191 mathescape=true, 196 192 keepspaces=true, 197 193 showstringspaces=false, 198 194 showlines=true, 199 aboveskip=4pt, 200 belowskip=2pt, 201 moredelim=**[is][\color{red}]{®}{®}, % red highlighting 202 moredelim=**[is][\color{blue}]{©}{©}, % blue highlighting 203 moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % temporarily turn off keywords 204 % literate={\\`}{\raisebox{0.3ex}{\ttfamily\upshape \hspace*{-2pt}`}}1, % escape \`, otherwise used for red highlighting 195 aboveskip=6pt, 196 belowskip=4pt, 197 literate={\\`}{\raisebox{0.3ex}{\ttfamily\upshape \hspace*{-2pt}`}}1, % escape \`, otherwise used for red highlighting 205 198 }% 206 199 … … 210 203 \lst@ProcessOther{"22}{\lst@ttfamily{"}{\raisebox{0.3ex}{\ttfamily\upshape "}}} % replace double quote 211 204 \lst@ProcessOther{"27}{\lst@ttfamily{'}{\raisebox{0.3ex}{\ttfamily\upshape '\hspace*{-2pt}}}} % replace single quote 212 \lst@ProcessOther{"2D}{\lst@ttfamily{-}{\t extbf{\texttt{-}}}} % replace minus213 \lst@ProcessOther{"3C}{\lst@ttfamily{<}{\text bf{\texttt{<}}}} % replace less than214 \lst@ProcessOther{"3E}{\lst@ttfamily{ >}{\textbf{\texttt{>}}}} % replace greater than205 \lst@ProcessOther{"2D}{\lst@ttfamily{-}{\ttfamily\upshape -}} % replace minus 206 \lst@ProcessOther{"3C}{\lst@ttfamily{<}{\texttt{<}}} % replace less than 207 \lst@ProcessOther{"3E}{\lst@ttfamily{<}{\texttt{>}}} % replace greater than 215 208 \lst@ProcessOther{"5E}{\raisebox{0.4ex}{$\scriptstyle\land\,$}} % replace circumflex 216 209 \lst@ProcessOther{"5F}{\lst@ttfamily{\char95}{{\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}}} % replace underscore -
doc/refrat/refrat.tex
r7cc6bd6 r9243a501 11 11 %% Created On : Wed Apr 6 14:52:25 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sat Apr 30 13:45:40201614 %% Update Count : 2913 %% Last Modified On : Sat Apr 9 10:19:12 2016 14 %% Update Count : 8 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 17 17 % requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended 18 19 % red highlighting ®...® (registered trademark sumbol)20 % blue highlighting ©...© (copyright symbol)21 % latex escape §...§ (section symbol)22 % keyword escape ¶...¶ (pilcrow symbol)23 % math escape $...$ (dollar symbol)24 18 25 19 \documentclass[openright,twoside]{report} … … 131 125 \CFA's scope rules differ from C's in one major respect: a declaration of an identifier may overload\index{overloading} outer declarations of lexically identical identifiers in the same 132 126 \Index{name space}, instead of hiding them. 133 The outer declaration is hidden if the two declarations have \Index{compatible type}, or if one declares an array type and the other declares a pointer type and the element type and pointed-at type are compatible, or if one has function type and the other is a pointer to a compatible function type, or if one declaration is a \lstinline @type@\use{type} or134 \lstinline @typedef@\use{typedef} declaration and the other is not. The outer declaration becomes127 The outer declaration is hidden if the two declarations have \Index{compatible type}, or if one declares an array type and the other declares a pointer type and the element type and pointed-at type are compatible, or if one has function type and the other is a pointer to a compatible function type, or if one declaration is a \lstinline$type$\use{type} or 128 \lstinline$typedef$\use{typedef} declaration and the other is not. The outer declaration becomes 135 129 \Index{visible} when the scope of the inner declaration terminates. 136 130 \begin{rationale} 137 Hence, a \CFA program can declare an \lstinline @int v@ and a \lstinline@float v@in the same scope;131 Hence, a \CFA program can declare an \lstinline$int v$ and a \lstinline$float v$ in the same scope; 138 132 a {\CC} program can not. 139 133 \end{rationale} … … 149 143 Identifiers with \Index{no linkage} always denote unique entities. 150 144 \begin{rationale} 151 A \CFA program can declare an \lstinline @extern int v@ and an \lstinline@extern float v@;145 A \CFA program can declare an \lstinline$extern int v$ and an \lstinline$extern float v$; 152 146 a C program cannot. 153 147 \end{rationale} … … 172 166 \end{lstlisting} 173 167 174 The type parameters in an instantiation of a generic type must satisfy any constraints in the forall specifier on the type generator declaration, e.g., \lstinline @sumable@.168 The type parameters in an instantiation of a generic type must satisfy any constraints in the forall specifier on the type generator declaration, e.g., \lstinline$sumable$. 175 169 The instantiation then has the semantics that would result if the type parameters were substituted into the type generator declaration by macro substitution. 176 170 … … 233 227 In \CFA, these conversions play a role in overload resolution, and collectively are called the \define{safe arithmetic conversion}s. 234 228 235 Let \ lstinline@int$_r$@ and \lstinline@unsigned$_r$@be the signed and unsigned integer types with integer conversion rank\index{integer conversion rank}\index{rank|see{integer conversion rank}} $r$.236 Let \ lstinline@unsigned$_{mr}$@be the unsigned integer type with maximal rank.229 Let \(int_r\) and \(unsigned_r\) be the signed and unsigned integer types with integer conversion rank\index{integer conversion rank}\index{rank|see{integer conversion rank}} $r$. 230 Let \(unsigned_{mr}\) be the unsigned integer type with maximal rank. 237 231 238 232 The following conversions are \emph{direct} safe arithmetic conversions. … … 241 235 The \Index{integer promotion}s. 242 236 \item 243 For every rank $r$ greater than or equal to the rank of \lstinline @int@, conversion from \lstinline@int$_r$@ to \lstinline@unsigned$_r$@.244 \item 245 For every rank $r$ greater than or equal to the rank of \lstinline @int@, where \lstinline@int$_{r+1}$@ exists and can represent all values of \lstinline@unsigned$_r$@, conversion from \lstinline@unsigned$_r$@ to \lstinline@int$_{r+1}$@.246 \item 247 Conversion from \ lstinline@unsigned$_{mr}$@ to \lstinline@float@.237 For every rank $r$ greater than or equal to the rank of \lstinline$int$, conversion from \(int_r\) to \(unsigned_r\). 238 \item 239 For every rank $r$ greater than or equal to the rank of \lstinline$int$, where \(int_{r+1}\) exists and can represent all values of \(unsigned_r\), conversion from \(unsigned_r\) to \(int_{r+1}\). 240 \item 241 Conversion from \(unsigned_{mr}\) to \lstinline$float$. 248 242 \item 249 243 Conversion from an enumerated type to its compatible integer type. 250 244 \item 251 Conversion from \lstinline @float@ to \lstinline@double@, and from \lstinline@double@ to \lstinline@long double@.252 \item 253 Conversion from \lstinline @float _Complex@ to \lstinline@double _Complex@, and from \lstinline@double _Complex@ to \lstinline@long double _Complex@.245 Conversion from \lstinline$float$ to \lstinline$double$, and from \lstinline$double$ to \lstinline$long double$. 246 \item 247 Conversion from \lstinline$float _Complex$ to \lstinline$double _Complex$, and from \lstinline$double _Complex$ to \lstinline$long double _Complex$. 254 248 \begin{sloppypar} 255 249 \item 256 Conversion from \lstinline @float _Imaginary@ to \lstinline@double _Imaginary@, and from \lstinline@double _Imaginary@ to \lstinline@long double _Imaginary@, if the implementation supports imaginary types.250 Conversion from \lstinline$float _Imaginary$ to \lstinline$double _Imaginary$, and from \lstinline$double _Imaginary$ to \lstinline$long double$ \lstinline$_Imaginary$, if the implementation supports imaginary types. 257 251 \end{sloppypar} 258 252 \end{itemize} 259 253 260 If type \lstinline @T@ can be converted to type \lstinline@U@ by a safe direct arithmetic conversion and type \lstinline@U@ can be converted to type \lstinline@V@ by a safe arithmetic conversion, then the conversion from \lstinline@T@ to type \lstinline@V@is an \emph{indirect} safe arithmetic conversion.254 If type \lstinline$T$ can be converted to type \lstinline$U$ by a safe direct arithmetic conversion and type \lstinline$U$ can be converted to type \lstinline$V$ by a safe arithmetic conversion, then the conversion from \lstinline$T$ to type \lstinline$V$ is an \emph{indirect} safe arithmetic conversion. 261 255 262 256 \begin{rationale} … … 281 275 int x, y; 282 276 }; 283 void move_by( struct point * p1, struct point * p2 ) { §\impl{move_by}§277 void move_by( struct point * p1, struct point * p2 ) {@\impl{move_by}@ 284 278 p1->x += p2.x; 285 279 p1->y += p2.y; … … 291 285 move_to( &cp1, &cp2 ); 292 286 \end{lstlisting} 293 Thanks to implicit conversion, the two arguments that \lstinline @move_by()@receives are pointers to294 \lstinline @cp1@'s second member and \lstinline@cp2@'s second member.287 Thanks to implicit conversion, the two arguments that \lstinline$move_by()$ receives are pointers to 288 \lstinline$cp1$'s second member and \lstinline$cp2$'s second member. 295 289 296 290 … … 334 328 a direct safe arithmetic conversion; 335 329 \item 336 from any object type or incomplete type to \lstinline @void@;337 \item 338 from a pointer to any non-\lstinline @void@ type to a pointer to \lstinline@void@;330 from any object type or incomplete type to \lstinline$void$; 331 \item 332 from a pointer to any non-\lstinline$void$ type to a pointer to \lstinline$void$; 339 333 \item 340 334 from a pointer to any type to a pointer to a more qualified version of the type\index{qualified type}; … … 347 341 Conversions that are not safe conversions are \define{unsafe conversion}s. 348 342 \begin{rationale} 349 As in C, there is an implicit conversion from \lstinline @void *@to any pointer type.343 As in C, there is an implicit conversion from \lstinline$void *$ to any pointer type. 350 344 This is clearly dangerous, and {\CC} does not have this implicit conversion. 351 345 \CFA\index{deficiencies!void * conversion} keeps it, in the interest of remaining as pure a superset of C as possible, but discourages it by making it unsafe. … … 373 367 \begin{itemize} 374 368 \item 375 The cost of an implicit conversion from \lstinline @int@ to \lstinline@long@is 1.376 The cost of an implicit conversion from \lstinline @long@ to \lstinline@double@ is 3, because it is defined in terms of conversions from \lstinline@long@ to \lstinline@unsigned long@, then to \lstinline@float@, and then to \lstinline@double@.377 378 \item 379 If \lstinline @int@ can represent all the values of \lstinline@unsigned short@, then the cost of an implicit conversion from \lstinline@unsigned short@ to \lstinline@unsigned@is 2:380 \lstinline @unsigned short@ to \lstinline@int@ to \lstinline@unsigned@.381 Otherwise, \lstinline @unsigned short@ is converted directly to \lstinline@unsigned@, and the cost is 1.382 383 \item 384 If \lstinline @long@ can represent all the values of \lstinline@unsigned@, then the conversion cost of \lstinline@unsigned@ to \lstinline@long@is 1.369 The cost of an implicit conversion from \lstinline$int$ to \lstinline$long$ is 1. 370 The cost of an implicit conversion from \lstinline$long$ to \lstinline$double$ is 3, because it is defined in terms of conversions from \lstinline$long$ to \lstinline$unsigned long$, then to \lstinline$float$, and then to \lstinline$double$. 371 372 \item 373 If \lstinline$int$ can represent all the values of \lstinline$unsigned short$, then the cost of an implicit conversion from \lstinline$unsigned short$ to \lstinline$unsigned$ is 2: 374 \lstinline$unsigned short$ to \lstinline$int$ to \lstinline$unsigned$. 375 Otherwise, \lstinline$unsigned short$ is converted directly to \lstinline$unsigned$, and the cost is 1. 376 377 \item 378 If \lstinline$long$ can represent all the values of \lstinline$unsigned$, then the conversion cost of \lstinline$unsigned$ to \lstinline$long$ is 1. 385 379 Otherwise, the conversion is an unsafe conversion, and its conversion cost is undefined. 386 380 \end{itemize} … … 390 384 \begin{syntax} 391 385 \oldlhs{keyword} 392 \rhs \lstinline @forall@393 \rhs \lstinline @lvalue@394 \rhs \lstinline @trait@395 \rhs \lstinline @dtype@396 \rhs \lstinline @ftype@397 \rhs \lstinline @otype@386 \rhs \lstinline$forall$ 387 \rhs \lstinline$lvalue$ 388 \rhs \lstinline$trait$ 389 \rhs \lstinline$dtype$ 390 \rhs \lstinline$ftype$ 391 \rhs \lstinline$type$ 398 392 \end{syntax} 399 393 … … 402 396 403 397 \CFA allows operator \Index{overloading} by associating operators with special function identifiers. 404 Furthermore, the constants ``\lstinline @0@'' and ``\lstinline@1@'' have special status for many of C's data types (and for many programmer-defined data types as well), so \CFA treats them as overloadable identifiers.398 Furthermore, the constants ``\lstinline$0$'' and ``\lstinline$1$'' have special status for many of C's data types (and for many programmer-defined data types as well), so \CFA treats them as overloadable identifiers. 405 399 Programmers can use these identifiers to declare functions and objects that implement operators and constants for their own types. 406 400 … … 411 405 \begin{syntax} 412 406 \oldlhs{identifier} 413 \rhs \lstinline @0@414 \rhs \lstinline @1@407 \rhs \lstinline$0$ 408 \rhs \lstinline$1$ 415 409 \end{syntax} 416 410 417 \index{constant identifiers}\index{identifiers!for constants} The tokens ``\lstinline @0@''\impl{0} and ``\lstinline@1@''\impl{1} are identifiers.411 \index{constant identifiers}\index{identifiers!for constants} The tokens ``\lstinline$0$''\impl{0} and ``\lstinline$1$''\impl{1} are identifiers. 418 412 No other tokens defined by the rules for integer constants are considered to be identifiers. 419 413 \begin{rationale} 420 Why ``\lstinline @0@'' and ``\lstinline@1@''? Those integers have special status in C.414 Why ``\lstinline$0$'' and ``\lstinline$1$''? Those integers have special status in C. 421 415 All scalar types can be incremented and decremented, which is defined in terms of adding or subtracting 1. 422 The operations ``\lstinline @&&@'', ``\lstinline@||@'', and ``\lstinline@!@'' can be applied to any scalar arguments, and are defined in terms of comparison against 0.416 The operations ``\lstinline$&&$'', ``\lstinline$||$'', and ``\lstinline$!$'' can be applied to any scalar arguments, and are defined in terms of comparison against 0. 423 417 A \nonterm{constant-expression} that evaluates to 0 is effectively compatible with every pointer type. 424 418 425 419 In C, the integer constants 0 and 1 suffice because the integer promotion rules can convert them to any arithmetic type, and the rules for pointer expressions treat constant expressions evaluating to 0 as a special case. 426 420 However, user-defined arithmetic types often need the equivalent of a 1 or 0 for their functions or operators, polymorphic functions often need 0 and 1 constants of a type matching their polymorphic parameters, and user-defined pointer-like types may need a null value. 427 Defining special constants for a user-defined type is more efficient than defining a conversion to the type from \lstinline @_Bool@.428 429 Why \emph{just} ``\lstinline @0@'' and ``\lstinline@1@''? Why not other integers? No other integers have special status in C.430 A facility that let programmers declare specific constants---``\lstinline @const Rational 12@'', for instance---would not be much of an improvement.421 Defining special constants for a user-defined type is more efficient than defining a conversion to the type from \lstinline$_Bool$. 422 423 Why \emph{just} ``\lstinline$0$'' and ``\lstinline$1$''? Why not other integers? No other integers have special status in C. 424 A facility that let programmers declare specific constants---``\lstinline$const Rational 12$'', for instance---would not be much of an improvement. 431 425 Some facility for defining the creation of values of programmer-defined types from arbitrary integer tokens would be needed. 432 426 The complexity of such a feature doesn't seem worth the gain. … … 444 438 \begin{tabular}[t]{ll} 445 439 %identifier & operation \\ \hline 446 \lstinline @?[?]@& subscripting \impl{?[?]}\\447 \lstinline @?()@& function call \impl{?()}\\448 \lstinline @?++@& postfix increment \impl{?++}\\449 \lstinline @?--@& postfix decrement \impl{?--}\\450 \lstinline @++?@& prefix increment \impl{++?}\\451 \lstinline @--?@& prefix decrement \impl{--?}\\452 \lstinline @*?@& dereference \impl{*?}\\453 \lstinline @+?@& unary plus \impl{+?}\\454 \lstinline @-?@& arithmetic negation \impl{-?}\\455 \lstinline @~?@& bitwise negation \impl{~?}\\456 \lstinline @!?@& logical complement \impl{"!?}\\457 \lstinline @?*?@& multiplication \impl{?*?}\\458 \lstinline @?/?@& division \impl{?/?}\\440 \lstinline$?[?]$ & subscripting \impl{?[?]}\\ 441 \lstinline$?()$ & function call \impl{?()}\\ 442 \lstinline$?++$ & postfix increment \impl{?++}\\ 443 \lstinline$?--$ & postfix decrement \impl{?--}\\ 444 \lstinline$++?$ & prefix increment \impl{++?}\\ 445 \lstinline$--?$ & prefix decrement \impl{--?}\\ 446 \lstinline$*?$ & dereference \impl{*?}\\ 447 \lstinline$+?$ & unary plus \impl{+?}\\ 448 \lstinline$-?$ & arithmetic negation \impl{-?}\\ 449 \lstinline$~?$ & bitwise negation \impl{~?}\\ 450 \lstinline$!?$ & logical complement \impl{"!?}\\ 451 \lstinline$?*?$ & multiplication \impl{?*?}\\ 452 \lstinline$?/?$ & division \impl{?/?}\\ 459 453 \end{tabular}\hfil 460 454 \begin{tabular}[t]{ll} 461 455 %identifier & operation \\ \hline 462 \lstinline @?%?@& remainder \impl{?%?}\\463 \lstinline @?+?@& addition \impl{?+?}\\464 \lstinline @?-?@& subtraction \impl{?-?}\\465 \lstinline @?<<?@& left shift \impl{?<<?}\\466 \lstinline @?>>?@& right shift \impl{?>>?}\\467 \lstinline @?<?@& less than \impl{?<?}\\468 \lstinline @?<=?@& less than or equal \impl{?<=?}\\469 \lstinline @?>=?@& greater than or equal \impl{?>=?}\\470 \lstinline @?>?@& greater than \impl{?>?}\\471 \lstinline @?==?@& equality \impl{?==?}\\472 \lstinline @?!=?@& inequality \impl{?"!=?}\\473 \lstinline @?&?@& bitwise AND \impl{?&?}\\456 \lstinline$?%?$ & remainder \impl{?%?}\\ 457 \lstinline$?+?$ & addition \impl{?+?}\\ 458 \lstinline$?-?$ & subtraction \impl{?-?}\\ 459 \lstinline$?<<?$ & left shift \impl{?<<?}\\ 460 \lstinline$?>>?$ & right shift \impl{?>>?}\\ 461 \lstinline$?<?$ & less than \impl{?<?}\\ 462 \lstinline$?<=?$ & less than or equal \impl{?<=?}\\ 463 \lstinline$?>=?$ & greater than or equal \impl{?>=?}\\ 464 \lstinline$?>?$ & greater than \impl{?>?}\\ 465 \lstinline$?==?$ & equality \impl{?==?}\\ 466 \lstinline$?!=?$ & inequality \impl{?"!=?}\\ 467 \lstinline$?&?$ & bitwise AND \impl{?&?}\\ 474 468 \end{tabular}\hfil 475 469 \begin{tabular}[t]{ll} 476 470 %identifier & operation \\ \hline 477 \lstinline @?^?@& exclusive OR \impl{?^?}\\478 \lstinline @?|?@& inclusive OR \impl{?"|?}\\479 \lstinline @?=?@& simple assignment \impl{?=?}\\480 \lstinline @?*=?@& multiplication assignment \impl{?*=?}\\481 \lstinline @?/=?@& division assignment \impl{?/=?}\\482 \lstinline @?%=?@& remainder assignment \impl{?%=?}\\483 \lstinline @?+=?@& addition assignment \impl{?+=?}\\484 \lstinline @?-=?@& subtraction assignment \impl{?-=?}\\485 \lstinline @?<<=?@& left-shift assignment \impl{?<<=?}\\486 \lstinline @?>>=?@& right-shift assignment \impl{?>>=?}\\487 \lstinline @?&=?@& bitwise AND assignment \impl{?&=?}\\488 \lstinline @?^=?@& exclusive OR assignment \impl{?^=?}\\489 \lstinline @?|=?@& inclusive OR assignment \impl{?"|=?}\\471 \lstinline$?^?$ & exclusive OR \impl{?^?}\\ 472 \lstinline$?|?$ & inclusive OR \impl{?"|?}\\ 473 \lstinline$?=?$ & simple assignment \impl{?=?}\\ 474 \lstinline$?*=?$ & multiplication assignment \impl{?*=?}\\ 475 \lstinline$?/=?$ & division assignment \impl{?/=?}\\ 476 \lstinline$?%=?$ & remainder assignment \impl{?%=?}\\ 477 \lstinline$?+=?$ & addition assignment \impl{?+=?}\\ 478 \lstinline$?-=?$ & subtraction assignment \impl{?-=?}\\ 479 \lstinline$?<<=?$ & left-shift assignment \impl{?<<=?}\\ 480 \lstinline$?>>=?$ & right-shift assignment \impl{?>>=?}\\ 481 \lstinline$?&=?$ & bitwise AND assignment \impl{?&=?}\\ 482 \lstinline$?^=?$ & exclusive OR assignment \impl{?^=?}\\ 483 \lstinline$?|=?$ & inclusive OR assignment \impl{?"|=?}\\ 490 484 \end{tabular} 491 485 \hfil … … 502 496 503 497 \begin{rationale} 504 The use of ``\lstinline @?@'' in identifiers means that some C programs are not \CFA programs. For instance, the sequence of characters ``\lstinline@(i < 0)?--i:i@'' is legal in a C program, but a505 \CFA compiler detects a syntax error because it treats ``\lstinline @?--@'' as an identifier, not as the two tokens ``\lstinline@?@'' and ``\lstinline@--@''.498 The use of ``\lstinline$?$'' in identifiers means that some C programs are not \CFA programs. For instance, the sequence of characters ``\lstinline$(i < 0)?--i:i$'' is legal in a C program, but a 499 \CFA compiler detects a syntax error because it treats ``\lstinline$?--$'' as an identifier, not as the two tokens ``\lstinline$?$'' and ``\lstinline$--$''. 506 500 \end{rationale} 507 501 … … 510 504 \begin{itemize} 511 505 \item 512 The logical operators ``\lstinline @&&@'' and ``\lstinline@||@'', and the conditional operator513 ``\lstinline @?:@''.506 The logical operators ``\lstinline$&&$'' and ``\lstinline$||$'', and the conditional operator 507 ``\lstinline$?:$''. 514 508 These operators do not always evaluate their operands, and hence can not be properly defined by functions unless some mechanism like call-by-name is added to the language. 515 Note that the definitions of ``\lstinline @&&@'' and ``\lstinline@||@'' say that they work by checking that their arguments are unequal to 0, so defining ``\lstinline@!=@'' and ``\lstinline@0@'' for user-defined types is enough to allow them to be used in logical expressions.509 Note that the definitions of ``\lstinline$&&$'' and ``\lstinline$||$'' say that they work by checking that their arguments are unequal to 0, so defining ``\lstinline$!=$'' and ``\lstinline$0$'' for user-defined types is enough to allow them to be used in logical expressions. 516 510 517 511 \item … … 522 516 \item 523 517 The ``address of'' operator. 524 It would seem useful to define a unary ``\lstinline @&@'' operator that returns values of some programmer-defined pointer-like type.518 It would seem useful to define a unary ``\lstinline$&$'' operator that returns values of some programmer-defined pointer-like type. 525 519 The problem lies with the type of the operator. 526 Consider the expression ``\lstinline @p = &x@'', where \lstinline@x@is of type527 \lstinline @T@ and \lstinline@p@ has the programmer-defined type \lstinline@T_ptr@.528 The expression might be treated as a call to the unary function ``\lstinline @&?@''.529 Now what is the type of the function's parameter? It can not be \lstinline @T@, because then \lstinline@x@would be passed by value, and there is no way to create a useful pointer-like result from a value.530 Hence the parameter must have type \lstinline @T *@.531 But then the expression must be rewritten as ``\lstinline @p = &?( &x )@''520 Consider the expression ``\lstinline$p = &x$'', where \lstinline$x$ is of type 521 \lstinline$T$ and \lstinline$p$ has the programmer-defined type \lstinline$T_ptr$. 522 The expression might be treated as a call to the unary function ``\lstinline$&?$''. 523 Now what is the type of the function's parameter? It can not be \lstinline$T$, because then \lstinline$x$ would be passed by value, and there is no way to create a useful pointer-like result from a value. 524 Hence the parameter must have type \lstinline$T *$. 525 But then the expression must be rewritten as ``\lstinline$p = &?( &x )$'' 532 526 ---which doesn't seem like progress! 533 527 534 528 The rule for address-of expressions would have to be something like ``keep applying address-of functions until you get one that takes a pointer argument, then use the built-in operator and stop''. 535 It seems simpler to define a conversion function from \lstinline @T *@ to \lstinline@T_ptr@.536 537 \item 538 The \lstinline @sizeof@operator.529 It seems simpler to define a conversion function from \lstinline$T *$ to \lstinline$T_ptr$. 530 531 \item 532 The \lstinline$sizeof$ operator. 539 533 It is already defined for every object type, and intimately tied into the language's storage allocation model. 540 534 Redefining it seems pointless. 541 535 542 536 \item 543 The ``member of'' operators ``\lstinline @.@'' and ``\lstinline@->@''.537 The ``member of'' operators ``\lstinline$.$'' and ``\lstinline$->$''. 544 538 These are not really infix operators, since their right ``operand'' is not a value or object. 545 539 … … 578 572 The ``fewest unsafe conversions'' rule ensures that the usual conversions are done, if possible. 579 573 The ``lowest total expression cost'' rule chooses the proper common type. 580 The odd-looking ``highest argument conversion cost'' rule ensures that, when unary expressions must be converted, conversions of function results are preferred to conversion of function arguments: \lstinline @(double)-i@ will be preferred to \lstinline@-(double)i@.574 The odd-looking ``highest argument conversion cost'' rule ensures that, when unary expressions must be converted, conversions of function results are preferred to conversion of function arguments: \lstinline$(double)-i$ will be preferred to \lstinline$-(double)i$. 581 575 582 576 The ``least polymorphic'' rule reduces the number of polymorphic function calls, since such functions are presumably more expensive than monomorphic functions and since the more specific function is presumably more appropriate. 583 577 It also gives preference to monomorphic values (such as the 584 \lstinline @int@ \lstinline@0@) over polymorphic values (such as the \Index{null pointer}585 \lstinline @0@\use{0}).578 \lstinline$int$ \lstinline$0$) over polymorphic values (such as the \Index{null pointer} 579 \lstinline$0$\use{0}). 586 580 However, interpretations that call polymorphic functions are preferred to interpretations that perform unsafe conversions, because those conversions potentially lose accuracy or violate strong typing. 587 581 … … 603 597 \begin{rationale} 604 598 Predefined functions and constants have internal linkage because that simplifies optimization in traditional compile-and-link environments. 605 For instance, ``\lstinline @an_int + an_int@'' is equivalent to ``\lstinline@?+?(an_int, an_int)@''.599 For instance, ``\lstinline$an_int + an_int$'' is equivalent to ``\lstinline$?+?(an_int, an_int)$''. 606 600 If integer addition has not been redefined in the current scope, a compiler can generate code to perform the addition directly. 607 601 If predefined functions had external linkage, this optimization would be difficult. … … 629 623 \rhs \nonterm{constant} 630 624 \rhs \nonterm{string-literal} 631 \rhs \lstinline @(@ \nonterm{expression} \lstinline@)@625 \rhs \lstinline$($ \nonterm{expression} \lstinline$)$ 632 626 \rhs \nonterm{generic-selection} 633 627 \end{syntax} … … 635 629 \predefined 636 630 \begin{lstlisting} 637 const int 1; §\use{1}§638 const int 0; §\use{0}§631 const int 1;@\use{1}@ 632 const int 0;@\use{0}@ 639 633 forall( dtype DT ) DT * const 0; 640 634 forall( ftype FT ) FT * const 0; … … 645 639 646 640 A \nonterm{constant} or \nonterm{string-literal} has one valid interpretation, which has the type and value defined by {\c11}. 647 The predefined integer identifiers ``\lstinline @1@'' and ``\lstinline@0@'' have the integer values 1 and 0, respectively.648 The other two predefined ``\lstinline @0@'' identifiers are bound to polymorphic pointer values that, when specialized\index{specialization} with a data type or function type respectively, produce a null pointer of that type.641 The predefined integer identifiers ``\lstinline$1$'' and ``\lstinline$0$'' have the integer values 1 and 0, respectively. 642 The other two predefined ``\lstinline$0$'' identifiers are bound to polymorphic pointer values that, when specialized\index{specialization} with a data type or function type respectively, produce a null pointer of that type. 649 643 650 644 A parenthesised expression has the same interpretations as the contained \nonterm{expression}. 651 645 652 646 \examples 653 The expression \lstinline @(void *)0@\use{0} specializes the (polymorphic) null pointer to a null pointer to \lstinline@void@. \lstinline@(const void *)0@ does the same, and also uses a safe conversion from \lstinline@void *@ to \lstinline@const void *@.647 The expression \lstinline$(void *)0$\use{0} specializes the (polymorphic) null pointer to a null pointer to \lstinline$void$. \lstinline$(const void *)0$ does the same, and also uses a safe conversion from \lstinline$void *$ to \lstinline$const void *$. 654 648 In each case, the null pointer conversion is better\index{best valid interpretations} than the unsafe conversion of the integer 655 \lstinline @0@to a pointer.649 \lstinline$0$ to a pointer. 656 650 657 651 \begin{rationale} … … 659 653 660 654 \CFA does not have C's concept of ``null pointer constants'', which are not typed values but special strings of tokens. 661 The C token ``\lstinline @0@'' is an expression of type \lstinline@int@with the value ``zero'', and it \emph{also} is a null pointer constant.655 The C token ``\lstinline$0$'' is an expression of type \lstinline$int$ with the value ``zero'', and it \emph{also} is a null pointer constant. 662 656 Similarly, 663 ``\lstinline @(void *)0@ is an expression of type \lstinline@(void *)@whose value is a null pointer, and it also is a null pointer constant.664 However, in C, ``\lstinline @(void *)(void *)0@'' is657 ``\lstinline$(void *)0$ is an expression of type \lstinline$(void *)$ whose value is a null pointer, and it also is a null pointer constant. 658 However, in C, ``\lstinline$(void *)(void *)0$'' is 665 659 \emph{not} a null pointer constant, even though it is null-valued, a pointer, and constant! The semantics of C expressions contain many special cases to deal with subexpressions that are null pointer constants. 666 660 … … 669 663 \begin{lstlisting} 670 664 forall( dtype DT ) DT * const 0; 671 \end{lstlisting} means that \lstinline @0@is a polymorphic object, and contains a value that can have \emph{any} pointer-to-object type or pointer-to-incomplete type.665 \end{lstlisting} means that \lstinline$0$ is a polymorphic object, and contains a value that can have \emph{any} pointer-to-object type or pointer-to-incomplete type. 672 666 The only such value is the null pointer. 673 667 Therefore the type \emph{alone} is enough to identify a null pointer. … … 679 673 680 674 \constraints The best interpretation of the controlling expression shall be unambiguous\index{ambiguous interpretation}, and shall have type compatible with at most one of the types named in its generic association list. 681 If a generic selection has no \lstinline @default@generic association, the best interpretation of its controlling expression shall have type compatible with exactly one of the types named in its generic association list.675 If a generic selection has no \lstinline$default$ generic association, the best interpretation of its controlling expression shall have type compatible with exactly one of the types named in its generic association list. 682 676 683 677 \semantics … … 690 684 \lhs{postfix-expression} 691 685 \rhs \nonterm{primary-expression} 692 \rhs \nonterm{postfix-expression} \lstinline @[@ \nonterm{expression} \lstinline@]@693 \rhs \nonterm{postfix-expression} \lstinline @(@694 \nonterm{argument-expression-list}\opt \lstinline @)@695 \rhs \nonterm{postfix-expression} \lstinline @.@\nonterm{identifier}696 \rhs \nonterm{postfix-expression} \lstinline @->@\nonterm{identifier}697 \rhs \nonterm{postfix-expression} \lstinline @++@698 \rhs \nonterm{postfix-expression} \lstinline @--@699 \rhs \lstinline @(@ \nonterm{type-name} \lstinline@)@ \lstinline@{@ \nonterm{initializer-list} \lstinline@}@700 \rhs \lstinline @(@ \nonterm{type-name} \lstinline@)@ \lstinline@{@ \nonterm{initializer-list} \lstinline@,@ \lstinline@}@686 \rhs \nonterm{postfix-expression} \lstinline$[$ \nonterm{expression} \lstinline$]$ 687 \rhs \nonterm{postfix-expression} \lstinline$($ 688 \nonterm{argument-expression-list}\opt \lstinline$)$ 689 \rhs \nonterm{postfix-expression} \lstinline$.$ \nonterm{identifier} 690 \rhs \nonterm{postfix-expression} \lstinline$->$ \nonterm{identifier} 691 \rhs \nonterm{postfix-expression} \lstinline$++$ 692 \rhs \nonterm{postfix-expression} \lstinline$--$ 693 \rhs \lstinline$($ \nonterm{type-name} \lstinline$)$ \lstinline${$ \nonterm{initializer-list} \lstinline$}$ 694 \rhs \lstinline$($ \nonterm{type-name} \lstinline$)$ \lstinline${$ \nonterm{initializer-list} \lstinline$,$ \lstinline$}$ 701 695 \lhs{argument-expression-list} 702 696 \rhs \nonterm{assignment-expression} 703 \rhs \nonterm{argument-expression-list} \lstinline @,@697 \rhs \nonterm{argument-expression-list} \lstinline$,$ 704 698 \nonterm{assignment-expression} 705 699 \end{syntax} … … 707 701 \rewriterules 708 702 \begin{lstlisting} 709 a[b] §\rewrite§ ?[?]( b, a ) // if a has integer type§\use{?[?]}§710 a[b] §\rewrite§?[?]( a, b ) // otherwise711 a( §\emph{arguments}§ ) §\rewrite§ ?()( a, §\emph{arguments}§ )§\use{?()}§712 a++ §\rewrite§ ?++(&( a ))§\use{?++}§713 a-- §\rewrite§ ?--(&( a ))§\use{?--}§703 a[b] @\rewrite@ ?[?]( b, a ) // if a has integer type@\use{?[?]}@ 704 a[b] @\rewrite@ ?[?]( a, b ) // otherwise 705 a( @\emph{arguments}@ ) @\rewrite@ ?()( a, @\emph{arguments}@ )@\use{?()}@ 706 a++ @\rewrite@ ?++(&( a ))@\use{?++}@ 707 a-- @\rewrite@ ?--(&( a ))@\use{?--}@ 714 708 \end{lstlisting} 715 709 … … 719 713 \predefined 720 714 \begin{lstlisting} 721 forall( otype T ) lvalue T ?[?]( T *, ptrdiff_t ); §\use{ptrdiff_t}§715 forall( otype T ) lvalue T ?[?]( T *, ptrdiff_t );@\use{ptrdiff_t}@ 722 716 forall( otype T ) lvalue _Atomic T ?[?]( _Atomic T *, ptrdiff_t ); 723 717 forall( otype T ) lvalue const T ?[?]( const T *, ptrdiff_t ); … … 739 733 The interpretations of subscript expressions are the interpretations of the corresponding function call expressions. 740 734 \begin{rationale} 741 C defines subscripting as pointer arithmetic in a way that makes \lstinline @a[i]@and742 \lstinline @i[a]@ equivalent. \CFA provides the equivalence through a rewrite rule to reduce the number of overloadings of \lstinline@?[?]@.735 C defines subscripting as pointer arithmetic in a way that makes \lstinline$a[i]$ and 736 \lstinline$i[a]$ equivalent. \CFA provides the equivalence through a rewrite rule to reduce the number of overloadings of \lstinline$?[?]$. 743 737 744 738 Subscript expressions are rewritten as function calls that pass the first parameter by value. 745 739 This is somewhat unfortunate, since array-like types tend to be large. 746 The alternative is to use the rewrite rule ``\lstinline @a[b]@ \rewrite \lstinline@?[?](&(a), b)@''.747 However, C semantics forbid this approach: the \lstinline @a@ in ``\lstinline@a[b]@'' can be an arbitrary pointer value, which does not have an address.740 The alternative is to use the rewrite rule ``\lstinline$a[b]$ \rewrite \lstinline$?[?](&(a), b)$''. 741 However, C semantics forbid this approach: the \lstinline$a$ in ``\lstinline$a[b]$'' can be an arbitrary pointer value, which does not have an address. 748 742 749 743 The repetitive form of the predefined identifiers shows up a deficiency\index{deficiencies!pointers … … 760 754 \nonterm{postfix-expression} in a function call may have some interpretations that are function designators and some that are not. 761 755 762 For those interpretations of the \nonterm{postfix-expression} that are not function designators, the expression is rewritten and becomes a call of a function named ``\lstinline @?()@''.756 For those interpretations of the \nonterm{postfix-expression} that are not function designators, the expression is rewritten and becomes a call of a function named ``\lstinline$?()$''. 763 757 The valid interpretations of the rewritten expression are determined in the manner described below. 764 758 … … 768 762 \item if the argument corresponds to a parameter in the function designator's prototype, the argument interpretation must have the same type as the corresponding parameter, or be implicitly convertible to the parameter's type 769 763 \item if the function designator's type does not include a prototype or if the argument corresponds to 770 ``\lstinline @...@'' in a prototype, a \Index{default argument promotion} is applied to it.764 ``\lstinline$...$'' in a prototype, a \Index{default argument promotion} is applied to it. 771 765 \end{itemize} 772 766 The type of the valid interpretation is the return type of the function designator. … … 776 770 \begin{itemize} 777 771 \item 778 If the declaration of the implicit parameter uses \Index{type-class} \lstinline @type@\use{type}, the implicit argument must be an object type;779 if it uses \lstinline @dtype@, the implicit argument must be an object type or an incomplete type;780 and if it uses \lstinline @ftype@, the implicit argument must be a function type.772 If the declaration of the implicit parameter uses \Index{type-class} \lstinline$type$\use{type}, the implicit argument must be an object type; 773 if it uses \lstinline$dtype$, the implicit argument must be an object type or an incomplete type; 774 and if it uses \lstinline$ftype$, the implicit argument must be a function type. 781 775 782 776 \item if an explicit parameter's type uses any implicit parameters, then the corresponding explicit argument must have a type that is (or can be safely converted\index{safe conversion} to) the type produced by substituting the implicit arguments for the implicit parameters in the explicit parameter type. … … 797 791 \begin{rationale} 798 792 One desirable property of a polymorphic programming language is \define{generalizability}: the ability to replace an abstraction with a more general but equivalent abstraction without requiring changes in any of the uses of the original\cite{Cormack90}. 799 For instance, it should be possible to replace a function ``\lstinline @int f( int );@'' with ``\lstinline@forall( otype T ) T f( T );@'' without affecting any calls of \lstinline@f@.793 For instance, it should be possible to replace a function ``\lstinline$int f( int );$'' with ``\lstinline$forall( otype T ) T f( T );$'' without affecting any calls of \lstinline$f$. 800 794 801 795 \CFA\index{deficiencies!generalizability} does not fully possess this property, because … … 811 805 f = g( d, f ); // (3) (unsafe conversion to float) 812 806 \end{lstlisting} 813 If \lstinline @g@ was replaced by ``\lstinline@forall( otype T ) T g( T, T );@'', the first and second calls would be unaffected, but the third would change: \lstinline@f@would be converted to814 \lstinline @double@, and the result would be a \lstinline@double@.815 816 Another example is the function ``\lstinline @void h( int *);@''.807 If \lstinline$g$ was replaced by ``\lstinline$forall( otype T ) T g( T, T );$'', the first and second calls would be unaffected, but the third would change: \lstinline$f$ would be converted to 808 \lstinline$double$, and the result would be a \lstinline$double$. 809 810 Another example is the function ``\lstinline$void h( int *);$''. 817 811 This function can be passed a 818 \lstinline @void *@ argument, but the generalization ``\lstinline@forall( otype T ) void h( T *);@'' can not.819 In this case, \lstinline @void@ is not a valid value for \lstinline@T@because it is not an object type.820 If unsafe conversions were allowed, \lstinline @T@could be inferred to be \emph{any} object type, which is undesirable.812 \lstinline$void *$ argument, but the generalization ``\lstinline$forall( otype T ) void h( T *);$'' can not. 813 In this case, \lstinline$void$ is not a valid value for \lstinline$T$ because it is not an object type. 814 If unsafe conversions were allowed, \lstinline$T$ could be inferred to be \emph{any} object type, which is undesirable. 821 815 \end{rationale} 822 816 823 817 \examples 824 A function called ``\lstinline @?()@'' might be part of a numerical differentiation package.818 A function called ``\lstinline$?()$'' might be part of a numerical differentiation package. 825 819 \begin{lstlisting} 826 820 extern otype Derivative; … … 833 827 d = sin_dx( 12.9 ); 834 828 \end{lstlisting} 835 Here, the only interpretation of \lstinline @sin_dx@ is as an object of type \lstinline@Derivative@.836 For that interpretation, the function call is treated as ``\lstinline @?()( sin_dx, 12.9 )@''.829 Here, the only interpretation of \lstinline$sin_dx$ is as an object of type \lstinline$Derivative$. 830 For that interpretation, the function call is treated as ``\lstinline$?()( sin_dx, 12.9 )$''. 837 831 \begin{lstlisting} 838 832 int f( long ); // (1) … … 841 835 int i = f( 5 ); // calls (1) 842 836 \end{lstlisting} 843 Function (1) provides a valid interpretation of ``\lstinline @f( 5 )@'', using an implicit \lstinline@int@ to \lstinline@long@conversion.844 The other functions do not, since the second requires two arguments, and since there is no implicit conversion from \lstinline @int@ to \lstinline@int *@that could be used with the third function.837 Function (1) provides a valid interpretation of ``\lstinline$f( 5 )$'', using an implicit \lstinline$int$ to \lstinline$long$ conversion. 838 The other functions do not, since the second requires two arguments, and since there is no implicit conversion from \lstinline$int$ to \lstinline$int *$ that could be used with the third function. 845 839 846 840 \begin{lstlisting} … … 848 842 double d = h( 1.5 ); 849 843 \end{lstlisting} 850 ``\lstinline @1.5@'' is a \lstinline@double@ constant, so \lstinline@T@is inferred to be851 \lstinline @double@, and the result of the function call is a \lstinline@double@.844 ``\lstinline$1.5$'' is a \lstinline$double$ constant, so \lstinline$T$ is inferred to be 845 \lstinline$double$, and the result of the function call is a \lstinline$double$. 852 846 853 847 \begin{lstlisting} … … 864 858 g( i, p ); // calls (4) 865 859 \end{lstlisting} 866 The first call has valid interpretations for all four versions of \lstinline @g@. (6) and (7) are discarded because they involve unsafe \lstinline@double@-to-\lstinline@long@conversions. (5) is chosen because it is less polymorphic than (4).860 The first call has valid interpretations for all four versions of \lstinline$g$. (6) and (7) are discarded because they involve unsafe \lstinline$double$-to-\lstinline$long$ conversions. (5) is chosen because it is less polymorphic than (4). 867 861 868 862 For the second call, (7) is again discarded. 869 Of the remaining interpretations for (4), (5), and (6) (with \lstinline @i@ converted to \lstinline@long@), (6) is chosen because it is the least polymorphic.863 Of the remaining interpretations for (4), (5), and (6) (with \lstinline$i$ converted to \lstinline$long$), (6) is chosen because it is the least polymorphic. 870 864 871 865 The third call has valid interpretations for all of the functions; … … 876 870 forall( otype T ) T min( T, T ); 877 871 double max( double, double ); 878 trait min_max( T ) { §\impl{min_max}§872 trait min_max( T ) {@\impl{min_max}@ 879 873 T min( T, T ); 880 874 T max( T, T ); … … 883 877 shuffle( 9, 10 ); 884 878 \end{lstlisting} 885 The only possibility for \lstinline @U@ is \lstinline@double@, because that is the type used in the only visible \lstinline@max@ function. 9 and 10 must be converted to \lstinline@double@, and886 \lstinline @min@ must be specialized with \lstinline@T@ bound to \lstinline@double@.879 The only possibility for \lstinline$U$ is \lstinline$double$, because that is the type used in the only visible \lstinline$max$ function. 9 and 10 must be converted to \lstinline$double$, and 880 \lstinline$min$ must be specialized with \lstinline$T$ bound to \lstinline$double$. 887 881 \begin{lstlisting} 888 882 extern void q( int ); // (8) … … 892 886 r( 0 ); 893 887 \end{lstlisting} 894 The \lstinline @int 0@ could be passed to (8), or the \lstinline@(void *)@ \Index{specialization} of the null pointer\index{null pointer} \lstinline@0@\use{0} could be passed to (9).895 The former is chosen because the \lstinline @int@ \lstinline@0@is \Index{less polymorphic}.896 For the same reason, \lstinline @int@ \lstinline@0@ is passed to \lstinline@r()@, even though it has \emph{no} declared parameter types.888 The \lstinline$int 0$ could be passed to (8), or the \lstinline$(void *)$ \Index{specialization} of the null pointer\index{null pointer} \lstinline$0$\use{0} could be passed to (9). 889 The former is chosen because the \lstinline$int$ \lstinline$0$ is \Index{less polymorphic}. 890 For the same reason, \lstinline$int$ \lstinline$0$ is passed to \lstinline$r()$, even though it has \emph{no} declared parameter types. 897 891 898 892 899 893 \subsubsection{Structure and union members} 900 894 901 \semantics In the member selection expression ``\lstinline @s@.\lstinline@m@'', there shall be at least one interpretation of \lstinline@s@ whose type is a structure type or union type containing a member named \lstinline@m@.902 If two or more interpretations of \lstinline @s@have members named903 \lstinline @m@with mutually compatible types, then the expression has an \Index{ambiguous interpretation} whose type is the composite type of the types of the members.904 If an interpretation of \lstinline @s@ has a member \lstinline@m@whose type is not compatible with any other905 \lstinline @s@'s \lstinline@m@, then the expression has an interpretation with the member's type.895 \semantics In the member selection expression ``\lstinline$s$.\lstinline$m$'', there shall be at least one interpretation of \lstinline$s$ whose type is a structure type or union type containing a member named \lstinline$m$. 896 If two or more interpretations of \lstinline$s$ have members named 897 \lstinline$m$ with mutually compatible types, then the expression has an \Index{ambiguous interpretation} whose type is the composite type of the types of the members. 898 If an interpretation of \lstinline$s$ has a member \lstinline$m$ whose type is not compatible with any other 899 \lstinline$s$'s \lstinline$m$, then the expression has an interpretation with the member's type. 906 900 The expression has no other interpretations. 907 901 908 The expression ``\lstinline@p->m@'' has the same interpretations as the expression ``\lstinline@(*p).m@''. 902 The expression ``\lstinline$p->m$'' has the same interpretations as the expression 903 ``\lstinline$(*p).m$''. 909 904 910 905 … … 1001 996 * ?--( _Atomic const restrict volatile T * _Atomic restrict volatile * ); 1002 997 \end{lstlisting} 1003 For every extended integer type \lstinline @X@there exist998 For every extended integer type \lstinline$X$ there exist 1004 999 % Don't use predefined: keep this out of prelude.cf. 1005 1000 \begin{lstlisting} … … 1007 1002 ?--( volatile X * ), ?--( _Atomic volatile X * ); 1008 1003 \end{lstlisting} 1009 For every complete enumerated type \lstinline @E@there exist1004 For every complete enumerated type \lstinline$E$ there exist 1010 1005 % Don't use predefined: keep this out of prelude.cf. 1011 1006 \begin{lstlisting} … … 1015 1010 1016 1011 \begin{rationale} 1017 Note that ``\lstinline @++@'' and ``\lstinline@--@'' are rewritten as function calls that are given a pointer to that operand. (This is true of all operators that modify an operand.) As Hamish Macdonald has pointed out, this forces the modified operand of such expressions to be an lvalue.1012 Note that ``\lstinline$++$'' and ``\lstinline$--$'' are rewritten as function calls that are given a pointer to that operand. (This is true of all operators that modify an operand.) As Hamish Macdonald has pointed out, this forces the modified operand of such expressions to be an lvalue. 1018 1013 This partially enforces the C semantic rule that such operands must be \emph{modifiable} lvalues. 1019 1014 \end{rationale} … … 1021 1016 \begin{rationale} 1022 1017 In C, a semantic rule requires that pointer operands of increment and decrement be pointers to object types. 1023 Hence, \lstinline @void *@objects cannot be incremented.1024 In \CFA, the restriction follows from the use of a \lstinline @type@ parameter in the predefined function definitions, as opposed to \lstinline@dtype@, since only object types can be inferred arguments corresponding to the type parameter \lstinline@T@.1018 Hence, \lstinline$void *$ objects cannot be incremented. 1019 In \CFA, the restriction follows from the use of a \lstinline$type$ parameter in the predefined function definitions, as opposed to \lstinline$dtype$, since only object types can be inferred arguments corresponding to the type parameter \lstinline$T$. 1025 1020 \end{rationale} 1026 1021 1027 1022 \semantics 1028 1023 First, each interpretation of the operand of an increment or decrement expression is considered separately. 1029 For each interpretation that is a bit-field or is declared with the \Indexc{register}\index{storage-class specifier}, the expression has one valid interpretation, with the type of the operand, and the expression is ambiguous if the operand is. 1024 For each interpretation that is a bit-field or is declared with the 1025 \lstinline$register$\index{register@{\lstinline$register$}} \index{Itorage-class specifier}, the expression has one valid interpretation, with the type of the operand, and the expression is ambiguous if the operand is. 1030 1026 1031 1027 For the remaining interpretations, the expression is rewritten, and the interpretations of the expression are the interpretations of the corresponding function call. … … 1040 1036 \end{lstlisting} 1041 1037 \begin{sloppypar} 1042 Since \lstinline@&(vs)@ has type \lstinline@volatile short int *@, the best valid interpretation of 1043 \lstinline@vs++@ calls the \lstinline@?++@ function with the \lstinline@volatile short *@ parameter. 1044 \lstinline@s++@ does the same, applying the safe conversion from \lstinline@short int *@ to \lstinline@volatile short int *@. 1045 Note that there is no conversion that adds an \lstinline@_Atomic@ qualifier, so the \lstinline@_Atomic volatile short int@ overloading does not provide a valid interpretation. 1038 Since \lstinline$&(vs)$ has type \lstinline$volatile short int *$, the best valid interpretation of 1039 \lstinline$vs++$ calls the \lstinline$?++$ function with the \lstinline$volatile short *$ parameter. 1040 \lstinline$s++$ does the same, applying the safe conversion from \lstinline$short int *$ to 1041 \lstinline$volatile short int *$. 1042 Note that there is no conversion that adds an \lstinline$_Atomic$ qualifier, so the \lstinline$_Atomic volatile short int$ overloading does not provide a valid interpretation. 1046 1043 \end{sloppypar} 1047 1044 1048 There is no safe conversion from \lstinline @const short int *@ to \lstinline@volatile short int *@, and no \lstinline@?++@ function that accepts a \lstinline@const *@ parameter, so \lstinline@cs++@has no valid interpretations.1049 1050 The best valid interpretation of \lstinline @as++@ calls the \lstinline@short ?++@ function with the \lstinline@_Atomic volatile short int *@ parameter, applying a safe conversion to add the \lstinline@volatile@qualifier.1045 There is no safe conversion from \lstinline$const short int *$ to \lstinline$volatile short int *$, and no \lstinline$?++$ function that accepts a \lstinline$const *$ parameter, so \lstinline$cs++$ has no valid interpretations. 1046 1047 The best valid interpretation of \lstinline$as++$ calls the \lstinline$short ?++$ function with the \lstinline$_Atomic volatile short int *$ parameter, applying a safe conversion to add the \lstinline$volatile$ qualifier. 1051 1048 \begin{lstlisting} 1052 1049 char * const restrict volatile * restrict volatile pqpc; … … 1055 1052 ppc++; 1056 1053 \end{lstlisting} 1057 Since \lstinline @&(pqpc)@ has type \lstinline@char * const restrict volatile * restrict volatile *@, the best valid interpretation of \lstinline@pqpc++@ calls the polymorphic \lstinline@?++@ function with the \lstinline@const restrict volatile T * restrict volatile *@ parameter, inferring \lstinline@T@ to be \lstinline@char *@.1058 1059 \lstinline @ppc++@ calls the same function, again inferring \lstinline@T@ to be \lstinline@char *@, and using the safe conversions from \lstinline@T@ to \lstinline@T const@ \lstinline@restrict volatile@.1054 Since \lstinline$&(pqpc)$ has type \lstinline$char * const restrict volatile * restrict volatile *$, the best valid interpretation of \lstinline$pqpc++$ calls the polymorphic \lstinline$?++$ function with the \lstinline$const restrict volatile T * restrict volatile *$ parameter, inferring \lstinline$T$ to be \lstinline$char *$. 1055 1056 \lstinline$ppc++$ calls the same function, again inferring \lstinline$T$ to be \lstinline$char *$, and using the safe conversions from \lstinline$T$ to \lstinline$T const$ \lstinline$restrict volatile$. 1060 1057 1061 1058 \begin{rationale} … … 1071 1068 \begin{enumerate} 1072 1069 \item 1073 ``\lstinline @char * p; p++;@''.1074 The argument to \lstinline @?++@ has type \lstinline@char * *@, and the result has type \lstinline@char *@.1075 The expression would be valid if \lstinline @?++@were declared by1070 ``\lstinline$char * p; p++;$''. 1071 The argument to \lstinline$?++$ has type \lstinline$char * *$, and the result has type \lstinline$char *$. 1072 The expression would be valid if \lstinline$?++$ were declared by 1076 1073 \begin{lstlisting} 1077 1074 forall( otype T ) T * ?++( T * * ); 1078 \end{lstlisting} with \lstinline @T@ inferred to be \lstinline@char@.1079 1080 \item 1081 ``\lstinline @char *restrict volatile qp; qp++@''.1082 The result again has type \lstinline @char *@, but the argument now has type \lstinline@char *restrict volatile *@, so it cannot be passed to the hypothetical function declared in point 1.1075 \end{lstlisting} with \lstinline$T$ inferred to be \lstinline$char$. 1076 1077 \item 1078 ``\lstinline$char *restrict volatile qp; qp++$''. 1079 The result again has type \lstinline$char *$, but the argument now has type \lstinline$char *restrict volatile *$, so it cannot be passed to the hypothetical function declared in point 1. 1083 1080 Hence the actual predefined function is 1084 1081 \begin{lstlisting} 1085 1082 forall( otype T ) T * ?++( T * restrict volatile * ); 1086 \end{lstlisting} which also accepts a \lstinline @char * *@argument, because of the safe conversions that add1087 \lstinline @volatile@ and \lstinline@restrict@qualifiers. (The parameter is not const-qualified, so constant pointers cannot be incremented.)1088 1089 \item 1090 ``\lstinline @char *_Atomic ap; ap++@''.1091 The result again has type \lstinline @char *@, but no safe conversion adds an \lstinline@_Atomic@qualifier, so the function in point 2 is not applicable.1092 A separate overloading of \lstinline @?++@is required.1093 1094 \item 1095 ``\lstinline @char const volatile * pq; pq++@''.1083 \end{lstlisting} which also accepts a \lstinline$char * *$ argument, because of the safe conversions that add 1084 \lstinline$volatile$ and \lstinline$restrict$ qualifiers. (The parameter is not const-qualified, so constant pointers cannot be incremented.) 1085 1086 \item 1087 ``\lstinline$char *_Atomic ap; ap++$''. 1088 The result again has type \lstinline$char *$, but no safe conversion adds an \lstinline$_Atomic$ qualifier, so the function in point 2 is not applicable. 1089 A separate overloading of \lstinline$?++$ is required. 1090 1091 \item 1092 ``\lstinline$char const volatile * pq; pq++$''. 1096 1093 Here the result has type 1097 \lstinline @char const volatile *@, so a new overloading is needed:1094 \lstinline$char const volatile *$, so a new overloading is needed: 1098 1095 \begin{lstlisting} 1099 1096 forall( otype T ) T const volatile * ?++( T const volatile *restrict volatile * ); … … 1102 1099 1103 1100 \item 1104 ``\lstinline @float *restrict * prp; prp++@''.1105 The \lstinline @restrict@ qualifier is handled just like \lstinline@const@ and \lstinline@volatile@in the previous case:1101 ``\lstinline$float *restrict * prp; prp++$''. 1102 The \lstinline$restrict$ qualifier is handled just like \lstinline$const$ and \lstinline$volatile$ in the previous case: 1106 1103 \begin{lstlisting} 1107 1104 forall( otype T ) T restrict * ?++( T restrict *restrict volatile * ); 1108 \end{lstlisting} with \lstinline @T@ inferred to be \lstinline@float *@.1109 This looks odd, because {\c11} contains a constraint that requires restrict-qualified types to be pointer-to-object types, and \lstinline @T@is not syntactically a pointer type. \CFA loosens the constraint.1105 \end{lstlisting} with \lstinline$T$ inferred to be \lstinline$float *$. 1106 This looks odd, because {\c11} contains a constraint that requires restrict-qualified types to be pointer-to-object types, and \lstinline$T$ is not syntactically a pointer type. \CFA loosens the constraint. 1110 1107 \end{enumerate} 1111 1108 \end{rationale} … … 1123 1120 \lhs{unary-expression} 1124 1121 \rhs \nonterm{postfix-expression} 1125 \rhs \lstinline @++@\nonterm{unary-expression}1126 \rhs \lstinline @--@\nonterm{unary-expression}1122 \rhs \lstinline$++$ \nonterm{unary-expression} 1123 \rhs \lstinline$--$ \nonterm{unary-expression} 1127 1124 \rhs \nonterm{unary-operator} \nonterm{cast-expression} 1128 \rhs \lstinline @sizeof@\nonterm{unary-expression}1129 \rhs \lstinline @sizeof@ \lstinline@(@ \nonterm{type-name} \lstinline@)@1130 \lhs{unary-operator} one of \rhs \lstinline @&@ \lstinline@*@ \lstinline@+@ \lstinline@-@ \lstinline@~@ \lstinline@!@1125 \rhs \lstinline$sizeof$ \nonterm{unary-expression} 1126 \rhs \lstinline$sizeof$ \lstinline$($ \nonterm{type-name} \lstinline$)$ 1127 \lhs{unary-operator} one of \rhs \lstinline$&$ \lstinline$*$ \lstinline$+$ \lstinline$-$ \lstinline$~$ \lstinline$!$ 1131 1128 \end{syntax} 1132 1129 1133 1130 \rewriterules 1134 1131 \begin{lstlisting} 1135 *a §\rewrite§ *?( a ) §\use{*?}§1136 +a §\rewrite§ +?( a ) §\use{+?}§1137 -a §\rewrite§ -?( a ) §\use{-?}§1138 ~a §\rewrite§ ~?( a ) §\use{~?}§1139 !a §\rewrite§ !?( a ) §\use{"!?}§1140 ++a §\rewrite§ ++?(&( a )) §\use{++?}§1141 --a §\rewrite§ --?(&( a )) §\use{--?}§1132 *a @\rewrite@ *?( a ) @\use{*?}@ 1133 +a @\rewrite@ +?( a ) @\use{+?}@ 1134 -a @\rewrite@ -?( a ) @\use{-?}@ 1135 ~a @\rewrite@ ~?( a ) @\use{~?}@ 1136 !a @\rewrite@ !?( a ) @\use{"!?}@ 1137 ++a @\rewrite@ ++?(&( a )) @\use{++?}@ 1138 --a @\rewrite@ --?(&( a )) @\use{--?}@ 1142 1139 \end{lstlisting} 1143 1140 … … 1235 1232 * --?( _Atomic const restrict volatile T * _Atomic restrict volatile * ); 1236 1233 \end{lstlisting} 1237 For every extended integer type \lstinline @X@there exist1234 For every extended integer type \lstinline$X$ there exist 1238 1235 % Don't use predefined: keep this out of prelude.cf. 1239 1236 \begin{lstlisting} … … 1243 1240 --?( _Atomic volatile X * ); 1244 1241 \end{lstlisting} 1245 For every complete enumerated type \lstinline @E@there exist1242 For every complete enumerated type \lstinline$E$ there exist 1246 1243 % Don't use predefined: keep this out of prelude.cf. 1247 1244 \begin{lstlisting} … … 1280 1277 1281 1278 \constraints 1282 The operand of the unary ``\lstinline @&@'' operator shall have exactly one1279 The operand of the unary ``\lstinline$&$'' operator shall have exactly one 1283 1280 \Index{interpretation}\index{ambiguous interpretation}, which shall be unambiguous. 1284 1281 1285 1282 \semantics 1286 The ``\lstinline @&@'' expression has one interpretation which is of type \lstinline@T *@, where1287 \lstinline @T@is the type of the operand.1283 The ``\lstinline$&$'' expression has one interpretation which is of type \lstinline$T *$, where 1284 \lstinline$T$ is the type of the operand. 1288 1285 1289 1286 The interpretations of an indirection expression are the interpretations of the corresponding function call. … … 1314 1311 forall( ftype FT ) int !?( FT * ); 1315 1312 \end{lstlisting} 1316 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1313 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1317 1314 % Don't use predefined: keep this out of prelude.cf. 1318 1315 \begin{lstlisting} … … 1327 1324 \begin{lstlisting} 1328 1325 long int li; 1329 void eat_double( double ); §\use{eat_double}§1330 eat_double(-li ); // §\rewrite§eat_double( -?( li ) );1331 \end{lstlisting} 1332 The valid interpretations of ``\lstinline @-li@'' (assuming no extended integer types exist) are1326 void eat_double( double );@\use{eat_double}@ 1327 eat_double(-li ); // @\rewrite@ eat_double( -?( li ) ); 1328 \end{lstlisting} 1329 The valid interpretations of ``\lstinline$-li$'' (assuming no extended integer types exist) are 1333 1330 \begin{center} 1334 1331 \begin{tabular}{llc} interpretation & result type & expression conversion cost \\ 1335 1332 \hline 1336 \lstinline @-?( (int)li )@ & \lstinline@int@& (unsafe) \\1337 \lstinline @-?( (unsigned)li)@ & \lstinline@unsigned int@& (unsafe) \\1338 \lstinline @-?( (long)li)@ & \lstinline@long@& 0 \\1339 \lstinline @-?( (long unsigned int)li)@ & \lstinline@long unsigned int@& 1 \\1340 \lstinline @-?( (long long int)li)@ & \lstinline@long long int@& 2 \\1341 \lstinline @-?( (long long unsigned int)li)@ & \lstinline@long long unsigned int@& 3 \\1342 \lstinline @-?( (float)li)@ & \lstinline@float@& 4 \\1343 \lstinline @-?( (double)li)@ & \lstinline@double@& 5 \\1344 \lstinline @-?( (long double)li)@ & \lstinline@long double@& 6 \\1345 \lstinline @-?( (_Complex float)li)@ & \lstinline@float@& (unsafe) \\1346 \lstinline @-?( (_Complex double)li)@ & \lstinline@double@& (unsafe) \\1347 \lstinline @-?( (_Complex long double)li)@ & \lstinline@long double@& (unsafe) \\1333 \lstinline$-?( (int)li )$ & \lstinline$int$ & (unsafe) \\ 1334 \lstinline$-?( (unsigned)li)$ & \lstinline$unsigned int$ & (unsafe) \\ 1335 \lstinline$-?( (long)li)$ & \lstinline$long$ & 0 \\ 1336 \lstinline$-?( (long unsigned int)li)$ & \lstinline$long unsigned int$ & 1 \\ 1337 \lstinline$-?( (long long int)li)$ & \lstinline$long long int$ & 2 \\ 1338 \lstinline$-?( (long long unsigned int)li)$ & \lstinline$long long unsigned int$& 3 \\ 1339 \lstinline$-?( (float)li)$ & \lstinline$float$ & 4 \\ 1340 \lstinline$-?( (double)li)$ & \lstinline$double$ & 5 \\ 1341 \lstinline$-?( (long double)li)$ & \lstinline$long double$ & 6 \\ 1342 \lstinline$-?( (_Complex float)li)$ & \lstinline$float$ & (unsafe) \\ 1343 \lstinline$-?( (_Complex double)li)$ & \lstinline$double$ & (unsafe) \\ 1344 \lstinline$-?( (_Complex long double)li)$ & \lstinline$long double$ & (unsafe) \\ 1348 1345 \end{tabular} 1349 1346 \end{center} 1350 The valid interpretations of the \lstinline @eat_double@call, with the cost of the argument conversion and the cost of the entire expression, are1347 The valid interpretations of the \lstinline$eat_double$ call, with the cost of the argument conversion and the cost of the entire expression, are 1351 1348 \begin{center} 1352 1349 \begin{tabular}{lcc} interpretation & argument cost & expression cost \\ 1353 1350 \hline 1354 \lstinline @eat_double( (double)-?( (int)li) )@& 7 & (unsafe) \\1355 \lstinline @eat_double( (double)-?( (unsigned)li) )@& 6 & (unsafe) \\1356 \lstinline @eat_double( (double)-?(li) )@& 5 & \(0+5=5\) \\1357 \lstinline @eat_double( (double)-?( (long unsigned int)li) )@& 4 & \(1+4=5\) \\1358 \lstinline @eat_double( (double)-?( (long long int)li) )@& 3 & \(2+3=5\) \\1359 \lstinline @eat_double( (double)-?( (long long unsigned int)li) )@& 2 & \(3+2=5\) \\1360 \lstinline @eat_double( (double)-?( (float)li) )@& 1 & \(4+1=5\) \\1361 \lstinline @eat_double( (double)-?( (double)li) )@& 0 & \(5+0=5\) \\1362 \lstinline @eat_double( (double)-?( (long double)li) )@& (unsafe) & (unsafe) \\1363 \lstinline @eat_double( (double)-?( (_Complex float)li) )@& (unsafe) & (unsafe) \\1364 \lstinline @eat_double( (double)-?( (_Complex double)li) )@& (unsafe) & (unsafe) \\1365 \lstinline @eat_double( (double)-?( (_Complex long double)li) )@& (unsafe) & (unsafe) \\1351 \lstinline$eat_double( (double)-?( (int)li) )$ & 7 & (unsafe) \\ 1352 \lstinline$eat_double( (double)-?( (unsigned)li) )$ & 6 & (unsafe) \\ 1353 \lstinline$eat_double( (double)-?(li) )$ & 5 & \(0+5=5\) \\ 1354 \lstinline$eat_double( (double)-?( (long unsigned int)li) )$ & 4 & \(1+4=5\) \\ 1355 \lstinline$eat_double( (double)-?( (long long int)li) )$ & 3 & \(2+3=5\) \\ 1356 \lstinline$eat_double( (double)-?( (long long unsigned int)li) )$& 2 & \(3+2=5\) \\ 1357 \lstinline$eat_double( (double)-?( (float)li) )$ & 1 & \(4+1=5\) \\ 1358 \lstinline$eat_double( (double)-?( (double)li) )$ & 0 & \(5+0=5\) \\ 1359 \lstinline$eat_double( (double)-?( (long double)li) )$ & (unsafe) & (unsafe) \\ 1360 \lstinline$eat_double( (double)-?( (_Complex float)li) )$ & (unsafe) & (unsafe) \\ 1361 \lstinline$eat_double( (double)-?( (_Complex double)li) )$ & (unsafe) & (unsafe) \\ 1362 \lstinline$eat_double( (double)-?( (_Complex long double)li) )$ & (unsafe) & (unsafe) \\ 1366 1363 \end{tabular} 1367 1364 \end{center} 1368 Each has result type \lstinline @void@, so the best must be selected.1365 Each has result type \lstinline$void$, so the best must be selected. 1369 1366 The interpretations involving unsafe conversions are discarded. 1370 1367 The remainder have equal expression conversion costs, so the 1371 1368 ``highest argument conversion cost'' rule is invoked, and the chosen interpretation is 1372 \lstinline @eat_double( (double)-?(li) )@.1373 1374 1375 \subsubsection [The sizeof and \_Alignof operators]{The \lstinline@sizeof@ and \lstinline@_Alignof@operators}1369 \lstinline$eat_double( (double)-?(li) )$. 1370 1371 1372 \subsubsection{The \lstinline$sizeof$ and \lstinline$_Alignof$ operators} 1376 1373 1377 1374 \constraints 1378 The operand of \lstinline@sizeof@ or \lstinline@_Alignof@ shall not be \lstinline@type@, \lstinline@dtype@, or \lstinline@ftype@. 1379 1380 When the \lstinline@sizeof@\use{sizeof} operator is applied to an expression, the expression shall have exactly one \Index{interpretation}\index{ambiguous interpretation}, which shall be unambiguous. \semantics A \lstinline@sizeof@ or \lstinline@_Alignof@ expression has one interpretation, of type \lstinline@size_t@. 1381 1382 When \lstinline@sizeof@ is applied to an identifier declared by a \nonterm{type-declaration} or a 1375 The operand of \lstinline$sizeof$ or \lstinline$_Alignof$ shall not be \lstinline$type$, 1376 \lstinline$dtype$, or \lstinline$ftype$. 1377 1378 When the \lstinline$sizeof$\use{sizeof} operator is applied to an expression, the expression shall have exactly one \Index{interpretation}\index{ambiguous interpretation}, which shall be unambiguous. \semantics A \lstinline$sizeof$ or \lstinline$_Alignof$ expression has one interpretation, of type \lstinline$size_t$. 1379 1380 When \lstinline$sizeof$ is applied to an identifier declared by a \nonterm{type-declaration} or a 1383 1381 \nonterm{type-parameter}, it yields the size in bytes of the type that implements the operand. 1384 1382 When the operand is an opaque type or an inferred type parameter\index{inferred parameter}, the expression is not a constant expression. 1385 1383 1386 When \lstinline @_Alignof@is applied to an identifier declared by a \nonterm{type-declaration} or a1384 When \lstinline$_Alignof$ is applied to an identifier declared by a \nonterm{type-declaration} or a 1387 1385 \nonterm{type-parameter}, it yields the alignment requirement of the type that implements the operand. 1388 1386 When the operand is an opaque type or an inferred type parameter\index{inferred parameter}, the expression is not a constant expression. … … 1391 1389 otype Pair = struct { int first, second; }; 1392 1390 size_t p_size = sizeof(Pair); // constant expression 1393 extern otype Rational; §\use{Rational}§1391 extern otype Rational;@\use{Rational}@ 1394 1392 size_t c_size = sizeof(Rational); // non-constant expression 1395 1393 forall(type T) T f(T p1, T p2) { … … 1398 1396 } 1399 1397 \end{lstlisting} 1400 ``\lstinline @sizeof Rational@'', although not statically known, is fixed.1401 Within \lstinline @f()@,1402 ``\lstinline @sizeof(T)@'' is fixed for each call of \lstinline@f()@, but may vary from call to call.1398 ``\lstinline$sizeof Rational$'', although not statically known, is fixed. 1399 Within \lstinline$f()$, 1400 ``\lstinline$sizeof(T)$'' is fixed for each call of \lstinline$f()$, but may vary from call to call. 1403 1401 \end{rationale} 1404 1402 … … 1409 1407 \lhs{cast-expression} 1410 1408 \rhs \nonterm{unary-expression} 1411 \rhs \lstinline @(@ \nonterm{type-name} \lstinline@)@\nonterm{cast-expression}1409 \rhs \lstinline$($ \nonterm{type-name} \lstinline$)$ \nonterm{cast-expression} 1412 1410 \end{syntax} 1413 1411 1414 1412 \constraints 1415 The \nonterm{type-name} in a \nonterm{cast-expression} shall not be \lstinline @type@,1416 \lstinline @dtype@, or \lstinline@ftype@.1413 The \nonterm{type-name} in a \nonterm{cast-expression} shall not be \lstinline$type$, 1414 \lstinline$dtype$, or \lstinline$ftype$. 1417 1415 1418 1416 \semantics 1419 1417 1420 In a \Index{cast expression} ``\lstinline @(@\nonterm{type-name}\lstinline@)e@'', if1421 \nonterm{type-name} is the type of an interpretation of \lstinline @e@, then that interpretation is the only interpretation of the cast expression;1422 otherwise, \lstinline @e@shall have some interpretation that can be converted to \nonterm{type-name}, and the interpretation of the cast expression is the cast of the interpretation that can be converted at the lowest cost.1418 In a \Index{cast expression} ``\lstinline$($\nonterm{type-name}\lstinline$)e$'', if 1419 \nonterm{type-name} is the type of an interpretation of \lstinline$e$, then that interpretation is the only interpretation of the cast expression; 1420 otherwise, \lstinline$e$ shall have some interpretation that can be converted to \nonterm{type-name}, and the interpretation of the cast expression is the cast of the interpretation that can be converted at the lowest cost. 1423 1421 The cast expression's interpretation is ambiguous\index{ambiguous interpretation} if more than one interpretation can be converted at the lowest cost or if the selected interpretation is ambiguous. 1424 1422 … … 1433 1431 \lhs{multiplicative-expression} 1434 1432 \rhs \nonterm{cast-expression} 1435 \rhs \nonterm{multiplicative-expression} \lstinline @*@\nonterm{cast-expression}1436 \rhs \nonterm{multiplicative-expression} \lstinline @/@\nonterm{cast-expression}1437 \rhs \nonterm{multiplicative-expression} \lstinline @%@\nonterm{cast-expression}1433 \rhs \nonterm{multiplicative-expression} \lstinline$*$ \nonterm{cast-expression} 1434 \rhs \nonterm{multiplicative-expression} \lstinline$/$ \nonterm{cast-expression} 1435 \rhs \nonterm{multiplicative-expression} \lstinline$%$ \nonterm{cast-expression} 1438 1436 \end{syntax} 1439 1437 1440 1438 \rewriterules 1441 1439 \begin{lstlisting} 1442 a * b §\rewrite§ ?*?( a, b )§\use{?*?}§1443 a / b §\rewrite§ ?/?( a, b )§\use{?/?}§1444 a % b §\rewrite§ ?%?( a, b )§\use{?%?}§1440 a * b @\rewrite@ ?*?( a, b )@\use{?*?}@ 1441 a / b @\rewrite@ ?/?( a, b )@\use{?/?}@ 1442 a % b @\rewrite@ ?%?( a, b )@\use{?%?}@ 1445 1443 \end{lstlisting} 1446 1444 … … 1469 1467 ?*?( _Complex long double, _Complex long double ), ?/?( _Complex long double, _Complex long double ); 1470 1468 \end{lstlisting} 1471 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1469 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1472 1470 % Don't use predefined: keep this out of prelude.cf. 1473 1471 \begin{lstlisting} … … 1487 1485 int i; 1488 1486 long li; 1489 void eat_double( double ); §\use{eat_double}§1487 void eat_double( double );@\use{eat_double}@ 1490 1488 eat_double( li % i ); 1491 1489 \end{lstlisting} 1492 ``\lstinline @li % i@'' is rewritten as ``\lstinline@?%?(li, i )@''.1493 The valid interpretations of \lstinline @?%?(li, i )@, the cost\index{conversion cost} of converting their arguments, and the cost of converting the result to \lstinline@double@(assuming no extended integer types are present ) are1490 ``\lstinline$li % i$'' is rewritten as ``\lstinline$?%?(li, i )$''. 1491 The valid interpretations of \lstinline$?%?(li, i )$, the cost\index{conversion cost} of converting their arguments, and the cost of converting the result to \lstinline$double$ (assuming no extended integer types are present ) are 1494 1492 \begin{center} 1495 1493 \begin{tabular}{lcc} interpretation & argument cost & result cost \\ 1496 1494 \hline 1497 \lstinline @ ?%?( (int)li, i )@& (unsafe) & 6 \\1498 \lstinline @ ?%?( (unsigned)li,(unsigned)i )@& (unsafe) & 5 \\1499 \lstinline @ ?%?( li, (long)i )@& 1 & 4 \\1500 \lstinline @ ?%?( (long unsigned)li,(long unsigned)i )@& 3 & 3 \\1501 \lstinline @ ?%?( (long long)li,(long long)i )@& 5 & 2 \\1502 \lstinline @ ?%?( (long long unsigned)li, (long long unsigned)i )@& 7 & 1 \\1495 \lstinline$ ?%?( (int)li, i )$ & (unsafe) & 6 \\ 1496 \lstinline$ ?%?( (unsigned)li,(unsigned)i )$ & (unsafe) & 5 \\ 1497 \lstinline$ ?%?( li, (long)i )$ & 1 & 4 \\ 1498 \lstinline$ ?%?( (long unsigned)li,(long unsigned)i )$ & 3 & 3 \\ 1499 \lstinline$ ?%?( (long long)li,(long long)i )$ & 5 & 2 \\ 1500 \lstinline$ ?%?( (long long unsigned)li, (long long unsigned)i )$ & 7 & 1 \\ 1503 1501 \end{tabular} 1504 1502 \end{center} 1505 The best interpretation of \lstinline @eat_double( li, i )@is1506 \lstinline @eat_double( (double)?%?(li, (long)i ))@, which has no unsafe conversions and the lowest total cost.1507 1508 \begin{rationale} 1509 {\c11} defines most arithmetic operations to apply an \Index{integer promotion} to any argument that belongs to a type that has an \Index{integer conversion rank} less than that of \lstinline @int@.If1510 \lstinline @s@ is a \lstinline@short int@, ``\lstinline@s *s@'' does not have type \lstinline@short int@;1511 it is treated as ``\lstinline @( (int)s ) * ( (int)s )@'', and has type \lstinline@int@. \CFA matches that pattern;1512 it does not predefine ``\lstinline @short ?*?( short, short )@''.1503 The best interpretation of \lstinline$eat_double( li, i )$ is 1504 \lstinline$eat_double( (double)?%?(li, (long)i ))$, which has no unsafe conversions and the lowest total cost. 1505 1506 \begin{rationale} 1507 {\c11} defines most arithmetic operations to apply an \Index{integer promotion} to any argument that belongs to a type that has an \Index{integer conversion rank} less than that of \lstinline$int$.If 1508 \lstinline$s$ is a \lstinline$short int$, ``\lstinline$s *s$'' does not have type \lstinline$short int$; 1509 it is treated as ``\lstinline$( (int)s ) * ( (int)s )$'', and has type \lstinline$int$. \CFA matches that pattern; 1510 it does not predefine ``\lstinline$short ?*?( short, short )$''. 1513 1511 1514 1512 These ``missing'' operators limit polymorphism. … … 1519 1517 square( s ); 1520 1518 \end{lstlisting} 1521 Since \CFA does not define a multiplication operator for \lstinline @short int@,1522 \lstinline @square( s )@ is treated as \lstinline@square( (int)s )@, and the result has type1523 \lstinline @int@.1519 Since \CFA does not define a multiplication operator for \lstinline$short int$, 1520 \lstinline$square( s )$ is treated as \lstinline$square( (int)s )$, and the result has type 1521 \lstinline$int$. 1524 1522 This is mildly surprising, but it follows the {\c11} operator pattern. 1525 1523 … … 1531 1529 \end{lstlisting} 1532 1530 This has no valid interpretations, because \CFA has no conversion from ``array of 1533 \lstinline @short int@'' to ``array of \lstinline@int@''.1531 \lstinline$short int$'' to ``array of \lstinline$int$''. 1534 1532 The alternatives in such situations include 1535 1533 \begin{itemize} 1536 1534 \item 1537 Defining monomorphic overloadings of \lstinline @product@ for \lstinline@short@and the other1535 Defining monomorphic overloadings of \lstinline$product$ for \lstinline$short$ and the other 1538 1536 ``small'' types. 1539 1537 \item 1540 Defining ``\lstinline @short ?*?( short, short )@'' within the scope containing the call to1541 \lstinline @product@.1542 \item 1543 Defining \lstinline @product@to take as an argument a conversion function from the ``small'' type to the operator's argument type.1538 Defining ``\lstinline$short ?*?( short, short )$'' within the scope containing the call to 1539 \lstinline$product$. 1540 \item 1541 Defining \lstinline$product$ to take as an argument a conversion function from the ``small'' type to the operator's argument type. 1544 1542 \end{itemize} 1545 1543 \end{rationale} … … 1551 1549 \lhs{additive-expression} 1552 1550 \rhs \nonterm{multiplicative-expression} 1553 \rhs \nonterm{additive-expression} \lstinline @+@\nonterm{multiplicative-expression}1554 \rhs \nonterm{additive-expression} \lstinline @-@\nonterm{multiplicative-expression}1551 \rhs \nonterm{additive-expression} \lstinline$+$ \nonterm{multiplicative-expression} 1552 \rhs \nonterm{additive-expression} \lstinline$-$ \nonterm{multiplicative-expression} 1555 1553 \end{syntax} 1556 1554 1557 1555 \rewriterules 1558 1556 \begin{lstlisting} 1559 a + b §\rewrite§ ?+?( a, b )§\use{?+?}§1560 a - b §\rewrite§ ?-?( a, b )§\use{?-?}§1557 a + b @\rewrite@ ?+?( a, b )@\use{?+?}@ 1558 a - b @\rewrite@ ?-?( a, b )@\use{?-?}@ 1561 1559 \end{lstlisting} 1562 1560 … … 1611 1609 * ?-?( _Atomic const restrict volatile T *, _Atomic const restrict volatile T * ); 1612 1610 \end{lstlisting} 1613 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1611 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1614 1612 % Don't use predefined: keep this out of prelude.cf. 1615 1613 \begin{lstlisting} … … 1621 1619 1622 1620 \begin{rationale} 1623 \lstinline @ptrdiff_t@ is an implementation-defined identifier defined in \lstinline@<stddef.h>@that is synonymous with a signed integral type that is large enough to hold the difference between two pointers.1621 \lstinline$ptrdiff_t$ is an implementation-defined identifier defined in \lstinline$<stddef.h>$ that is synonymous with a signed integral type that is large enough to hold the difference between two pointers. 1624 1622 It seems reasonable to use it for pointer addition as well. (This is technically a difference between \CFA and C, which only specifies that pointer addition uses an \emph{integral} argument.) Hence it is also used for subscripting, which is defined in terms of pointer addition. 1625 The {\c11} standard uses \lstinline @size_t@ in several cases where a library function takes an argument that is used as a subscript, but \lstinline@size_t@is unsuitable here because it is an unsigned type.1623 The {\c11} standard uses \lstinline$size_t$ in several cases where a library function takes an argument that is used as a subscript, but \lstinline$size_t$ is unsuitable here because it is an unsigned type. 1626 1624 \end{rationale} 1627 1625 … … 1632 1630 \lhs{shift-expression} 1633 1631 \rhs \nonterm{additive-expression} 1634 \rhs \nonterm{shift-expression} \lstinline @<<@\nonterm{additive-expression}1635 \rhs \nonterm{shift-expression} \lstinline @>>@\nonterm{additive-expression}1632 \rhs \nonterm{shift-expression} \lstinline$<<$ \nonterm{additive-expression} 1633 \rhs \nonterm{shift-expression} \lstinline$>>$ \nonterm{additive-expression} 1636 1634 \end{syntax} 1637 1635 1638 1636 \rewriterules \use{?>>?}%use{?<<?} 1639 1637 \begin{lstlisting} 1640 a << b §\rewrite§?<<?( a, b )1641 a >> b §\rewrite§?>>?( a, b )1638 a << b @\rewrite@ ?<<?( a, b ) 1639 a >> b @\rewrite@ ?>>?( a, b ) 1642 1640 \end{lstlisting} 1643 1641 … … 1651 1649 long long unsigned int ?<<?( long long unsigned int, int ), ?>>?( long long unsigned int, int); 1652 1650 \end{lstlisting} 1653 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1651 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1654 1652 % Don't use predefined: keep this out of prelude.cf. 1655 1653 \begin{lstlisting} … … 1671 1669 \lhs{relational-expression} 1672 1670 \rhs \nonterm{shift-expression} 1673 \rhs \nonterm{relational-expression} \lstinline @< @\nonterm{shift-expression}1674 \rhs \nonterm{relational-expression} \lstinline @> @\nonterm{shift-expression}1675 \rhs \nonterm{relational-expression} \lstinline @<=@\nonterm{shift-expression}1676 \rhs \nonterm{relational-expression} \lstinline @>=@\nonterm{shift-expression}1671 \rhs \nonterm{relational-expression} \lstinline$< $ \nonterm{shift-expression} 1672 \rhs \nonterm{relational-expression} \lstinline$> $ \nonterm{shift-expression} 1673 \rhs \nonterm{relational-expression} \lstinline$<=$ \nonterm{shift-expression} 1674 \rhs \nonterm{relational-expression} \lstinline$>=$ \nonterm{shift-expression} 1677 1675 \end{syntax} 1678 1676 1679 1677 \rewriterules\use{?>?}\use{?>=?}%use{?<?}%use{?<=?} 1680 1678 \begin{lstlisting} 1681 a < b §\rewrite§?<?( a, b )1682 a > b §\rewrite§?>?( a, b )1683 a <= b §\rewrite§?<=?( a, b )1684 a >= b §\rewrite§?>=?( a, b )1679 a < b @\rewrite@ ?<?( a, b ) 1680 a > b @\rewrite@ ?>?( a, b ) 1681 a <= b @\rewrite@ ?<=?( a, b ) 1682 a >= b @\rewrite@ ?>=?( a, b ) 1685 1683 \end{lstlisting} 1686 1684 … … 1714 1712 ?>=?( _Atomic const restrict volatile DT *, _Atomic const restrict volatile DT * ); 1715 1713 \end{lstlisting} 1716 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1714 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1717 1715 % Don't use predefined: keep this out of prelude.cf. 1718 1716 \begin{lstlisting} … … 1732 1730 \lhs{equality-expression} 1733 1731 \rhs \nonterm{relational-expression} 1734 \rhs \nonterm{equality-expression} \lstinline @==@\nonterm{relational-expression}1735 \rhs \nonterm{equality-expression} \lstinline @!=@\nonterm{relational-expression}1732 \rhs \nonterm{equality-expression} \lstinline$==$ \nonterm{relational-expression} 1733 \rhs \nonterm{equality-expression} \lstinline$!=$ \nonterm{relational-expression} 1736 1734 \end{syntax} 1737 1735 1738 1736 \rewriterules 1739 1737 \begin{lstlisting} 1740 a == b §\rewrite§ ?==?( a, b )§\use{?==?}§1741 a != b §\rewrite§ ?!=?( a, b )§\use{?"!=?}§1738 a == b @\rewrite@ ?==?( a, b )@\use{?==?}@ 1739 a != b @\rewrite@ ?!=?( a, b )@\use{?"!=?}@ 1742 1740 \end{lstlisting} 1743 1741 … … 1792 1790 ?==?( forall( ftype FT2) FT2*, forall( ftype FT3) FT3 * ), ?!=?( forall( ftype FT2) FT2*, forall( ftype FT3) FT3 * ); 1793 1791 \end{lstlisting} 1794 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1792 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1795 1793 % Don't use predefined: keep this out of prelude.cf. 1796 1794 \begin{lstlisting} … … 1800 1798 1801 1799 \begin{rationale} 1802 The polymorphic equality operations come in three styles: comparisons between pointers of compatible types, between pointers to \lstinline @void@and pointers to object types or incomplete types, and between the \Index{null pointer} constant and pointers to any type.1800 The polymorphic equality operations come in three styles: comparisons between pointers of compatible types, between pointers to \lstinline$void$ and pointers to object types or incomplete types, and between the \Index{null pointer} constant and pointers to any type. 1803 1801 In the last case, a special constraint rule for null pointer constant operands has been replaced by a consequence of the \CFA type system. 1804 1802 \end{rationale} … … 1821 1819 \lhs{AND-expression} 1822 1820 \rhs \nonterm{equality-expression} 1823 \rhs \nonterm{AND-expression} \lstinline @&@\nonterm{equality-expression}1821 \rhs \nonterm{AND-expression} \lstinline$&$ \nonterm{equality-expression} 1824 1822 \end{syntax} 1825 1823 1826 1824 \rewriterules 1827 1825 \begin{lstlisting} 1828 a & b §\rewrite§ ?&?( a, b )§\use{?&?}§1826 a & b @\rewrite@ ?&?( a, b )@\use{?&?}@ 1829 1827 \end{lstlisting} 1830 1828 … … 1838 1836 long long unsigned int ?&?( long long unsigned int, long long unsigned int ); 1839 1837 \end{lstlisting} 1840 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1838 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1841 1839 % Don't use predefined: keep this out of prelude.cf. 1842 1840 \begin{lstlisting} … … 1853 1851 \lhs{exclusive-OR-expression} 1854 1852 \rhs \nonterm{AND-expression} 1855 \rhs \nonterm{exclusive-OR-expression} \lstinline @^@\nonterm{AND-expression}1853 \rhs \nonterm{exclusive-OR-expression} \lstinline$^$ \nonterm{AND-expression} 1856 1854 \end{syntax} 1857 1855 1858 1856 \rewriterules 1859 1857 \begin{lstlisting} 1860 a ^ b §\rewrite§ ?^?( a, b )§\use{?^?}§1858 a ^ b @\rewrite@ ?^?( a, b )@\use{?^?}@ 1861 1859 \end{lstlisting} 1862 1860 … … 1870 1868 long long unsigned int ?^?( long long unsigned int, long long unsigned int ); 1871 1869 \end{lstlisting} 1872 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1870 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1873 1871 % Don't use predefined: keep this out of prelude.cf. 1874 1872 \begin{lstlisting} … … 1885 1883 \lhs{inclusive-OR-expression} 1886 1884 \rhs \nonterm{exclusive-OR-expression} 1887 \rhs \nonterm{inclusive-OR-expression} \lstinline @|@\nonterm{exclusive-OR-expression}1885 \rhs \nonterm{inclusive-OR-expression} \lstinline$|$ \nonterm{exclusive-OR-expression} 1888 1886 \end{syntax} 1889 1887 1890 1888 \rewriterules\use{?"|?} 1891 1889 \begin{lstlisting} 1892 a | b §\rewrite§?|?( a, b )1890 a | b @\rewrite@ ?|?( a, b ) 1893 1891 \end{lstlisting} 1894 1892 … … 1902 1900 long long unsigned int ?|?( long long unsigned int, long long unsigned int ); 1903 1901 \end{lstlisting} 1904 For every extended integer type \lstinline @X@ with \Index{integer conversion rank} greater than the rank of \lstinline@int@there exist1902 For every extended integer type \lstinline$X$ with \Index{integer conversion rank} greater than the rank of \lstinline$int$ there exist 1905 1903 % Don't use predefined: keep this out of prelude.cf. 1906 1904 \begin{lstlisting} … … 1917 1915 \lhs{logical-AND-expression} 1918 1916 \rhs \nonterm{inclusive-OR-expression} 1919 \rhs \nonterm{logical-AND-expression} \lstinline @&&@\nonterm{inclusive-OR-expression}1917 \rhs \nonterm{logical-AND-expression} \lstinline$&&$ \nonterm{inclusive-OR-expression} 1920 1918 \end{syntax} 1921 1919 1922 \semantics The operands of the expression ``\lstinline @a && b@'' are treated as1923 ``\lstinline @(int)((a)!=0)@'' and ``\lstinline@(int)((b)!=0)@'', which shall both be unambiguous.1924 The expression has only one interpretation, which is of type \lstinline @int@.1925 \begin{rationale} 1926 When the operands of a logical expression are values of built-in types, and ``\lstinline @!=@'' has not been redefined for those types, the compiler can optimize away the function calls.1927 1928 A common C idiom omits comparisons to \lstinline @0@in the controlling expressions of loops and1929 \lstinline @if@statements.1930 For instance, the loop below iterates as long as \lstinline @rp@ points at a \lstinline@Rational@value that is non-zero.1931 1932 \begin{lstlisting} 1933 extern otype Rational; §\use{Rational}§1934 extern const Rational 0; §\use{0}§1920 \semantics The operands of the expression ``\lstinline$a && b$'' are treated as 1921 ``\lstinline$(int)((a)!=0)$'' and ``\lstinline$(int)((b)!=0)$'', which shall both be unambiguous. 1922 The expression has only one interpretation, which is of type \lstinline$int$. 1923 \begin{rationale} 1924 When the operands of a logical expression are values of built-in types, and ``\lstinline$!=$'' has not been redefined for those types, the compiler can optimize away the function calls. 1925 1926 A common C idiom omits comparisons to \lstinline$0$ in the controlling expressions of loops and 1927 \lstinline$if$ statements. 1928 For instance, the loop below iterates as long as \lstinline$rp$ points at a \lstinline$Rational$ value that is non-zero. 1929 1930 \begin{lstlisting} 1931 extern otype Rational;@\use{Rational}@ 1932 extern const Rational 0;@\use{0}@ 1935 1933 extern int ?!=?( Rational, Rational ); 1936 1934 Rational *rp; 1937 1935 while ( rp && *rp ) { ... } 1938 1936 \end{lstlisting} 1939 The logical expression calls the \lstinline @Rational@ inequality operator, passing it \lstinline@*rp@ and the \lstinline@Rational 0@, and getting a 1 or 0 as a result.1940 In contrast, {\CC} would apply a programmer-defined \lstinline @Rational@-to-\lstinline@int@ conversion to \lstinline@*rp@in the equivalent situation.1941 The conversion to \lstinline @int@would produce a general integer value, which is unfortunate, and possibly dangerous if the conversion was not written with this situation in mind.1937 The logical expression calls the \lstinline$Rational$ inequality operator, passing it \lstinline$*rp$ and the \lstinline$Rational 0$, and getting a 1 or 0 as a result. 1938 In contrast, {\CC} would apply a programmer-defined \lstinline$Rational$-to-\lstinline$int$ conversion to \lstinline$*rp$ in the equivalent situation. 1939 The conversion to \lstinline$int$ would produce a general integer value, which is unfortunate, and possibly dangerous if the conversion was not written with this situation in mind. 1942 1940 \end{rationale} 1943 1941 … … 1948 1946 \lhs{logical-OR-expression} 1949 1947 \rhs \nonterm{logical-AND-expression} 1950 \rhs \nonterm{logical-OR-expression} \lstinline @||@\nonterm{logical-AND-expression}1948 \rhs \nonterm{logical-OR-expression} \lstinline$||$ \nonterm{logical-AND-expression} 1951 1949 \end{syntax} 1952 1950 1953 1951 \semantics 1954 1952 1955 The operands of the expression ``\lstinline @a || b@'' are treated as ``\lstinline@(int)((a)!=0)@'' and ``\lstinline@(int)((b))!=0)@'', which shall both be unambiguous.1956 The expression has only one interpretation, which is of type \lstinline @int@.1953 The operands of the expression ``\lstinline$a || b$'' are treated as ``\lstinline$(int)((a)!=0)$'' and ``\lstinline$(int)((b))!=0)$'', which shall both be unambiguous. 1954 The expression has only one interpretation, which is of type \lstinline$int$. 1957 1955 1958 1956 … … 1962 1960 \lhs{conditional-expression} 1963 1961 \rhs \nonterm{logical-OR-expression} 1964 \rhs \nonterm{logical-OR-expression} \lstinline @?@\nonterm{expression}1965 \lstinline @:@\nonterm{conditional-expression}1962 \rhs \nonterm{logical-OR-expression} \lstinline$?$ \nonterm{expression} 1963 \lstinline$:$ \nonterm{conditional-expression} 1966 1964 \end{syntax} 1967 1965 1968 1966 \semantics 1969 In the conditional expression\use{?:} ``\lstinline @a?b:c@'', if the second and third operands both have an interpretation with \lstinline@void@ type, then the expression has an interpretation with type \lstinline@void@, equivalent to1967 In the conditional expression\use{?:} ``\lstinline$a?b:c$'', if the second and third operands both have an interpretation with \lstinline$void$ type, then the expression has an interpretation with type \lstinline$void$, equivalent to 1970 1968 \begin{lstlisting} 1971 1969 ( int)(( a)!=0) ? ( void)( b) : ( void)( c) 1972 1970 \end{lstlisting} 1973 1971 1974 If the second and third operands both have interpretations with non-\lstinline @void@ types, the expression is treated as if it were the call ``\lstinline@cond((a)!=0, b, c)@'', with \lstinline@cond@declared as1972 If the second and third operands both have interpretations with non-\lstinline$void$ types, the expression is treated as if it were the call ``\lstinline$cond((a)!=0, b, c)$'', with \lstinline$cond$ declared as 1975 1973 \begin{lstlisting} 1976 1974 forall( otype T ) T cond( int, T, T ); … … 2024 2022 rand() ? i : l; 2025 2023 \end{lstlisting} 2026 The best interpretation infers the expression's type to be \lstinline @long@and applies the safe2027 \lstinline @int@-to-\lstinline@long@ conversion to \lstinline@i@.2024 The best interpretation infers the expression's type to be \lstinline$long$ and applies the safe 2025 \lstinline$int$-to-\lstinline$long$ conversion to \lstinline$i$. 2028 2026 2029 2027 \begin{lstlisting} … … 2032 2030 rand() ? cip : vip; 2033 2031 \end{lstlisting} 2034 The expression has type \lstinline @const volatile int *@, with safe conversions applied to the second and third operands to add \lstinline@volatile@ and \lstinline@const@qualifiers, respectively.2032 The expression has type \lstinline$const volatile int *$, with safe conversions applied to the second and third operands to add \lstinline$volatile$ and \lstinline$const$ qualifiers, respectively. 2035 2033 2036 2034 \begin{lstlisting} 2037 2035 rand() ? cip : 0; 2038 2036 \end{lstlisting} 2039 The expression has type \lstinline @const int *@, with a specialization conversion applied to2040 \lstinline @0@.2037 The expression has type \lstinline$const int *$, with a specialization conversion applied to 2038 \lstinline$0$. 2041 2039 2042 2040 … … 2049 2047 \nonterm{assignment-expression} 2050 2048 \lhs{assignment-operator} one of 2051 \rhs \lstinline @=@\ \ \lstinline@*=@\ \ \lstinline@/=@\ \ \lstinline@%=@\ \ \lstinline@+=@\ \ \lstinline@-=@\ \2052 \lstinline @<<=@\ \ \lstinline@>>=@\ \ \lstinline@&=@\ \ \lstinline@^=@\ \ \lstinline@|=@2049 \rhs \lstinline$=$\ \ \lstinline$*=$\ \ \lstinline$/=$\ \ \lstinline$%=$\ \ \lstinline$+=$\ \ \lstinline$-=$\ \ 2050 \lstinline$<<=$\ \ \lstinline$>>=$\ \ \lstinline$&=$\ \ \lstinline$^=$\ \ \lstinline$|=$ 2053 2051 \end{syntax} 2054 2052 … … 2059 2057 \use{?>>=?}\use{?&=?}\use{?^=?}\use{?"|=?}%use{?<<=?} 2060 2058 \begin{lstlisting} 2061 a §$\leftarrow$§ b §\rewrite§ ?§$\leftarrow$§?( &( a ), b )2059 a @$\leftarrow$@ b @\rewrite@ ?@$\leftarrow$@?( &( a ), b ) 2062 2060 \end{lstlisting} 2063 2061 2064 2062 \semantics 2065 2063 Each interpretation of the left operand of an assignment expression is considered separately. 2066 For each interpretation that is a bit-field or is declared with the \lstinline @register@storage class specifier, the expression has one valid interpretation, with the type of the left operand.2064 For each interpretation that is a bit-field or is declared with the \lstinline$register$ storage class specifier, the expression has one valid interpretation, with the type of the left operand. 2067 2065 The right operand is cast to that type, and the assignment expression is ambiguous if either operand is. 2068 2066 For the remaining interpretations, the expression is rewritten, and the interpretations of the assignment expression are the interpretations of the corresponding function call. … … 2297 2295 \end{lstlisting} 2298 2296 \begin{rationale} 2299 The pattern of overloadings for simple assignment resembles that of pointer increment and decrement, except that the polymorphic pointer assignment functions declare a \lstinline @dtype@ parameter, instead of a \lstinline@type@parameter, because the left operand may be a pointer to an incomplete type.2300 \end{rationale} 2301 2302 For every complete structure or union type \lstinline @S@there exist2297 The pattern of overloadings for simple assignment resembles that of pointer increment and decrement, except that the polymorphic pointer assignment functions declare a \lstinline$dtype$ parameter, instead of a \lstinline$type$ parameter, because the left operand may be a pointer to an incomplete type. 2298 \end{rationale} 2299 2300 For every complete structure or union type \lstinline$S$ there exist 2303 2301 % Don't use predefined: keep this out of prelude.cf. 2304 2302 \begin{lstlisting} … … 2306 2304 \end{lstlisting} 2307 2305 2308 For every extended integer type \lstinline @X@there exist2306 For every extended integer type \lstinline$X$ there exist 2309 2307 % Don't use predefined: keep this out of prelude.cf. 2310 2308 \begin{lstlisting} … … 2312 2310 \end{lstlisting} 2313 2311 2314 For every complete enumerated type \lstinline @E@there exist2312 For every complete enumerated type \lstinline$E$ there exist 2315 2313 % Don't use predefined: keep this out of prelude.cf. 2316 2314 \begin{lstlisting} … … 2318 2316 \end{lstlisting} 2319 2317 \begin{rationale} 2320 The right-hand argument is \lstinline @int@ because enumeration constants have type \lstinline@int@.2318 The right-hand argument is \lstinline$int$ because enumeration constants have type \lstinline$int$. 2321 2319 \end{rationale} 2322 2320 … … 2579 2577 \end{lstlisting} 2580 2578 2581 For every extended integer type \lstinline @X@there exist2579 For every extended integer type \lstinline$X$ there exist 2582 2580 % Don't use predefined: keep this out of prelude.cf. 2583 2581 \begin{lstlisting} … … 2594 2592 \end{lstlisting} 2595 2593 2596 For every complete enumerated type \lstinline @E@there exist2594 For every complete enumerated type \lstinline$E$ there exist 2597 2595 % Don't use predefined: keep this out of prelude.cf. 2598 2596 \begin{lstlisting} … … 2615 2613 \lhs{expression} 2616 2614 \rhs \nonterm{assignment-expression} 2617 \rhs \nonterm{expression} \lstinline @,@\nonterm{assignment-expression}2615 \rhs \nonterm{expression} \lstinline$,$ \nonterm{assignment-expression} 2618 2616 \end{syntax} 2619 2617 2620 2618 \semantics 2621 In the comma expression ``\lstinline @a, b@'', the first operand is interpreted as2622 ``\lstinline @( void )(a)@'', which shall be unambiguous\index{ambiguous interpretation}.2619 In the comma expression ``\lstinline$a, b$'', the first operand is interpreted as 2620 ``\lstinline$( void )(a)$'', which shall be unambiguous\index{ambiguous interpretation}. 2623 2621 The interpretations of the expression are the interpretations of the second operand. 2624 2622 … … 2655 2653 { ... } 2656 2654 \end{lstlisting} 2657 Without the rule, \lstinline @Complex@would be a type in the first case, and a parameter name in the second.2655 Without the rule, \lstinline$Complex$ would be a type in the first case, and a parameter name in the second. 2658 2656 \end{rationale} 2659 2657 … … 2681 2679 \examples 2682 2680 \begin{lstlisting} 2683 struct point { §\impl{point}§2681 struct point {@\impl{point}@ 2684 2682 int x, y; 2685 2683 }; 2686 struct color_point { §\impl{color_point}§2684 struct color_point {@\impl{color_point}@ 2687 2685 enum { RED, BLUE, GREEN } color; 2688 2686 struct point; … … 2691 2689 cp.x = 0; 2692 2690 cp.color = RED; 2693 struct literal { §\impl{literal}§2691 struct literal {@\impl{literal}@ 2694 2692 enum { NUMBER, STRING } tag; 2695 2693 union { … … 2712 2710 \begin{syntax} 2713 2711 \lhs{forall-specifier} 2714 \rhs \lstinline @forall@ \lstinline@(@ \nonterm{type-parameter-list} \lstinline@)@2712 \rhs \lstinline$forall$ \lstinline$($ \nonterm{type-parameter-list} \lstinline$)$ 2715 2713 \end{syntax} 2716 2714 … … 2724 2722 } mkPair( T, T ); // illegal 2725 2723 \end{lstlisting} 2726 If an instance of \lstinline @struct Pair@was declared later in the current scope, what would the members' type be?2724 If an instance of \lstinline$struct Pair$ was declared later in the current scope, what would the members' type be? 2727 2725 \end{rationale} 2728 2726 \end{comment} … … 2731 2729 The \nonterm{type-parameter-list}s and assertions of the \nonterm{forall-specifier}s declare type identifiers, function and object identifiers with \Index{no linkage}. 2732 2730 2733 If, in the declaration ``\lstinline @T D@'', \lstinline@T@contains \nonterm{forall-specifier}s and2734 \lstinline @D@has the form2735 \begin{lstlisting} 2736 D( §\normalsize\nonterm{parameter-type-list}§)2737 \end{lstlisting} then a type identifier declared by one of the \nonterm{forall-specifier}s is an \define{inferred parameter} of the function declarator if and only if it is not an inferred parameter of a function declarator in \lstinline @D@, and it is used in the type of a parameter in the following2731 If, in the declaration ``\lstinline$T D$'', \lstinline$T$ contains \nonterm{forall-specifier}s and 2732 \lstinline$D$ has the form 2733 \begin{lstlisting} 2734 D( @\normalsize\nonterm{parameter-type-list}@ ) 2735 \end{lstlisting} then a type identifier declared by one of the \nonterm{forall-specifier}s is an \define{inferred parameter} of the function declarator if and only if it is not an inferred parameter of a function declarator in \lstinline$D$, and it is used in the type of a parameter in the following 2738 2736 \nonterm{type-parameter-list} or it and an inferred parameter are used as arguments of a 2739 2737 \Index{specification} in one of the \nonterm{forall-specifier}s. … … 2746 2744 If this restriction were lifted, it would be possible to write 2747 2745 \begin{lstlisting} 2748 forall( otype T ) T * alloc( void ); §\use{alloc}§int *p = alloc();2749 \end{lstlisting} 2750 Here \lstinline @alloc()@ would receive \lstinline@int@as an inferred argument, and return an2751 \lstinline @int *@.2752 In general, if a call to \lstinline @alloc()@ is a subexpression of an expression involving polymorphic functions and overloaded identifiers, there could be considerable distance between the call and the subexpression that causes \lstinline@T@to be bound.2753 2754 With the current restriction, \lstinline @alloc()@must be given an argument that determines2755 \lstinline @T@:2756 \begin{lstlisting} 2757 forall( otype T ) T * alloc( T initial_value ); §\use{alloc}§2746 forall( otype T ) T * alloc( void );@\use{alloc}@ int *p = alloc(); 2747 \end{lstlisting} 2748 Here \lstinline$alloc()$ would receive \lstinline$int$ as an inferred argument, and return an 2749 \lstinline$int *$. 2750 In general, if a call to \lstinline$alloc()$ is a subexpression of an expression involving polymorphic functions and overloaded identifiers, there could be considerable distance between the call and the subexpression that causes \lstinline$T$ to be bound. 2751 2752 With the current restriction, \lstinline$alloc()$ must be given an argument that determines 2753 \lstinline$T$: 2754 \begin{lstlisting} 2755 forall( otype T ) T * alloc( T initial_value );@\use{alloc}@ 2758 2756 \end{lstlisting} 2759 2757 \end{rationale} … … 2780 2778 forall( otype T ) T fT( T ); 2781 2779 \end{lstlisting} 2782 \lstinline @fi()@ takes an \lstinline@int@ and returns an \lstinline@int@. \lstinline@fT()@takes a2783 \lstinline @T@ and returns a \lstinline@T@, for any type \lstinline@T@.2780 \lstinline$fi()$ takes an \lstinline$int$ and returns an \lstinline$int$. \lstinline$fT()$ takes a 2781 \lstinline$T$ and returns a \lstinline$T$, for any type \lstinline$T$. 2784 2782 \begin{lstlisting} 2785 2783 int (*pfi )( int ) = fi; 2786 2784 forall( otype T ) T (*pfT )( T ) = fT; 2787 2785 \end{lstlisting} 2788 \lstinline @pfi@ and \lstinline@pfT@ are pointers to functions. \lstinline@pfT@is not polymorphic, but the function it points at is.2786 \lstinline$pfi$ and \lstinline$pfT$ are pointers to functions. \lstinline$pfT$ is not polymorphic, but the function it points at is. 2789 2787 \begin{lstlisting} 2790 2788 int (*fvpfi( void ))( int ) { … … 2795 2793 } 2796 2794 \end{lstlisting} 2797 \lstinline @fvpfi()@ and \lstinline@fvpfT()@ are functions taking no arguments and returning pointers to functions. \lstinline@fvpfT()@is monomorphic, but the function that its return value points at is polymorphic.2795 \lstinline$fvpfi()$ and \lstinline$fvpfT()$ are functions taking no arguments and returning pointers to functions. \lstinline$fvpfT()$ is monomorphic, but the function that its return value points at is polymorphic. 2798 2796 \begin{lstlisting} 2799 2797 forall( otype T ) int ( *fTpfi( T ) )( int ); … … 2801 2799 forall( otype T, otype U ) U ( *fTpfU( T ) )( U ); 2802 2800 \end{lstlisting} 2803 \lstinline @fTpfi()@is a polymorphic function that returns a pointer to a monomorphic function taking an integer and returning an integer.2804 It could return \lstinline @pfi@. \lstinline@fTpfT()@is subtle: it is a polymorphic function returning a \emph{monomorphic} function taking and returning2805 \lstinline @T@, where \lstinline@T@ is an inferred parameter of \lstinline@fTpfT()@.2806 For instance, in the expression ``\lstinline @fTpfT(17)@'', \lstinline@T@ is inferred to be \lstinline@int@, and the returned value would have type \lstinline@int ( * )( int )@. ``\lstinline@fTpfT(17)(13)@'' and2807 ``\lstinline @fTpfT("yes")("no")@'' are legal, but ``\lstinline@fTpfT(17)("no")@'' is illegal.2808 \lstinline @fTpfU()@ is polymorphic ( in type \lstinline@T@), and returns a pointer to a function that is polymorphic ( in type \lstinline@U@). ``\lstinline@f5(17)("no")@'' is a legal expression of type2809 \lstinline @char *@.2801 \lstinline$fTpfi()$ is a polymorphic function that returns a pointer to a monomorphic function taking an integer and returning an integer. 2802 It could return \lstinline$pfi$. \lstinline$fTpfT()$ is subtle: it is a polymorphic function returning a \emph{monomorphic} function taking and returning 2803 \lstinline$T$, where \lstinline$T$ is an inferred parameter of \lstinline$fTpfT()$. 2804 For instance, in the expression ``\lstinline$fTpfT(17)$'', \lstinline$T$ is inferred to be \lstinline$int$, and the returned value would have type \lstinline$int ( * )( int )$. ``\lstinline$fTpfT(17)(13)$'' and 2805 ``\lstinline$fTpfT("yes")("no")$'' are legal, but ``\lstinline$fTpfT(17)("no")$'' is illegal. 2806 \lstinline$fTpfU()$ is polymorphic ( in type \lstinline$T$), and returns a pointer to a function that is polymorphic ( in type \lstinline$U$). ``\lstinline$f5(17)("no")$'' is a legal expression of type 2807 \lstinline$char *$. 2810 2808 \begin{lstlisting} 2811 2809 forall( otype T, otype U, otype V ) U * f( T *, U, V * const ); 2812 2810 forall( otype U, otype V, otype W ) U * g( V *, U, W * const ); 2813 2811 \end{lstlisting} 2814 The functions \lstinline @f()@ and \lstinline@g()@have compatible types.2812 The functions \lstinline$f()$ and \lstinline$g()$ have compatible types. 2815 2813 Let \(f\) and \(g\) be their types; 2816 then \(f_1\) = \lstinline @T@, \(f_2\) = \lstinline@U@, \(f_3\) = \lstinline@V@, \(g_1\)2817 = \lstinline @V@, \(g_2\) = \lstinline@U@, and \(g_3\) = \lstinline@W@.2814 then \(f_1\) = \lstinline$T$, \(f_2\) = \lstinline$U$, \(f_3\) = \lstinline$V$, \(g_1\) 2815 = \lstinline$V$, \(g_2\) = \lstinline$U$, and \(g_3\) = \lstinline$W$. 2818 2816 Replacing every \(f_i\) by \(g_i\) in \(f\) gives 2819 2817 \begin{lstlisting} … … 2821 2819 \end{lstlisting} which has a return type and parameter list that is compatible with \(g\). 2822 2820 \begin{rationale} 2823 The word ``\lstinline @type@'' in a forall specifier is redundant at the moment, but I want to leave room for inferred parameters of ordinary types in case parameterized types get added one day.2821 The word ``\lstinline$type$'' in a forall specifier is redundant at the moment, but I want to leave room for inferred parameters of ordinary types in case parameterized types get added one day. 2824 2822 2825 2823 Even without parameterized types, I might try to allow … … 2847 2845 \subsection{Type qualifiers} 2848 2846 2849 \CFA defines a new type qualifier \lstinline @lvalue@\impl{lvalue}\index{lvalue}.2847 \CFA defines a new type qualifier \lstinline$lvalue$\impl{lvalue}\index{lvalue}. 2850 2848 \begin{syntax} 2851 2849 \oldlhs{type-qualifier} 2852 \rhs \lstinline @lvalue@2850 \rhs \lstinline$lvalue$ 2853 2851 \end{syntax} 2854 2852 2855 2853 \constraints 2856 \ Indexc{restrict} Types other than type parameters and pointer types whose referenced type is an object type shall not be restrict-qualified.2854 \lstinline$restrict$\index{register@{\lstinline$restrict$}} Types other than type parameters and pointer types whose referenced type is an object type shall not be restrict-qualified. 2857 2855 2858 2856 \semantics 2859 An object's type may be a restrict-qualified type parameter. 2860 \lstinline@restrict@ does not establish any special semantics in that case. 2857 An object's type may be a restrict-qualified type parameter. \lstinline$restrict$ does not establish any special semantics in that case. 2861 2858 2862 2859 \begin{rationale} … … 2864 2861 \end{rationale} 2865 2862 2866 \lstinline @lvalue@may be used to qualify the return type of a function type.2867 Let \lstinline @T@be an unqualified version of a type;2863 \lstinline$lvalue$ may be used to qualify the return type of a function type. 2864 Let \lstinline$T$ be an unqualified version of a type; 2868 2865 then the result of calling a function with return type 2869 \lstinline @lvalue T@ is a \Index{modifiable lvalue} of type \lstinline@T@.2870 \lstinline @const@\use{const} and \lstinline@volatile@\use{volatile} qualifiers may also be added to indicate that the function result is a constant or volatile lvalue.2871 \begin{rationale} 2872 The \lstinline @const@ and \lstinline@volatile@ qualifiers can only be sensibly used to qualify the return type of a function if the \lstinline@lvalue@qualifier is also used.2866 \lstinline$lvalue T$ is a \Index{modifiable lvalue} of type \lstinline$T$. 2867 \lstinline$const$\use{const} and \lstinline$volatile$\use{volatile} qualifiers may also be added to indicate that the function result is a constant or volatile lvalue. 2868 \begin{rationale} 2869 The \lstinline$const$ and \lstinline$volatile$ qualifiers can only be sensibly used to qualify the return type of a function if the \lstinline$lvalue$ qualifier is also used. 2873 2870 \end{rationale} 2874 2871 … … 2877 2874 2878 2875 \begin{rationale} 2879 \lstinline @lvalue@ provides some of the functionality of {\CC}'s ``\lstinline@T&@'' ( reference to object of type \lstinline@T@) type.2876 \lstinline$lvalue$ provides some of the functionality of {\CC}'s ``\lstinline$T&$'' ( reference to object of type \lstinline$T$) type. 2880 2877 Reference types have four uses in {\CC}. 2881 2878 \begin{itemize} 2882 2879 \item 2883 They are necessary for user-defined operators that return lvalues, such as ``subscript'' and ``dereference''. 2884 2885 \item 2886 A reference can be used to define an alias for a complicated lvalue expression, as a way of getting some of the functionality of the Pascal \lstinline@with@ statement. 2880 They are necessary for user-defined operators that return lvalues, such as ``subscript'' and 2881 ``dereference''. 2882 2883 \item 2884 A reference can be used to define an alias for a complicated lvalue expression, as a way of getting some of the functionality of the Pascal \lstinline$with$ statement. 2887 2885 The following {\CC} code gives an example. 2888 2886 \begin{lstlisting} … … 2897 2895 A reference parameter can be used to allow a function to modify an argument without forcing the caller to pass the address of the argument. 2898 2896 This is most useful for user-defined assignment operators. 2899 In {\CC}, plain assignment is done by a function called ``\lstinline @operator=@'', and the two expressions2897 In {\CC}, plain assignment is done by a function called ``\lstinline$operator=$'', and the two expressions 2900 2898 \begin{lstlisting} 2901 2899 a = b; 2902 2900 operator=( a, b ); 2903 2901 \end{lstlisting} are equivalent. 2904 If \lstinline @a@ and \lstinline@b@ are of type \lstinline@T@, then the first parameter of \lstinline@operator=@ must have type ``\lstinline@T&@''.2902 If \lstinline$a$ and \lstinline$b$ are of type \lstinline$T$, then the first parameter of \lstinline$operator=$ must have type ``\lstinline$T&$''. 2905 2903 It cannot have type 2906 \lstinline @T@, because then assignment couldn't alter the variable, and it can't have type2907 ``\lstinline @T *@'', because the assignment would have to be written ``\lstinline@&a = b;@''.2908 2909 In the case of user-defined operators, this could just as well be handled by using pointer types and by changing the rewrite rules so that ``\lstinline @a = b;@'' is equivalent to2910 ``\lstinline @operator=(&( a), b )@''.2911 Reference parameters of ``normal'' functions are Bad Things, because they remove a useful property of C function calls: an argument can only be modified by a function if it is preceded by ``\lstinline @&@''.2904 \lstinline$T$, because then assignment couldn't alter the variable, and it can't have type 2905 ``\lstinline$T *$'', because the assignment would have to be written ``\lstinline$&a = b;$''. 2906 2907 In the case of user-defined operators, this could just as well be handled by using pointer types and by changing the rewrite rules so that ``\lstinline$a = b;$'' is equivalent to 2908 ``\lstinline$operator=(&( a), b )$''. 2909 Reference parameters of ``normal'' functions are Bad Things, because they remove a useful property of C function calls: an argument can only be modified by a function if it is preceded by ``\lstinline$&$''. 2912 2910 2913 2911 \item 2914 2912 References to \Index{const-qualified} types can be used instead of value parameters. Given the 2915 {\CC} function call ``\lstinline @fiddle( a_thing )@'', where the type of \lstinline@a_thing@is2916 \lstinline @Thing@, the type of \lstinline@fiddle@could be either of2913 {\CC} function call ``\lstinline$fiddle( a_thing )$'', where the type of \lstinline$a_thing$ is 2914 \lstinline$Thing$, the type of \lstinline$fiddle$ could be either of 2917 2915 \begin{lstlisting} 2918 2916 void fiddle( Thing ); 2919 2917 void fiddle( const Thing & ); 2920 2918 \end{lstlisting} 2921 If the second form is used, then constructors and destructors are not invoked to create a temporary variable at the call site ( and it is bad style for the caller to make any assumptions about such things), and within \lstinline @fiddle@the parameter is subject to the usual problems caused by aliases.2922 The reference form might be chosen for efficiency's sake if \lstinline @Thing@s are too large or their constructors or destructors are too expensive.2919 If the second form is used, then constructors and destructors are not invoked to create a temporary variable at the call site ( and it is bad style for the caller to make any assumptions about such things), and within \lstinline$fiddle$ the parameter is subject to the usual problems caused by aliases. 2920 The reference form might be chosen for efficiency's sake if \lstinline$Thing$s are too large or their constructors or destructors are too expensive. 2923 2921 An implementation may switch between them without causing trouble for well-behaved clients. 2924 2922 This leaves the implementor to define ``too large'' and ``too expensive''. … … 2928 2926 void fiddle( const volatile Thing ); 2929 2927 \end{lstlisting} with call-by-reference. 2930 Since it knows all about the size of \lstinline @Thing@s and the parameter passing mechanism, it should be able to come up with a better definition of ``too large'', and may be able to make a good guess at ``too expensive''.2928 Since it knows all about the size of \lstinline$Thing$s and the parameter passing mechanism, it should be able to come up with a better definition of ``too large'', and may be able to make a good guess at ``too expensive''. 2931 2929 \end{itemize} 2932 2930 … … 2948 2946 \begin{syntax} 2949 2947 \lhs{spec-definition} 2950 \rhs \lstinline @spec@\nonterm{identifier}2951 \lstinline @(@ \nonterm{type-parameter-list} \lstinline@)@2952 \lstinline @{@ \nonterm{spec-declaration-list}\opt \lstinline@}@2948 \rhs \lstinline$spec$ \nonterm{identifier} 2949 \lstinline$($ \nonterm{type-parameter-list} \lstinline$)$ 2950 \lstinline${$ \nonterm{spec-declaration-list}\opt \lstinline$}$ 2953 2951 \lhs{spec-declaration-list} 2954 \rhs \nonterm{spec-declaration} \lstinline @;@2955 \rhs \nonterm{spec-declaration-list} \nonterm{spec-declaration} \lstinline @;@2952 \rhs \nonterm{spec-declaration} \lstinline$;$ 2953 \rhs \nonterm{spec-declaration-list} \nonterm{spec-declaration} \lstinline$;$ 2956 2954 \lhs{spec-declaration} 2957 2955 \rhs \nonterm{specifier-qualifier-list} \nonterm{declarator-list} 2958 2956 \lhs{declarator-list} 2959 2957 \rhs \nonterm{declarator} 2960 \rhs \nonterm{declarator-list} \lstinline @,@\nonterm{declarator}2958 \rhs \nonterm{declarator-list} \lstinline$,$ \nonterm{declarator} 2961 2959 \end{syntax} 2962 2960 \begin{rationale} … … 2980 2978 \rhs \nonterm{assertion-list} \nonterm{assertion} 2981 2979 \lhs{assertion} 2982 \rhs \lstinline @|@ \nonterm{identifier} \lstinline@(@ \nonterm{type-name-list} \lstinline@)@2983 \rhs \lstinline @|@\nonterm{spec-declaration}2980 \rhs \lstinline$|$ \nonterm{identifier} \lstinline$($ \nonterm{type-name-list} \lstinline$)$ 2981 \rhs \lstinline$|$ \nonterm{spec-declaration} 2984 2982 \lhs{type-name-list} 2985 2983 \rhs \nonterm{type-name} 2986 \rhs \nonterm{type-name-list} \lstinline @,@\nonterm{type-name}2984 \rhs \nonterm{type-name-list} \lstinline$,$ \nonterm{type-name} 2987 2985 \end{syntax} 2988 2986 … … 2991 2989 The \nonterm{type-name-list} shall contain one \nonterm{type-name} argument for each \nonterm{type-parameter} in that specification's \nonterm{spec-parameter-list}. 2992 2990 If the 2993 \nonterm{type-parameter} uses type-class \lstinline @type@\use{type}, the argument shall be the type name of an \Index{object type};2994 if it uses \lstinline @dtype@, the argument shall be the type name of an object type or an \Index{incomplete type};2995 and if it uses \lstinline @ftype@, the argument shall be the type name of a \Index{function type}.2991 \nonterm{type-parameter} uses type-class \lstinline$type$\use{type}, the argument shall be the type name of an \Index{object type}; 2992 if it uses \lstinline$dtype$, the argument shall be the type name of an object type or an \Index{incomplete type}; 2993 and if it uses \lstinline$ftype$, the argument shall be the type name of a \Index{function type}. 2996 2994 2997 2995 \semantics … … 3006 3004 \examples 3007 3005 \begin{lstlisting} 3008 forall( otype T | T ?*?( T, T )) §\use{?*?}§3009 T square( T val ) { §\impl{square}§3006 forall( otype T | T ?*?( T, T ))@\use{?*?}@ 3007 T square( T val ) {@\impl{square}@ 3010 3008 return val + val; 3011 3009 } 3012 trait summable( otype T ) { §\impl{summable}§3013 T ?+=?( T *, T ); §\use{?+=?}§3014 const T 0; §\use{0}§3010 trait summable( otype T ) {@\impl{summable}@ 3011 T ?+=?( T *, T );@\use{?+=?}@ 3012 const T 0;@\use{0}@ 3015 3013 }; 3016 trait list_of( otype List, otype Element ) { §\impl{list_of}§3014 trait list_of( otype List, otype Element ) {@\impl{list_of}@ 3017 3015 Element car( List ); 3018 3016 List cdr( List ); … … 3023 3021 trait sum_list( otype List, otype Element | summable( Element ) | list_of( List, Element ) ) {}; 3024 3022 \end{lstlisting} 3025 \lstinline @sum_list@contains seven declarations, which describe a list whose elements can be added up.3026 The assertion ``\lstinline @|sum_list( i_list, int )@''\use{sum_list} produces the assertion parameters3023 \lstinline$sum_list$ contains seven declarations, which describe a list whose elements can be added up. 3024 The assertion ``\lstinline$|sum_list( i_list, int )$''\use{sum_list} produces the assertion parameters 3027 3025 \begin{lstlisting} 3028 3026 int ?+=?( int *, int ); … … 3041 3039 \lhs{type-parameter-list} 3042 3040 \rhs \nonterm{type-parameter} 3043 \rhs \nonterm{type-parameter-list} \lstinline @,@\nonterm{type-parameter}3041 \rhs \nonterm{type-parameter-list} \lstinline$,$ \nonterm{type-parameter} 3044 3042 \lhs{type-parameter} 3045 3043 \rhs \nonterm{type-class} \nonterm{identifier} \nonterm{assertion-list}\opt 3046 3044 \lhs{type-class} 3047 \rhs \lstinline @type@3048 \rhs \lstinline @dtype@3049 \rhs \lstinline @ftype@3045 \rhs \lstinline$type$ 3046 \rhs \lstinline$dtype$ 3047 \rhs \lstinline$ftype$ 3050 3048 \lhs{type-declaration} 3051 \rhs \nonterm{storage-class-specifier}\opt \lstinline @type@\nonterm{type-declarator-list} \verb|;|3049 \rhs \nonterm{storage-class-specifier}\opt \lstinline$type$ \nonterm{type-declarator-list} \verb|;| 3052 3050 \lhs{type-declarator-list} 3053 3051 \rhs \nonterm{type-declarator} 3054 \rhs \nonterm{type-declarator-list} \lstinline @,@\nonterm{type-declarator}3052 \rhs \nonterm{type-declarator-list} \lstinline$,$ \nonterm{type-declarator} 3055 3053 \lhs{type-declarator} 3056 \rhs \nonterm{identifier} \nonterm{assertion-list}\opt \lstinline @=@\nonterm{type-name}3054 \rhs \nonterm{identifier} \nonterm{assertion-list}\opt \lstinline$=$ \nonterm{type-name} 3057 3055 \rhs \nonterm{identifier} \nonterm{assertion-list}\opt 3058 3056 \end{syntax} … … 3065 3063 3066 3064 An identifier declared by a \nonterm{type-parameter} has \Index{no linkage}. 3067 Identifiers declared with type-class \lstinline @type@\use{type} are \Index{object type}s;3065 Identifiers declared with type-class \lstinline$type$\use{type} are \Index{object type}s; 3068 3066 those declared with type-class 3069 \lstinline @dtype@\use{dtype} are \Index{incomplete type}s;3067 \lstinline$dtype$\use{dtype} are \Index{incomplete type}s; 3070 3068 and those declared with type-class 3071 \lstinline @ftype@\use{ftype} are \Index{function type}s.3069 \lstinline$ftype$\use{ftype} are \Index{function type}s. 3072 3070 The identifier has \Index{block scope} that terminates at the end of the \nonterm{spec-declaration-list} or polymorphic function that contains the \nonterm{type-parameter}. 3073 3071 … … 3077 3075 Within the scope of the declaration, \Index{implicit conversion}s can be performed between the defined type and the implementation type, and between pointers to the defined type and pointers to the implementation type. 3078 3076 3079 A type declaration without an \Index{initializer} and without a \Index{storage-class specifier} or with storage-class specifier \lstinline @static@\use{static} defines an \Index{incomplete type}.3077 A type declaration without an \Index{initializer} and without a \Index{storage-class specifier} or with storage-class specifier \lstinline$static$\use{static} defines an \Index{incomplete type}. 3080 3078 If a 3081 3079 \Index{translation unit} or \Index{block} contains one or more such declarations for an identifier, it must contain exactly one definition of the identifier ( but not in an enclosed block, which would define a new type known only within that block). … … 3097 3095 3098 3096 A type declaration without an initializer and with \Index{storage-class specifier} 3099 \lstinline @extern@\use{extern} is an \define{opaque type declaration}.3097 \lstinline$extern$\use{extern} is an \define{opaque type declaration}. 3100 3098 Opaque types are 3101 3099 \Index{object type}s. … … 3112 3110 \end{rationale} 3113 3111 3114 An \Index{incomplete type} which is not a qualified version\index{qualified type} of a type is a value of \Index{type-class} \lstinline @dtype@.3115 An object type\index{object types} which is not a qualified version of a type is a value of type-classes \lstinline @type@ and \lstinline@dtype@.3112 An \Index{incomplete type} which is not a qualified version\index{qualified type} of a type is a value of \Index{type-class} \lstinline$dtype$. 3113 An object type\index{object types} which is not a qualified version of a type is a value of type-classes \lstinline$type$ and \lstinline$dtype$. 3116 3114 A 3117 \Index{function type} is a value of type-class \lstinline @ftype@.3115 \Index{function type} is a value of type-class \lstinline$ftype$. 3118 3116 \begin{rationale} 3119 3117 Syntactically, a type value is a \nonterm{type-name}, which is a declaration for an object which omits the identifier being declared. … … 3125 3123 Type qualifiers are a weak point of C's type system. 3126 3124 Consider the standard library function 3127 \lstinline @strchr()@which, given a string and a character, returns a pointer to the first occurrence of the character in the string.3128 \begin{lstlisting} 3129 char *strchr( const char *s, int c ) { §\impl{strchr}§3125 \lstinline$strchr()$ which, given a string and a character, returns a pointer to the first occurrence of the character in the string. 3126 \begin{lstlisting} 3127 char *strchr( const char *s, int c ) {@\impl{strchr}@ 3130 3128 char real_c = c; // done because c was declared as int. 3131 3129 for ( ; *s != real_c; s++ ) … … 3134 3132 } 3135 3133 \end{lstlisting} 3136 The parameter \lstinline @s@ must be \lstinline@const char *@, because \lstinline@strchr()@ might be used to search a constant string, but the return type must be \lstinline@char *@, because the result might be used to modify a non-constant string.3134 The parameter \lstinline$s$ must be \lstinline$const char *$, because \lstinline$strchr()$ might be used to search a constant string, but the return type must be \lstinline$char *$, because the result might be used to modify a non-constant string. 3137 3135 Hence the body must perform a cast, and ( even worse) 3138 \lstinline @strchr()@provides a type-safe way to attempt to modify constant strings.3139 What is needed is some way to say that \lstinline @s@'s type might contain qualifiers, and the result type has exactly the same qualifiers.3136 \lstinline$strchr()$ provides a type-safe way to attempt to modify constant strings. 3137 What is needed is some way to say that \lstinline$s$'s type might contain qualifiers, and the result type has exactly the same qualifiers. 3140 3138 Polymorphic functions do not provide a fix for this deficiency\index{deficiencies!pointers to qualified types}, because type qualifiers are not part of type values. 3141 Instead, overloading can be used to define \lstinline @strchr()@for each combination of qualifiers.3139 Instead, overloading can be used to define \lstinline$strchr()$ for each combination of qualifiers. 3142 3140 \end{rationale} 3143 3141 … … 3164 3162 \end{lstlisting} 3165 3163 Without this restriction, \CFA might require ``module initialization'' code ( since 3166 \lstinline @Rational@ has external linkage, it must be created before any other translation unit instantiates it), and would force an ordering on the initialization of the translation unit that defines \lstinline@Huge@ and the translation that declares \lstinline@Rational@.3164 \lstinline$Rational$ has external linkage, it must be created before any other translation unit instantiates it), and would force an ordering on the initialization of the translation unit that defines \lstinline$Huge$ and the translation that declares \lstinline$Rational$. 3167 3165 3168 3166 A benefit of the restriction is that it prevents the declaration in separate translation units of types that contain each other, which would be hard to prevent otherwise. … … 3181 3179 \nonterm{struct-declaration}, type declarations can not be structure members. 3182 3180 The form of 3183 \nonterm{type-declaration} forbids arrays of, pointers to, and functions returning \lstinline @type@.3181 \nonterm{type-declaration} forbids arrays of, pointers to, and functions returning \lstinline$type$. 3184 3182 Hence the syntax of \nonterm{type-specifier} does not have to be extended to allow type-valued expressions. 3185 3183 It also side-steps the problem of type-valued expressions producing different values in different declarations. … … 3196 3194 #include <stdlib.h> 3197 3195 T * new( otype T ) { return ( T * )malloc( sizeof( T) ); }; 3198 §\ldots§int * ip = new( int );3199 \end{lstlisting} 3200 This looks sensible, but \CFA's declaration-before-use rules mean that ``\lstinline @T@'' in the function body refers to the parameter, but the ``\lstinline@T@'' in the return type refers to the meaning of \lstinline@T@ in the scope that contains \lstinline@new@;3196 @\ldots@ int * ip = new( int ); 3197 \end{lstlisting} 3198 This looks sensible, but \CFA's declaration-before-use rules mean that ``\lstinline$T$'' in the function body refers to the parameter, but the ``\lstinline$T$'' in the return type refers to the meaning of \lstinline$T$ in the scope that contains \lstinline$new$; 3201 3199 it could be undefined, or a type name, or a function or variable name. 3202 3200 Nothing good can result from such a situation. … … 3215 3213 f2( v2 ); 3216 3214 \end{lstlisting} 3217 \lstinline @V1@ is passed by value, so \lstinline@f1()@'s assignment to \lstinline@a[0]@ does not modify v1. \lstinline@V2@ is converted to a pointer, so \lstinline@f2()@ modifies \lstinline@v2[0]@.3215 \lstinline$V1$ is passed by value, so \lstinline$f1()$'s assignment to \lstinline$a[0]$ does not modify v1. \lstinline$V2$ is converted to a pointer, so \lstinline$f2()$ modifies \lstinline$v2[0]$. 3218 3216 3219 3217 A translation unit containing the declarations 3220 3218 \begin{lstlisting} 3221 extern type Complex; §\use{Complex}§// opaque type declaration3222 extern float abs( Complex ); §\use{abs}§3223 \end{lstlisting} can contain declarations of complex numbers, which can be passed to \lstinline @abs@.3224 Some other translation unit must implement \lstinline @Complex@ and \lstinline@abs@.3219 extern type Complex;@\use{Complex}@ // opaque type declaration 3220 extern float abs( Complex );@\use{abs}@ 3221 \end{lstlisting} can contain declarations of complex numbers, which can be passed to \lstinline$abs$. 3222 Some other translation unit must implement \lstinline$Complex$ and \lstinline$abs$. 3225 3223 That unit might contain the declarations 3226 3224 \begin{lstlisting} 3227 otype Complex = struct { float re, im; }; §\impl{Complex}§3228 Complex cplx_i = { 0.0, 1.0 }; §\impl{cplx_i}§3229 float abs( Complex c ) { §\impl{abs( Complex )}§3225 otype Complex = struct { float re, im; };@\impl{Complex}@ 3226 Complex cplx_i = { 0.0, 1.0 };@\impl{cplx_i}@ 3227 float abs( Complex c ) {@\impl{abs( Complex )}@ 3230 3228 return sqrt( c.re * c.re + c.im * c.im ); 3231 3229 } 3232 3230 \end{lstlisting} 3233 Note that \lstinline @c@ is implicitly converted to a \lstinline@struct@so that its components can be retrieved.3234 3235 \begin{lstlisting} 3236 otype Time_of_day = int; §\impl{Time_of_day}§// seconds since midnight.3237 Time_of_day ?+?( Time_of_day t1, int seconds ) { §\impl{?+?}§3231 Note that \lstinline$c$ is implicitly converted to a \lstinline$struct$ so that its components can be retrieved. 3232 3233 \begin{lstlisting} 3234 otype Time_of_day = int;@\impl{Time_of_day}@ // seconds since midnight. 3235 Time_of_day ?+?( Time_of_day t1, int seconds ) {@\impl{?+?}@ 3238 3236 return (( int)t1 + seconds ) % 86400; 3239 3237 } 3240 3238 \end{lstlisting} 3241 \lstinline @t1@must be cast to its implementation type to prevent infinite recursion.3239 \lstinline$t1$ must be cast to its implementation type to prevent infinite recursion. 3242 3240 3243 3241 \begin{rationale} 3244 3242 Within the scope of a type definition, an instance of the type can be viewed as having that type or as having the implementation type. 3245 In the \lstinline @Time_of_day@example, the difference is important.3243 In the \lstinline$Time_of_day$ example, the difference is important. 3246 3244 Different languages have treated the distinction between the abstraction and the implementation in different ways. 3247 3245 \begin{itemize} 3248 3246 \item 3249 3247 Inside a Clu cluster \cite{CLU}, the declaration of an instance states which view applies. 3250 Two primitives called \lstinline @up@ and \lstinline@down@can be used to convert between the views.3248 Two primitives called \lstinline$up$ and \lstinline$down$ can be used to convert between the views. 3251 3249 \item 3252 3250 The Simula class \cite{SIMULA87} is essentially a record type. 3253 3251 Since the only operations on a record are member selection and assignment, which can not be overloaded, there is never any ambiguity as to whether the abstraction or the implementation view is being used. 3254 3252 In {\CC} 3255 \cite{C++}, operations on class instances include assignment and ``\lstinline @&@'', which can be overloaded.3253 \cite{C++}, operations on class instances include assignment and ``\lstinline$&$'', which can be overloaded. 3256 3254 A ``scope resolution'' operator can be used inside the class to specify whether the abstract or implementation version of the operation should be used. 3257 3255 \item … … 3266 3264 In this case, explicit conversions between the derived type and the old type can be used. 3267 3265 \end{itemize} 3268 \CFA's rules are like Clu's, except that implicit conversions and conversion costs allow it to do away with most uses of \lstinline @up@ and \lstinline@down@.3266 \CFA's rules are like Clu's, except that implicit conversions and conversion costs allow it to do away with most uses of \lstinline$up$ and \lstinline$down$. 3269 3267 \end{rationale} 3270 3268 … … 3272 3270 \subsubsection{Default functions and objects} 3273 3271 3274 A declaration\index{type declaration} of a type identifier \lstinline @T@with type-class3275 \lstinline @type@implicitly declares a \define{default assignment} function3276 \lstinline @T ?=?( T *, T )@\use{?=?}, with the same \Index{scope} and \Index{linkage} as the identifier \lstinline@T@.3272 A declaration\index{type declaration} of a type identifier \lstinline$T$ with type-class 3273 \lstinline$type$ implicitly declares a \define{default assignment} function 3274 \lstinline$T ?=?( T *, T )$\use{?=?}, with the same \Index{scope} and \Index{linkage} as the identifier \lstinline$T$. 3277 3275 \begin{rationale} 3278 3276 Assignment is central to C's imperative programming style, and every existing C object type has assignment defined for it ( except for array types, which are treated as pointer types for purposes of assignment). 3279 3277 Without this rule, nearly every inferred type parameter would need an accompanying assignment assertion parameter. 3280 3278 If a type parameter should not have an assignment operation, 3281 \lstinline @dtype@should be used.3279 \lstinline$dtype$ should be used. 3282 3280 If a type should not have assignment defined, the user can define an assignment function that causes a run-time error, or provide an external declaration but no definition and thus cause a link-time error. 3283 3281 \end{rationale} 3284 3282 3285 A definition\index{type definition} of a type identifier \lstinline @T@ with \Index{implementation type} \lstinline@I@ and type-class \lstinline@type@implicitly defines a default assignment function.3286 A definition\index{type definition} of a type identifier \lstinline @T@ with implementation type \lstinline@I@and an assertion list implicitly defines \define{default function}s and3283 A definition\index{type definition} of a type identifier \lstinline$T$ with \Index{implementation type} \lstinline$I$ and type-class \lstinline$type$ implicitly defines a default assignment function. 3284 A definition\index{type definition} of a type identifier \lstinline$T$ with implementation type \lstinline$I$ and an assertion list implicitly defines \define{default function}s and 3287 3285 \define{default object}s as declared by the assertion declarations. 3288 The default objects and functions have the same \Index{scope} and \Index{linkage} as the identifier \lstinline @T@.3286 The default objects and functions have the same \Index{scope} and \Index{linkage} as the identifier \lstinline$T$. 3289 3287 Their values are determined as follows: 3290 3288 \begin{itemize} 3291 3289 \item 3292 If at the definition of \lstinline @T@ there is visible a declaration of an object with the same name as the default object, and if the type of that object with all occurrence of \lstinline@I@ replaced by \lstinline@T@is compatible with the type of the default object, then the default object is initialized with that object.3293 Otherwise the scope of the declaration of \lstinline @T@must contain a definition of the default object.3290 If at the definition of \lstinline$T$ there is visible a declaration of an object with the same name as the default object, and if the type of that object with all occurrence of \lstinline$I$ replaced by \lstinline$T$ is compatible with the type of the default object, then the default object is initialized with that object. 3291 Otherwise the scope of the declaration of \lstinline$T$ must contain a definition of the default object. 3294 3292 3295 3293 \item 3296 If at the definition of \lstinline @T@ there is visible a declaration of a function with the same name as the default function, and if the type of that function with all occurrence of \lstinline@I@ replaced by \lstinline@T@is compatible with the type of the default function, then the default function calls that function after converting its arguments and returns the converted result.3297 3298 Otherwise, if \lstinline @I@ contains exactly one anonymous member\index{anonymous member} such that at the definition of \lstinline@T@ there is visible a declaration of a function with the same name as the default function, and the type of that function with all occurrences of the anonymous member's type in its parameter list replaced by \lstinline@T@is compatible with the type of the default function, then the default function calls that function after converting its arguments and returns the result.3299 3300 Otherwise the scope of the declaration of \lstinline @T@must contain a definition of the default function.3294 If at the definition of \lstinline$T$ there is visible a declaration of a function with the same name as the default function, and if the type of that function with all occurrence of \lstinline$I$ replaced by \lstinline$T$ is compatible with the type of the default function, then the default function calls that function after converting its arguments and returns the converted result. 3295 3296 Otherwise, if \lstinline$I$ contains exactly one anonymous member\index{anonymous member} such that at the definition of \lstinline$T$ there is visible a declaration of a function with the same name as the default function, and the type of that function with all occurrences of the anonymous member's type in its parameter list replaced by \lstinline$T$ is compatible with the type of the default function, then the default function calls that function after converting its arguments and returns the result. 3297 3298 Otherwise the scope of the declaration of \lstinline$T$ must contain a definition of the default function. 3301 3299 \end{itemize} 3302 3300 \begin{rationale} … … 3304 3302 \end{rationale} 3305 3303 3306 A function or object with the same type and name as a default function or object that is declared within the scope of the definition of \lstinline @T@replaces the default function or object.3304 A function or object with the same type and name as a default function or object that is declared within the scope of the definition of \lstinline$T$ replaces the default function or object. 3307 3305 3308 3306 \examples … … 3314 3312 Pair b = { 1, 1 }; 3315 3313 \end{lstlisting} 3316 The definition of \lstinline @Pair@ implicitly defines two objects \lstinline@a@ and \lstinline@b@.3317 \lstinline @Pair a@ inherits its value from the \lstinline@struct impl a@.3314 The definition of \lstinline$Pair$ implicitly defines two objects \lstinline$a$ and \lstinline$b$. 3315 \lstinline$Pair a$ inherits its value from the \lstinline$struct impl a$. 3318 3316 The definition of 3319 \lstinline @Pair b@ is compulsory because there is no \lstinline@struct impl b@to construct a value from.3317 \lstinline$Pair b$ is compulsory because there is no \lstinline$struct impl b$ to construct a value from. 3320 3318 \begin{lstlisting} 3321 3319 trait ss( otype T ) { … … 3323 3321 void munge( T * ); 3324 3322 } 3325 otype Whatsit | ss( Whatsit ); §\use{Whatsit}§3326 otype Doodad | ss( Doodad ) = struct doodad { §\use{Doodad}§3323 otype Whatsit | ss( Whatsit );@\use{Whatsit}@ 3324 otype Doodad | ss( Doodad ) = struct doodad {@\use{Doodad}@ 3327 3325 Whatsit; // anonymous member 3328 3326 int extra; … … 3330 3328 Doodad clone( Doodad ) { ... } 3331 3329 \end{lstlisting} 3332 The definition of \lstinline @Doodad@implicitly defines three functions:3330 The definition of \lstinline$Doodad$ implicitly defines three functions: 3333 3331 \begin{lstlisting} 3334 3332 Doodad ?=?( Doodad *, Doodad ); … … 3336 3334 void munge( Doodad * ); 3337 3335 \end{lstlisting} 3338 The assignment function inherits \lstinline @struct doodad@'s assignment function because the types match when \lstinline@struct doodad@ is replaced by \lstinline@Doodad@throughout.3339 \lstinline @munge()@ inherits \lstinline@Whatsit@'s \lstinline@munge()@because the types match when3340 \lstinline @Whatsit@ is replaced by \lstinline@Doodad@ in the parameter list. \lstinline@clone()@ does \emph{not} inherit \lstinline@Whatsit@'s \lstinline@clone()@: replacement in the parameter list yields ``\lstinline@Whatsit clone( Doodad )@'', which is not compatible with3341 \lstinline @Doodad@'s \lstinline@clone()@'s type.3336 The assignment function inherits \lstinline$struct doodad$'s assignment function because the types match when \lstinline$struct doodad$ is replaced by \lstinline$Doodad$ throughout. 3337 \lstinline$munge()$ inherits \lstinline$Whatsit$'s \lstinline$munge()$ because the types match when 3338 \lstinline$Whatsit$ is replaced by \lstinline$Doodad$ in the parameter list. \lstinline$clone()$ does \emph{not} inherit \lstinline$Whatsit$'s \lstinline$clone()$: replacement in the parameter list yields ``\lstinline$Whatsit clone( Doodad )$'', which is not compatible with 3339 \lstinline$Doodad$'s \lstinline$clone()$'s type. 3342 3340 Hence the definition of 3343 ``\lstinline @Doodad clone( Doodad )@'' is necessary.3341 ``\lstinline$Doodad clone( Doodad )$'' is necessary. 3344 3342 3345 3343 Default functions and objects are subject to the normal scope rules. 3346 3344 \begin{lstlisting} 3347 otype T = §\ldots§;3348 T a_T = §\ldots§; // Default assignment used.3345 otype T = @\ldots@; 3346 T a_T = @\ldots@; // Default assignment used. 3349 3347 T ?=?( T *, T ); 3350 T a_T = §\ldots§; // Programmer-defined assignment called.3348 T a_T = @\ldots@; // Programmer-defined assignment called. 3351 3349 \end{lstlisting} 3352 3350 \begin{rationale} … … 3381 3379 \begin{syntax} 3382 3380 \oldlhs{labeled-statement} 3383 \rhs \lstinline @case@\nonterm{case-value-list} : \nonterm{statement}3381 \rhs \lstinline$case$ \nonterm{case-value-list} : \nonterm{statement} 3384 3382 \lhs{case-value-list} 3385 3383 \rhs \nonterm{case-value} 3386 \rhs \nonterm{case-value-list} \lstinline @,@\nonterm{case-value}3384 \rhs \nonterm{case-value-list} \lstinline$,$ \nonterm{case-value} 3387 3385 \lhs{case-value} 3388 3386 \rhs \nonterm{constant-expression} 3389 3387 \rhs \nonterm{subrange} 3390 3388 \lhs{subrange} 3391 \rhs \nonterm{constant-expression} \lstinline @~@\nonterm{constant-expression}3389 \rhs \nonterm{constant-expression} \lstinline$~$ \nonterm{constant-expression} 3392 3390 \end{syntax} 3393 3391 … … 3402 3400 case 1~4, 9~14, 27~32: 3403 3401 \end{lstlisting} 3404 The \lstinline @case@ and \lstinline@default@ clauses are restricted within the \lstinline@switch@ and \lstinline@choose@statements, precluding Duff's device.3402 The \lstinline$case$ and \lstinline$default$ clauses are restricted within the \lstinline$switch$ and \lstinline$choose$ statements, precluding Duff's device. 3405 3403 3406 3404 3407 3405 \subsection{Expression and null statements} 3408 3406 3409 The expression in an expression statement is treated as being cast to \lstinline @void@.3407 The expression in an expression statement is treated as being cast to \lstinline$void$. 3410 3408 3411 3409 … … 3414 3412 \begin{syntax} 3415 3413 \oldlhs{selection-statement} 3416 \rhs \lstinline @choose@ \lstinline@(@ \nonterm{expression} \lstinline@)@\nonterm{statement}3414 \rhs \lstinline$choose$ \lstinline$($ \nonterm{expression} \lstinline$)$ \nonterm{statement} 3417 3415 \end{syntax} 3418 3416 3419 The controlling expression \lstinline @E@ in the \lstinline@switch@ and \lstinline@choose@statement:3417 The controlling expression \lstinline$E$ in the \lstinline$switch$ and \lstinline$choose$ statement: 3420 3418 \begin{lstlisting} 3421 3419 switch ( E ) ... … … 3423 3421 \end{lstlisting} may have more than one interpretation, but it shall have only one interpretation with an integral type. 3424 3422 An \Index{integer promotion} is performed on the expression if necessary. 3425 The constant expressions in \lstinline @case@statements with the switch are converted to the promoted type.3423 The constant expressions in \lstinline$case$ statements with the switch are converted to the promoted type. 3426 3424 3427 3425 3428 3426 \setcounter{subsubsection}{3} 3429 \subsubsection [The choose statement]{The \lstinline@choose@statement}3430 3431 The \lstinline @choose@ statement is the same as the \lstinline@switch@ statement except control transfers to the end of the \lstinline@choose@ statement at a \lstinline@case@ or \lstinline@default@labeled statement.3432 The \lstinline @fallthru@ statement is used to fall through to the next \lstinline@case@ or \lstinline@default@labeled statement.3427 \subsubsection{The \lstinline$choose$ statement} 3428 3429 The \lstinline$choose$ statement is the same as the \lstinline$switch$ statement except control transfers to the end of the \lstinline$choose$ statement at a \lstinline$case$ or \lstinline$default$ labeled statement. 3430 The \lstinline$fallthru$ statement is used to fall through to the next \lstinline$case$ or \lstinline$default$ labeled statement. 3433 3431 The following have identical meaning: 3434 3432 \begin{flushleft} … … 3455 3453 \end{tabular} 3456 3454 \end{flushleft} 3457 The \lstinline @choose@ statement addresses the problem of accidental fall-through associated with the \lstinline@switch@statement.3455 The \lstinline$choose$ statement addresses the problem of accidental fall-through associated with the \lstinline$switch$ statement. 3458 3456 3459 3457 3460 3458 \subsection{Iteration statements} 3461 3459 3462 The controlling expression \lstinline @E@in the loops3460 The controlling expression \lstinline$E$ in the loops 3463 3461 \begin{lstlisting} 3464 3462 if ( E ) ... 3465 3463 while ( E ) ... 3466 3464 do ... while ( E ); 3467 \end{lstlisting} is treated as ``\lstinline @( int )((E)!=0)@''.3465 \end{lstlisting} is treated as ``\lstinline$( int )((E)!=0)$''. 3468 3466 3469 3467 The statement 3470 3468 \begin{lstlisting} 3471 for ( a; b; c ) §\ldots§3469 for ( a; b; c ) @\ldots@ 3472 3470 \end{lstlisting} is treated as 3473 3471 \begin{lstlisting} … … 3480 3478 \begin{syntax} 3481 3479 \oldlhs{jump-statement} 3482 \rhs \lstinline @continue@\nonterm{identifier}\opt3483 \rhs \lstinline @break@\nonterm{identifier}\opt3480 \rhs \lstinline$continue$ \nonterm{identifier}\opt 3481 \rhs \lstinline$break$ \nonterm{identifier}\opt 3484 3482 \rhs \ldots 3485 \rhs \lstinline @throw@\nonterm{assignment-expression}\opt3486 \rhs \lstinline @throwResume@\nonterm{assignment-expression}\opt \nonterm{at-expression}\opt3487 \lhs{at-expression} \lstinline @_At@\nonterm{assignment-expression}3483 \rhs \lstinline$throw$ \nonterm{assignment-expression}\opt 3484 \rhs \lstinline$throwResume$ \nonterm{assignment-expression}\opt \nonterm{at-expression}\opt 3485 \lhs{at-expression} \lstinline$_At$ \nonterm{assignment-expression} 3488 3486 \end{syntax} 3489 3487 3490 Labeled \lstinline @continue@ and \lstinline@break@ allow useful but restricted control-flow that reduces the need for the \lstinline@goto@statement for exiting multiple nested control-structures.3488 Labeled \lstinline$continue$ and \lstinline$break$ allow useful but restricted control-flow that reduces the need for the \lstinline$goto$ statement for exiting multiple nested control-structures. 3491 3489 \begin{lstlisting} 3492 3490 L1: { // compound … … 3515 3513 3516 3514 \setcounter{subsubsection}{1} 3517 \subsubsection [The continue statement]{The \lstinline@continue@statement}3518 3519 The identifier in a \lstinline @continue@statement shall name a label located on an enclosing iteration statement.3520 3521 3522 \subsubsection [The break statement]{The \lstinline@break@statement}3523 3524 The identifier in a \lstinline @break@statement shall name a label located on an enclosing compound, selection or iteration statement.3525 3526 3527 \subsubsection [The return statement]{The \lstinline@return@statement}3528 3529 An expression in a \lstinline @return@statement is treated as being cast to the result type of the function.3530 3531 3532 \subsubsection [The throw statement]{The \lstinline@throw@statement}3515 \subsubsection{The \lstinline$continue$ statement} 3516 3517 The identifier in a \lstinline$continue$ statement shall name a label located on an enclosing iteration statement. 3518 3519 3520 \subsubsection{The \lstinline$break$ statement} 3521 3522 The identifier in a \lstinline$break$ statement shall name a label located on an enclosing compound, selection or iteration statement. 3523 3524 3525 \subsubsection{The \lstinline$return$ statement} 3526 3527 An expression in a \lstinline$return$ statement is treated as being cast to the result type of the function. 3528 3529 3530 \subsubsection{The \lstinline$throw$ statement} 3533 3531 3534 3532 When an exception is raised, \Index{propagation} directs control from a raise in the source execution to a handler in the faulting execution. 3535 3533 3536 3534 3537 \subsubsection [The throwResume statement]{The \lstinline@throwResume@statement}3535 \subsubsection{The \lstinline$throwResume$ statement} 3538 3536 3539 3537 … … 3542 3540 \begin{syntax} 3543 3541 \lhs{exception-statement} 3544 \rhs \lstinline @try@\nonterm{compound-statement} \nonterm{handler-list}3545 \rhs \lstinline @try@\nonterm{compound-statement} \nonterm{finally-clause}3546 \rhs \lstinline @try@\nonterm{compound-statement} \nonterm{handler-list} \nonterm{finally-clause}3542 \rhs \lstinline$try$ \nonterm{compound-statement} \nonterm{handler-list} 3543 \rhs \lstinline$try$ \nonterm{compound-statement} \nonterm{finally-clause} 3544 \rhs \lstinline$try$ \nonterm{compound-statement} \nonterm{handler-list} \nonterm{finally-clause} 3547 3545 \lhs{handler-list} 3548 3546 \rhs \nonterm{handler-clause} 3549 \rhs \lstinline @catch@ \lstinline@(@ \ldots \lstinline@)@\nonterm{compound-statement}3550 \rhs \nonterm{handler-clause} \lstinline @catch@ \lstinline@(@ \ldots \lstinline@)@\nonterm{compound-statement}3551 \rhs \lstinline @catchResume@ \lstinline@(@ \ldots \lstinline@)@\nonterm{compound-statement}3552 \rhs \nonterm{handler-clause} \lstinline @catchResume@ \lstinline@(@ \ldots \lstinline@)@\nonterm{compound-statement}3547 \rhs \lstinline$catch$ \lstinline$($ \ldots \lstinline$)$ \nonterm{compound-statement} 3548 \rhs \nonterm{handler-clause} \lstinline$catch$ \lstinline$($ \ldots \lstinline$)$ \nonterm{compound-statement} 3549 \rhs \lstinline$catchResume$ \lstinline$($ \ldots \lstinline$)$ \nonterm{compound-statement} 3550 \rhs \nonterm{handler-clause} \lstinline$catchResume$ \lstinline$($ \ldots \lstinline$)$ \nonterm{compound-statement} 3553 3551 \lhs{handler-clause} 3554 \rhs \lstinline @catch@ \lstinline@(@ \nonterm{exception-declaration} \lstinline@)@\nonterm{compound-statement}3555 \rhs \nonterm{handler-clause} \lstinline @catch@ \lstinline@(@ \nonterm{exception-declaration} \lstinline@)@\nonterm{compound-statement}3556 \rhs \lstinline @catchResume@ \lstinline@(@ \nonterm{exception-declaration} \lstinline@)@\nonterm{compound-statement}3557 \rhs \nonterm{handler-clause} \lstinline @catchResume@ \lstinline@(@ \nonterm{exception-declaration} \lstinline@)@\nonterm{compound-statement}3552 \rhs \lstinline$catch$ \lstinline$($ \nonterm{exception-declaration} \lstinline$)$ \nonterm{compound-statement} 3553 \rhs \nonterm{handler-clause} \lstinline$catch$ \lstinline$($ \nonterm{exception-declaration} \lstinline$)$ \nonterm{compound-statement} 3554 \rhs \lstinline$catchResume$ \lstinline$($ \nonterm{exception-declaration} \lstinline$)$ \nonterm{compound-statement} 3555 \rhs \nonterm{handler-clause} \lstinline$catchResume$ \lstinline$($ \nonterm{exception-declaration} \lstinline$)$ \nonterm{compound-statement} 3558 3556 \lhs{finally-clause} 3559 \rhs \lstinline @finally@\nonterm{compound-statement}3557 \rhs \lstinline$finally$ \nonterm{compound-statement} 3560 3558 \lhs{exception-declaration} 3561 3559 \rhs \nonterm{type-specifier} … … 3565 3563 \rhs \nonterm{new-abstract-declarator-tuple} 3566 3564 \lhs{asynchronous-statement} 3567 \rhs \lstinline @enable@\nonterm{identifier-list} \nonterm{compound-statement}3568 \rhs \lstinline @disable@\nonterm{identifier-list} \nonterm{compound-statement}3565 \rhs \lstinline$enable$ \nonterm{identifier-list} \nonterm{compound-statement} 3566 \rhs \lstinline$disable$ \nonterm{identifier-list} \nonterm{compound-statement} 3569 3567 \end{syntax} 3570 3568 … … 3572 3570 3573 3571 3574 \subsubsection [The try statement]{The \lstinline@try@statement}3575 3576 The \lstinline @try@statement is a block with associated handlers, called a \Index{guarded block};3572 \subsubsection{The \lstinline$try$ statement} 3573 3574 The \lstinline$try$ statement is a block with associated handlers, called a \Index{guarded block}; 3577 3575 all other blocks are \Index{unguarded block}s. 3578 A \lstinline @goto@, \lstinline@break@, \lstinline@return@, or \lstinline@continue@statement can be used to transfer control out of a try block or handler, but not into one.3579 3580 3581 \subsubsection [The enable/disable statements]{The \lstinline@enable@/\lstinline@disable@statements}3582 3583 The \lstinline @enable@/\lstinline@disable@statements toggle delivery of \Index{asynchronous exception}s.3576 A \lstinline$goto$, \lstinline$break$, \lstinline$return$, or \lstinline$continue$ statement can be used to transfer control out of a try block or handler, but not into one. 3577 3578 3579 \subsubsection{The \lstinline$enable$/\lstinline$disable$ statements} 3580 3581 The \lstinline$enable$/\lstinline$disable$ statements toggle delivery of \Index{asynchronous exception}s. 3584 3582 3585 3583 … … 3591 3589 \subsection{Predefined macro names} 3592 3590 3593 The implementation shall define the macro names \lstinline @__LINE__@, \lstinline@__FILE__@,3594 \lstinline @__DATE__@, and \lstinline@__TIME__@, as in the {\c11} standard.3595 It shall not define the macro name \lstinline @__STDC__@.3596 3597 In addition, the implementation shall define the macro name \lstinline @__CFORALL__@to be the decimal constant 1.3591 The implementation shall define the macro names \lstinline$__LINE__$, \lstinline$__FILE__$, 3592 \lstinline$__DATE__$, and \lstinline$__TIME__$, as in the {\c11} standard. 3593 It shall not define the macro name \lstinline$__STDC__$. 3594 3595 In addition, the implementation shall define the macro name \lstinline$__CFORALL__$ to be the decimal constant 1. 3598 3596 3599 3597 … … 3612 3610 The pointer, integral, and floating-point types are all \define{scalar types}. 3613 3611 All of these types can be logically negated and compared. 3614 The assertion ``\lstinline @scalar( Complex )@'' should be read as ``type \lstinline@Complex@is scalar''.3615 \begin{lstlisting} 3616 trait scalar( otype T ) { §\impl{scalar}§3612 The assertion ``\lstinline$scalar( Complex )$'' should be read as ``type \lstinline$Complex$ is scalar''. 3613 \begin{lstlisting} 3614 trait scalar( otype T ) {@\impl{scalar}@ 3617 3615 int !?( T ); 3618 3616 int ?<?( T, T ), ?<=?( T, T ), ?==?( T, T ), ?>=?( T, T ), ?>?( T, T ), ?!=?( T, T ); … … 3624 3622 This is equivalent to inheritance of specifications. 3625 3623 \begin{lstlisting} 3626 trait arithmetic( otype T | scalar( T ) ) { §\impl{arithmetic}§§\use{scalar}§3624 trait arithmetic( otype T | scalar( T ) ) {@\impl{arithmetic}@@\use{scalar}@ 3627 3625 T +?( T ), -?( T ); 3628 3626 T ?*?( T, T ), ?/?( T, T ), ?+?( T, T ), ?-?( T, T ); … … 3630 3628 \end{lstlisting} 3631 3629 3632 The various flavors of \lstinline @char@ and \lstinline@int@and the enumerated types make up the3630 The various flavors of \lstinline$char$ and \lstinline$int$ and the enumerated types make up the 3633 3631 \define{integral types}. 3634 3632 \begin{lstlisting} 3635 trait integral( otype T | arithmetic( T ) ) { §\impl{integral}§§\use{arithmetic}§3633 trait integral( otype T | arithmetic( T ) ) {@\impl{integral}@@\use{arithmetic}@ 3636 3634 T ~?( T ); 3637 3635 T ?&?( T, T ), ?|?( T, T ), ?^?( T, T ); … … 3647 3645 The only operation that can be applied to all modifiable lvalues is simple assignment. 3648 3646 \begin{lstlisting} 3649 trait m_lvalue( otype T ) { §\impl{m_lvalue}§3647 trait m_lvalue( otype T ) {@\impl{m_lvalue}@ 3650 3648 T ?=?( T *, T ); 3651 3649 }; … … 3657 3655 Scalars can also be incremented and decremented. 3658 3656 \begin{lstlisting} 3659 trait m_l_scalar( otype T | scalar( T ) | m_lvalue( T ) ) { §\impl{m_l_scalar}§3660 T ?++( T * ), ?--( T * ); §\use{scalar}§§\use{m_lvalue}§3657 trait m_l_scalar( otype T | scalar( T ) | m_lvalue( T ) ) {@\impl{m_l_scalar}@ 3658 T ?++( T * ), ?--( T * );@\use{scalar}@@\use{m_lvalue}@ 3661 3659 T ++?( T * ), --?( T * ); 3662 3660 }; … … 3664 3662 3665 3663 Modifiable arithmetic lvalues are both modifiable scalar lvalues and arithmetic. 3666 Note that this results in the ``inheritance'' of \lstinline @scalar@along both paths.3667 \begin{lstlisting} 3668 trait m_l_arithmetic( otype T | m_l_scalar( T ) | arithmetic( T ) ) { §\impl{m_l_arithmetic}§3669 T ?/=?( T *, T ), ?*=?( T *, T ); §\use{m_l_scalar}§§\use{arithmetic}§3664 Note that this results in the ``inheritance'' of \lstinline$scalar$ along both paths. 3665 \begin{lstlisting} 3666 trait m_l_arithmetic( otype T | m_l_scalar( T ) | arithmetic( T ) ) {@\impl{m_l_arithmetic}@ 3667 T ?/=?( T *, T ), ?*=?( T *, T );@\use{m_l_scalar}@@\use{arithmetic}@ 3670 3668 T ?+=?( T *, T ), ?-=?( T *, T ); 3671 3669 }; 3672 trait m_l_integral( otype T | m_l_arithmetic( T ) | integral( T ) ) { §\impl{m_l_integral}§3673 T ?&=?( T *, T ), ?|=?( T *, T ), ?^=?( T *, T ); §\use{m_l_arithmetic}§3674 T ?%=?( T *, T ), ?<<=?( T *, T ), ?>>=?( T *, T ); §\use{integral}§3670 trait m_l_integral( otype T | m_l_arithmetic( T ) | integral( T ) ) {@\impl{m_l_integral}@ 3671 T ?&=?( T *, T ), ?|=?( T *, T ), ?^=?( T *, T );@\use{m_l_arithmetic}@ 3672 T ?%=?( T *, T ), ?<<=?( T *, T ), ?>>=?( T *, T );@\use{integral}@ 3675 3673 }; 3676 3674 \end{lstlisting} … … 3680 3678 3681 3679 Array types can barely be said to exist in {\c11}, since in most cases an array name is treated as a constant pointer to the first element of the array, and the subscript expression 3682 ``\lstinline @a[i]@'' is equivalent to the dereferencing expression ``\lstinline@(*( a+( i )))@''.3683 Technically, pointer arithmetic and pointer comparisons other than ``\lstinline @==@'' and3684 ``\lstinline @!=@'' are only defined for pointers to array elements, but the type system does not enforce those restrictions.3680 ``\lstinline$a[i]$'' is equivalent to the dereferencing expression ``\lstinline$(*( a+( i )))$''. 3681 Technically, pointer arithmetic and pointer comparisons other than ``\lstinline$==$'' and 3682 ``\lstinline$!=$'' are only defined for pointers to array elements, but the type system does not enforce those restrictions. 3685 3683 Consequently, there is no need for a separate ``array type'' specification. 3686 3684 3687 3685 Pointer types are scalar types. 3688 Like other scalar types, they have ``\lstinline @+@'' and3689 ``\lstinline @-@'' operators, but the types do not match the types of the operations in3690 \lstinline @arithmetic@, so these operators cannot be consolidated in \lstinline@scalar@.3691 \begin{lstlisting} 3692 trait pointer( type P | scalar( P ) ) { §\impl{pointer}§§\use{scalar}§3686 Like other scalar types, they have ``\lstinline$+$'' and 3687 ``\lstinline$-$'' operators, but the types do not match the types of the operations in 3688 \lstinline$arithmetic$, so these operators cannot be consolidated in \lstinline$scalar$. 3689 \begin{lstlisting} 3690 trait pointer( type P | scalar( P ) ) {@\impl{pointer}@@\use{scalar}@ 3693 3691 P ?+?( P, long int ), ?+?( long int, P ), ?-?( P, long int ); 3694 3692 ptrdiff_t ?-?( P, P ); 3695 3693 }; 3696 trait m_l_pointer( type P | pointer( P ) | m_l_scalar( P ) ) { §\impl{m_l_pointer}§3694 trait m_l_pointer( type P | pointer( P ) | m_l_scalar( P ) ) {@\impl{m_l_pointer}@ 3697 3695 P ?+=?( P *, long int ), ?-=?( P *, long int ); 3698 3696 P ?=?( P *, void * ); … … 3703 3701 Specifications that define the dereference operator ( or subscript operator ) require two parameters, one for the pointer type and one for the pointed-at ( or element ) type. 3704 3702 Different specifications are needed for each set of \Index{type qualifier}s, because qualifiers are not included in types. 3705 The assertion ``\lstinline @|ptr_to( Safe_pointer, int )@'' should be read as3706 ``\lstinline @Safe_pointer@ acts like a pointer to \lstinline@int@''.3707 \begin{lstlisting} 3708 trait ptr_to( otype P | pointer( P ), otype T ) { §\impl{ptr_to}§§\use{pointer}§3703 The assertion ``\lstinline$|ptr_to( Safe_pointer, int )$'' should be read as 3704 ``\lstinline$Safe_pointer$ acts like a pointer to \lstinline$int$''. 3705 \begin{lstlisting} 3706 trait ptr_to( otype P | pointer( P ), otype T ) {@\impl{ptr_to}@@\use{pointer}@ 3709 3707 lvalue T *?( P ); 3710 3708 lvalue T ?[?]( P, long int ); 3711 3709 }; 3712 trait ptr_to_const( otype P | pointer( P ), otype T ) { §\impl{ptr_to_const}§3710 trait ptr_to_const( otype P | pointer( P ), otype T ) {@\impl{ptr_to_const}@ 3713 3711 const lvalue T *?( P ); 3714 const lvalue T ?[?]( P, long int ); §\use{pointer}§3712 const lvalue T ?[?]( P, long int );@\use{pointer}@ 3715 3713 }; 3716 trait ptr_to_volatile( otype P | pointer( P ), otype T ) } §\impl{ptr_to_volatile}§3714 trait ptr_to_volatile( otype P | pointer( P ), otype T ) }@\impl{ptr_to_volatile}@ 3717 3715 volatile lvalue T *?( P ); 3718 volatile lvalue T ?[?]( P, long int ); §\use{pointer}§3716 volatile lvalue T ?[?]( P, long int );@\use{pointer}@ 3719 3717 }; 3720 trait ptr_to_const_volatile( otype P | pointer( P ), otype T ) } §\impl{ptr_to_const_volatile}§3721 const volatile lvalue T *?( P ); §\use{pointer}§3718 trait ptr_to_const_volatile( otype P | pointer( P ), otype T ) }@\impl{ptr_to_const_volatile}@ 3719 const volatile lvalue T *?( P );@\use{pointer}@ 3722 3720 const volatile lvalue T ?[?]( P, long int ); 3723 3721 }; 3724 3722 \end{lstlisting} 3725 3723 3726 Assignment to pointers is more complicated than is the case with other types, because the target's type can have extra type qualifiers in the pointed-at type: a ``\lstinline @T *@'' can be assigned to a ``\lstinline@const T *@'', a ``\lstinline@volatile T *@'', and a ``\lstinline@const volatile T *@''.3724 Assignment to pointers is more complicated than is the case with other types, because the target's type can have extra type qualifiers in the pointed-at type: a ``\lstinline$T *$'' can be assigned to a ``\lstinline$const T *$'', a ``\lstinline$volatile T *$'', and a ``\lstinline$const volatile T *$''. 3727 3725 Again, the pointed-at type is passed in, so that assertions can connect these specifications to the 3728 ``\lstinline @ptr_to@'' specifications.3729 \begin{lstlisting} 3730 trait m_l_ptr_to( otype P | m_l_pointer( P ), §\use{m_l_pointer}§§\impl{m_l_ptr_to}§ otype T | ptr_to( P, T )§\use{ptr_to}§{3726 ``\lstinline$ptr_to$'' specifications. 3727 \begin{lstlisting} 3728 trait m_l_ptr_to( otype P | m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to}@ otype T | ptr_to( P, T )@\use{ptr_to}@ { 3731 3729 P ?=?( P *, T * ); 3732 3730 T * ?=?( T **, P ); 3733 3731 }; 3734 trait m_l_ptr_to_const( otype P | m_l_pointer( P ), §\use{m_l_pointer}§§\impl{m_l_ptr_to_const}§ otype T | ptr_to_const( P, T )§\use{ptr_to_const}§) {3732 trait m_l_ptr_to_const( otype P | m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to_const}@ otype T | ptr_to_const( P, T )@\use{ptr_to_const}@) { 3735 3733 P ?=?( P *, const T * ); 3736 3734 const T * ?=?( const T **, P ); 3737 3735 }; 3738 trait m_l_ptr_to_volatile( otype P | m_l_pointer( P ), §\use{m_l_pointer}§§\impl{m_l_ptr_to_volatile}§ otype T | ptr_to_volatile( P, T )) {§\use{ptr_to_volatile}§3736 trait m_l_ptr_to_volatile( otype P | m_l_pointer( P ),@\use{m_l_pointer}@@\impl{m_l_ptr_to_volatile}@ otype T | ptr_to_volatile( P, T )) {@\use{ptr_to_volatile}@ 3739 3737 P ?=?( P *, volatile T * ); 3740 3738 volatile T * ?=?( volatile T **, P ); 3741 3739 }; 3742 trait m_l_ptr_to_const_volatile( otype P | ptr_to_const_volatile( P ), §\use{ptr_to_const_volatile}§§\impl{m_l_ptr_to_const_volatile}§3743 otype T | m_l_ptr_to_volatile( P, T ) | m_l_ptr_to_const( P )) { §\use{m_l_ptr_to_const}§§\use{m_l_ptr_to_volatile}§3740 trait m_l_ptr_to_const_volatile( otype P | ptr_to_const_volatile( P ),@\use{ptr_to_const_volatile}@@\impl{m_l_ptr_to_const_volatile}@ 3741 otype T | m_l_ptr_to_volatile( P, T ) | m_l_ptr_to_const( P )) {@\use{m_l_ptr_to_const}@@\use{m_l_ptr_to_volatile}@ 3744 3742 P ?=?( P *, const volatile T * ); 3745 3743 const volatile T * ?=?( const volatile T **, P ); … … 3750 3748 An alternative specification can make use of the fact that qualification of the pointed-at type is part of a pointer type to capture that regularity. 3751 3749 \begin{lstlisting} 3752 trait m_l_ptr_like( type MyP | m_l_pointer( MyP ), §\use{m_l_pointer}§§\impl{m_l_ptr_like}§type CP | m_l_pointer( CP ) ) {3750 trait m_l_ptr_like( type MyP | m_l_pointer( MyP ),@\use{m_l_pointer}@@\impl{m_l_ptr_like}@ type CP | m_l_pointer( CP ) ) { 3753 3751 MyP ?=?( MyP *, CP ); 3754 3752 CP ?=?( CP *, MyP ); 3755 3753 }; 3756 3754 \end{lstlisting} 3757 The assertion ``\lstinline @| m_l_ptr_like( Safe_ptr, const int * )@'' should be read as3758 ``\lstinline @Safe_ptr@ is a pointer type like \lstinline@const int *@''.3755 The assertion ``\lstinline$| m_l_ptr_like( Safe_ptr, const int * )$'' should be read as 3756 ``\lstinline$Safe_ptr$ is a pointer type like \lstinline$const int *$''. 3759 3757 This specification has two defects, compared to the original four: there is no automatic assertion that dereferencing a 3760 \lstinline @MyP@ produces an lvalue of the type that \lstinline@CP@points at, and the3761 ``\lstinline @|m_l_pointer( CP )@'' assertion provides only a weak assurance that the argument passed to \lstinline@CP@really is a pointer type.3758 \lstinline$MyP$ produces an lvalue of the type that \lstinline$CP$ points at, and the 3759 ``\lstinline$|m_l_pointer( CP )$'' assertion provides only a weak assurance that the argument passed to \lstinline$CP$ really is a pointer type. 3762 3760 3763 3761 … … 3765 3763 3766 3764 Different operators often have related meanings; 3767 for instance, in C, ``\lstinline @+@'',3768 ``\lstinline @+=@'', and the two versions of ``\lstinline@++@'' perform variations of addition.3765 for instance, in C, ``\lstinline$+$'', 3766 ``\lstinline$+=$'', and the two versions of ``\lstinline$++$'' perform variations of addition. 3769 3767 Languages like {\CC} and Ada allow programmers to define operators for new types, but do not require that these relationships be preserved, or even that all of the operators be implemented. 3770 3768 Completeness and consistency is left to the good taste and discretion of the programmer. … … 3779 3777 The different comparison operators have obvious relationships, but there is no obvious subset of the operations to use in the implementation of the others. 3780 3778 However, it is usually convenient to implement a single comparison function that returns a negative integer, 0, or a positive integer if its first argument is respectively less than, equal to, or greater than its second argument; 3781 the library function \lstinline @strcmp@is an example.3782 3783 C and \CFA have an extra, non-obvious comparison operator: ``\lstinline @!@'', logical negation, returns 1 if its operand compares equal to 0, and 0 otherwise.3779 the library function \lstinline$strcmp$ is an example. 3780 3781 C and \CFA have an extra, non-obvious comparison operator: ``\lstinline$!$'', logical negation, returns 1 if its operand compares equal to 0, and 0 otherwise. 3784 3782 \begin{lstlisting} 3785 3783 trait comparable( otype T ) { … … 3830 3828 3831 3829 Note that, although an arithmetic type would certainly provide comparison functions, and an integral type would provide arithmetic operations, there does not have to be any relationship among 3832 \lstinline @int_base@, \lstinline@arith_base@ and \lstinline@comparable@.3830 \lstinline$int_base$, \lstinline$arith_base$ and \lstinline$comparable$. 3833 3831 Note also that these declarations provide guidance and assistance, but they do not define an absolutely minimal set of requirements. 3834 A truly minimal implementation of an arithmetic type might only provide \lstinline@0@, \lstinline@1@, and \lstinline@?-=?@, which would be used by polymorphic \lstinline@?+=?@, \lstinline@?*=?@, and \lstinline@?/=?@ functions. 3835 3836 Note also that \lstinline@short@ is an integer type in C11 terms, but has no operations! 3832 A truly minimal implementation of an arithmetic type might only provide 3833 \lstinline$0$, \lstinline$1$, and \lstinline$?-=?$, which would be used by polymorphic 3834 \lstinline$?+=?$, \lstinline$?*=?$, and \lstinline$?/=?$ functions. 3835 3836 Note also that \lstinline$short$ is an integer type in C11 terms, but has no operations! 3837 3837 3838 3838 … … 3841 3841 3842 3842 Restrict allowed to qualify anything, or type/dtype parameters, but only affects pointers. 3843 This gets into \lstinline @noalias@territory.3844 Qualifying anything (``\lstinline @short restrict rs@'') means pointer parameters of \lstinline@?++@, etc, would need restrict qualifiers.3843 This gets into \lstinline$noalias$ territory. 3844 Qualifying anything (``\lstinline$short restrict rs$'') means pointer parameters of \lstinline$?++$, etc, would need restrict qualifiers. 3845 3845 3846 3846 Enumerated types. … … 3852 3852 Color, enum Color ) really make sense? ?++ does, but it adds (int)1. 3853 3853 3854 Operators on {,signed,unsigned} char and other small types. \lstinline@?<?@harmless;3854 Operators on {,signed,unsigned} char and other small types. ?<? harmless; 3855 3855 ?*? questionable for chars. 3856 3856 Generic selections make these choices visible. … … 3858 3858 ``promotion'' function? 3859 3859 3860 \lstinline @register@assignment might be handled as assignment to a temporary with copying back and forth, but copying must not be done by assignment.3861 3862 Don't use \lstinline@ptrdiff_t@by name in the predefineds.3860 \lstinline$register$ assignment might be handled as assignment to a temporary with copying back and forth, but copying must not be done by assignment. 3861 3862 Don't use ptrdiff\_t by name in the predefineds. 3863 3863 3864 3864 Polymorphic objects. -
doc/user/user.tex
r7cc6bd6 r9243a501 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sat Apr 30 13:54:32201614 %% Update Count : 22113 %% Last Modified On : Thu Apr 21 08:15:37 2016 14 %% Update Count : 131 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 17 17 % requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended 18 19 % red highlighting ®...® (registered trademark sumbol)20 % blue highlighting ©...© (copyright symbol)21 % latex escape §...§ (section symbol)22 % keyword escape ¶...¶ (pilcrow symbol)23 % math escape $...$ (dollar symbol)24 18 25 19 \documentclass[openright,twoside]{article} … … 232 226 233 227 234 \section [Compiling CFA Program]{Compiling \CFA Program}228 \section{Compiling \CFA Program} 235 229 236 230 The command \lstinline@cfa@ is used to compile \CFA program(s). 237 231 This command works like the GNU \lstinline@gcc@\index{gcc} command, e.g.: 238 232 \begin{lstlisting} 239 cfa [ gcc-options ] C/ §\CFA§-files [ assembler/loader-files ]240 \end{lstlisting} 241 \index c{cfa}\index{compilation!cfa@\lstinline$cfa$}233 cfa [ gcc-options ] C/@{\CFA}@-files [ assembler/loader-files ] 234 \end{lstlisting} 235 \index{cfa@\lstinline$cfa$}\index{compilation!cfa@\lstinline$cfa$} 242 236 By default, \CFA programs having the following \lstinline@gcc@ flags turned on: 243 237 \begin{description} 244 \item\hspace*{-4pt}\Indexc{-std=gnu99}\index{compilation option!-std=gnu99@{\lstinline$-std=gnu99$}} 238 \item 239 \hspace*{-4pt}\lstinline@-std=gnu99@ 240 \index{-std=gnu99@{\lstinline$-std=gnu99$}}\index{compilation option!-std=gnu99@{\lstinline$-std=gnu99$}} 245 241 The 1999 C standard plus GNU extensions. 246 \item\hspace*{-4pt}\Indexc{-fgnu89-¶inline¶}\index{compilation option!-fgnu89-inline@{\lstinline$-fgnu89-¶inline¶$}} 242 \item 243 \hspace*{-4pt}\lstinline@-fgnu89-inline@ 244 \index{-fgnu89-inline@{\lstinline$-fgnu89-inline$}}\index{compilation option!-fgnu89-inline@{\lstinline$-fgnu89-inline$}} 247 245 Use the traditional GNU semantics for inline routines in C99 mode. 248 246 \end{description} 249 247 The following new \CFA option is available: 250 248 \begin{description} 251 \item\hspace*{-4pt}\Indexc{-CFA}\index{compilation option!-CFA@{\lstinline$-CFA$}} 249 \item 250 \hspace*{-4pt}\lstinline@-CFA@ 251 \index{-CFA@{\lstinline$-CFA$}}\index{compilation option!-CFA@{\lstinline$-CFA$}} 252 252 Only the C preprocessor and the \CFA translator steps are performed and the transformed program is written to standard output, which makes it possible to examine the code generated by the \CFA translator. 253 253 \end{description} … … 255 255 The following preprocessor variables are available: 256 256 \begin{description} 257 \item\hspace*{-4pt}\Indexc{__CFA__}\index{preprocessor variables!__CFA__@{\lstinline$__CFA__$}} 257 \item 258 \hspace*{-4pt}\lstinline$__CFA__$ 259 \index{__CFA__@{\lstinline$__CFA__$}}\index{preprocessor variables!__CFA__@{\lstinline$__CFA__$}} 258 260 is always available during preprocessing and its value is the current major \Index{version number} of \CFA.\footnote{ 259 261 The C preprocessor allows only integer values in a preprocessor variable so a value like ``\Version'' is not allowed. 260 262 Hence, the need to have three variables for the major, minor and patch version number.} 261 263 262 \item\hspace*{-4pt}\Indexc{__CFA_MINOR__}\index{preprocessor variables!__CFA_MINOR__@{\lstinline$__CFA_MINOR__$}} 264 \item 265 \hspace*{-4pt}\lstinline$__CFA_MINOR__$ 266 \index{__CFA_MINOR__@{\lstinline$__CFA_MINOR__$}}\index{preprocessor variables!__CFA_MINOR__@{\lstinline$__CFA_MINOR__$}} 263 267 is always available during preprocessing and its value is the current minor \Index{version number} of \CFA. 264 268 265 \item\hspace*{-4pt}\Indexc{__CFA_PATCH__}\index{preprocessor variables!__CFA_PATCH__@\lstinline$__CFA_PATCH__$} 269 \item 270 \hspace*{-4pt}\lstinline$__CFA_PATCH__$ 271 \index{__CFA_PATCH__@%(__CFA_PATCH__%)}\index{preprocessor variables!__CFA_PATCH__@%(__CFA_PATCH__%)} 266 272 is always available during preprocessing and its value is the current patch \Index{version number} of \CFA. 267 273 268 \item\hspace*{-4pt}\Indexc{__CFORALL__}\index{preprocessor variables!__CFORALL__@\lstinline$__CFORALL__$} 274 \item 275 \hspace*{-4pt}\lstinline$__CFORALL__$ 276 \index{__CFORALL__@%(__CFORALL__%)}\index{preprocessor variables!__CFORALL__@%(__CFORALL__%)} 269 277 is always available during preprocessing and it has no value. 270 278 \end{description} … … 274 282 \begin{lstlisting} 275 283 #ifndef __CFORALL__ 276 #include <stdio.h> // C header file284 #include <stdio.h> // C header file 277 285 #else 278 #include <fstream> // §\CFA{}§header file286 #include <fstream> // @\CFA{}@ header file 279 287 #endif 280 288 \end{lstlisting} … … 286 294 Numeric constants are extended to allow \Index{underscore}s within constants\index{constant!underscore}, e.g.: 287 295 \begin{lstlisting} 288 2 ®_®147®_®483®_®648; // decimal constant296 2`_`147`_`483`_`648; // decimal constant 289 297 56_ul; // decimal unsigned long constant 290 298 0_377; // octal constant … … 352 360 \multicolumn{1}{c@{\hspace{30pt}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 353 361 \begin{lstlisting} 354 ®* int x, y;® 362 `* int x, y;` 355 363 \end{lstlisting} 356 364 & … … 480 488 The point of the new syntax is to allow returning multiple values from a routine~\cite{CLU,Galletly96}, e.g.: 481 489 \begin{lstlisting} 482 ®[ int o1, int o2, char o3 ]®f( int i1, char i2, char i3 ) {483 §\emph{routine body}§490 `[ int o1, int o2, char o3 ]` f( int i1, char i2, char i3 ) { 491 @\emph{routine body}@ 484 492 } 485 493 \end{lstlisting} … … 492 500 Declaration qualifiers can only appear at the start of a routine definition, e.g.: 493 501 \begin{lstlisting} 494 extern [ int x ] g( int y ) { §\,§}502 extern [ int x ] g( int y ) {@\,@} 495 503 \end{lstlisting} 496 504 Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified; 497 505 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: 498 506 \begin{lstlisting} 499 [ §\,§] g();// no input or output parameters507 [@\,@] g(@\,@); // no input or output parameters 500 508 [ void ] g( void ); // no input or output parameters 501 509 \end{lstlisting} … … 548 556 Because the value in the return variable is automatically returned when a \CFA routine terminates, the \lstinline@return@ statement \emph{does not} contain an expression, as in: 549 557 \begin{lstlisting} 550 ®[ int x ]®f() {558 `[ int x ]` f() { 551 559 ... x = 0; ... x = y; ... 552 ®return;®// implicitly return x560 `return;` // implicitly return x 553 561 } 554 562 \end{lstlisting} … … 773 781 \subsection{Type Nesting} 774 782 775 \CFA allows \Index{type nesting}, and type qualification of the nested types, where as C hoists\index{type hoisting} (refactors) nested types into the enclosing scope and has no type qualification.783 \CFA allows \Index{type nesting}, and type qualification of the nested types, where as C hoists\index{type!hoisting} (refactors) nested types into the enclosing scope and has no type qualification. 776 784 \begin{quote2} 777 785 \begin{tabular}{@{}l@{\hspace{30pt}}l|l@{}} … … 828 836 829 837 int fred() { 830 s.t.c = ®S.®R; // type qualification831 struct ®S.®T t = { ®S.®R, 1, 2 };832 enum ®S.®C c;833 union ®S.T.®U u;838 s.t.c = `S.`R; // type qualification 839 struct `S.`T t = { `S.`R, 1, 2 }; 840 enum `S.`C c; 841 union `S.T.`U u; 834 842 } 835 843 \end{lstlisting} … … 855 863 qsort( ia, size ); // sort ascending order using builtin ?<? 856 864 { 857 ®int ?<?( int x, int y ) { return x > y; }®// nested routine865 `int ?<?( int x, int y ) { return x > y; }` // nested routine 858 866 qsort( ia, size ); // sort descending order by local redefinition 859 867 } … … 865 873 \begin{lstlisting} 866 874 [* [int]( int )] foo() { // int (*foo())( int ) 867 int ®i®= 7;875 int `i` = 7; 868 876 int bar( int p ) { 869 ®i®+= 1; // dependent on local variable870 sout | ®i®| endl;877 `i` += 1; // dependent on local variable 878 sout | `i` | endl; 871 879 } 872 880 return bar; // undefined because of local dependence … … 889 897 The general syntax of a tuple is: 890 898 \begin{lstlisting} 891 [ §\emph{exprlist}§]899 [ $\emph{exprlist}$ ] 892 900 \end{lstlisting} 893 901 where \lstinline@$\emph{exprlist}$@ is a list of one or more expressions separated by commas. … … 909 917 The general syntax of a tuple type is: 910 918 \begin{lstlisting} 911 [ §\emph{typelist}§]919 [ @\emph{typelist}@ ] 912 920 \end{lstlisting} 913 921 where \lstinline@$\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. … … 1039 1047 Mass assignment has the following form: 1040 1048 \begin{lstlisting} 1041 [ §\emph{lvalue}§, ..., §\emph{lvalue}§ ] = §\emph{expr}§;1042 \end{lstlisting} 1043 The left-hand side is a tuple of \ emph{lvalues}, which is a list of expressions each yielding an address, i.e., any data object that can appear on the left-hand side of a conventional assignment statement.1049 [ @\emph{lvalue}@, ..., @\emph{lvalue}@ ] = @\emph{expr}@; 1050 \end{lstlisting} 1051 The left-hand side is a tuple of \lstinline@$\emph{lvalues}$@, which is a list of expressions each yielding an address, i.e., any data object that can appear on the left-hand side of a conventional assignment statement. 1044 1052 \lstinline@$\emph{expr}$@ is any standard arithmetic expression. 1045 1053 Clearly, the types of the entities being assigned must be type compatible with the value of the expression. … … 1078 1086 Multiple assignment has the following form: 1079 1087 \begin{lstlisting} 1080 [ §\emph{lvalue}§, . . ., §\emph{lvalue}§ ] = [ §\emph{expr}§, . . ., §\emph{expr}§];1081 \end{lstlisting} 1082 The left-hand side is a tuple of \ emph{lvalues}, and the right-hand side is a tuple of \emph{expr}s.1083 Each \ emph{expr} appearing on the righthand 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.1088 [ @\emph{lvalue}@, . . ., @\emph{lvalue}@ ] = [ @\emph{expr}@, . . ., @\emph{expr}@ ]; 1089 \end{lstlisting} 1090 The left-hand side is a tuple of \lstinline@$\emph{lvalues}$@, and the right-hand side is a tuple of \lstinline@$\emph{expr}$@s. 1091 Each \lstinline@$\emph{expr}$@ appearing on the righthand side of a multiple assignment statement is assigned to the corresponding \lstinline@$\emph{lvalues}$@ on the left-hand side of the statement using parallel semantics for each assignment. 1084 1092 An example of multiple assignment is: 1085 1093 \begin{lstlisting} … … 1118 1126 Cascade assignment has the following form: 1119 1127 \begin{lstlisting} 1120 §\emph{tuple}§ = §\emph{tuple}§ = ... = §\emph{tuple}§;1128 @\emph{tuple}@ = @\emph{tuple}@ = ... = @\emph{tuple}@; 1121 1129 \end{lstlisting} 1122 1130 and it has the same parallel semantics as for mass and multiple assignment. … … 1136 1144 Its general form is: 1137 1145 \begin{lstlisting} 1138 §\emph{expr}§ . [ §\emph{fieldlist}§]1139 §\emph{expr}§ -> [ §\emph{fieldlist}§]1140 \end{lstlisting} 1141 \ emph{expr}is any expression yielding a value of type record, e.g., \lstinline@struct@, \lstinline@union@.1142 Each element of \ emph{ fieldlist} is an element of the record specified by \emph{expr}.1146 @\emph{expr}@ . [ @\emph{fieldlist}@ ] 1147 @\emph{expr}@ -> [ @\emph{fieldlist}@ ] 1148 \end{lstlisting} 1149 \lstinline@$\emph{expr}$@ is any expression yielding a value of type record, e.g., \lstinline@struct@, \lstinline@union@. 1150 Each element of \lstinline@$\emph{ fieldlist}$@ is an element of the record specified by \lstinline@$\emph{expr}$@. 1143 1151 A record-field tuple may be used anywhere a tuple can be used. An example of the use of a record-field tuple is 1144 1152 the following: … … 1180 1188 \multicolumn{1}{c@{\hspace{30pt}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1181 1189 \begin{lstlisting} 1182 ®L1:®for ( ... ) {1183 ®L2:®for ( ... ) {1184 ®L3:®for ( ... ) {1185 ... break ®L1®; ...1186 ... break ®L2®; ...1187 ... break ®L3®; // or break1190 `L1:` for ( ... ) { 1191 `L2:` for ( ... ) { 1192 `L3:` for ( ... ) { 1193 ... break `L1`; ... 1194 ... break `L2`; ... 1195 ... break `L3`; // or break 1188 1196 } 1189 1197 } … … 1210 1218 \multicolumn{1}{c@{\hspace{30pt}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1211 1219 \begin{lstlisting} 1212 ®L1®: for ( ... ) {1213 ®L2®: for ( ... ) {1214 ®L3®: for ( ... ) {1215 ... continue ®L1®; ...1216 ... continue ®L2®; ...1217 ... continue ®L3®; ...1220 `L1`: for ( ... ) { 1221 `L2`: for ( ... ) { 1222 `L3`: for ( ... ) { 1223 ... continue `L1`; ... 1224 ... continue `L2`; ... 1225 ... continue `L3`; ... 1218 1226 1219 1227 } … … 1451 1459 \begin{lstlisting} 1452 1460 switch ( i ) { 1453 ®case 1, 3, 5®:1461 `case 1, 3, 5`: 1454 1462 ... 1455 ®case 2, 4, 6®:1463 `case 2, 4, 6`: 1456 1464 ... 1457 1465 } … … 1483 1491 \begin{lstlisting} 1484 1492 switch ( i ) { 1485 ®case 1~5:®1493 `case 1~5:` 1486 1494 ... 1487 ®case 10~15:®1495 `case 10~15:` 1488 1496 ... 1489 1497 } … … 2040 2048 For example, given 2041 2049 \begin{lstlisting} 2042 auto j = ®...®2050 auto j = `...` 2043 2051 \end{lstlisting} 2044 2052 and the need to write a routine to compute using \lstinline@j@ 2045 2053 \begin{lstlisting} 2046 void rtn( ®...®parm );2054 void rtn( `...` parm ); 2047 2055 rtn( j ); 2048 2056 \end{lstlisting} … … 2364 2372 To make this work, a space is required after the field selection: 2365 2373 \begin{lstlisting} 2366 ®s.§\textvisiblespace§0®= 0;2367 ®s.§\textvisiblespace§1®= 1;2374 `s.@\textvisiblespace@0` = 0; 2375 `s.@\textvisiblespace@1` = 1; 2368 2376 \end{lstlisting} 2369 2377 While this sytact is awkward, it is unlikely many programers will name fields of a structure 0 or 1. 2370 Like the \CC lexical problem with closing template-syntax, e.g, \lstinline@Foo<Bar<int ®>>®@, this issue can be solved with a more powerful lexer/parser.2378 Like the \CC lexical problem with closing template-syntax, e.g, \lstinline@Foo<Bar<int`>>`@, this issue can be solved with a more powerful lexer/parser. 2371 2379 2372 2380 There are several ambiguous cases with operator identifiers, e.g., \lstinline@int *?*?()@, where the string \lstinline@*?*?@ can be lexed as \lstinline@*@/\lstinline@?*?@ or \lstinline@*?@/\lstinline@*?@. … … 2375 2383 The first case is for the function-call identifier \lstinline@?()@: 2376 2384 \begin{lstlisting} 2377 int * §\textvisiblespace§?()(); // declaration: space required after '*'2378 * §\textvisiblespace§?()(); // expression: space required after '*'2385 int *@\textvisiblespace@?()(); // declaration: space required after '*' 2386 *@\textvisiblespace@?()(); // expression: space required after '*' 2379 2387 \end{lstlisting} 2380 2388 Without the space, the string \lstinline@*?()@ is ambiguous without N character look ahead; … … 2383 2391 The 4 remaining cases occur in expressions: 2384 2392 \begin{lstlisting} 2385 i++ §\textvisiblespace§?i:0; // space required before '?'2386 i-- §\textvisiblespace§?i:0; // space required before '?'2387 i §\textvisiblespace§?++i:0; // space required after '?'2388 i §\textvisiblespace§?--i:0; // space required after '?'2393 i++@\textvisiblespace@?i:0; // space required before '?' 2394 i--@\textvisiblespace@?i:0; // space required before '?' 2395 i@\textvisiblespace@?++i:0; // space required after '?' 2396 i@\textvisiblespace@?--i:0; // space required after '?' 2389 2397 \end{lstlisting} 2390 2398 In the first two cases, the string \lstinline@i++?@ is ambiguous, where this string can be lexed as \lstinline@i@ / \lstinline@++?@ or \lstinline@i++@ / \lstinline@?@; … … 3317 3325 3318 3326 3319 \subsection [Comparing Key Features of CFA]{Comparing Key Features of \CFA}3327 \subsection{Comparing Key Features of \CFA} 3320 3328 3321 3329 … … 3691 3699 3692 3700 \begin{comment} 3693 \subsubsection{Modules /Packages}3701 \subsubsection{Modules/Packages} 3694 3702 3695 3703 \begin{lstlisting} … … 3933 3941 3934 3942 3935 \subsubsection [C++]{\CC}3943 \subsubsection{\CC} 3936 3944 3937 3945 \CC is a general-purpose programming language. … … 4071 4079 Given that nested types in C are equivalent to not using them, i.e., they are essentially useless, it is unlikely there are any realistic usages that break because of this incompatibility. 4072 4080 4081 4073 4082 \item 4074 4083 Change: In C++, the name of a nested class is local to its enclosing class. … … 4081 4090 struct Y yy; // valid C, invalid C++ 4082 4091 \end{lstlisting} 4083 Rationale: C++ classes have member functions which require that classes establish scopes. 4084 The C rule would leave classes as an incomplete scope mechanism which would prevent C++ programmers from maintaining locality within a class. A coherent set of scope rules for C++ based on the C rule would be very complicated and C++ programmers would be unable to predict reliably the meanings of nontrivial examples involving nested or local functions. 4085 Effect on original feature: Change of semantics of welldefined feature. 4086 Difficulty of converting: Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example: 4092 Rationale: C++ classes have member functions which require that classes establish scopes. The C rule 4093 would leave classes as an incomplete scope mechanism which would prevent C++ programmers from maintaining 4094 locality within a class. A coherent set of scope rules for C++ based on the C rule would be very 4095 complicated and C++ programmers would be unable to predict reliably the meanings of nontrivial examples 4096 involving nested or local functions. 4097 Effect on original feature: Change of semantics of welldefined 4098 feature. 4099 Difficulty of converting: Semantic transformation. To make the struct type name visible in the scope of 4100 the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing 4101 struct is defined. Example: 4087 4102 \begin{lstlisting} 4088 4103 struct Y; // struct Y and struct X are at the same scope … … 4091 4106 }; 4092 4107 \end{lstlisting} 4093 All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of the enclosing struct could be exported to the scope of the enclosing struct. 4094 Note: this is a consequence of the difference in scope rules, which is documented in 3.3. 4108 All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of 4109 the enclosing struct could be exported to the scope of the enclosing struct. Note: this is a consequence of 4110 the difference in scope rules, which is documented in 3.3. 4095 4111 How widely used: Seldom. 4096 4112 \end{enumerate} … … 4108 4124 \begin{lstlisting} 4109 4125 int x = 0, y = 1, z = 2; 4110 ®sout® ®|® x ®|® y ®|® z ®| endl®;4126 `sout` `|` x `|` y `|` z `| endl`; 4111 4127 \end{lstlisting} 4112 4128 & … … 4117 4133 \end{tabular} 4118 4134 \end{quote2} 4119 The \CFA form is half as many characters, and is similar to \Index{Python}I/O with respect to implicit separators.4135 The \CFA form is half as many characters, and is similar to Python I/O with respect to implicit separators. 4120 4136 4121 4137 The logical-or operator is used because it is the lowest-priority overloadable operator, other than assignment. … … 4144 4160 A seperator does not appear at the start or end of a line. 4145 4161 \begin{lstlisting}[belowskip=0pt] 4146 sout |1 | 2 | 3 | endl;4162 sout 1 | 2 | 3 | endl; 4147 4163 \end{lstlisting} 4148 4164 \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4163 4179 which is a local mechanism to disable insertion of the separator character. 4164 4180 \item 4165 A seperator does not appear before a C string starting with the (extended) \Index{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off]@([{$£¥¡¿«@4181 A seperator does not appear before a C string starting with the \Index{extended ASCII}\index{ASCII} characters: \lstinline[mathescape=off]@([{$£¥¿«@ 4166 4182 %$ 4167 4183 \begin{lstlisting}[mathescape=off] 4168 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x $" | 4 | "x £" | 5 | "x ¥" | 6 | "x ¡" | 7 | "x ¿" | 8 | "x «" | 9| endl;4184 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x $" | 4 | "x £" | 5 | "x ¥" | 6 | "x ¿" | 7 | "x «" | 8 | endl; 4169 4185 \end{lstlisting} 4170 4186 %$ 4171 4187 \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] 4172 x (1 x [2 x {3 x $4 x £5 x ¥6 x ¡7 x ¿8 x «94188 x (1 x [2 x {3 x $4 x £5 x ¥6 x ¿7 x «8 4173 4189 \end{lstlisting} 4174 4190 %$ 4175 4191 \item 4176 A seperator does not appear after a C string ending with the (extended) \Index{ASCII}\index{ASCII!extended}characters: \lstinline@,.:;!?)]}%¢»@4192 A seperator does not appear after a C string ending with the extended ASCII characters: \lstinline@,.:;!?)]}%¢»@ 4177 4193 \begin{lstlisting}[belowskip=0pt] 4178 4194 sout | 1 | ", x" | 2 | ". x" | 3 | ": x" | 4 | "; x" | 5 | "! x" | 6 | "? x" | 7 | ") x" | 8 | "] x" | 9 | "} x" 4179 | 10 | "% x" | 11 | "¢ x" | 12 |"» x" | endl;4195 | 10 | "% x" | 11 | L"¢ x" | 12 | L"» x" | endl; 4180 4196 \end{lstlisting} 4181 4197 \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4183 4199 \end{lstlisting} 4184 4200 \item 4185 A seperator does not appear before or after a C string begining/ending with the \Index{ASCII} quote or whitespace characters: \lstinline[showspaces=true]@`'" \t\v\f\r\n@4201 A seperator does not appear before or after a C string begining/ending with the characters: \lstinline@\f\n\r\t\v\`'"@ 4186 4202 \begin{lstlisting}[belowskip=0pt] 4187 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x" | "x " | 4 | " x" | "x\t" | 1 | "\tx" | endl; 4188 \end{lstlisting} 4189 \begin{lstlisting}[mathescape=off,showspaces=true,showtabs=true,aboveskip=0pt,belowskip=0pt] 4190 x`1`x'2'x"3"x x 4 x x 1 x 4203 sout | "x '" | 1 | "' x \`" | 2 | "\` x \"" | 3 | "\" x" | endl; 4204 \end{lstlisting} 4205 \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] 4206 x '1' x \`2\` x "3" x 4207 \end{lstlisting} 4208 \begin{lstlisting}[showtabs=true,aboveskip=0pt] 4209 sout | "x\t" | 1 | "\tx" | endl; 4210 x 1 x 4191 4211 \end{lstlisting} 4192 4212 \end{enumerate} … … 4220 4240 \end{lstlisting} 4221 4241 \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] 4222 1 2 34242 1 2 3 4223 4243 \end{lstlisting} 4224 4244 \begin{lstlisting}[mathescape=off,aboveskip=0pt,aboveskip=0pt,belowskip=0pt] … … 4231 4251 \end{lstlisting} 4232 4252 %$ 4233 \begin{comment} 4253 \VRef[Figure]{f:ExampleIO} shows an example of input and output I/O in \CFA. 4254 4255 \begin{figure} 4256 \begin{lstlisting}[mathescape=off] 4234 4257 #include <fstream> 4235 4258 4236 4259 int main() { 4237 int x = 3, y = 5, z = 7; 4238 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl; 4239 sout | 1 | 2 | 3 | endl; 4240 sout | '1' | '2' | '3' | endl; 4241 sout | 1 | "" | 2 | "" | 3 | endl; 4242 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x $" | 4 | "x £" | 5 | "x ¥" | 6 | "x ¡" | 7 | "x ¿" | 8 | "x «" | 9 | endl; 4243 sout | 1 | ", x" | 2 | ". x" | 3 | ": x" | 4 | "; x" | 5 | "! x" | 6 | "? x" | 7 | ") x" | 8 | "] x" | 9 | "} x" 4244 | 10 | "% x" | 11 | "¢ x" | 12 | "» x" | endl; 4245 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x" | "x " | 4 | " x" | "x\t" | 1 | "\tx" | endl; 4246 sout | sepOn | 1 | 2 | 3 | sepOn | endl; // separator at start of line 4247 sout | 1 | sepOff | 2 | 3 | endl; // turn off implicit separator temporarily 4248 sout | sepDisable | 1 | 2 | 3 | endl; // turn off implicit separation, affects all subsequent prints 4249 sout | 1 | sepOn | 2 | 3 | endl; // turn on implicit separator temporarily 4250 sout | sepEnable | 1 | 2 | 3 | endl; // turn on implicit separation, affects all subsequent prints 4251 sepSet( sout, ", $" ); // change separator from " " to ", $" 4252 sout | 1 | 2 | 3 | endl; 4253 4254 } 4255 4256 // Local Variables: // 4257 // tab-width: 4 // 4258 // End: // 4259 \end{comment} 4260 %$ 4260 char c; // basic types 4261 short int si; 4262 unsigned short int usi; 4263 int i; 4264 unsigned int ui; 4265 long int li; 4266 unsigned long int uli; 4267 long long int lli; 4268 unsigned long long int ulli; 4269 float f; 4270 double d; 4271 long double ld; 4272 float _Complex fc; 4273 double _Complex dc; 4274 long double _Complex ldc; 4275 char s1[10], s2[10]; 4276 4277 ifstream in; // create / open file 4278 open( &in, "input.data", "r" ); 4279 4280 &in | &c // character 4281 | &si | &usi | &i | &ui | &li | &uli | &lli | &ulli // integral 4282 | &f | &d | &ld // floating point 4283 | &fc | &dc | &ldc // floating-point complex 4284 | cstr( s1 ) | cstr( s2, 10 ); // C string, length unchecked and checked 4285 4286 sout | c | ' ' | endl // character 4287 | si | usi | i | ui | li | uli | lli | ulli | endl // integral 4288 | f | d | ld | endl // floating point 4289 | fc | dc | ldc | endl; // complex 4290 sout | endl; 4291 sout | f | "" | d | "" | ld | endl // floating point without separator 4292 | sepDisable | fc | dc | ldc | sepEnable | endl // complex without separator 4293 | sepOn | s1 | sepOff | s2 | endl // local separator removal 4294 | s1 | "" | s2 | endl; // C string withou separator 4295 sout | endl; 4296 sepSet( sout, ", $" ); // change separator, maximum of 15 characters 4297 sout | f | d | ld | endl // floating point without separator 4298 | fc | dc | ldc | endl // complex without separator 4299 | s1 | s2 | endl; 4300 } 4301 4302 $ cat input.data 4303 A 1 2 3 4 5 6 7 8 1.1 1.2 1.3 1.1+2.3 1.1-2.3 1.1-2.3 abc xyz 4304 $ a.out 4305 A 4306 1 2 3 4 5 6 7 8 4307 1.1 1.2 1.3 4308 1.1+2.3i 1.1-2.3i 1.1-2.3i 4309 4310 1.11.21.3 4311 1.1+2.3i1.1-2.3i1.1-2.3i 4312 abcxyz 4313 abcxyz 4314 4315 1.1, $1.2, $1.3 4316 1.1+2.3i, $1.1-2.3i, $1.1-2.3i 4317 abc, $xyz 4318 \end{lstlisting} 4319 \caption{Example I/O} 4320 \label{f:ExampleIO} 4321 \end{figure} 4261 4322 4262 4323 … … 4270 4331 4271 4332 \begin{lstlisting} 4272 forall( otype T ) T * malloc( void ); §\indexc{malloc}§4333 forall( otype T ) T * malloc( void ); 4273 4334 forall( otype T ) T * malloc( char fill ); 4274 4335 forall( otype T ) T * malloc( T * ptr, size_t size ); 4275 4336 forall( otype T ) T * malloc( T * ptr, size_t size, unsigned char fill ); 4276 forall( otype T ) T * calloc( size_t nmemb );§\indexc{calloc}§4277 forall( otype T ) T * realloc( T * ptr, size_t size ); §\indexc{ato}§4337 forall( otype T ) T * calloc( size_t size ); 4338 forall( otype T ) T * realloc( T * ptr, size_t size ); 4278 4339 forall( otype T ) T * realloc( T * ptr, size_t size, unsigned char fill ); 4279 4340 4280 forall( otype T ) T * aligned_alloc( size_t alignment ); §\indexc{ato}§4341 forall( otype T ) T * aligned_alloc( size_t alignment ); 4281 4342 forall( otype T ) T * memalign( size_t alignment ); // deprecated 4282 4343 forall( otype T ) int posix_memalign( T ** ptr, size_t alignment ); … … 4287 4348 4288 4349 4289 \subsection{ato /strto}4290 4291 \begin{lstlisting} 4292 int ato( const char * ptr ); §\indexc{ato}§4350 \subsection{ato/strto} 4351 4352 \begin{lstlisting} 4353 int ato( const char * ptr ); 4293 4354 unsigned int ato( const char * ptr ); 4294 4355 long int ato( const char * ptr ); … … 4318 4379 4319 4380 4320 \subsection{bsearch /qsort}4381 \subsection{bsearch/qsort} 4321 4382 4322 4383 \begin{lstlisting} 4323 4384 forall( otype T | { int ?<?( T, T ); } ) 4324 T * bsearch( const T key, const T * arr, size_t dimension ); §\indexc{bsearch}§4385 T * bsearch( const T key, const T * arr, size_t dimension ); 4325 4386 4326 4387 forall( otype T | { int ?<?( T, T ); } ) 4327 void qsort( const T * arr, size_t dimension ); §\indexc{qsort}§4388 void qsort( const T * arr, size_t dimension ); 4328 4389 \end{lstlisting} 4329 4390 … … 4332 4393 4333 4394 \begin{lstlisting} 4334 char abs( char );§\indexc{abs}§ 4335 int abs( int ); 4395 char abs( char ); 4396 extern "C" { 4397 int abs( int ); // use default C routine for int 4398 } // extern "C" 4336 4399 long int abs( long int ); 4337 4400 long long int abs( long long int ); … … 4339 4402 double abs( double ); 4340 4403 long double abs( long double ); 4341 float abs( float _Complex ); 4342 double abs( double _Complex ); 4343 long double abs( long double _Complex ); 4404 float _Complex abs( float _Complex ); 4405 double _Complex abs( double _Complex ); 4406 long double _Complex abs( long double _Complex ); 4407 \end{lstlisting} 4408 4409 4410 \subsection{floor/ceil} 4411 4412 \begin{lstlisting} 4413 float floor( float ); 4414 extern "C" { 4415 double floor( double ); // use C routine for double 4416 } // extern "C" 4417 long double floor( long double ); 4418 4419 float ceil( float ); 4420 extern "C" { 4421 double ceil( double ); // use C routine for double 4422 } // extern "C" 4423 long double ceil( long double ); 4344 4424 \end{lstlisting} 4345 4425 … … 4348 4428 4349 4429 \begin{lstlisting} 4350 void rand48seed( long int s ); §\indexc{rand48seed}§4351 char rand48(); §\indexc{rand48}§4430 void rand48seed( long int s ); 4431 char rand48(); 4352 4432 int rand48(); 4353 4433 unsigned int rand48(); … … 4362 4442 4363 4443 4364 \subsection{min / max /swap}4444 \subsection{min/max/swap} 4365 4445 4366 4446 \begin{lstlisting} 4367 4447 forall( otype T | { int ?<?( T, T ); } ) 4368 T min( const T t1, const T t2 ); §\indexc{min}§4448 T min( const T t1, const T t2 ); 4369 4449 4370 4450 forall( otype T | { int ?>?( T, T ); } ) 4371 T max( const T t1, const T t2 ); §\indexc{max}§4451 T max( const T t1, const T t2 ); 4372 4452 4373 4453 forall( otype T ) 4374 void swap( T * t1, T * t2 );§\indexc{swap}§ 4375 \end{lstlisting} 4376 4377 4378 \section{Math Library} 4379 \label{s:Math Library} 4380 4381 The goal of the \CFA math-library is to wrap many of the existing C math library-routines that are explicitly polymorphic into implicitly polymorphic versions. 4382 4383 4384 \subsection{General} 4385 4386 \begin{lstlisting} 4387 float fabs( float );§\indexc{fabs}§ 4388 double fabs( double ); 4389 long double fabs( long double ); 4390 float cabs( float _Complex ); 4391 double cabs( double _Complex ); 4392 long double cabs( long double _Complex ); 4393 4394 float ?%?( float, float );§\indexc{fmod}§ 4395 float fmod( float, float ); 4396 double ?%?( double, double ); 4397 double fmod( double, double ); 4398 long double ?%?( long double, long double ); 4399 long double fmod( long double, long double ); 4400 4401 float remainder( float, float );§\indexc{remainder}§ 4402 double remainder( double, double ); 4403 long double remainder( long double, long double ); 4404 4405 [ int, float ] remquo( float, float );§\indexc{remquo}§ 4406 float remquo( float, float, int * ); 4407 [ int, double ] remquo( double, double ); 4408 double remquo( double, double, int * ); 4409 [ int, long double ] remquo( long double, long double ); 4410 long double remquo( long double, long double, int * ); 4411 4412 [ int, float ] div( float, float ); // alternative name for remquo 4413 float div( float, float, int * );§\indexc{div}§ 4414 [ int, double ] div( double, double ); 4415 double div( double, double, int * ); 4416 [ int, long double ] div( long double, long double ); 4417 long double div( long double, long double, int * ); 4418 4419 float fma( float, float, float );§\indexc{fma}§ 4420 double fma( double, double, double ); 4421 long double fma( long double, long double, long double ); 4422 4423 float fdim( float, float );§\indexc{fdim}§ 4424 double fdim( double, double ); 4425 long double fdim( long double, long double ); 4426 4427 float nan( const char * );§\indexc{nan}§ 4428 double nan( const char * ); 4429 long double nan( const char * ); 4430 \end{lstlisting} 4431 4432 4433 \subsection{Exponential} 4434 4435 \begin{lstlisting} 4436 float exp( float );§\indexc{exp}§ 4437 double exp( double ); 4438 long double exp( long double ); 4439 float _Complex exp( float _Complex ); 4440 double _Complex exp( double _Complex ); 4441 long double _Complex exp( long double _Complex ); 4442 4443 float exp2( float );§\indexc{exp2}§ 4444 double exp2( double ); 4445 long double exp2( long double ); 4446 float _Complex exp2( float _Complex ); 4447 double _Complex exp2( double _Complex ); 4448 long double _Complex exp2( long double _Complex ); 4449 4450 float expm1( float );§\indexc{expm1}§ 4451 double expm1( double ); 4452 long double expm1( long double ); 4453 4454 float log( float );§\indexc{log}§ 4455 double log( double ); 4456 long double log( long double ); 4457 float _Complex log( float _Complex ); 4458 double _Complex log( double _Complex ); 4459 long double _Complex log( long double _Complex ); 4460 4461 float log2( float );§\indexc{log2}§ 4462 double log2( double ); 4463 long double log2( long double ); 4464 float _Complex log2( float _Complex ); 4465 double _Complex log2( double _Complex ); 4466 long double _Complex log2( long double _Complex ); 4467 4468 float log10( float );§\indexc{log10}§ 4469 double log10( double ); 4470 long double log10( long double ); 4471 float _Complex log10( float _Complex ); 4472 double _Complex log10( double _Complex ); 4473 long double _Complex log10( long double _Complex ); 4474 4475 float log1p( float );§\indexc{log1p}§ 4476 double log1p( double ); 4477 long double log1p( long double ); 4478 4479 int ilogb( float );§\indexc{ilogb}§ 4480 int ilogb( double ); 4481 int ilogb( long double ); 4482 4483 float logb( float );§\indexc{logb}§ 4484 double logb( double ); 4485 long double logb( long double ); 4486 \end{lstlisting} 4487 4488 4489 \subsection{Power} 4490 4491 \begin{lstlisting} 4492 float sqrt( float );§\indexc{sqrt}§ 4493 double sqrt( double ); 4494 long double sqrt( long double ); 4495 float _Complex sqrt( float _Complex ); 4496 double _Complex sqrt( double _Complex ); 4497 long double _Complex sqrt( long double _Complex ); 4498 4499 float cbrt( float );§\indexc{cbrt}§ 4500 double cbrt( double ); 4501 long double cbrt( long double ); 4502 4503 float hypot( float, float );§\indexc{hypot}§ 4504 double hypot( double, double ); 4505 long double hypot( long double, long double ); 4506 4507 float pow( float, float );§\indexc{pow}§ 4508 double pow( double, double ); 4509 long double pow( long double, long double ); 4510 float _Complex pow( float _Complex, float _Complex ); 4511 double _Complex pow( double _Complex, double _Complex ); 4512 long double _Complex pow( long double _Complex, long double _Complex ); 4513 \end{lstlisting} 4514 4515 4516 \subsection{Trigonometric} 4517 4518 \begin{lstlisting} 4519 float sin( float );§\indexc{sin}§ 4520 double sin( double ); 4521 long double sin( long double ); 4522 float _Complex sin( float _Complex ); 4523 double _Complex sin( double _Complex ); 4524 long double _Complex sin( long double _Complex ); 4525 4526 float cos( float );§\indexc{cos}§ 4527 double cos( double ); 4528 long double cos( long double ); 4529 float _Complex cos( float _Complex ); 4530 double _Complex cos( double _Complex ); 4531 long double _Complex cos( long double _Complex ); 4532 4533 float tan( float );§\indexc{tan}§ 4534 double tan( double ); 4535 long double tan( long double ); 4536 float _Complex tan( float _Complex ); 4537 double _Complex tan( double _Complex ); 4538 long double _Complex tan( long double _Complex ); 4539 4540 float asin( float );§\indexc{asin}§ 4541 double asin( double ); 4542 long double asin( long double ); 4543 float _Complex asin( float _Complex ); 4544 double _Complex asin( double _Complex ); 4545 long double _Complex asin( long double _Complex ); 4546 4547 float acos( float );§\indexc{acos}§ 4548 double acos( double ); 4549 long double acos( long double ); 4550 float _Complex acos( float _Complex ); 4551 double _Complex acos( double _Complex ); 4552 long double _Complex acos( long double _Complex ); 4553 4554 float atan( float );§\indexc{atan}§ 4555 double atan( double ); 4556 long double atan( long double ); 4557 float _Complex atan( float _Complex ); 4558 double _Complex atan( double _Complex ); 4559 long double _Complex atan( long double _Complex ); 4560 4561 float atan2( float, float );§\indexc{atan2}§ 4562 double atan2( double, double ); 4563 long double atan2( long double, long double ); 4564 4565 float atan( float, float ); // alternative name for atan2 4566 double atan( double, double );§\indexc{atan}§ 4567 long double atan( long double, long double ); 4568 \end{lstlisting} 4569 4570 4571 \subsection{Hyperbolic} 4572 4573 \begin{lstlisting} 4574 float sinh( float );§\indexc{sinh}§ 4575 double sinh( double ); 4576 long double sinh( long double ); 4577 float _Complex sinh( float _Complex ); 4578 double _Complex sinh( double _Complex ); 4579 long double _Complex sinh( long double _Complex ); 4580 4581 float cosh( float );§\indexc{cosh}§ 4582 double cosh( double ); 4583 long double cosh( long double ); 4584 float _Complex cosh( float _Complex ); 4585 double _Complex cosh( double _Complex ); 4586 long double _Complex cosh( long double _Complex ); 4587 4588 float tanh( float );§\indexc{tanh}§ 4589 double tanh( double ); 4590 long double tanh( long double ); 4591 float _Complex tanh( float _Complex ); 4592 double _Complex tanh( double _Complex ); 4593 long double _Complex tanh( long double _Complex ); 4594 4595 float asinh( float );§\indexc{asinh}§ 4596 double asinh( double ); 4597 long double asinh( long double ); 4598 float _Complex asinh( float _Complex ); 4599 double _Complex asinh( double _Complex ); 4600 long double _Complex asinh( long double _Complex ); 4601 4602 float acosh( float );§\indexc{acosh}§ 4603 double acosh( double ); 4604 long double acosh( long double ); 4605 float _Complex acosh( float _Complex ); 4606 double _Complex acosh( double _Complex ); 4607 long double _Complex acosh( long double _Complex ); 4608 4609 float atanh( float );§\indexc{atanh}§ 4610 double atanh( double ); 4611 long double atanh( long double ); 4612 float _Complex atanh( float _Complex ); 4613 double _Complex atanh( double _Complex ); 4614 long double _Complex atanh( long double _Complex ); 4615 \end{lstlisting} 4616 4617 4618 \subsection{Error / Gamma} 4619 4620 \begin{lstlisting} 4621 float erf( float );§\indexc{erf}§ 4622 double erf( double ); 4623 long double erf( long double ); 4624 float _Complex erf( float _Complex ); 4625 double _Complex erf( double _Complex ); 4626 long double _Complex erf( long double _Complex ); 4627 4628 float erfc( float );§\indexc{erfc}§ 4629 double erfc( double ); 4630 long double erfc( long double ); 4631 float _Complex erfc( float _Complex ); 4632 double _Complex erfc( double _Complex ); 4633 long double _Complex erfc( long double _Complex ); 4634 4635 float lgamma( float );§\indexc{lgamma}§ 4636 double lgamma( double ); 4637 long double lgamma( long double ); 4638 float lgamma( float, int * ); 4639 double lgamma( double, int * ); 4640 long double lgamma( long double, int * ); 4641 4642 float tgamma( float );§\indexc{tgamma}§ 4643 double tgamma( double ); 4644 long double tgamma( long double ); 4645 \end{lstlisting} 4646 4647 4648 \subsection{Nearest Integer} 4649 4650 \begin{lstlisting} 4651 float floor( float );§\indexc{floor}§ 4652 double floor( double ); 4653 long double floor( long double ); 4654 4655 float ceil( float );§\indexc{ceil}§ 4656 double ceil( double ); 4657 long double ceil( long double ); 4658 4659 float trunc( float );§\indexc{trunc}§ 4660 double trunc( double ); 4661 long double trunc( long double ); 4662 4663 float rint( float );§\indexc{rint}§ 4664 long double rint( long double ); 4665 long int rint( float ); 4666 long int rint( double ); 4667 long int rint( long double ); 4668 long long int rint( float ); 4669 long long int rint( double ); 4670 long long int rint( long double ); 4671 4672 long int lrint( float );§\indexc{lrint}§ 4673 long int lrint( double ); 4674 long int lrint( long double ); 4675 long long int llrint( float ); 4676 long long int llrint( double ); 4677 long long int llrint( long double ); 4678 4679 float nearbyint( float );§\indexc{nearbyint}§ 4680 double nearbyint( double ); 4681 long double nearbyint( long double ); 4682 4683 float round( float );§\indexc{round}§ 4684 long double round( long double ); 4685 long int round( float ); 4686 long int round( double ); 4687 long int round( long double ); 4688 long long int round( float ); 4689 long long int round( double ); 4690 long long int round( long double ); 4691 4692 long int lround( float );§\indexc{lround}§ 4693 long int lround( double ); 4694 long int lround( long double ); 4695 long long int llround( float ); 4696 long long int llround( double ); 4697 long long int llround( long double ); 4698 \end{lstlisting} 4699 4700 4701 \subsection{Manipulation} 4702 4703 \begin{lstlisting} 4704 float copysign( float, float );§\indexc{copysign}§ 4705 double copysign( double, double ); 4706 long double copysign( long double, long double ); 4707 4708 float frexp( float, int * );§\indexc{frexp}§ 4709 double frexp( double, int * ); 4710 long double frexp( long double, int * ); 4711 4712 float ldexp( float, int );§\indexc{ldexp}§ 4713 double ldexp( double, int ); 4714 long double ldexp( long double, int ); 4715 4716 [ float, float ] modf( float );§\indexc{modf}§ 4717 float modf( float, float * ); 4718 [ double, double ] modf( double ); 4719 double modf( double, double * ); 4720 [ long double, long double ] modf( long double ); 4721 long double modf( long double, long double * ); 4722 4723 float nextafter( float, float );§\indexc{nextafter}§ 4724 double nextafter( double, double ); 4725 long double nextafter( long double, long double ); 4726 4727 float nexttoward( float, long double );§\indexc{nexttoward}§ 4728 double nexttoward( double, long double ); 4729 long double nexttoward( long double, long double ); 4730 4731 float scalbn( float, int );§\indexc{scalbn}§ 4732 double scalbn( double, int ); 4733 long double scalbn( long double, int ); 4734 4735 float scalbln( float, long int );§\indexc{scalbln}§ 4736 double scalbln( double, long int ); 4737 long double scalbln( long double, long int ); 4454 void swap( T * t1, T * t2 ); 4738 4455 \end{lstlisting} 4739 4456 … … 4747 4464 \begin{lstlisting} 4748 4465 // implementation 4749 struct Rational { §\indexc{Rational}§4466 struct Rational { 4750 4467 long int numerator, denominator; // invariant: denominator > 0 4751 4468 }; // Rational -
src/CodeGen/CodeGenerator.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // CodeGenerator.cc -- 7 // CodeGenerator.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 11:59:36 201613 // Update Count : 2 5511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:32:16 2016 13 // Update Count : 243 14 14 // 15 15 … … 67 67 string mangleName( DeclarationWithType *decl ) { 68 68 if ( decl->get_mangleName() != "" ) { 69 // need to incorporate scope level in order to differentiate names for destructors 70 return decl->get_scopedMangleName(); 69 return decl->get_mangleName(); 71 70 } else { 72 71 return decl->get_name(); … … 100 99 handleStorageClass( objectDecl ); 101 100 output << genType( objectDecl->get_type(), mangleName( objectDecl ) ); 102 101 103 102 if ( objectDecl->get_init() ) { 104 103 output << " = "; … … 114 113 if ( aggDecl->get_name() != "" ) 115 114 output << aggDecl->get_name(); 116 115 117 116 std::list< Declaration * > &memb = aggDecl->get_members(); 118 117 … … 120 119 output << " {" << endl; 121 120 122 cur_indent += CodeGenerator::tabsize; 121 cur_indent += CodeGenerator::tabsize; 123 122 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++) { 124 output << indent; 123 output << indent; 125 124 (*i)->accept( *this ); 126 125 output << ";" << endl; 127 126 } 128 127 129 cur_indent -= CodeGenerator::tabsize; 128 cur_indent -= CodeGenerator::tabsize; 130 129 131 130 output << indent << "}"; … … 142 141 handleAggregate( aggregateDecl ); 143 142 } 144 143 145 144 void CodeGenerator::visit( EnumDecl *aggDecl ) { 146 145 output << "enum "; … … 148 147 if ( aggDecl->get_name() != "" ) 149 148 output << aggDecl->get_name(); 150 149 151 150 std::list< Declaration* > &memb = aggDecl->get_members(); 152 151 … … 154 153 output << " {" << endl; 155 154 156 cur_indent += CodeGenerator::tabsize; 155 cur_indent += CodeGenerator::tabsize; 157 156 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++) { 158 157 ObjectDecl *obj = dynamic_cast< ObjectDecl* >( *i ); 159 158 assert( obj ); 160 output << indent << mangleName( obj ); 159 output << indent << mangleName( obj ); 161 160 if ( obj->get_init() ) { 162 161 output << " = "; … … 166 165 } // for 167 166 168 cur_indent -= CodeGenerator::tabsize; 167 cur_indent -= CodeGenerator::tabsize; 169 168 170 169 output << indent << "}"; 171 170 } // if 172 171 } 173 172 174 173 void CodeGenerator::visit( TraitDecl *aggregateDecl ) {} 175 174 176 175 void CodeGenerator::visit( TypedefDecl *typeDecl ) { 177 176 output << "typedef "; 178 177 output << genType( typeDecl->get_base(), typeDecl->get_name() ); 179 178 } 180 179 181 180 void CodeGenerator::visit( TypeDecl *typeDecl ) { 182 181 // really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes, … … 214 213 printDesignators( init->get_designators() ); 215 214 output << "{ "; 216 if ( init->begin_initializers() == init->end_initializers() ) { 217 // illegal to leave initializer list empty for scalar initializers, 218 // but always legal to have 0 219 output << "0"; 220 } else { 221 genCommaList( init->begin_initializers(), init->end_initializers() ); 222 } 215 genCommaList( init->begin_initializers(), init->end_initializers() ); 223 216 output << " }"; 224 217 } 225 218 226 void CodeGenerator::visit( Constant *constant ) { 219 void CodeGenerator::visit( Constant *constant ) { 227 220 output << constant->get_value() ; 228 221 } … … 238 231 case OT_POSTFIXASSIGN: 239 232 case OT_INFIXASSIGN: 240 case OT_CTOR:241 case OT_DTOR:242 233 { 243 234 assert( arg != applicationExpr->get_args().end() ); 244 235 if ( AddressExpr *addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) { 245 // remove & from first assignment/ctor argument236 246 237 *arg = addrExpr->get_arg(); 247 238 } else { 248 // no address-of operator, so must be a pointer - add dereference249 239 UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) ); 250 240 newExpr->get_args().push_back( *arg ); … … 253 243 break; 254 244 } 255 245 256 246 default: 257 247 // do nothing 258 248 ; 259 249 } 260 250 261 251 switch ( opInfo.type ) { 262 252 case OT_INDEX: … … 267 257 output << "]"; 268 258 break; 269 259 270 260 case OT_CALL: 271 261 // there are no intrinsic definitions of the function call operator 272 262 assert( false ); 273 263 break; 274 275 case OT_CTOR: 276 case OT_DTOR: 277 if ( applicationExpr->get_args().size() == 1 ) { 278 // the expression fed into a single parameter constructor or destructor 279 // may contain side effects - output as a void expression 280 output << "((void)("; 281 (*arg++)->accept( *this ); 282 output << ")) /* " << opInfo.inputName << " */"; 283 } else if ( applicationExpr->get_args().size() == 2 ) { 284 // intrinsic two parameter constructors are essentially bitwise assignment 285 output << "("; 286 (*arg++)->accept( *this ); 287 output << opInfo.symbol; 288 (*arg)->accept( *this ); 289 output << ") /* " << opInfo.inputName << " */"; 290 } else { 291 // no constructors with 0 or more than 2 parameters 292 assert( false ); 293 } 294 break; 295 264 296 265 case OT_PREFIX: 297 266 case OT_PREFIXASSIGN: … … 302 271 output << ")"; 303 272 break; 304 273 305 274 case OT_POSTFIX: 306 275 case OT_POSTFIXASSIGN: … … 309 278 output << opInfo.symbol; 310 279 break; 311 312 280 313 281 case OT_INFIX: … … 320 288 output << ")"; 321 289 break; 322 290 323 291 case OT_CONSTANT: 324 292 case OT_LABELADDRESS: … … 339 307 } // if 340 308 } 341 309 342 310 void CodeGenerator::visit( UntypedExpr *untypedExpr ) { 343 311 if ( NameExpr *nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) { … … 353 321 output << "]"; 354 322 break; 355 323 356 324 case OT_CALL: 357 325 assert( false ); 358 359 360 case OT_CTOR: 361 case OT_DTOR: 362 if ( untypedExpr->get_args().size() == 1 ) { 363 // the expression fed into a single parameter constructor or destructor 364 // may contain side effects - output as a void expression 365 output << "((void)("; 366 (*arg++)->accept( *this ); 367 output << ")) /* " << opInfo.inputName << " */"; 368 } else if ( untypedExpr->get_args().size() == 2 ) { 369 // intrinsic two parameter constructors are essentially bitwise assignment 370 output << "("; 371 (*arg++)->accept( *this ); 372 output << opInfo.symbol; 373 (*arg)->accept( *this ); 374 output << ") /* " << opInfo.inputName << " */"; 375 } else { 376 // no constructors with 0 or more than 2 parameters 377 assert( false ); 378 } 379 break; 380 326 break; 327 381 328 case OT_PREFIX: 382 329 case OT_PREFIXASSIGN: … … 388 335 output << ")"; 389 336 break; 390 337 391 338 case OT_POSTFIX: 392 339 case OT_POSTFIXASSIGN: … … 395 342 output << opInfo.symbol; 396 343 break; 397 344 398 345 case OT_INFIX: 399 346 case OT_INFIXASSIGN: … … 405 352 output << ")"; 406 353 break; 407 354 408 355 case OT_CONSTANT: 409 356 // there are no intrinsic definitions of 0 or 1 as functions … … 423 370 } // if 424 371 } 425 372 426 373 void CodeGenerator::visit( NameExpr *nameExpr ) { 427 374 OperatorInfo opInfo; … … 433 380 } // if 434 381 } 435 382 436 383 void CodeGenerator::visit( AddressExpr *addressExpr ) { 437 384 output << "(&"; … … 462 409 output << ")"; 463 410 } 464 411 465 412 void CodeGenerator::visit( UntypedMemberExpr *memberExpr ) { 466 413 assert( false ); 467 414 } 468 415 469 416 void CodeGenerator::visit( MemberExpr *memberExpr ) { 470 417 memberExpr->get_aggregate()->accept( *this ); 471 418 output << "." << mangleName( memberExpr->get_member() ); 472 419 } 473 420 474 421 void CodeGenerator::visit( VariableExpr *variableExpr ) { 475 422 OperatorInfo opInfo; … … 480 427 } // if 481 428 } 482 429 483 430 void CodeGenerator::visit( ConstantExpr *constantExpr ) { 484 431 assert( constantExpr->get_constant() ); 485 432 constantExpr->get_constant()->accept( *this ); 486 433 } 487 434 488 435 void CodeGenerator::visit( SizeofExpr *sizeofExpr ) { 489 436 output << "sizeof("; … … 522 469 assert( false && "OffsetPackExpr should not reach code generation" ); 523 470 } 524 471 525 472 void CodeGenerator::visit( LogicalExpr *logicalExpr ) { 526 473 output << "("; … … 534 481 output << ")"; 535 482 } 536 483 537 484 void CodeGenerator::visit( ConditionalExpr *conditionalExpr ) { 538 485 output << "("; … … 544 491 output << ")"; 545 492 } 546 493 547 494 void CodeGenerator::visit( CommaExpr *commaExpr ) { 548 495 output << "("; … … 552 499 output << ")"; 553 500 } 554 501 555 502 void CodeGenerator::visit( TupleExpr *tupleExpr ) {} 556 503 557 504 void CodeGenerator::visit( TypeExpr *typeExpr ) {} 558 505 … … 585 532 } 586 533 } 587 cur_indent -= CodeGenerator::tabsize; 534 cur_indent -= CodeGenerator::tabsize; 588 535 589 536 output << indent << "}"; … … 591 538 592 539 void CodeGenerator::visit( ExprStmt *exprStmt ) { 593 // I don't see why this check is necessary. 594 // If this starts to cause problems then put it back in, 540 // I don't see why this check is necessary. 541 // If this starts to cause problems then put it back in, 595 542 // with an explanation 596 543 assert( exprStmt ); … … 642 589 switchStmt->get_condition()->accept( *this ); 643 590 output << " ) "; 644 591 645 592 output << "{" << std::endl; 646 593 cur_indent += CodeGenerator::tabsize; … … 662 609 } // if 663 610 output << ":\n"; 664 611 665 612 std::list<Statement *> sts = caseStmt->get_statements(); 666 613 … … 679 626 if ( ! branchStmt->get_target().empty() ) 680 627 output << "goto " << branchStmt->get_target(); 681 else { 628 else { 682 629 if ( branchStmt->get_computedTarget() != 0 ) { 683 630 output << "goto *"; … … 730 677 731 678 void CodeGenerator::visit( ForStmt *forStmt ) { 732 // initialization is always hoisted, so don't 733 // bother doing anything with that 679 // initialization is always hoisted, so don't 680 // bother doing anything with that 734 681 output << "for (;"; 735 682 … … 755 702 void CodeGenerator::visit( DeclStmt *declStmt ) { 756 703 declStmt->get_decl()->accept( *this ); 757 704 758 705 if ( doSemicolon( declStmt->get_decl() ) ) { 759 706 output << ";"; -
src/CodeGen/FixNames.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FixNames.cc -- 7 // FixNames.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon Apr 11 15:38:10 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon May 18 23:36:42 2015 13 13 // Update Count : 1 14 14 // … … 26 26 virtual void visit( ObjectDecl *objectDecl ); 27 27 virtual void visit( FunctionDecl *functionDecl ); 28 29 virtual void visit( CompoundStmt *compoundStmt );30 31 private:32 int scopeLevel = 1;33 34 void fixDWT( DeclarationWithType *dwt );35 28 }; 36 29 … … 40 33 } 41 34 42 void FixNames::fixDWT( DeclarationWithType *dwt ) {35 void fixDWT( DeclarationWithType *dwt ) { 43 36 if ( dwt->get_name() != "" ) { 44 37 if ( LinkageSpec::isDecoratable( dwt->get_linkage() ) ) { 45 38 dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) ); 46 dwt->set_scopeLevel( scopeLevel );47 39 } // if 48 40 } // if … … 58 50 fixDWT( functionDecl ); 59 51 } 60 61 void FixNames::visit( CompoundStmt *compoundStmt ) {62 scopeLevel++;63 Visitor::visit( compoundStmt );64 scopeLevel--;65 }66 52 } // namespace CodeGen 67 53 -
src/CodeGen/OperatorTable.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // OperatorTable.cc -- 7 // OperatorTable.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : T hu Apr 14 16:48:27 201613 // Update Count : 911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jun 23 17:41:14 2015 13 // Update Count : 5 14 14 // 15 15 … … 21 21 const OperatorInfo tableValues[] = { 22 22 { "?[?]", "", "_operator_index", OT_INDEX }, 23 { "?{}", "=", "_constructor", OT_CTOR },24 { "^?{}", "", "_destructor", OT_DTOR },25 23 { "?()", "", "_operator_call", OT_CALL }, 26 24 { "?++", "++", "_operator_postincr", OT_POSTFIXASSIGN }, -
src/CodeGen/OperatorTable.h
r7cc6bd6 r9243a501 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Jun 24 16:17:57 201513 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jun 23 16:09:27 2015 13 // Update Count : 3 14 14 // 15 15 … … 22 22 enum OperatorType { 23 23 OT_INDEX, 24 OT_CTOR,25 OT_DTOR,26 24 OT_CALL, 27 25 OT_PREFIX, -
src/GenPoly/Box.cc
r7cc6bd6 r9243a501 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue May 03 16:44:47 201613 // Update Count : 2 9511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 5 16:45:07 2016 13 // Update Count : 286 14 14 // 15 15 … … 133 133 Value *lookup( Key *key, const std::list< TypeExpr* >& params ) const { 134 134 TypeList typeList( params ); 135 135 136 136 // scan scopes for matches to the key 137 137 for ( typename InnerMap::const_iterator insts = instantiations.find( key ); insts != instantiations.end(); insts = instantiations.findNext( insts, key ) ) { … … 160 160 virtual Declaration *mutate( UnionDecl *unionDecl ); 161 161 }; 162 162 163 163 /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call 164 164 class Pass1 : public PolyMutator { … … 208 208 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; ///< Currently known assignment operators 209 209 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope 210 210 211 211 DeclarationWithType *retval; 212 212 bool useRetval; … … 226 226 virtual Type *mutate( PointerType *pointerType ); 227 227 virtual Type *mutate( FunctionType *funcType ); 228 228 229 229 private: 230 230 void addAdapters( FunctionType *functionType ); … … 297 297 /// Exits the type-variable scope 298 298 void endTypeScope(); 299 299 300 300 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName 301 301 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName … … 351 351 PolyGenericCalculator polyCalculator; 352 352 Pass3 pass3; 353 353 354 354 layoutBuilder.mutateDeclarationList( translationUnit ); 355 355 mutateTranslationUnit/*All*/( translationUnit, pass1 ); … … 370 370 return functionDecl; 371 371 } 372 372 373 373 /// Get a list of type declarations that will affect a layout function 374 374 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) { … … 380 380 } 381 381 } 382 382 383 383 return otypeDecls; 384 384 } … … 387 387 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) { 388 388 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 389 389 390 390 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) { 391 391 TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param ); … … 444 444 return makeCond( ifCond, ifExpr ); 445 445 } 446 446 447 447 /// adds an expression to a compound statement 448 448 void addExpr( CompoundStmt *stmts, Expression *expr ) { … … 454 454 stmts->get_kids().push_back( stmt ); 455 455 } 456 456 457 457 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) { 458 458 // do not generate layout function for "empty" tag structs … … 467 467 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 468 468 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 469 469 470 470 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 471 471 layoutFnType->get_parameters().push_back( sizeParam ); … … 497 497 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) ); 498 498 } 499 499 500 500 // place current size in the current offset index 501 501 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ), … … 505 505 // add member size to current size 506 506 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) ); 507 507 508 508 // take max of member alignment and global alignment 509 509 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) ); … … 515 515 return structDecl; 516 516 } 517 517 518 518 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) { 519 519 // do not generate layout function for "empty" tag unions 520 520 if ( unionDecl->get_members().empty() ) return unionDecl; 521 521 522 522 // get parameters that can change layout, exiting early if none 523 523 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() ); … … 528 528 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ); 529 529 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType ); 530 530 531 531 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 ); 532 532 layoutFnType->get_parameters().push_back( sizeParam ); … … 545 545 assert( dwt ); 546 546 Type *memberType = dwt->get_type(); 547 547 548 548 // take max member size and global size 549 549 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) ); 550 550 551 551 // take max of member alignment and global alignment 552 552 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) ); … … 558 558 return unionDecl; 559 559 } 560 560 561 561 ////////////////////////////////////////// Pass1 //////////////////////////////////////////////////// 562 562 … … 619 619 return 0; 620 620 } 621 621 622 622 /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise 623 623 /// Only picks assignments where neither parameter is cv-qualified … … 631 631 Type *paramType2 = funType->get_parameters().back()->get_type(); 632 632 if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0; 633 633 634 634 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) { 635 635 Type *baseType1 = pointerType->get_base(); … … 784 784 arg++; 785 785 } else { 786 /// xxx - should this be an assertion? 787 throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr ); 786 throw SemanticError( "unbound type variable in application ", appExpr ); 788 787 } // if 789 788 } // if … … 804 803 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes ); 805 804 } 806 805 807 806 // add type information args for presently unseen types in parameter list 808 807 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) { … … 883 882 assert( env ); 884 883 Type *concrete = replaceWithConcrete( appExpr, polyType ); 885 // add out-parameter for return value 884 // add out-parameter for return value 886 885 return addRetParam( appExpr, function, concrete, arg ); 887 886 } … … 911 910 } else if ( arg->get_results().front()->get_isLvalue() ) { 912 911 // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue) 913 // xxx - need to test that this code is still reachable914 912 if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) { 915 913 commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) ); … … 1293 1291 } else if ( needsAdapter( function, scopeTyVars ) ) { 1294 1292 // std::cerr << "needs adapter: "; 1295 // printTyVarMap( std::cerr, scopeTyVars ); 1296 // std::cerr << *env << std::endl; 1293 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { 1294 // std::cerr << i->first << " "; 1295 // } 1296 // std::cerr << "\n"; 1297 1297 // change the application so it calls the adapter rather than the passed function 1298 1298 ret = applyAdapter( appExpr, function, arg, scopeTyVars ); … … 1345 1345 } // if 1346 1346 } // if 1347 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward1348 // out of the if condition.1349 bool polytype = isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env );1350 1347 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) ); 1351 if ( polytype|| needs ) {1348 if ( isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env ) || needs ) { 1352 1349 Expression *ret = addrExpr->get_arg(); 1353 1350 delete ret->get_results().front(); … … 1369 1366 return new VariableExpr( functionObj ); 1370 1367 } 1371 1368 1372 1369 Statement * Pass1::mutate( ReturnStmt *returnStmt ) { 1373 1370 if ( retval && returnStmt->get_expr() ) { … … 1889 1886 } 1890 1887 } 1891 1888 1892 1889 Type *ret = Mutator::mutate( funcType ); 1893 1890 … … 1908 1905 1909 1906 std::list<Expression*> designators; 1910 objectDecl->set_init( new SingleInit( alloc, designators , false ) ); // not constructed1907 objectDecl->set_init( new SingleInit( alloc, designators ) ); 1911 1908 } 1912 1909 } … … 1949 1946 return derefdVar; 1950 1947 } 1951 1948 1952 1949 Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) { 1953 1950 // mutate, exiting early if no longer MemberExpr … … 2147 2144 Type *ty = offsetofExpr->get_type(); 2148 2145 if ( ! findGeneric( ty ) ) return offsetofExpr; 2149 2146 2150 2147 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) { 2151 2148 // replace offsetof expression by index into offset array -
src/GenPoly/CopyParams.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // CopyParams.cc -- 7 // CopyParams.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz11 // Last Modified By : Peter A. Buhr 12 12 // Last Modified On : Tue May 19 07:33:31 2015 13 13 // Update Count : 1 … … 29 29 public: 30 30 CopyParams(); 31 31 32 32 virtual void visit( FunctionDecl *funcDecl ); 33 33 virtual void visit( AddressExpr *addrExpr ); … … 50 50 if ( funcDecl->get_statements() ) { 51 51 funcDecl->get_statements()->accept( *this ); 52 52 53 53 if ( ! modVars.empty() ) { 54 54 std::map< std::string, DeclarationWithType* > assignOps; … … 57 57 if ( (*tyVar)->get_kind() == TypeDecl::Any ) { 58 58 assert( !(*tyVar)->get_assertions().empty() ); 59 assert( (*tyVar)->get_assertions().front()->get_name() == "?=?" );60 59 assignOps[ (*tyVar)->get_name() ] = (*tyVar)->get_assertions().front(); 61 60 } // if -
src/GenPoly/GenPoly.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // GenPoly.cc -- 7 // GenPoly.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon May 02 14:53:33 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 15 16:11:18 2015 13 13 // Update Count : 13 14 14 // … … 81 81 return 0; 82 82 } 83 83 84 84 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { 85 85 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { … … 112 112 return 0; 113 113 } 114 114 115 115 Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { 116 116 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { … … 146 146 return isPolyType( type, env ); 147 147 } 148 148 149 149 Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) { 150 150 int dummy; … … 192 192 if ( ! fn || fn->get_name() != std::string("*?") ) return 0; 193 193 expr = *untypedExpr->begin_args(); 194 } else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) {195 // copy constructors insert comma exprs, look at second argument which contains the variable196 expr = commaExpr->get_arg2();197 continue;198 194 } else break; 199 195 … … 213 209 } 214 210 } 215 211 216 212 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) { 217 213 for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) { -
src/GenPoly/PolyMutator.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // PolyMutator.cc -- 7 // PolyMutator.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Mon May 02 14:50:58 201612 // Last Modified On : Fri Aug 14 15:28:50 2015 13 13 // Update Count : 11 14 14 // … … 63 63 env = expr->get_env(); 64 64 } 65 // xxx - should env be cloned (or moved) onto the result of the mutate?66 65 return expr->acceptMutator( *this ); 67 66 } else { … … 145 144 return untypedExpr; 146 145 } 147 148 146 147 149 148 Initializer *PolyMutator::mutate( SingleInit *singleInit ) { 150 149 singleInit->set_value( mutateExpression( singleInit->get_value() ) ); -
src/GenPoly/Specialize.cc
r7cc6bd6 r9243a501 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Thu Apr 28 15:17:45201613 // Update Count : 2412 // Last Modified On : Wed Jan 20 12:40:33 2016 13 // Update Count : 18 14 14 // 15 15 … … 41 41 virtual Expression * mutate( AddressExpr *castExpr ); 42 42 virtual Expression * mutate( CastExpr *castExpr ); 43 //virtual Expression * mutate( LogicalExpr *logicalExpr );44 //virtual Expression * mutate( ConditionalExpr *conditionalExpr );45 //virtual Expression * mutate( CommaExpr *commaExpr );43 virtual Expression * mutate( LogicalExpr *logicalExpr ); 44 virtual Expression * mutate( ConditionalExpr *conditionalExpr ); 45 virtual Expression * mutate( CommaExpr *commaExpr ); 46 46 47 47 private: … … 142 142 143 143 Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) { 144 assert( ! actual->get_results().empty() ); // using front, should have this assert144 assert( ! actual->get_results().empty() ); 145 145 if ( needsSpecialization( formalType, actual->get_results().front(), env ) ) { 146 146 FunctionType *funType; … … 212 212 } 213 213 214 // Removing these for now. Richard put these in for some reason, but it's not clear why. 215 // In particular, copy constructors produce a comma expression, and with this code the parts 216 // of that comma expression are not specialized, which causes problems. 217 218 // Expression * Specialize::mutate( LogicalExpr *logicalExpr ) { 219 // return logicalExpr; 220 // } 221 222 // Expression * Specialize::mutate( ConditionalExpr *condExpr ) { 223 // return condExpr; 224 // } 225 226 // Expression * Specialize::mutate( CommaExpr *commaExpr ) { 227 // return commaExpr; 228 // } 214 Expression * Specialize::mutate( LogicalExpr *logicalExpr ) { 215 return logicalExpr; 216 } 217 218 Expression * Specialize::mutate( ConditionalExpr *condExpr ) { 219 return condExpr; 220 } 221 222 Expression * Specialize::mutate( CommaExpr *commaExpr ) { 223 return commaExpr; 224 } 229 225 } // namespace GenPoly 230 226 -
src/InitTweak/InitModel.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // InitModel.cc -- 7 // InitModel.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : T hu Jan 07 13:38:46 201613 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 19 16:37:08 2015 13 // Update Count : 1 14 14 // 15 15 … … 198 198 assert(init == 0 && single != 0); 199 199 std::list< Expression * > empty; 200 init = new SingleInit( single->get_expr(), empty , false ); // cannot be constructed200 init = new SingleInit( single->get_expr(), empty ); 201 201 return; 202 202 } … … 214 214 } // if 215 215 216 std::list< Expression * > desig; 217 init = new ListInit( contents, desig, false ); // cannot be constructed 216 init = new ListInit( contents ); 218 217 return; 219 218 } -
src/InitTweak/module.mk
r7cc6bd6 r9243a501 11 11 ## Created On : Mon Jun 1 17:49:17 2015 12 12 ## Last Modified By : Rob Schluntz 13 ## Last Modified On : Thu Apr 28 12:23:17201614 ## Update Count : 313 ## Last Modified On : Mon Jan 11 14:40:16 2016 14 ## Update Count : 2 15 15 ############################################################################### 16 16 17 SRC += InitTweak/ GenInit.cc \18 InitTweak/FixInit.cc 17 SRC += InitTweak/RemoveInit.cc 18 -
src/MakeLibCfa.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // MakeLibCfa.cc -- 7 // MakeLibCfa.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 10:33:33 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri Apr 22 13:54:15 201613 // Update Count : 4014 // 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 26 16:52:59 2015 13 // Update Count : 14 14 // 15 15 16 16 #include "MakeLibCfa.h" … … 29 29 void visit( FunctionDecl* funcDecl ); 30 30 void visit( ObjectDecl* objDecl ); 31 31 32 32 std::list< Declaration* > &get_newDecls() { return newDecls; } 33 33 private: … … 43 43 void MakeLibCfa::visit( FunctionDecl* origFuncDecl ) { 44 44 if ( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return; 45 if ( origFuncDecl->get_statements() ) return; 46 45 47 46 FunctionDecl *funcDecl = origFuncDecl->clone(); 48 47 CodeGen::OperatorInfo opInfo; … … 55 54 assert( param != funcDecl->get_functionType()->get_parameters().end() ); 56 55 57 for ( ; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) { 58 if ( (*param)->get_name() == "" ) { 59 (*param)->set_name( paramNamer.newName() ); 60 (*param)->set_linkage( LinkageSpec::C ); 61 } 62 newExpr->get_args().push_back( new VariableExpr( *param ) ); 63 } // for 64 65 funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) ); 66 newDecls.push_back( funcDecl ); 56 if ( (*param)->get_name() == "" ) { 57 (*param)->set_name( paramNamer.newName() ); 58 (*param)->set_linkage( LinkageSpec::C ); 59 } // if 67 60 68 61 switch ( opInfo.type ) { … … 72 65 case CodeGen::OT_POSTFIX: 73 66 case CodeGen::OT_INFIX: 67 newExpr->get_args().push_back( new VariableExpr( *param ) ); 68 break; 74 69 case CodeGen::OT_PREFIXASSIGN: 75 70 case CodeGen::OT_POSTFIXASSIGN: 76 71 case CodeGen::OT_INFIXASSIGN: 77 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) ); 72 { 73 newExpr->get_args().push_back( new VariableExpr( *param ) ); 74 // UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 75 // deref->get_args().push_back( new VariableExpr( *param ) ); 76 // newExpr->get_args().push_back( deref ); 78 77 break; 79 case CodeGen::OT_CTOR: 80 // ctors don't return a value 81 if ( funcDecl->get_functionType()->get_parameters().size() == 1 ) { 82 // intrinsic default constructors should do nothing 83 // delete newExpr; 84 break; 85 } else { 86 assert( funcDecl->get_functionType()->get_parameters().size() == 2 ); 87 // anything else is a single parameter constructor that is effectively a C-style assignment 88 // delete newExpr->get_function(); 89 assert(newExpr->get_args().size()==2); 90 newExpr->set_function( new NameExpr( "?=?" ) ); 91 funcDecl->get_statements()->get_kids().push_back( new ExprStmt( std::list< Label >(), newExpr ) ); 92 } 93 break; 94 case CodeGen::OT_DTOR: 95 // intrinsic destructors should do nothing 96 // delete newExpr; 97 break; 78 } 98 79 case CodeGen::OT_CONSTANT: 99 80 case CodeGen::OT_LABELADDRESS: … … 101 82 assert( false ); 102 83 } // switch 84 85 for ( param++; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) { 86 if ( (*param)->get_name() == "" ) { 87 (*param)->set_name( paramNamer.newName() ); 88 (*param)->set_linkage( LinkageSpec::C ); 89 } 90 newExpr->get_args().push_back( new VariableExpr( *param ) ); 91 } // for 92 funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) ); 93 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) ); 94 newDecls.push_back( funcDecl ); 103 95 } 104 96 105 97 void MakeLibCfa::visit( ObjectDecl* origObjDecl ) { 106 98 if ( origObjDecl->get_linkage() != LinkageSpec::Intrinsic ) return; 107 99 108 100 ObjectDecl *objDecl = origObjDecl->clone(); 109 101 assert( ! objDecl->get_init() ); 110 102 std::list< Expression* > noDesignators; 111 objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators , false ) ); // cannot be constructed103 objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators ) ); 112 104 newDecls.push_back( objDecl ); 113 105 } 114 106 } // namespace LibCfa 107 108 // Local Variables: // 109 // tab-width: 4 // 110 // mode: c++ // 111 // compile-command: "make install" // 112 // End: // -
src/Makefile.in
r7cc6bd6 r9243a501 123 123 GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \ 124 124 GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \ 125 InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) \ 126 InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT) \ 125 InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT) \ 127 126 Parser/driver_cfa_cpp-parser.$(OBJEXT) \ 128 127 Parser/driver_cfa_cpp-lex.$(OBJEXT) \ … … 160 159 SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT) \ 161 160 SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT) \ 162 SymTab/driver_cfa_cpp-Autogen.$(OBJEXT) \163 161 SynTree/driver_cfa_cpp-Type.$(OBJEXT) \ 164 162 SynTree/driver_cfa_cpp-VoidType.$(OBJEXT) \ … … 347 345 GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \ 348 346 GenPoly/CopyParams.cc GenPoly/FindFunction.cc \ 349 GenPoly/DeclMutator.cc InitTweak/GenInit.cc \ 350 InitTweak/FixInit.cc Parser/parser.yy Parser/lex.ll \ 351 Parser/TypedefTable.cc Parser/ParseNode.cc \ 352 Parser/DeclarationNode.cc Parser/ExpressionNode.cc \ 353 Parser/StatementNode.cc Parser/InitializerNode.cc \ 354 Parser/TypeData.cc Parser/LinkageSpec.cc \ 355 Parser/parseutility.cc Parser/Parser.cc \ 347 GenPoly/DeclMutator.cc InitTweak/RemoveInit.cc \ 348 Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \ 349 Parser/ParseNode.cc Parser/DeclarationNode.cc \ 350 Parser/ExpressionNode.cc Parser/StatementNode.cc \ 351 Parser/InitializerNode.cc Parser/TypeData.cc \ 352 Parser/LinkageSpec.cc Parser/parseutility.cc Parser/Parser.cc \ 356 353 ResolvExpr/AlternativeFinder.cc ResolvExpr/Alternative.cc \ 357 354 ResolvExpr/Unify.cc ResolvExpr/PtrsAssignable.cc \ … … 365 362 SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \ 366 363 SymTab/ImplementationType.cc SymTab/TypeEquality.cc \ 367 SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \ 368 SynTree/BasicType.cc SynTree/PointerType.cc \ 369 SynTree/ArrayType.cc SynTree/FunctionType.cc \ 370 SynTree/ReferenceToType.cc SynTree/TupleType.cc \ 371 SynTree/TypeofType.cc SynTree/AttrType.cc \ 364 SynTree/Type.cc SynTree/VoidType.cc SynTree/BasicType.cc \ 365 SynTree/PointerType.cc SynTree/ArrayType.cc \ 366 SynTree/FunctionType.cc SynTree/ReferenceToType.cc \ 367 SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \ 372 368 SynTree/VarArgsType.cc SynTree/Constant.cc \ 373 369 SynTree/Expression.cc SynTree/TupleExpr.cc \ … … 565 561 @$(MKDIR_P) InitTweak/$(DEPDIR) 566 562 @: > InitTweak/$(DEPDIR)/$(am__dirstamp) 567 InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT): InitTweak/$(am__dirstamp) \ 568 InitTweak/$(DEPDIR)/$(am__dirstamp) 569 InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT): InitTweak/$(am__dirstamp) \ 570 InitTweak/$(DEPDIR)/$(am__dirstamp) 563 InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT): \ 564 InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp) 571 565 Parser/parser.h: Parser/parser.cc 572 566 @if test ! -f $@; then rm -f Parser/parser.cc; else :; fi … … 676 670 SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT): SymTab/$(am__dirstamp) \ 677 671 SymTab/$(DEPDIR)/$(am__dirstamp) 678 SymTab/driver_cfa_cpp-Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \679 SymTab/$(DEPDIR)/$(am__dirstamp)680 672 SynTree/$(am__dirstamp): 681 673 @$(MKDIR_P) SynTree … … 800 792 -rm -f GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT) 801 793 -rm -f GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT) 802 -rm -f InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT) 803 -rm -f InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) 794 -rm -f InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT) 804 795 -rm -f Parser/driver_cfa_cpp-DeclarationNode.$(OBJEXT) 805 796 -rm -f Parser/driver_cfa_cpp-ExpressionNode.$(OBJEXT) … … 831 822 -rm -f ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) 832 823 -rm -f ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT) 833 -rm -f SymTab/driver_cfa_cpp-Autogen.$(OBJEXT)834 824 -rm -f SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT) 835 825 -rm -f SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT) … … 907 897 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po@am__quote@ 908 898 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po@am__quote@ 909 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po@am__quote@ 910 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po@am__quote@ 899 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Po@am__quote@ 911 900 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Po@am__quote@ 912 901 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Po@am__quote@ … … 938 927 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Po@am__quote@ 939 928 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po@am__quote@ 940 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po@am__quote@941 929 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po@am__quote@ 942 930 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po@am__quote@ … … 1378 1366 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-DeclMutator.obj `if test -f 'GenPoly/DeclMutator.cc'; then $(CYGPATH_W) 'GenPoly/DeclMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/DeclMutator.cc'; fi` 1379 1367 1380 InitTweak/driver_cfa_cpp-GenInit.o: InitTweak/GenInit.cc 1381 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-GenInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo -c -o InitTweak/driver_cfa_cpp-GenInit.o `test -f 'InitTweak/GenInit.cc' || echo '$(srcdir)/'`InitTweak/GenInit.cc 1382 @am__fastdepCXX_TRUE@ $(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po 1383 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InitTweak/GenInit.cc' object='InitTweak/driver_cfa_cpp-GenInit.o' libtool=no @AMDEPBACKSLASH@ 1384 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1385 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-GenInit.o `test -f 'InitTweak/GenInit.cc' || echo '$(srcdir)/'`InitTweak/GenInit.cc 1386 1387 InitTweak/driver_cfa_cpp-GenInit.obj: InitTweak/GenInit.cc 1388 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-GenInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo -c -o InitTweak/driver_cfa_cpp-GenInit.obj `if test -f 'InitTweak/GenInit.cc'; then $(CYGPATH_W) 'InitTweak/GenInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/GenInit.cc'; fi` 1389 @am__fastdepCXX_TRUE@ $(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po 1390 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InitTweak/GenInit.cc' object='InitTweak/driver_cfa_cpp-GenInit.obj' libtool=no @AMDEPBACKSLASH@ 1391 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1392 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-GenInit.obj `if test -f 'InitTweak/GenInit.cc'; then $(CYGPATH_W) 'InitTweak/GenInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/GenInit.cc'; fi` 1393 1394 InitTweak/driver_cfa_cpp-FixInit.o: InitTweak/FixInit.cc 1395 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixInit.o `test -f 'InitTweak/FixInit.cc' || echo '$(srcdir)/'`InitTweak/FixInit.cc 1396 @am__fastdepCXX_TRUE@ $(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po 1397 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InitTweak/FixInit.cc' object='InitTweak/driver_cfa_cpp-FixInit.o' libtool=no @AMDEPBACKSLASH@ 1398 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1399 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixInit.o `test -f 'InitTweak/FixInit.cc' || echo '$(srcdir)/'`InitTweak/FixInit.cc 1400 1401 InitTweak/driver_cfa_cpp-FixInit.obj: InitTweak/FixInit.cc 1402 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixInit.obj `if test -f 'InitTweak/FixInit.cc'; then $(CYGPATH_W) 'InitTweak/FixInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixInit.cc'; fi` 1403 @am__fastdepCXX_TRUE@ $(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po 1404 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InitTweak/FixInit.cc' object='InitTweak/driver_cfa_cpp-FixInit.obj' libtool=no @AMDEPBACKSLASH@ 1405 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1406 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixInit.obj `if test -f 'InitTweak/FixInit.cc'; then $(CYGPATH_W) 'InitTweak/FixInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixInit.cc'; fi` 1368 InitTweak/driver_cfa_cpp-RemoveInit.o: InitTweak/RemoveInit.cc 1369 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-RemoveInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo -c -o InitTweak/driver_cfa_cpp-RemoveInit.o `test -f 'InitTweak/RemoveInit.cc' || echo '$(srcdir)/'`InitTweak/RemoveInit.cc 1370 @am__fastdepCXX_TRUE@ $(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Po 1371 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InitTweak/RemoveInit.cc' object='InitTweak/driver_cfa_cpp-RemoveInit.o' libtool=no @AMDEPBACKSLASH@ 1372 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1373 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-RemoveInit.o `test -f 'InitTweak/RemoveInit.cc' || echo '$(srcdir)/'`InitTweak/RemoveInit.cc 1374 1375 InitTweak/driver_cfa_cpp-RemoveInit.obj: InitTweak/RemoveInit.cc 1376 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-RemoveInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo -c -o InitTweak/driver_cfa_cpp-RemoveInit.obj `if test -f 'InitTweak/RemoveInit.cc'; then $(CYGPATH_W) 'InitTweak/RemoveInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/RemoveInit.cc'; fi` 1377 @am__fastdepCXX_TRUE@ $(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Po 1378 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InitTweak/RemoveInit.cc' object='InitTweak/driver_cfa_cpp-RemoveInit.obj' libtool=no @AMDEPBACKSLASH@ 1379 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1380 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-RemoveInit.obj `if test -f 'InitTweak/RemoveInit.cc'; then $(CYGPATH_W) 'InitTweak/RemoveInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/RemoveInit.cc'; fi` 1407 1381 1408 1382 Parser/driver_cfa_cpp-parser.o: Parser/parser.cc … … 1895 1869 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1896 1870 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-TypeEquality.obj `if test -f 'SymTab/TypeEquality.cc'; then $(CYGPATH_W) 'SymTab/TypeEquality.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/TypeEquality.cc'; fi` 1897 1898 SymTab/driver_cfa_cpp-Autogen.o: SymTab/Autogen.cc1899 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Autogen.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo -c -o SymTab/driver_cfa_cpp-Autogen.o `test -f 'SymTab/Autogen.cc' || echo '$(srcdir)/'`SymTab/Autogen.cc1900 @am__fastdepCXX_TRUE@ $(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po1901 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SymTab/Autogen.cc' object='SymTab/driver_cfa_cpp-Autogen.o' libtool=no @AMDEPBACKSLASH@1902 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1903 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Autogen.o `test -f 'SymTab/Autogen.cc' || echo '$(srcdir)/'`SymTab/Autogen.cc1904 1905 SymTab/driver_cfa_cpp-Autogen.obj: SymTab/Autogen.cc1906 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Autogen.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo -c -o SymTab/driver_cfa_cpp-Autogen.obj `if test -f 'SymTab/Autogen.cc'; then $(CYGPATH_W) 'SymTab/Autogen.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Autogen.cc'; fi`1907 @am__fastdepCXX_TRUE@ $(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po1908 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SymTab/Autogen.cc' object='SymTab/driver_cfa_cpp-Autogen.obj' libtool=no @AMDEPBACKSLASH@1909 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1910 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Autogen.obj `if test -f 'SymTab/Autogen.cc'; then $(CYGPATH_W) 'SymTab/Autogen.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Autogen.cc'; fi`1911 1871 1912 1872 SynTree/driver_cfa_cpp-Type.o: SynTree/Type.cc -
src/Parser/DeclarationNode.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // DeclarationNode.cc -- 7 // DeclarationNode.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 12:34:05 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:38:09201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 13 16:53:17 2016 13 13 // Update Count : 161 14 14 // … … 97 97 os << endl << string( indent + 2, ' ' ) << "with initializer "; 98 98 initializer->printOneLine( os ); 99 os << " maybe constructed? " << initializer->get_maybeConstructed();100 101 99 } // if 102 100 … … 355 353 } // if 356 354 } 357 355 358 356 DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) { 359 357 if ( q ) { … … 506 504 assert( false ); 507 505 } // switch 508 506 509 507 return this; 510 508 } … … 617 615 assert( a->type->kind == TypeData::Array ); 618 616 TypeData *lastArray = findLast( a->type ); 619 if ( type ) { 617 if ( type ) { 620 618 switch ( type->kind ) { 621 619 case TypeData::Aggregate: … … 661 659 } // if 662 660 } 663 661 664 662 DeclarationNode *DeclarationNode::addIdList( DeclarationNode *ids ) { 665 663 type = addIdListToType( type, ids ); … … 866 864 Type *DeclarationNode::buildType() const { 867 865 assert( type ); 868 866 869 867 switch ( type->kind ) { 870 868 case TypeData::Enum: -
src/Parser/InitializerNode.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // InitializerNode.cc -- 8 // 7 // InitializerNode.cc -- 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:20:24 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Jan 07 13:32:57 201613 // Update Count : 1314 // 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Oct 8 17:18:55 2015 13 // Update Count : 4 14 // 15 15 16 16 #include <cassert> … … 23 23 24 24 InitializerNode::InitializerNode( ExpressionNode *_expr, bool aggrp, ExpressionNode *des ) 25 : expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ) , maybeConstructed( true ){25 : expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ) { 26 26 if ( aggrp ) 27 27 kids = dynamic_cast< InitializerNode *>( get_link() ); … … 32 32 33 33 InitializerNode::InitializerNode( InitializerNode *init, bool aggrp, ExpressionNode *des ) 34 : expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) , maybeConstructed( true ){34 : expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) { 35 35 if ( init != 0 ) 36 36 set_link(init); … … 91 91 } // if 92 92 93 return new ListInit( initlist, designlist , maybeConstructed);93 return new ListInit( initlist, designlist ); 94 94 } else { 95 95 std::list< Expression *> designators; … … 99 99 100 100 if ( get_expression() != 0) 101 return new SingleInit( get_expression()->build(), designators , maybeConstructed);101 return new SingleInit( get_expression()->build(), designators ); 102 102 } // if 103 103 -
src/Parser/ParseNode.h
r7cc6bd6 r9243a501 10 10 // Created On : Sat May 16 13:28:16 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Thu Apr 14 15:37:52 201612 // Last Modified On : Mon Apr 11 11:50:52 2016 13 13 // Update Count : 205 14 14 // … … 185 185 // monadic 186 186 UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress, 187 Ctor, Dtor,188 187 }; 189 188 … … 526 525 ExpressionNode *get_designators() const { return designator; } 527 526 528 InitializerNode *set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }529 bool get_maybeConstructed() const { return maybeConstructed; }530 531 527 InitializerNode *next_init() const { return kids; } 532 528 … … 540 536 ExpressionNode *designator; // may be list 541 537 InitializerNode *kids; 542 bool maybeConstructed;543 538 }; 544 539 -
src/Parser/TypeData.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // TypeData.cc -- 7 // TypeData.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:12:51 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 06 16:57:53201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:26:45 2016 13 13 // Update Count : 49 14 14 // … … 449 449 for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) { 450 450 if ( (*i)->get_kind() == TypeDecl::Any ) { 451 // add assertion parameters to `type' tyvars in reverse order452 // add dtor: void ^?{}(T *)453 FunctionType *dtorType = new FunctionType( Type::Qualifiers(), false );454 dtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );455 (*i)->get_assertions().push_front( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, dtorType, 0, false, false ) );456 457 // add copy ctor: void ?{}(T *, T)458 FunctionType *copyCtorType = new FunctionType( Type::Qualifiers(), false );459 copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );460 copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );461 (*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, copyCtorType, 0, false, false ) );462 463 // add default ctor: void ?{}(T *)464 FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false );465 ctorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );466 (*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, ctorType, 0, false, false ) );467 468 // add assignment operator: T * ?=?(T *, T)469 451 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 470 452 assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); … … 920 902 if ( cur->get_enumeratorValue() != NULL ) { 921 903 ObjectDecl *member = dynamic_cast<ObjectDecl *>(*members); 922 member->set_init( new SingleInit( maybeBuild< Expression >( cur->get_enumeratorValue() ) , std::list< Expression * >()) );904 member->set_init( new SingleInit( maybeBuild< Expression >( cur->get_enumeratorValue() ) ) ); 923 905 } // if 924 906 } // for -
src/Parser/parser.cc
r7cc6bd6 r9243a501 7468 7468 /* Line 1806 of yacc.c */ 7469 7469 #line 1704 "parser.yy" 7470 { (yyval.in) = (yyvsp[(2) - (2)].in) ->set_maybeConstructed( false ); }7470 { (yyval.in) = (yyvsp[(2) - (2)].in); } 7471 7471 break; 7472 7472 -
src/Parser/parser.yy
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // cfa.y -- 8 // 7 // cfa.y -- 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 1 20:22:55 2001 … … 12 12 // Last Modified On : Wed Apr 13 16:58:43 2016 13 13 // Update Count : 1519 14 // 14 // 15 15 16 16 // This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on the C … … 1702 1702 { $$ = $2; } 1703 1703 | ATassign initializer 1704 { $$ = $2 ->set_maybeConstructed( false ); }1704 { $$ = $2; } 1705 1705 ; 1706 1706 -
src/ResolvExpr/AlternativeFinder.cc
r7cc6bd6 r9243a501 10 10 // Created On : Sat May 16 23:52:08 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Wed Apr 20 14:24:03201612 // Last Modified On : Wed Feb 10 17:00:04 2016 13 13 // Update Count : 24 14 14 // … … 982 982 } // for 983 983 } 984 985 void AlternativeFinder::visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {986 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );987 }988 984 } // namespace ResolvExpr 989 985 -
src/ResolvExpr/AlternativeFinder.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // AlternativeFinder.h -- 7 // AlternativeFinder.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:56:12 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue Apr 19 11:44:53 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 16 23:58:43 2015 13 13 // Update Count : 2 14 // 14 // 15 15 16 16 #ifndef ALTERNATIVEFINDER_H … … 54 54 virtual void visit( NameExpr *variableExpr ); 55 55 virtual void visit( VariableExpr *variableExpr ); 56 virtual void visit( ConstantExpr *constantExpr ); 56 virtual void visit( ConstantExpr *constantExpr ); 57 57 virtual void visit( SizeofExpr *sizeofExpr ); 58 58 virtual void visit( AlignofExpr *alignofExpr ); … … 65 65 virtual void visit( CommaExpr *commaExpr ); 66 66 virtual void visit( TupleExpr *tupleExpr ); 67 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );68 67 public: // xxx - temporary hack - should make Tuples::TupleAssignment a friend 69 68 template< typename InputIterator, typename OutputIterator > -
src/ResolvExpr/Resolver.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Resolver.cc -- 7 // Resolver.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : T ue Apr 26 16:08:21 201613 // Update Count : 20311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 24 16:43:11 2016 13 // Update Count : 181 14 14 // 15 15 … … 33 33 public: 34 34 Resolver() : SymTab::Indexer( false ), switchType( 0 ) {} 35 35 36 36 virtual void visit( FunctionDecl *functionDecl ); 37 37 virtual void visit( ObjectDecl *functionDecl ); … … 54 54 virtual void visit( SingleInit *singleInit ); 55 55 virtual void visit( ListInit *listInit ); 56 virtual void visit( ConstructorInit *ctorInit );57 56 private: 58 57 typedef std::list< Initializer * >::iterator InitIterator; … … 60 59 void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & ); 61 60 void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator & ); 62 void fallbackInit( ConstructorInit * ctorInit ); 61 63 62 std::list< Type * > functionReturn; 64 63 Type *initContext; … … 83 82 } 84 83 85 86 84 namespace { 87 85 void finishExpr( Expression *expr, const TypeEnvironment &env ) { … … 89 87 env.makeSubstitution( *expr->get_env() ); 90 88 } 91 } // namespace 92 93 Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) { 94 global_renamer.reset(); 95 TypeEnvironment env; 96 Expression *newExpr = resolveInVoidContext( untyped, indexer, env ); 97 finishExpr( newExpr, env ); 98 return newExpr; 99 } 100 101 namespace { 89 90 Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) { 91 global_renamer.reset(); 92 TypeEnvironment env; 93 Expression *newExpr = resolveInVoidContext( untyped, indexer, env ); 94 finishExpr( newExpr, env ); 95 return newExpr; 96 } 97 102 98 Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) { 103 99 TypeEnvironment env; … … 130 126 } // if 131 127 } 132 128 133 129 Expression *findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer ) { 134 130 TypeEnvironment env; … … 163 159 return newExpr; 164 160 } 165 166 } 167 161 162 } 163 168 164 void Resolver::visit( ObjectDecl *objectDecl ) { 169 165 Type *new_type = resolveTypeof( objectDecl->get_type(), *this ); … … 262 258 forStmt->set_condition( newExpr ); 263 259 } // if 264 260 265 261 if ( forStmt->get_increment() ) { 266 262 Expression * newExpr = findVoidExpression( forStmt->get_increment(), *this ); … … 276 272 delete switchStmt->get_condition(); 277 273 switchStmt->set_condition( newExpr ); 278 274 279 275 visitor.Visitor::visit( switchStmt ); 280 276 } … … 318 314 bool isCharType( T t ) { 319 315 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) { 320 return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || 316 return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || 321 317 bt->get_kind() == BasicType::UnsignedChar; 322 318 } … … 330 326 string n = ne->get_name(); 331 327 if (n == "0") { 332 initContext = new BasicType(Type::Qualifiers(), 328 initContext = new BasicType(Type::Qualifiers(), 333 329 BasicType::SignedInt); 334 330 } else { … … 336 332 initContext = decl->get_type(); 337 333 } 338 } else if (ConstantExpr * e = 334 } else if (ConstantExpr * e = 339 335 dynamic_cast<ConstantExpr*>(singleInit->get_value())) { 340 336 Constant *c = e->get_constant(); … … 359 355 singleInit->set_value( ce->get_arg() ); 360 356 ce->set_arg( NULL ); 361 delete ce; 357 delete ce; 362 358 } 363 359 } … … 475 471 #endif 476 472 } 477 478 // ConstructorInit - fall back on C-style initializer479 void Resolver::fallbackInit( ConstructorInit * ctorInit ) {480 // could not find valid constructor, or found an intrinsic constructor481 // fall back on C-style initializer482 delete ctorInit->get_ctor();483 ctorInit->set_ctor( NULL );484 maybeAccept( ctorInit->get_init(), *this );485 }486 487 void Resolver::visit( ConstructorInit *ctorInit ) {488 try {489 maybeAccept( ctorInit->get_ctor(), *this );490 maybeAccept( ctorInit->get_dtor(), *this );491 } catch ( SemanticError ) {492 // no alternatives for the constructor initializer - fallback on C-style initializer493 // xxx- not sure if this makes a ton of sense - should maybe never be able to have this situation?494 fallbackInit( ctorInit );495 return;496 }497 498 // found a constructor - can get rid of C-style initializer499 delete ctorInit->get_init();500 ctorInit->set_init( NULL );501 }502 473 } // namespace ResolvExpr 503 474 -
src/ResolvExpr/Resolver.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Resolver.h -- 7 // Resolver.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:18:34 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:06:53 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun May 17 12:19:32 2015 13 13 // Update Count : 2 14 14 // … … 24 24 void resolve( std::list< Declaration * > translationUnit ); 25 25 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ); 26 Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );27 26 } // namespace ResolvExpr 28 27 -
src/SymTab/AddVisit.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // AddVisit.h -- 7 // AddVisit.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 16:14:32 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:52:42201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 7 14:42:21 2016 13 13 // Update Count : 5 14 14 // … … 48 48 // maybeAccept( caseStmt->get_condition(), visitor ); 49 49 // } 50 51 template< typename Visitor >52 void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {53 std::list< Declaration * >::iterator i = translationUnit.begin();54 while ( i != translationUnit.end() ) {55 (*i)->accept( visitor );56 std::list< Declaration * >::iterator next = i;57 next++;58 if ( ! visitor.get_declsToAdd().empty() ) {59 translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );60 } // if61 i = next;62 } // while63 }64 65 50 } // namespace SymTab 66 51 -
src/SymTab/Validate.cc
r7cc6bd6 r9243a501 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:50:04 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:37:23201613 // Update Count : 2 9711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 13 16:39:30 2016 13 // Update Count : 251 14 14 // 15 15 … … 56 56 #include "MakeLibCfa.h" 57 57 #include "TypeEquality.h" 58 #include "Autogen.h"59 58 #include "ResolvExpr/typeops.h" 60 59 … … 123 122 124 123 const Indexer *indexer; 124 }; 125 126 class AutogenerateRoutines : public Visitor { 127 public: 128 /// Generates assignment operators for aggregate types as required 129 static void autogenerateRoutines( std::list< Declaration * > &translationUnit ); 130 131 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; } 132 133 virtual void visit( EnumDecl *enumDecl ); 134 virtual void visit( StructDecl *structDecl ); 135 virtual void visit( UnionDecl *structDecl ); 136 virtual void visit( TypeDecl *typeDecl ); 137 virtual void visit( TraitDecl *ctxDecl ); 138 virtual void visit( FunctionDecl *functionDecl ); 139 140 virtual void visit( FunctionType *ftype ); 141 virtual void visit( PointerType *ftype ); 142 143 virtual void visit( CompoundStmt *compoundStmt ); 144 virtual void visit( SwitchStmt *switchStmt ); 145 virtual void visit( ChooseStmt *chooseStmt ); 146 // virtual void visit( CaseStmt *caseStmt ); 147 148 AutogenerateRoutines() : functionNesting( 0 ) {} 149 private: 150 template< typename StmtClass > void visitStatement( StmtClass *stmt ); 151 152 std::list< Declaration * > declsToAdd; 153 std::set< std::string > structsDone; 154 unsigned int functionNesting; // current level of nested functions 125 155 }; 126 156 … … 162 192 template<typename AggDecl> 163 193 void addImplicitTypedef( AggDecl * aggDecl ); 164 194 165 195 typedef std::map< std::string, std::pair< TypedefDecl *, int > > TypedefMap; 166 196 TypedefMap typedefNames; 167 197 int scopeLevel; 168 198 }; 169 170 class VerifyCtorDtor : public Visitor {171 public:172 /// ensure that constructors and destructors have at least one173 /// parameter, the first of which must be a pointer, and no174 /// return values.175 static void verify( std::list< Declaration * > &translationUnit );176 177 virtual void visit( FunctionDecl *funcDecl );178 };179 199 180 200 class CompoundLiteral : public GenPoly::DeclMutator { … … 197 217 ReturnChecker::checkFunctionReturns( translationUnit ); 198 218 mutateAll( translationUnit, compoundliteral ); 199 autogenerateRoutines( translationUnit );219 AutogenerateRoutines::autogenerateRoutines( translationUnit ); 200 220 acceptAll( translationUnit, pass3 ); 201 VerifyCtorDtor::verify( translationUnit );202 221 } 203 222 … … 209 228 type->accept( pass2 ); 210 229 type->accept( pass3 ); 230 } 231 232 template< typename Visitor > 233 void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) { 234 std::list< Declaration * >::iterator i = translationUnit.begin(); 235 while ( i != translationUnit.end() ) { 236 (*i)->accept( visitor ); 237 std::list< Declaration * >::iterator next = i; 238 next++; 239 if ( ! visitor.get_declsToAdd().empty() ) { 240 translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() ); 241 } // if 242 i = next; 243 } // while 211 244 } 212 245 … … 470 503 } 471 504 505 static const std::list< std::string > noLabels; 506 507 void AutogenerateRoutines::autogenerateRoutines( std::list< Declaration * > &translationUnit ) { 508 AutogenerateRoutines visitor; 509 acceptAndAdd( translationUnit, visitor, false ); 510 } 511 512 template< typename OutputIterator > 513 void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) { 514 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member ); 515 // unnamed bit fields are not copied as they cannot be accessed 516 if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return; 517 518 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) ); 519 520 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 521 derefExpr->get_args().push_back( new VariableExpr( dstParam ) ); 522 523 // do something special for unnamed members 524 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) ); 525 assignExpr->get_args().push_back( dstselect ); 526 527 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) ); 528 assignExpr->get_args().push_back( srcselect ); 529 530 *out++ = new ExprStmt( noLabels, assignExpr ); 531 } 532 533 template< typename OutputIterator > 534 void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) { 535 static UniqueName indexName( "_index" ); 536 537 // for a flexible array member nothing is done -- user must define own assignment 538 if ( ! array->get_dimension() ) return; 539 540 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 ); 541 *out++ = new DeclStmt( noLabels, index ); 542 543 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) ); 544 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 545 init->get_args().push_back( new NameExpr( "0" ) ); 546 Statement *initStmt = new ExprStmt( noLabels, init ); 547 std::list<Statement *> initList; 548 initList.push_back( initStmt ); 549 550 UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) ); 551 cond->get_args().push_back( new VariableExpr( index ) ); 552 cond->get_args().push_back( array->get_dimension()->clone() ); 553 554 UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) ); 555 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 556 557 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) ); 558 559 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 560 derefExpr->get_args().push_back( new VariableExpr( dstParam ) ); 561 562 Expression *dstselect = new MemberExpr( member, derefExpr ); 563 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) ); 564 dstIndex->get_args().push_back( dstselect ); 565 dstIndex->get_args().push_back( new VariableExpr( index ) ); 566 assignExpr->get_args().push_back( dstIndex ); 567 568 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) ); 569 UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); 570 srcIndex->get_args().push_back( srcselect ); 571 srcIndex->get_args().push_back( new VariableExpr( index ) ); 572 assignExpr->get_args().push_back( srcIndex ); 573 574 *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) ); 575 } 576 577 template< typename OutputIterator > 578 void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) { 579 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 580 copy->get_args().push_back( new VariableExpr( dstParam ) ); 581 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 582 copy->get_args().push_back( new SizeofExpr( unionType ) ); 583 584 *out++ = new ExprStmt( noLabels, copy ); 585 } 586 587 //E ?=?(E volatile*, int), 588 // ?=?(E _Atomic volatile*, int); 589 void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) { 590 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 591 592 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 ); 593 assignType->get_returnVals().push_back( returnVal ); 594 595 // need two assignment operators with different types 596 FunctionType * assignType2 = assignType->clone(); 597 598 // E ?=?(E volatile *, E) 599 Type *etype = refType->clone(); 600 // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false); 601 602 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 ); 603 assignType->get_parameters().push_back( dstParam ); 604 605 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 ); 606 assignType->get_parameters().push_back( srcParam ); 607 608 // E ?=?(E volatile *, int) 609 assignType2->get_parameters().push_back( dstParam->clone() ); 610 BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt); 611 ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 ); 612 assignType2->get_parameters().push_back( srcParam2 ); 613 614 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 615 // because each unit generates copies of the default routines for each aggregate. 616 617 // since there is no definition, these should not be inline 618 // make these intrinsic so that the code generator does not make use of them 619 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false ); 620 assignDecl->fixUniqueId(); 621 FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false ); 622 assignDecl2->fixUniqueId(); 623 624 // these should be built in the same way that the prelude 625 // functions are, so build a list containing the prototypes 626 // and allow MakeLibCfa to autogenerate the bodies. 627 std::list< Declaration * > assigns; 628 assigns.push_back( assignDecl ); 629 assigns.push_back( assignDecl2 ); 630 631 LibCfa::makeLibCfa( assigns ); 632 633 // need to remove the prototypes, since this may be nested in a routine 634 for (int start = 0, end = assigns.size()/2; start < end; start++) { 635 delete assigns.front(); 636 assigns.pop_front(); 637 } // for 638 639 declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() ); 640 } 641 642 /// Clones a reference type, replacing any parameters it may have with a clone of the provided list 643 template< typename GenericInstType > 644 GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) { 645 GenericInstType *clone = refType->clone(); 646 clone->get_parameters().clear(); 647 cloneAll( params, clone->get_parameters() ); 648 return clone; 649 } 650 651 /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only) 652 TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) { 653 TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() ); 654 655 if ( src->get_kind() == TypeDecl::Any ) { 656 // just include assignment operator assertion 657 TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst ); 658 FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false ); 659 assignFunctionType->get_returnVals().push_back( 660 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) ); 661 assignFunctionType->get_parameters().push_back( 662 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) ); 663 assignFunctionType->get_parameters().push_back( 664 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) ); 665 FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false ); 666 dst->get_assertions().push_back( assignAssert ); 667 } 668 669 return dst; 670 } 671 672 Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) { 673 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 674 675 // Make function polymorphic in same parameters as generic struct, if applicable 676 bool isGeneric = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 677 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 678 std::list< Expression* > structParams; // List of matching parameters to put on types 679 TypeSubstitution genericSubs; // Substitutions to make to member types of struct 680 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 681 isGeneric = true; 682 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 683 assignType->get_forall().push_back( typeParam ); 684 TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ); 685 genericSubs.add( (*param)->get_name(), newParamType ); 686 structParams.push_back( new TypeExpr( newParamType ) ); 687 } 688 689 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 690 assignType->get_returnVals().push_back( returnVal ); 691 692 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 ); 693 assignType->get_parameters().push_back( dstParam ); 694 695 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 696 assignType->get_parameters().push_back( srcParam ); 697 698 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 699 // because each unit generates copies of the default routines for each aggregate. 700 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 701 assignDecl->fixUniqueId(); 702 703 for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) { 704 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) { 705 // query the type qualifiers of this field and skip assigning it if it is marked const. 706 // If it is an array type, we need to strip off the array layers to find its qualifiers. 707 Type * type = dwt->get_type(); 708 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 709 type = at->get_base(); 710 } 711 712 if ( type->get_qualifiers().isConst ) { 713 // don't assign const members 714 continue; 715 } 716 717 if ( isGeneric ) { 718 // rewrite member type in terms of the type variables on this operator 719 DeclarationWithType *fixedMember = dwt->clone(); 720 genericSubs.apply( fixedMember ); 721 722 // assign to both destination and return value 723 if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) { 724 makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) ); 725 makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) ); 726 } else { 727 makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) ); 728 makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) ); 729 } // if 730 } else { 731 // assign to destination 732 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) { 733 makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) ); 734 } else { 735 makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) ); 736 } // if 737 } // if 738 } // if 739 } // for 740 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 741 742 return assignDecl; 743 } 744 745 Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) { 746 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 747 748 // Make function polymorphic in same parameters as generic union, if applicable 749 bool isGeneric = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct) 750 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 751 std::list< Expression* > unionParams; // List of matching parameters to put on types 752 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 753 isGeneric = true; 754 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 755 assignType->get_forall().push_back( typeParam ); 756 unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); 757 } 758 759 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 760 assignType->get_returnVals().push_back( returnVal ); 761 762 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 ); 763 assignType->get_parameters().push_back( dstParam ); 764 765 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 766 assignType->get_parameters().push_back( srcParam ); 767 768 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 769 // because each unit generates copies of the default routines for each aggregate. 770 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 771 assignDecl->fixUniqueId(); 772 773 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 774 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 775 776 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 777 778 return assignDecl; 779 } 780 781 void AutogenerateRoutines::visit( EnumDecl *enumDecl ) { 782 if ( ! enumDecl->get_members().empty() ) { 783 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() ); 784 // enumInst->set_baseEnum( enumDecl ); 785 // declsToAdd.push_back( 786 makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd ); 787 } 788 } 789 790 void AutogenerateRoutines::visit( StructDecl *structDecl ) { 791 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) { 792 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 793 structInst.set_baseStruct( structDecl ); 794 declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) ); 795 structsDone.insert( structDecl->get_name() ); 796 } // if 797 } 798 799 void AutogenerateRoutines::visit( UnionDecl *unionDecl ) { 800 if ( ! unionDecl->get_members().empty() ) { 801 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 802 unionInst.set_baseUnion( unionDecl ); 803 declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) ); 804 } // if 805 } 806 807 void AutogenerateRoutines::visit( TypeDecl *typeDecl ) { 808 CompoundStmt *stmts = 0; 809 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false ); 810 typeInst->set_baseType( typeDecl ); 811 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 ); 812 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 ); 813 if ( typeDecl->get_base() ) { 814 stmts = new CompoundStmt( std::list< Label >() ); 815 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 816 assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) ); 817 assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) ); 818 stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) ); 819 } // if 820 FunctionType *type = new FunctionType( Type::Qualifiers(), false ); 821 type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) ); 822 type->get_parameters().push_back( dst ); 823 type->get_parameters().push_back( src ); 824 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false ); 825 declsToAdd.push_back( func ); 826 } 827 828 void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) { 829 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) { 830 statements.insert( i, new DeclStmt( noLabels, *decl ) ); 831 } // for 832 declsToAdd.clear(); 833 } 834 835 void AutogenerateRoutines::visit( FunctionType *) { 836 // ensure that we don't add assignment ops for types defined as part of the function 837 } 838 839 void AutogenerateRoutines::visit( PointerType *) { 840 // ensure that we don't add assignment ops for types defined as part of the pointer 841 } 842 843 void AutogenerateRoutines::visit( TraitDecl *) { 844 // ensure that we don't add assignment ops for types defined as part of the context 845 } 846 847 template< typename StmtClass > 848 inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) { 849 std::set< std::string > oldStructs = structsDone; 850 addVisit( stmt, *this ); 851 structsDone = oldStructs; 852 } 853 854 void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) { 855 maybeAccept( functionDecl->get_functionType(), *this ); 856 acceptAll( functionDecl->get_oldDecls(), *this ); 857 functionNesting += 1; 858 maybeAccept( functionDecl->get_statements(), *this ); 859 functionNesting -= 1; 860 } 861 862 void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) { 863 visitStatement( compoundStmt ); 864 } 865 866 void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) { 867 visitStatement( switchStmt ); 868 } 869 870 void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) { 871 visitStatement( switchStmt ); 872 } 873 874 // void AutogenerateRoutines::visit( CaseStmt *caseStmt ) { 875 // visitStatement( caseStmt ); 876 // } 877 472 878 void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) { 473 879 ReturnChecker checker; … … 627 1033 return aggDecl; 628 1034 } 629 1035 630 1036 template<typename AggDecl> 631 1037 void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) { … … 666 1072 } 667 1073 668 void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {669 VerifyCtorDtor verifier;670 acceptAll( translationUnit, verifier );671 }672 673 void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {674 FunctionType * funcType = funcDecl->get_functionType();675 std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();676 std::list< DeclarationWithType * > ¶ms = funcType->get_parameters();677 678 if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {679 if ( params.size() == 0 ) {680 throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );681 }682 if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {683 throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );684 }685 if ( returnVals.size() != 0 ) {686 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );687 }688 }689 690 Visitor::visit( funcDecl );691 // original idea: modify signature of ctor/dtors and insert appropriate return statements692 // to cause desired behaviour693 // new idea: add comma exprs to every ctor call to produce first parameter.694 // this requires some memoization of the first parameter, because it can be a695 // complicated expression with side effects (see: malloc). idea: add temporary variable696 // that is assigned address of constructed object in ctor argument position and697 // return the temporary. It should also be done after all implicit ctors are698 // added, so not in this pass!699 }700 701 1074 DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) { 702 1075 storageclass = objectDecl->get_storageClass(); -
src/SymTab/module.mk
r7cc6bd6 r9243a501 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## module.mk -- 8 ## module.mk -- 9 9 ## 10 10 ## Author : Richard C. Bilson … … 20 20 SymTab/FixFunction.cc \ 21 21 SymTab/ImplementationType.cc \ 22 SymTab/TypeEquality.cc \ 23 SymTab/Autogen.cc 22 SymTab/TypeEquality.cc -
src/SynTree/CommaExpr.cc
r7cc6bd6 r9243a501 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Mon May 02 15:1 9:44201612 // Last Modified On : Mon May 02 15:11:29 2016 13 13 // Update Count : 1 14 14 // -
src/SynTree/CompoundStmt.cc
r7cc6bd6 r9243a501 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Mon May 02 15:1 9:17 201612 // Last Modified On : Mon May 02 15:10:47 2016 13 13 // Update Count : 3 14 14 // … … 18 18 #include <algorithm> 19 19 #include <functional> 20 #include "Expression.h"21 #include "Declaration.h"22 20 23 21 using std::string; 24 22 using std::endl; 25 26 class VarExprReplacer : public Visitor {27 public:28 typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;29 private:30 const DeclMap & declMap;31 public:32 VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}33 34 // replace variable with new node from decl map35 virtual void visit( VariableExpr * varExpr ) {36 if ( declMap.count( varExpr->get_var() ) ) {37 varExpr->set_var( declMap.at( varExpr->get_var() ) );38 }39 }40 };41 42 23 43 24 CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) { … … 46 27 CompoundStmt::CompoundStmt( const CompoundStmt &other ) : Statement( other ) { 47 28 cloneAll( other.kids, kids ); 48 49 // when cloning a compound statement, we may end up cloning declarations which50 // are referred to by VariableExprs throughout the block. Cloning a VariableExpr51 // does a shallow copy, so the VariableExpr will end up pointing to the original52 // declaration. If the original declaration is deleted, e.g. because the original53 // CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,54 // find all DeclarationWithType nodes (since a VariableExpr must point to a55 // DeclarationWithType) in the original CompoundStmt and map them to the cloned56 // node in the new CompoundStmt ('this'), then replace the Declarations referred to57 // by each VariableExpr according to the constructed map. Note that only the declarations58 // in the current level are collected into the map, because child CompoundStmts will59 // recursively execute this routine. There may be more efficient ways of doing60 // this.61 VarExprReplacer::DeclMap declMap;62 std::list< Statement * >::const_iterator origit = other.kids.begin();63 for ( Statement * s : kids ) {64 assert( origit != other.kids.end() );65 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {66 DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( *origit );67 assert( origDeclStmt );68 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {69 DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );70 assert( origdwt );71 declMap[ origdwt ] = dwt;72 }73 }74 }75 if ( ! declMap.empty() ) {76 VarExprReplacer replacer( declMap );77 accept( replacer );78 }79 29 } 80 30 -
src/SynTree/Declaration.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Declaration.h -- 7 // Declaration.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon Apr 11 16:55:12201613 // Update Count : 3 611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:28:11 2016 13 // Update Count : 33 14 14 // 15 15 … … 22 22 #include "Parser/LinkageSpec.h" 23 23 #include "Parser/ParseNode.h" 24 #include <string>25 24 26 25 class Declaration { … … 68 67 void set_mangleName( std::string newValue ) { mangleName = newValue; } 69 68 70 std::string get_scopedMangleName() const { return mangleName + "_" + std::to_string(scopeLevel); }71 72 int get_scopeLevel() const { return scopeLevel; }73 void set_scopeLevel( int newValue ) { scopeLevel = newValue; }74 75 69 virtual DeclarationWithType *clone() const = 0; 76 70 virtual DeclarationWithType *acceptMutator( Mutator &m ) = 0; … … 81 75 // this represents the type with all types and typedefs expanded it is generated by SymTab::Validate::Pass2 82 76 std::string mangleName; 83 // need to remember the scope level at which the variable was declared, so that84 // shadowed identifiers can be accessed85 int scopeLevel = 0;86 77 }; 87 78 -
src/SynTree/DeclarationWithType.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // DeclarationWithType.cc -- 7 // DeclarationWithType.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon Apr 11 15:35:27 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 13 08:08:07 2015 13 13 // Update Count : 3 14 14 // … … 23 23 24 24 DeclarationWithType::DeclarationWithType( const DeclarationWithType &other ) 25 : Declaration( other ), mangleName( other.mangleName ) , scopeLevel( other.scopeLevel ){25 : Declaration( other ), mangleName( other.mangleName ) { 26 26 } 27 27 -
src/SynTree/Expression.cc
r7cc6bd6 r9243a501 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Wed May 04 12:1 7:51201612 // Last Modified On : Wed May 04 12:14:09 2016 13 13 // Update Count : 40 14 14 // … … 79 79 80 80 VariableExpr::VariableExpr( DeclarationWithType *_var, Expression *_aname ) : Expression( _aname ), var( _var ) { 81 assert( var );82 assert( var->get_type() );83 81 add_result( var->get_type()->clone() ); 84 82 for ( std::list< Type* >::iterator i = get_results().begin(); i != get_results().end(); ++i ) { … … 465 463 } 466 464 467 468 ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( ApplicationExpr * callExpr ) : callExpr( callExpr ) {469 assert( callExpr );470 cloneAll( callExpr->get_results(), results );471 }472 473 ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other ) : Expression( other ), callExpr( maybeClone( other.callExpr ) ) {474 cloneAll( other.tempDecls, tempDecls );475 cloneAll( other.returnDecls, returnDecls );476 cloneAll( other.dtors, dtors );477 }478 479 ImplicitCopyCtorExpr::~ImplicitCopyCtorExpr() {480 delete callExpr;481 deleteAll( tempDecls );482 deleteAll( returnDecls );483 deleteAll( dtors );484 }485 486 void ImplicitCopyCtorExpr::print( std::ostream &os, int indent ) const {487 os << std::string( indent, ' ' ) << "Implicit Copy Constructor Expression: " << std::endl;488 assert( callExpr );489 callExpr->print( os, indent + 2 );490 os << std::endl << std::string( indent, ' ' ) << "with temporaries:" << std::endl;491 printAll(tempDecls, os, indent+2);492 os << std::endl << std::string( indent, ' ' ) << "with return temporaries:" << std::endl;493 printAll(returnDecls, os, indent+2);494 Expression::print( os, indent );495 }496 497 465 UntypedValofExpr::UntypedValofExpr( const UntypedValofExpr & other ) : Expression( other ), body ( maybeClone( other.body ) ) {} 498 466 -
src/SynTree/Expression.h
r7cc6bd6 r9243a501 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:06:49201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 8 17:18:06 2016 13 13 // Update Count : 21 14 14 // … … 22 22 #include "Mutator.h" 23 23 #include "Constant.h" 24 #include "Common/UniqueName.h"25 24 26 25 /// Expression is the root type for all expressions … … 560 559 }; 561 560 562 /// ImplicitCopyCtorExpr represents the application of a function to a set of parameters,563 /// along with a set of copy constructor calls, one for each argument.564 class ImplicitCopyCtorExpr : public Expression {565 public:566 ImplicitCopyCtorExpr( ApplicationExpr * callExpr );567 ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other );568 virtual ~ImplicitCopyCtorExpr();569 570 ApplicationExpr *get_callExpr() const { return callExpr; }571 void set_callExpr( ApplicationExpr *newValue ) { callExpr = newValue; }572 573 std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }574 void set_tempDecls( std::list< ObjectDecl * > newValue ) { tempDecls = newValue; }575 576 std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }577 void set_returnDecls( std::list< ObjectDecl * > newValue ) { returnDecls = newValue; }578 579 std::list< Expression * > & get_dtors() { return dtors; }580 void set_dtors( std::list< Expression * > newValue ) { dtors = newValue; }581 582 virtual ImplicitCopyCtorExpr *clone() const { return new ImplicitCopyCtorExpr( *this ); }583 virtual void accept( Visitor &v ) { v.visit( this ); }584 virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }585 virtual void print( std::ostream &os, int indent = 0 ) const;586 private:587 ApplicationExpr * callExpr;588 std::list< ObjectDecl * > tempDecls;589 std::list< ObjectDecl * > returnDecls;590 std::list< Expression * > dtors;591 };592 593 561 /// ValofExpr represents a GCC 'lambda expression' 594 562 class UntypedValofExpr : public Expression { -
src/SynTree/Initializer.cc
r7cc6bd6 r9243a501 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Tue Apr 26 1 5:51:35201612 // Last Modified On : Tue Apr 26 12:50:47 2016 13 13 // Update Count : 28 14 14 // … … 16 16 #include "Initializer.h" 17 17 #include "Expression.h" 18 #include "Statement.h"19 18 #include "Common/utility.h" 20 19 21 Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed) {}20 Initializer::Initializer() {} 22 21 23 22 Initializer::~Initializer() {} … … 32 31 void Initializer::print( std::ostream &os, int indent ) {} 33 32 34 SingleInit::SingleInit( Expression *v, const std::list< Expression *> &_designators, bool maybeConstructed ) : Initializer( maybeConstructed ),value ( v ), designators( _designators ) {33 SingleInit::SingleInit( Expression *v, std::list< Expression *> &_designators ) : value ( v ), designators( _designators ) { 35 34 } 36 35 37 SingleInit::SingleInit( const SingleInit &other ) : Initializer(other), value ( maybeClone( other.value )) {36 SingleInit::SingleInit( const SingleInit &other ) : value ( other.value ) { 38 37 cloneAll(other.designators, designators ); 39 38 } … … 56 55 } 57 56 58 ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed)59 : Initializer( maybeConstructed),initializers( _initializers ), designators( _designators ) {57 ListInit::ListInit( std::list<Initializer*> &_initializers, std::list<Expression *> &_designators ) 58 : initializers( _initializers ), designators( _designators ) { 60 59 } 61 60 … … 81 80 (*i)->print( os, indent + 2 ); 82 81 } 83 84 85 ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}86 ConstructorInit::~ConstructorInit() {87 delete ctor;88 delete init;89 }90 91 ConstructorInit *ConstructorInit::clone() const {92 return new ConstructorInit( *this );93 }94 95 void ConstructorInit::print( std::ostream &os, int indent ) {96 os << std::endl << std::string(indent, ' ') << "Constructor initializer: " << std::endl;97 if ( ctor ) {98 os << std::string(indent+2, ' ');99 os << "initially constructed with ";100 ctor->print( os, indent+4 );101 } // if102 103 if ( dtor ) {104 os << std::string(indent+2, ' ');105 os << "destructed with ";106 dtor->print( os, indent+4 );107 }108 109 if ( init ) {110 os << std::string(indent+2, ' ');111 os << "with fallback C-style initializer: ";112 init->print( os, indent+4 );113 }114 }115 116 std::ostream & operator<<( std::ostream & out, Initializer * init ) {117 init->print( out );118 return out;119 }120 121 82 // Local Variables: // 122 83 // tab-width: 4 // -
src/SynTree/Initializer.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Initializer.h -- 7 // Initializer.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue Apr 12 13:49:13 201613 // Update Count : 1 911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon May 18 09:03:48 2015 13 // Update Count : 1 14 14 // 15 15 … … 27 27 public: 28 28 // Initializer( std::string _name = std::string(""), int _pos = 0 ); 29 Initializer( bool maybeConstructed);29 Initializer( ); 30 30 virtual ~Initializer(); 31 31 … … 43 43 } 44 44 45 bool get_maybeConstructed() { return maybeConstructed; }46 47 45 virtual Initializer *clone() const = 0; 48 46 virtual void accept( Visitor &v ) = 0; … … 52 50 // std::string name; 53 51 // int pos; 54 bool maybeConstructed;55 52 }; 56 53 … … 58 55 class SingleInit : public Initializer { 59 56 public: 60 SingleInit( Expression *value, const std::list< Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false);57 SingleInit( Expression *value, std::list< Expression *> &designators = *(new std::list<Expression *>()) ); 61 58 SingleInit( const SingleInit &other ); 62 59 virtual ~SingleInit(); 63 60 64 61 Expression *get_value() { return value; } 65 62 void set_value( Expression *newValue ) { value = newValue; } … … 82 79 class ListInit : public Initializer { 83 80 public: 84 ListInit( const std::list<Initializer*> &initializers,85 const std::list<Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false);81 ListInit( std::list<Initializer*> &, 82 std::list<Expression *> &designators = *(new std::list<Expression *>()) ); 86 83 virtual ~ListInit(); 87 84 … … 103 100 }; 104 101 105 // ConstructorInit represents an initializer that is either a constructor expression or106 // a C-style initializer.107 class ConstructorInit : public Initializer {108 public:109 ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init );110 virtual ~ConstructorInit();111 112 void set_ctor( Statement * newValue ) { ctor = newValue; }113 Statement * get_ctor() const { return ctor; }114 void set_dtor( Statement * newValue ) { dtor = newValue; }115 Statement * get_dtor() const { return dtor; }116 void set_init( Initializer * newValue ) { init = newValue; }117 Initializer * get_init() const { return init; }118 119 virtual ConstructorInit *clone() const;120 virtual void accept( Visitor &v ) { v.visit( this ); }121 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }122 virtual void print( std::ostream &os, int indent = 0 );123 124 private:125 Statement * ctor;126 Statement * dtor;127 // C-style initializer made up of SingleInit and ListInit nodes to use as a fallback128 // if an appropriate constructor definition is not found by the resolver129 Initializer * init;130 };131 132 std::ostream & operator<<( std::ostream & out, Initializer * init );133 134 102 #endif // INITIALIZER_H 135 103 -
src/SynTree/Mutator.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Mutator.cc -- 7 // Mutator.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:07:29201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 1 18:05:16 2016 13 13 // Update Count : 16 14 14 // … … 337 337 } 338 338 339 Expression* Mutator::mutate( ImplicitCopyCtorExpr *impCpCtorExpr ) {340 impCpCtorExpr->set_callExpr( maybeMutate( impCpCtorExpr->get_callExpr(), *this ) );341 mutateAll( impCpCtorExpr->get_tempDecls(), *this );342 mutateAll( impCpCtorExpr->get_returnDecls(), *this );343 return impCpCtorExpr;344 }345 346 339 Expression *Mutator::mutate( UntypedValofExpr *valofExpr ) { 347 340 mutateAll( valofExpr->get_results(), *this ); … … 457 450 } 458 451 459 Initializer *Mutator::mutate( ConstructorInit *ctorInit ) {460 ctorInit->set_ctor( maybeMutate( ctorInit->get_ctor(), *this ) );461 ctorInit->set_init( maybeMutate( ctorInit->get_init(), *this ) );462 return ctorInit;463 }464 465 452 Subrange *Mutator::mutate( Subrange *subrange ) { 466 453 return subrange; -
src/SynTree/Mutator.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Mutator.h -- 7 // Mutator.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:32:00201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 1 17:26:56 2016 13 13 // Update Count : 10 14 14 // … … 62 62 virtual Expression* mutate( MemberExpr *memberExpr ); 63 63 virtual Expression* mutate( VariableExpr *variableExpr ); 64 virtual Expression* mutate( ConstantExpr *constantExpr ); 64 virtual Expression* mutate( ConstantExpr *constantExpr ); 65 65 virtual Expression* mutate( SizeofExpr *sizeofExpr ); 66 66 virtual Expression* mutate( AlignofExpr *alignofExpr ); … … 76 76 virtual Expression* mutate( TypeExpr *typeExpr ); 77 77 virtual Expression* mutate( AsmExpr *asmExpr ); 78 virtual Expression* mutate( ImplicitCopyCtorExpr *impCpCtorExpr );79 78 virtual Expression* mutate( UntypedValofExpr *valofExpr ); 80 79 virtual Expression* mutate( CompoundLiteralExpr *compLitExpr ); … … 97 96 virtual Initializer* mutate( SingleInit *singleInit ); 98 97 virtual Initializer* mutate( ListInit *listInit ); 99 virtual Initializer* mutate( ConstructorInit *ctorInit );100 98 101 99 virtual Subrange *mutate( Subrange *subrange ); -
src/SynTree/ObjectDecl.cc
r7cc6bd6 r9243a501 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Wed May 04 12:1 8:28201612 // Last Modified On : Wed May 04 12:11:56 2016 13 13 // Update Count : 30 14 14 // … … 19 19 #include "Expression.h" 20 20 #include "Common/utility.h" 21 #include "Statement.h"22 21 23 22 ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline, bool isNoreturn ) … … 60 59 os << " with initializer "; 61 60 init->print( os, indent ); 62 os << std::string(indent, ' ') << "maybeConstructed? " << init->get_maybeConstructed();63 61 } // if 64 62 -
src/SynTree/SynTree.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // SynTree.h -- 7 // SynTree.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:31:36201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 1 16:47:44 2016 13 13 // Update Count : 5 14 14 // … … 81 81 class TypeExpr; 82 82 class AsmExpr; 83 class ImplicitCopyCtorExpr;84 83 class UntypedValofExpr; 85 84 class CompoundLiteralExpr; … … 105 104 class SingleInit; 106 105 class ListInit; 107 class ConstructorInit;108 106 109 107 class Subrange; -
src/SynTree/TypeSubstitution.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // TypeSubstitution.cc -- 7 // TypeSubstitution.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue Apr 26 11:15:29201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:29:15 2016 13 13 // Update Count : 3 14 14 // … … 96 96 BoundVarsType::const_iterator bound = boundVars.find( inst->get_name() ); 97 97 if ( bound != boundVars.end() ) return inst; 98 98 99 99 TypeEnvType::const_iterator i = typeEnv.find( inst->get_name() ); 100 100 if ( i == typeEnv.end() ) { … … 217 217 } 218 218 219 std::ostream & operator<<( std::ostream & out, const TypeSubstitution & sub ) {220 sub.print( out );221 return out;222 }223 224 225 219 // Local Variables: // 226 220 // tab-width: 4 // -
src/SynTree/TypeSubstitution.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // TypeSubstitution.h -- 7 // TypeSubstitution.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri Apr 29 15:00:20201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:33:19 2016 13 13 // Update Count : 2 14 14 // … … 33 33 TypeSubstitution( const TypeSubstitution &other ); 34 34 virtual ~TypeSubstitution(); 35 35 36 36 TypeSubstitution &operator=( const TypeSubstitution &other ); 37 37 38 38 template< typename SynTreeClass > int apply( SynTreeClass *&input ); 39 39 template< typename SynTreeClass > int applyFree( SynTreeClass *&input ); 40 40 41 41 void add( std::string formalType, Type *actualType ); 42 42 void add( const TypeSubstitution &other ); … … 44 44 Type *lookup( std::string formalType ) const; 45 45 bool empty() const; 46 46 47 47 template< typename FormalIterator, typename ActualIterator > 48 48 void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ); 49 50 /// this function is unused... 49 51 50 template< typename TypeInstListIterator > 52 51 void extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result ); 53 52 54 53 void normalize(); 55 54 … … 64 63 /// Records type variable bindings from forall-statements and instantiations of generic types 65 64 template< typename TypeClass > Type *handleAggregateType( TypeClass *type ); 66 65 67 66 virtual Type* mutate(VoidType *basicType); 68 67 virtual Type* mutate(BasicType *basicType); … … 76 75 virtual Type* mutate(TupleType *tupleType); 77 76 virtual Type* mutate(VarArgsType *varArgsType); 78 77 79 78 // TODO: worry about traversing into a forall-qualified function type or type decl with assertions 80 79 81 80 void initialize( const TypeSubstitution &src, TypeSubstitution &dest ); 82 81 … … 137 136 return subCount; 138 137 } 139 138 140 139 template< typename SynTreeClass > 141 140 int TypeSubstitution::applyFree( SynTreeClass *&input ) { … … 150 149 return subCount; 151 150 } 152 151 153 152 template< typename TypeInstListIterator > 154 153 void TypeSubstitution::extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result ) { 155 // xxx - this function doesn't extract varEnv - is this intentional?156 154 while ( begin != end ) { 157 155 TypeEnvType::iterator cur = typeEnv.find( (*begin++)->get_name() ); … … 175 173 } 176 174 177 std::ostream & operator<<( std::ostream & out, const TypeSubstitution & sub );178 179 175 #endif // TYPESUBSTITUTION_H 180 176 -
src/SynTree/Visitor.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Visitor.cc -- 7 // Visitor.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:07:40201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 1 18:05:13 2016 13 13 // Update Count : 18 14 14 // … … 284 284 } 285 285 286 void Visitor::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {287 maybeAccept( impCpCtorExpr->get_callExpr(), *this );288 acceptAll( impCpCtorExpr->get_tempDecls(), *this );289 acceptAll( impCpCtorExpr->get_returnDecls(), *this );290 }291 292 286 void Visitor::visit( UntypedValofExpr *valofExpr ) { 293 287 acceptAll( valofExpr->get_results(), *this ); … … 385 379 } 386 380 387 void Visitor::visit( ConstructorInit *ctorInit ) {388 maybeAccept( ctorInit->get_ctor(), *this );389 maybeAccept( ctorInit->get_init(), *this );390 }391 392 381 void Visitor::visit( Subrange *subrange ) {} 393 382 -
src/SynTree/Visitor.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Visitor.h -- 7 // Visitor.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Thu Apr 14 15:30:58201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 1 17:26:55 2016 13 13 // Update Count : 7 14 14 // … … 62 62 virtual void visit( MemberExpr *memberExpr ); 63 63 virtual void visit( VariableExpr *variableExpr ); 64 virtual void visit( ConstantExpr *constantExpr ); 64 virtual void visit( ConstantExpr *constantExpr ); 65 65 virtual void visit( SizeofExpr *sizeofExpr ); 66 66 virtual void visit( AlignofExpr *alignofExpr ); … … 76 76 virtual void visit( TypeExpr *typeExpr ); 77 77 virtual void visit( AsmExpr *asmExpr ); 78 virtual void visit( ImplicitCopyCtorExpr *impCpCtorExpr );79 78 virtual void visit( UntypedValofExpr *valofExpr ); 80 79 virtual void visit( CompoundLiteralExpr *compLitExpr ); … … 97 96 virtual void visit( SingleInit *singleInit ); 98 97 virtual void visit( ListInit *listInit ); 99 virtual void visit( ConstructorInit *ctorInit );100 98 101 99 virtual void visit( Subrange *subrange ); -
src/examples/array.c
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // array.c -- 7 // array.c -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:21:52 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 18:13:52 2016 13 13 // Update Count : 3 14 14 // … … 26 26 // The first element is always at index 0. 27 27 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) ) 28 elt_type * begin( array_type *array ) {28 elt_type * begin( array_type array ) { 29 29 return &array[ 0 ]; 30 30 } … … 32 32 // The end iterator should point one past the last element. 33 33 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) ) 34 elt_type * end( array_type *array ) {34 elt_type * end( array_type array ) { 35 35 return &array[ last( array ) ] + 1; 36 36 } -
src/examples/array.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // array.h -- 7 // array.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:26:04201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 18:13:35 2016 13 13 // Update Count : 5 14 14 // … … 26 26 27 27 // A bounded array is an array that carries its maximum index with it. 28 trait bounded_array( otype array_type, otype elt_type | array( array_type *, elt_type ) ) {29 int last( array_type *);28 trait bounded_array( otype array_type, otype elt_type | array( array_type, elt_type ) ) { 29 int last( array_type ); 30 30 }; 31 31 … … 41 41 // return iterators corresponding to the first element and the one-past-the-end element, STL-style. 42 42 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) ) 43 elt_type * begin( array_type * array);43 elt_type *begin( array_type ); 44 44 45 // The end iterator should point one past the last element.46 45 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) ) 47 elt_type * end( array_type * array);46 elt_type *end( array_type ); 48 47 49 48 #endif // ARRAY_H -
src/examples/io.c
r7cc6bd6 r9243a501 11 11 // Created On : Wed Mar 2 16:56:02 2016 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Sat Apr 30 08:34:13201614 // Update Count : 2 713 // Last Modified On : Wed Apr 13 23:03:14 2016 14 // Update Count : 22 15 15 // 16 16 … … 52 52 | sepDisable | fc | dc | ldc | sepEnable | endl // complex without separator 53 53 | sepOn | s1 | sepOff | s2 | endl // local separator removal 54 | s1 | "" | s2 | endl; // C string withou tseparator54 | s1 | "" | s2 | endl; // C string withou separator 55 55 sout | endl; 56 56 … … 70 70 | "£" | 27 71 71 | "¥" | 27 72 | "¡" | 2773 72 | "¿" | 27 74 73 | "«" | 27 -
src/examples/vector_int.c
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // vector_int.c -- 7 // vector_int.c -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:27:12 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 27 18:38:05 2015 13 13 // Update Count : 3 14 14 // … … 22 22 #define DEFAULT_CAPACITY 20 23 23 24 v oid ?{}( vector_int * vec) {25 vec { DEFAULT_CAPACITY };24 vector_int vector_int_allocate() { 25 return vector_int_allocate( DEFAULT_CAPACITY ); 26 26 } 27 27 28 void ?{}( vector_int * vec, int reserve ) { 29 vec->last = -1; 30 vec->capacity = reserve; 31 vec->data = malloc( sizeof( int ) * reserve ); 28 vector_int vector_int_allocate( int reserve ) { 29 vector_int new_vector; 30 new_vector.last = -1; 31 new_vector.capacity = reserve; 32 new_vector.data = malloc( sizeof( int ) * reserve ); 33 return new_vector; 32 34 } 33 35 34 void ?{}( vector_int * vec, vector_int other ) { 35 vec->last = other.last; 36 vec->capacity = other.capacity; 37 vec->data = malloc( sizeof( int ) * other.capacity ); 38 for (int i = 0; i < vec->last; i++) { 39 vec->data[i] = other.data[i]; 40 } 41 } 42 43 void ^?{}( vector_int * vec ) { 44 free( vec->data ); 36 void vector_int_deallocate( vector_int vec ) { 37 free( vec.data ); 45 38 } 46 39 … … 63 56 // implement bounded_array 64 57 65 lvalue int ?[?]( vector_int *vec, int index ) {66 return vec ->data[ index ];58 lvalue int ?[?]( vector_int vec, int index ) { 59 return vec.data[ index ]; 67 60 } 68 61 69 int last( vector_int *vec ) {70 return vec ->last;62 int last( vector_int vec ) { 63 return vec.last; 71 64 } 72 65 -
src/examples/vector_int.h
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // vector_int.h -- 7 // vector_int.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:26:59 201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 27 18:39:05 2015 13 13 // Update Count : 2 14 14 // … … 25 25 } vector_int; 26 26 27 void ?{}( vector_int * ); // allocate vector with default capacity 28 void ?{}( vector_int *, int reserve ); // allocate vector with specified capacity 29 void ?{}( vector_int * vec, vector_int other ); // copy constructor 30 void ^?{}( vector_int * ); // deallocate vector's storage 27 vector_int vector_int_allocate(); // allocate vector with default capacity 28 vector_int vector_int_allocate( int reserve ); // allocate vector with specified capacity 29 void vector_int_deallocate( vector_int ); // deallocate vector's storage 31 30 32 31 void reserve( vector_int *vec, int reserve ); // reserve more capacity … … 35 34 // implement bounded_array 36 35 37 lvalue int ?[?]( vector_int *vec, int index ); // access to arbitrary element (does not resize)38 int last( vector_int *vec ); // return last element36 lvalue int ?[?]( vector_int vec, int index ); // access to arbitrary element (does not resize) 37 int last( vector_int vec ); // return last element 39 38 40 39 #endif // VECTOR_INT_H -
src/examples/vector_test.c
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // vector_test.c -- 7 // vector_test.c -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Apr 27 17:31:27201611 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 17 12:23:55 2016 13 13 // Update Count : 18 14 14 // … … 20 20 21 21 int main( void ) { 22 vector_int vec ;22 vector_int vec = vector_int_allocate(); 23 23 24 24 // read in numbers until EOF or error … … 34 34 35 35 sout | "Array elements:" | endl; 36 write( begin( &vec ), end( &vec ), sout );36 write( begin( vec ), end( vec ), sout ); 37 37 sout | endl; 38 38 39 39 sout | "Array elements reversed:" | endl; 40 write_reverse( begin( &vec ), end( &vec ), sout );40 write_reverse( begin( vec ), end( vec ), sout ); 41 41 sout | endl; 42 42 } -
src/initialization.txt
r7cc6bd6 r9243a501 34 34 sure that resolved initializers for all declarations are being 35 35 generated. 36 37 38 ------39 40 More recent email: (I am quoted; Richard is the responder)41 > As far as I'm aware, the only way that I could currently get the correct42 > results from the unification engine is by feeding it an expression that43 > looks like "?=?( ((struct Y)x.y).a, 10 )", then picking out the pieces that44 > I need (namely the correct choice for a). Does this seem like a reasonable45 > approach to solve this problem?46 47 No, unfortunately. Initialization isn't being rewritten as assignment,48 so you shouldn't allow the particular selection of assignment49 operators that happen to be in scope (and which may include50 user-defined operators) to guide the type resolution.51 52 I don't think there is any way to rewrite an initializer as a single53 expression and have the resolver just do the right thing. I see the54 algorithm as:55 56 For each alternative interpretation of the designator:57 Construct an expression that casts the initializer to the type of58 the designator59 Construct an AlternativeFinder and use it to find the lowest cost60 interpretation of the expression61 Add this interpretation to a list of possibilities62 Go through the list of possibilities and pick the lowest cost63 64 As with many things in the resolver, it's conceptually simple but the65 implementation may be a bit of a pain. It fits in with functions like66 findSingleExpression, findIntegralExpression in Resolver.cc, although67 it will be significantly more complicated than any of the existing68 ones.69 70 71 -
src/libcfa/Makefile.am
r7cc6bd6 r9243a501 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## Makefile.am -- 8 ## Makefile.am -- 9 9 ## 10 10 ## Author : Peter A. Buhr … … 51 51 52 52 CFLAGS = -g -Wall -Wno-unused-function -B${abs_top_srcdir}/src/driver -XCFA -t # TEMPORARY: does not build with -O2 53 CC = ${abs_top_srcdir}/src/driver/cfa 53 CC = ${abs_top_srcdir}/src/driver/cfa 54 54 55 55 # extension-less header files are overridden by default make rules => explicitly override rule … … 67 67 include_HEADERS = ${cheaders:=.h} ${libs} ${cfaheaders} 68 68 69 CLEANFILES = libcfa-prelude.c70 69 MAINTAINERCLEANFILES += ${includedir}/* -
src/libcfa/Makefile.in
r7cc6bd6 r9243a501 111 111 AWK = @AWK@ 112 112 BACKEND_CC = @BACKEND_CC@ 113 CC = ${abs_top_srcdir}/src/driver/cfa 113 CC = ${abs_top_srcdir}/src/driver/cfa 114 114 CCDEPMODE = @CCDEPMODE@ 115 115 CFA_BINDIR = @CFA_BINDIR@ … … 219 219 cfaheaders = # limits 220 220 include_HEADERS = ${cheaders:=.h} ${libs} ${cfaheaders} 221 CLEANFILES = libcfa-prelude.c222 221 all: all-am 223 222 … … 458 457 459 458 clean-generic: 460 -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)461 459 462 460 distclean-generic: -
src/libcfa/fstream
r7cc6bd6 r9243a501 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Apr 28 08:08:04201613 // Update Count : 8 812 // Last Modified On : Tue Apr 19 20:44:10 2016 13 // Update Count : 84 14 14 // 15 15 … … 22 22 struct ofstream { 23 23 void *file; 24 _BoolsepDefault;25 int sepOnOff; // FIX ME: type should be _Bool24 int sepDefault; 25 int sepOnOff; 26 26 char separator[separateSize]; 27 27 }; // ofstream -
src/libcfa/fstream.c
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // fstream.c -- 7 // fstream.c -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon May 02 15:14:52201613 // Update Count : 1 8711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 6 17:55:27 2016 13 // Update Count : 176 14 14 // 15 15 … … 75 75 if ( fclose( (FILE *)(os->file) ) == EOF ) { 76 76 perror( IO_MSG "close output" ); 77 } // if 77 } // if 78 78 } // close 79 79 … … 93 93 int prtfmt( ofstream * os, const char fmt[], ... ) { 94 94 va_list args; 95 95 96 va_start( args, fmt ); 96 97 int len = vfprintf( (FILE *)(os->file), fmt, args ); … … 102 103 } // if 103 104 va_end( args ); 104 105 sepReset( os ); // reset separator106 105 return len; 107 106 } // prtfmt … … 140 139 if ( fclose( (FILE *)(is->file) ) == EOF ) { 141 140 perror( IO_MSG "close input" ); 142 } // if 141 } // if 143 142 } // close 144 143 … … 155 154 return is; 156 155 } // read 157 156 158 157 ifstream *ungetc( ifstream * is, char c ) { 159 158 if ( fail( is ) ) { -
src/libcfa/iostream.c
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // iostream.c -- 7 // iostream.c -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Wed May 27 17:56:53 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon May 02 15:13:55201613 // Update Count : 30211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 6 16:13:29 2016 13 // Update Count : 278 14 14 // 15 15 … … 34 34 ostype * ?|?( ostype *os, short int si ) { 35 35 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 36 sepReset( os ); 36 37 prtfmt( os, "%hd", si ); 37 38 return os; … … 41 42 ostype * ?|?( ostype *os, unsigned short int usi ) { 42 43 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 44 sepReset( os ); 43 45 prtfmt( os, "%hu", usi ); 44 46 return os; … … 48 50 ostype * ?|?( ostype *os, int i ) { 49 51 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 52 sepReset( os ); 50 53 prtfmt( os, "%d", i ); 51 54 return os; … … 55 58 ostype * ?|?( ostype *os, unsigned int ui ) { 56 59 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 60 sepReset( os ); 57 61 prtfmt( os, "%u", ui ); 58 62 return os; … … 62 66 ostype * ?|?( ostype *os, long int li ) { 63 67 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 68 sepReset( os ); 64 69 prtfmt( os, "%ld", li ); 65 70 return os; … … 69 74 ostype * ?|?( ostype *os, unsigned long int uli ) { 70 75 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 76 sepReset( os ); 71 77 prtfmt( os, "%lu", uli ); 72 78 return os; … … 76 82 ostype * ?|?( ostype *os, long long int lli ) { 77 83 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 84 sepReset( os ); 78 85 prtfmt( os, "%lld", lli ); 79 86 return os; … … 83 90 ostype * ?|?( ostype *os, unsigned long long int ulli ) { 84 91 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 92 sepReset( os ); 85 93 prtfmt( os, "%llu", ulli ); 86 94 return os; … … 90 98 ostype * ?|?( ostype *os, float f ) { 91 99 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 100 sepReset( os ); 92 101 prtfmt( os, "%g", f ); 93 102 return os; … … 97 106 ostype * ?|?( ostype *os, double d ) { 98 107 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 108 sepReset( os ); 99 109 prtfmt( os, "%.*lg", DBL_DIG, d ); 100 110 return os; … … 104 114 ostype * ?|?( ostype *os, long double ld ) { 105 115 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 116 sepReset( os ); 106 117 prtfmt( os, "%.*Lg", LDBL_DIG, ld ); 107 118 return os; … … 144 155 // opening delimiters 145 156 ['('] : Open, ['['] : Open, ['{'] : Open, 146 ['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open, 147 [(unsigned char)'¡'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open, 157 ['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open, 148 158 // closing delimiters 149 159 [','] : Close, ['.'] : Close, [':'] : Close, [';'] : Close, ['!'] : Close, ['?'] : Close, … … 152 162 // opening-closing delimiters 153 163 ['\''] : OpenClose, ['`'] : OpenClose, ['"'] : OpenClose, 154 [' '] : OpenClose, ['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace164 ['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace 155 165 }; // mask 156 166 157 if ( cp[0] == '\0' ) { sepOff( os ); return os; } // null string => no separator 158 167 int len = strlen( cp ); 168 // null string => no separator 169 if ( len == 0 ) { sepOff( os ); return os; } 159 170 // first character IS NOT spacing or closing punctuation => add left separator 160 171 unsigned char ch = cp[0]; // must make unsigned … … 162 173 prtfmt( os, "%s", sepGet( os ) ); 163 174 } // if 164 165 // if string starts line, must reset to determine open state because separator is off166 sepReset( os ); // reset separator167 168 175 // last character IS spacing or opening punctuation => turn off separator for next item 169 unsigned int len = strlen( cp ),posn = len - 1;176 unsigned int posn = len - 1; 170 177 ch = cp[posn]; // must make unsigned 171 if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) { 178 if ( mask[ ch ] == Open || mask[ ch ] == OpenClose ) { 179 sepOff( os ); 180 } else { 172 181 sepOn( os ); 173 } else {174 sepOff( os );175 182 } // if 176 183 return write( os, cp, len ); … … 180 187 ostype * ?|?( ostype *os, const void *p ) { 181 188 if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) ); 189 sepReset( os ); 182 190 prtfmt( os, "%p", p ); 183 191 return os; … … 185 193 186 194 187 forall( dtype ostype | ostream( ostype ) ) 195 forall( dtype ostype | ostream( ostype ) ) 188 196 ostype * ?|?( ostype *os, ostype * (* manip)( ostype * ) ) { 189 197 return manip( os ); 190 198 } // ?|? 191 199 192 forall( dtype ostype | ostream( ostype ) ) 200 forall( dtype ostype | ostream( ostype ) ) 193 201 ostype * endl( ostype * os ) { 194 202 os | '\n'; … … 198 206 } // endl 199 207 200 forall( dtype ostype | ostream( ostype ) ) 208 forall( dtype ostype | ostream( ostype ) ) 201 209 ostype * sepOn( ostype * os ) { 202 210 sepOn( os ); … … 204 212 } // sepOn 205 213 206 forall( dtype ostype | ostream( ostype ) ) 214 forall( dtype ostype | ostream( ostype ) ) 207 215 ostype * sepOff( ostype * os ) { 208 216 sepOff( os ); … … 210 218 } // sepOff 211 219 212 forall( dtype ostype | ostream( ostype ) ) 220 forall( dtype ostype | ostream( ostype ) ) 213 221 ostype * sepEnable( ostype * os ) { 214 222 sepEnable( os ); … … 216 224 } // sepEnable 217 225 218 forall( dtype ostype | ostream( ostype ) ) 226 forall( dtype ostype | ostream( ostype ) ) 219 227 ostype * sepDisable( ostype * os ) { 220 228 sepDisable( os ); … … 336 344 } // ?|? 337 345 338 _Istream_cstrUC cstr( char * s tr ) { _Istream_cstrUC s = { str}; return s; }346 _Istream_cstrUC cstr( char * s ) { _Istream_cstrUC s = { s }; return s; } 339 347 forall( dtype istype | istream( istype ) ) 340 348 istype * ?|?( istype * is, _Istream_cstrUC cstr ) { … … 343 351 } // cstr 344 352 345 _Istream_cstrC cstr( char * s tr, int size ) { _Istream_cstrC s = { str, size }; return s; }353 _Istream_cstrC cstr( char * s, int size ) { _Istream_cstrC s = { s, size }; return s; } 346 354 forall( dtype istype | istream( istype ) ) 347 355 istype * ?|?( istype * is, _Istream_cstrC cstr ) { -
src/libcfa/prelude.cf
r7cc6bd6 r9243a501 1 1 # 2 "prelude.cf" // needed for error messages from this file 2 // -*- Mode: C -*- 3 // 2 // -*- Mode: C -*- 3 // 4 4 // Copyright (C) Glen Ditchfield 1994, 1999 5 // 5 // 6 6 // prelude.cf -- Standard Cforall Preample for C99 7 // 7 // 8 8 // Author : Glen Ditchfield 9 9 // Created On : Sat Nov 29 07:23:41 2014 … … 117 117 forall( ftype FT ) lvalue FT *?( FT * ); 118 118 119 _Bool +?( _Bool ), -?( _Bool ), ~?( _Bool ); 120 signed int +?( signed int ), -?( signed int ), ~?( signed int ); 121 unsigned int +?( unsigned int ), -?( unsigned int ), ~?( unsigned int ); 122 signed long int +?( signed long int ), -?( signed long int ), ~?( signed long int ); 123 unsigned long int +?( unsigned long int ), -?( unsigned long int ), ~?( unsigned long int ); 124 signed long long int +?( signed long long int ), -?( signed long long int ), ~?( signed long long int ); 125 unsigned long long int +?( unsigned long long int ), -?( unsigned long long int ), ~?( unsigned long long int ); 119 _Bool +?( _Bool ), -?( _Bool ), ~?( _Bool ); 120 signed int +?( signed int ), -?( signed int ), ~?( signed int ); 121 unsigned int +?( unsigned int ), -?( unsigned int ), ~?( unsigned int ); 122 signed long int +?( signed long int ), -?( signed long int ), ~?( signed long int ); 123 unsigned long int +?( unsigned long int ), -?( unsigned long int ), ~?( unsigned long int ); 124 signed long long int +?( signed long long int ), -?( signed long long int ), ~?( signed long long int ); 125 unsigned long long int +?( unsigned long long int ), -?( unsigned long long int ), ~?( unsigned long long int ); 126 126 float +?( float ), -?( float ); 127 127 double +?( double ), -?( double ); … … 627 627 ?+=?( long double _Complex *, long double _Complex ), ?+=?( volatile long double _Complex *, long double _Complex ), 628 628 ?-=?( long double _Complex *, long double _Complex ), ?-=?( volatile long double _Complex *, long double _Complex ); 629 630 631 632 633 634 // ------------------------------------------------------------635 //636 // Section ??? Constructors and Destructors637 //638 // ------------------------------------------------------------639 640 // default ctor641 void ?{}( _Bool * ), ?{}( volatile _Bool * );642 void ?{}( char * ), ?{}( volatile char * );643 void ?{}( unsigned char * ), ?{}( volatile unsigned char * );644 void ?{}( char signed * ), ?{}( volatile char signed * );645 void ?{}( int short * ), ?{}( volatile int short * );646 void ?{}( int short unsigned * ), ?{}( volatile int short unsigned * );647 void ?{}( signed int * ), ?{}( volatile signed int * );648 void ?{}( unsigned int * ), ?{}( volatile unsigned int * );649 void ?{}( signed long int * ), ?{}( volatile signed long int * );650 void ?{}( unsigned long int * ), ?{}( volatile unsigned long int * );651 void ?{}( signed long long int * ), ?{}( volatile signed long long int * );652 void ?{}( unsigned long long int * ), ?{}( volatile unsigned long long int * );653 void ?{}( float * ), ?{}( volatile float * );654 void ?{}( double * ), ?{}( volatile double * );655 void ?{}( long double * ), ?{}( volatile long double * );656 void ?{}( float _Complex * ), ?{}( volatile float _Complex * );657 void ?{}( double _Complex * ), ?{}( volatile double _Complex * );658 void ?{}( long double _Complex * ), ?{}( volatile long double _Complex * );659 660 // copy ctor661 void ?{}( _Bool *, _Bool ), ?{}( volatile _Bool *, _Bool );662 void ?{}( char *, char ), ?{}( volatile char *, char );663 void ?{}( unsigned char *, unsigned char ), ?{}( volatile unsigned char *, unsigned char );664 void ?{}( char signed *, char signed ), ?{}( volatile char signed *, char signed );665 void ?{}( int short *, int short ), ?{}( volatile int short *, int short );666 void ?{}( int short unsigned *, int short unsigned ), ?{}( volatile int short unsigned *, int short unsigned );667 void ?{}( signed int *, signed int), ?{}( volatile signed int *, signed int );668 void ?{}( unsigned int *, unsigned int), ?{}( volatile unsigned int *, unsigned int );669 void ?{}( signed long int *, signed long int), ?{}( volatile signed long int *, signed long int );670 void ?{}( unsigned long int *, unsigned long int), ?{}( volatile unsigned long int *, unsigned long int );671 void ?{}( signed long long int *, signed long long int), ?{}( volatile signed long long int *, signed long long int );672 void ?{}( unsigned long long int *, unsigned long long int), ?{}( volatile unsigned long long int *, unsigned long long int );673 void ?{}( float *, float), ?{}( volatile float *, float );674 void ?{}( double *, double), ?{}( volatile double *, double );675 void ?{}( long double *, long double), ?{}( volatile long double *, long double );676 void ?{}( float _Complex *, float _Complex), ?{}( volatile float _Complex *, float _Complex );677 void ?{}( double _Complex *, double _Complex), ?{}( volatile double _Complex *, double _Complex );678 void ?{}( long double _Complex *, long double _Complex), ?{}( volatile long double _Complex *, long double _Complex );679 680 // dtor681 void ^?{}( _Bool * ), ^?{}( volatile _Bool * );682 void ^?{}( char * ), ^?{}( volatile char * );683 void ^?{}( char unsigned * ), ^?{}( volatile char unsigned * );684 void ^?{}( char signed * ), ^?{}( volatile char signed * );685 void ^?{}( int short * ), ^?{}( volatile int short * );686 void ^?{}( int short unsigned * ), ^?{}( volatile int short unsigned * );687 void ^?{}( signed int * ), ^?{}( volatile signed int * );688 void ^?{}( unsigned int * ), ^?{}( volatile unsigned int * );689 void ^?{}( signed long int * ), ^?{}( volatile signed long int * );690 void ^?{}( unsigned long int * ), ^?{}( volatile unsigned long int * );691 void ^?{}( signed long long int * ), ^?{}( volatile signed long long int * );692 void ^?{}( unsigned long long int * ), ^?{}( volatile unsigned long long int * );693 void ^?{}( float * ), ^?{}( volatile float * );694 void ^?{}( double * ), ^?{}( volatile double * );695 void ^?{}( long double * ), ^?{}( volatile long double * );696 void ^?{}( float _Complex * ), ^?{}( volatile float _Complex * );697 void ^?{}( double _Complex * ), ^?{}( volatile double _Complex * );698 void ^?{}( long double _Complex * ), ^?{}( volatile long double _Complex * );699 700 // // default ctor701 // forall( dtype DT ) void ?{}( DT ** );702 // forall( dtype DT ) void ?{}( const DT ** );703 // forall( dtype DT ) void ?{}( volatile DT ** );704 // forall( dtype DT ) void ?{}( const volatile DT ** );705 706 // // copy ctor707 // forall( dtype DT ) void ?{}( DT **, DT* );708 // forall( dtype DT ) void ?{}( const DT **, DT* );709 // forall( dtype DT ) void ?{}( volatile DT **, DT* );710 // forall( dtype DT ) void ?{}( const volatile DT **, DT* );711 712 // // dtor713 // forall( dtype DT ) void ^?{}( DT ** );714 // forall( dtype DT ) void ^?{}( const DT ** );715 // forall( dtype DT ) void ^?{}( volatile DT ** );716 // forall( dtype DT ) void ^?{}( const volatile DT ** );717 718 // copied from assignment section719 // copy constructors720 forall( ftype FT ) void ?{}( FT **, FT * );721 forall( ftype FT ) void ?{}( FT * volatile *, FT * );722 723 forall( dtype DT ) void ?{}( DT * *, DT * );724 forall( dtype DT ) void ?{}( DT * volatile *, DT * );725 forall( dtype DT ) void ?{}( const DT * *, DT * );726 forall( dtype DT ) void ?{}( const DT * volatile *, DT * );727 forall( dtype DT ) void ?{}( const DT * *, const DT * );728 forall( dtype DT ) void ?{}( const DT * volatile *, const DT * );729 forall( dtype DT ) void ?{}( volatile DT * *, DT * );730 forall( dtype DT ) void ?{}( volatile DT * volatile *, DT * );731 forall( dtype DT ) void ?{}( volatile DT * *, volatile DT * );732 forall( dtype DT ) void ?{}( volatile DT * volatile *, volatile DT * );733 734 forall( dtype DT ) void ?{}( const volatile DT * *, DT * );735 forall( dtype DT ) void ?{}( const volatile DT * volatile *, DT * );736 forall( dtype DT ) void ?{}( const volatile DT * *, const DT * );737 forall( dtype DT ) void ?{}( const volatile DT * volatile *, const DT * );738 forall( dtype DT ) void ?{}( const volatile DT * *, volatile DT * );739 forall( dtype DT ) void ?{}( const volatile DT * volatile *, volatile DT * );740 forall( dtype DT ) void ?{}( const volatile DT * *, const volatile DT * );741 forall( dtype DT ) void ?{}( const volatile DT * volatile *, const volatile DT * );742 743 forall( dtype DT ) void ?{}( DT * *, void * );744 forall( dtype DT ) void ?{}( DT * volatile *, void * );745 forall( dtype DT ) void ?{}( const DT * *, void * );746 forall( dtype DT ) void ?{}( const DT * volatile *, void * );747 forall( dtype DT ) void ?{}( const DT * *, const void * );748 forall( dtype DT ) void ?{}( const DT * volatile *, const void * );749 forall( dtype DT ) void ?{}( volatile DT * *, void * );750 forall( dtype DT ) void ?{}( volatile DT * volatile *, void * );751 forall( dtype DT ) void ?{}( volatile DT * *, volatile void * );752 forall( dtype DT ) void ?{}( volatile DT * volatile *, volatile void * );753 754 forall( dtype DT ) void ?{}( const volatile DT * *, void * );755 forall( dtype DT ) void ?{}( const volatile DT * volatile *, void * );756 forall( dtype DT ) void ?{}( const volatile DT * *, const void * );757 forall( dtype DT ) void ?{}( const volatile DT * volatile *, const void * );758 forall( dtype DT ) void ?{}( const volatile DT * *, volatile void * );759 forall( dtype DT ) void ?{}( const volatile DT * volatile *, volatile void * );760 forall( dtype DT ) void ?{}( const volatile DT * *, const volatile void * );761 forall( dtype DT ) void ?{}( const volatile DT * volatile *, const volatile void * );762 763 forall( dtype DT ) void ?{}( void * *, DT * );764 forall( dtype DT ) void ?{}( void * volatile *, DT * );765 forall( dtype DT ) void ?{}( const void * *, DT * );766 forall( dtype DT ) void ?{}( const void * volatile *, DT * );767 forall( dtype DT ) void ?{}( const void * *, const DT * );768 forall( dtype DT ) void ?{}( const void * volatile *, const DT * );769 forall( dtype DT ) void ?{}( volatile void * *, DT * );770 forall( dtype DT ) void ?{}( volatile void * volatile *, DT * );771 forall( dtype DT ) void ?{}( volatile void * *, volatile DT * );772 forall( dtype DT ) void ?{}( volatile void * volatile *, volatile DT * );773 forall( dtype DT ) void ?{}( const volatile void * *, DT * );774 forall( dtype DT ) void ?{}( const volatile void * volatile *, DT * );775 forall( dtype DT ) void ?{}( const volatile void * *, const DT * );776 forall( dtype DT ) void ?{}( const volatile void * volatile *, const DT * );777 forall( dtype DT ) void ?{}( const volatile void * *, volatile DT * );778 forall( dtype DT ) void ?{}( const volatile void * volatile *, volatile DT * );779 forall( dtype DT ) void ?{}( const volatile void * *, const volatile DT * );780 forall( dtype DT ) void ?{}( const volatile void * volatile *, const volatile DT * );781 782 void ?{}( void * *, void * );783 void ?{}( void * volatile *, void * );784 void ?{}( const void * *, void * );785 void ?{}( const void * volatile *, void * );786 void ?{}( const void * *, const void * );787 void ?{}( const void * volatile *, const void * );788 void ?{}( volatile void * *, void * );789 void ?{}( volatile void * volatile *, void * );790 void ?{}( volatile void * *, volatile void * );791 void ?{}( volatile void * volatile *, volatile void * );792 void ?{}( const volatile void * *, void * );793 void ?{}( const volatile void * volatile *, void * );794 void ?{}( const volatile void * *, const void * );795 void ?{}( const volatile void * volatile *, const void * );796 void ?{}( const volatile void * *, volatile void * );797 void ?{}( const volatile void * volatile *, volatile void * );798 void ?{}( const volatile void * *, const volatile void * );799 void ?{}( const volatile void * volatile *, const volatile void * );800 801 //forall( dtype DT ) void ?{}( DT * *, forall( dtype DT2 ) const DT2 * );802 //forall( dtype DT ) void ?{}( DT * volatile *, forall( dtype DT2 ) const DT2 * );803 forall( dtype DT ) void ?{}( const DT * *, forall( dtype DT2 ) const DT2 * );804 forall( dtype DT ) void ?{}( const DT * volatile *, forall( dtype DT2 ) const DT2 * );805 //forall( dtype DT ) void ?{}( volatile DT * *, forall( dtype DT2 ) const DT2 * );806 //forall( dtype DT ) void ?{}( volatile DT * volatile *, forall( dtype DT2 ) const DT2 * );807 forall( dtype DT ) void ?{}( const volatile DT * *, forall( dtype DT2 ) const DT2 * );808 forall( dtype DT ) void ?{}( const volatile DT * volatile *, forall( dtype DT2 ) const DT2 * );809 810 forall( ftype FT ) void ?{}( FT * *, forall( ftype FT2 ) FT2 * );811 forall( ftype FT ) void ?{}( FT * volatile *, forall( ftype FT2 ) FT2 * );812 813 // default ctors814 forall( ftype FT ) void ?{}( FT * * );815 forall( ftype FT ) void ?{}( FT * volatile * );816 817 forall( dtype DT ) void ?{}( DT * *);818 forall( dtype DT ) void ?{}( DT * volatile *);819 forall( dtype DT ) void ?{}( const DT * *);820 forall( dtype DT ) void ?{}( const DT * volatile *);821 forall( dtype DT ) void ?{}( volatile DT * *);822 forall( dtype DT ) void ?{}( volatile DT * volatile *);823 forall( dtype DT ) void ?{}( const volatile DT * *);824 forall( dtype DT ) void ?{}( const volatile DT * volatile *);825 826 void ?{}( void * *);827 void ?{}( void * volatile *);828 void ?{}( const void * *);829 void ?{}( const void * volatile *);830 void ?{}( volatile void * *);831 void ?{}( volatile void * volatile *);832 void ?{}( const volatile void * *);833 void ?{}( const volatile void * volatile *);834 835 // dtors836 forall( ftype FT ) void ^?{}( FT * * );837 forall( ftype FT ) void ^?{}( FT * volatile * );838 839 forall( dtype DT ) void ^?{}( DT * *);840 forall( dtype DT ) void ^?{}( DT * volatile *);841 forall( dtype DT ) void ^?{}( const DT * *);842 forall( dtype DT ) void ^?{}( const DT * volatile *);843 forall( dtype DT ) void ^?{}( volatile DT * *);844 forall( dtype DT ) void ^?{}( volatile DT * volatile *);845 forall( dtype DT ) void ^?{}( const volatile DT * *);846 forall( dtype DT ) void ^?{}( const volatile DT * volatile *);847 848 void ^?{}( void * *);849 void ^?{}( void * volatile *);850 void ^?{}( const void * *);851 void ^?{}( const void * volatile *);852 void ^?{}( volatile void * *);853 void ^?{}( volatile void * volatile *);854 void ^?{}( const volatile void * *);855 void ^?{}( const volatile void * volatile *); -
src/libcfa/stdlib
r7cc6bd6 r9243a501 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 27 22:03:29201613 // Update Count : 9 612 // Last Modified On : Thu Apr 21 07:55:21 2016 13 // Update Count : 95 14 14 // 15 15 … … 45 45 46 46 forall( otype T ) T * aligned_alloc( size_t alignment ); 47 forall( otype T ) T * memalign( size_t alignment ); // deprecated47 forall( otype T ) T * memalign( size_t alignment ); 48 48 forall( otype T ) int posix_memalign( T ** ptr, size_t alignment ); 49 49 -
src/libcfa/stdlib.c
r7cc6bd6 r9243a501 10 10 // Created On : Thu Jan 28 17:10:29 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 2 8 07:54:21201613 // Update Count : 16 612 // Last Modified On : Thu Apr 21 07:58:29 2016 13 // Update Count : 165 14 14 // 15 15 … … 213 213 //--------------------------------------- 214 214 215 //forall( otype T | { T ?/?( T, T ); T ?%?( T, T ); } )216 // [ T, T ] div( T t1, T t2 ) { return [ t1 / t2, t1 % t2 ];}215 forall( otype T | { T ?/?( T, T ); T ?%?( T, T ); } ) 216 [ T, T ] div( T t1, T t2 ) { /* return [ t1 / t2, t1 % t2 ]; */ } 217 217 218 218 //--------------------------------------- -
src/main.cc
r7cc6bd6 r9243a501 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // main.cc -- 7 // main.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri Apr 29 12:02:21201613 // Update Count : 20011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 27 22:20:20 2016 13 // Update Count : 199 14 14 // 15 15 … … 40 40 #include "MakeLibCfa.h" 41 41 #include "InitTweak/Mutate.h" 42 #include "InitTweak/GenInit.h" 43 #include "InitTweak/FixInit.h" 42 #include "InitTweak/RemoveInit.h" 44 43 //#include "Explain/GenProlog.h" 45 44 //#include "Try/Visit.h" … … 56 55 57 56 static void parse( FILE * input, LinkageSpec::Type t, bool shouldExit = false ); 58 static void dump( std::list< Declaration * > & translationUnit , std::ostream & out = std::cout);57 static void dump( std::list< Declaration * > & translationUnit ); 59 58 60 59 bool 61 60 astp = false, 62 61 bresolvep = false, 63 bboxp = false,64 ctorinitp = false,65 62 exprp = false, 66 63 expraltp = false, … … 77 74 codegenp = false; 78 75 79 enum { Ast, B box, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };76 enum { Ast, Bresolver, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, }; 80 77 81 78 static struct option long_opts[] = { 82 79 { "ast", no_argument, 0, Ast }, 83 { "before-box", no_argument, 0, Bbox },84 80 { "before-resolver", no_argument, 0, Bresolver }, 85 { "ctorinitfix", no_argument, 0, CtorInitFix },86 81 { "expr", no_argument, 0, Expr }, 87 82 { "expralt", no_argument, 0, ExprAlt }, … … 105 100 106 101 opterr = 0; // prevent getopt from printing error messages 107 102 108 103 int c; 109 while ( (c = getopt_long( argc, argv, "ab BcefFglnpqrstvyzD:", long_opts, &long_index )) != -1 ) {104 while ( (c = getopt_long( argc, argv, "abefglnpqrstvyzD:", long_opts, &long_index )) != -1 ) { 110 105 switch ( c ) { 111 106 case Ast: … … 116 111 case 'b': // print before resolver steps 117 112 bresolvep = true; 118 break;119 case 'B': // print before resolver steps120 bboxp = true;121 break;122 case CtorInitFix:123 case 'c':124 ctorinitp = true;125 113 break; 126 114 case Expr: … … 199 187 output = new ofstream( argv[ optind ] ); 200 188 } // if 201 189 202 190 Parser::get_parser().set_debug( grammarp ); 203 191 … … 220 208 exit( 1 ); 221 209 } // if 222 210 223 211 parse( prelude, LinkageSpec::Intrinsic ); 224 212 } // if 225 213 } // if 226 214 227 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp ); 228 215 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp ); 216 229 217 if ( parsep ) { 230 218 Parser::get_parser().get_parseTree()->printList( std::cout ); … … 261 249 OPTPRINT( "mutate" ) 262 250 ControlStruct::mutate( translationUnit ); 263 OPTPRINT( "fixNames" ) 251 OPTPRINT( "fixNames" ) 264 252 CodeGen::fixNames( translationUnit ); 265 OPTPRINT( "tweak Init" )266 InitTweak:: genInit( translationUnit );253 OPTPRINT( "tweak" ) 254 InitTweak::tweak( translationUnit ); 267 255 268 256 if ( libcfap ) { … … 280 268 if ( exprp ) { 281 269 dump( translationUnit ); 282 return 0;283 }284 285 OPTPRINT( "fixInit" )286 // fix ObjectDecl - replaces ConstructorInit nodes287 InitTweak::fix( translationUnit );288 if ( ctorinitp ) {289 dump ( translationUnit );290 return 0;291 270 } 292 271 … … 297 276 OPTPRINT( "convertLvalue" ) 298 277 GenPoly::convertLvalue( translationUnit ); 299 300 if ( bboxp ) {301 dump( translationUnit );302 return 0;303 }304 278 OPTPRINT( "box" ) 305 279 GenPoly::box( translationUnit ); 306 280 307 281 // print tree right before code generation 308 282 if ( codegenp ) { … … 318 292 } catch ( SemanticError &e ) { 319 293 if ( errorp ) { 320 std::cerr << "---AST at error:---" << std::endl; 321 dump( translationUnit, std::cerr ); 322 std::cerr << std::endl << "---End of AST, begin error message:---\n" << std::endl; 294 dump( translationUnit ); 323 295 } 324 296 e.print( std::cerr ); … … 342 314 } // try 343 315 344 deleteAll( translationUnit );345 316 return 0; 346 317 } // main … … 360 331 } 361 332 362 static void dump( std::list< Declaration * > & translationUnit , std::ostream & out) {333 static void dump( std::list< Declaration * > & translationUnit ) { 363 334 std::list< Declaration * > decls; 364 335 if ( noprotop ) { 365 filter( translationUnit.begin(), translationUnit.end(), 336 filter( translationUnit.begin(), translationUnit.end(), 366 337 std::back_inserter( decls ), notPrelude ); 367 338 } else { … … 369 340 } 370 341 371 printAll( decls, out );342 printAll( decls, std::cout ); 372 343 deleteAll( translationUnit ); 373 344 }
Note:
See TracChangeset
for help on using the changeset viewer.