1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
2 | %% |
---|
3 | %% Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo |
---|
4 | %% |
---|
5 | %% The contents of this file are covered under the licence agreement in the |
---|
6 | %% file "LICENCE" distributed with Cforall. |
---|
7 | %% |
---|
8 | %% user.tex -- |
---|
9 | %% |
---|
10 | %% Author : Peter A. Buhr |
---|
11 | %% Created On : Wed Apr 6 14:53:29 2016 |
---|
12 | %% Last Modified By : Peter A. Buhr |
---|
13 | %% Last Modified On : Mon Feb 20 12:35:48 2017 |
---|
14 | %% Update Count : 1377 |
---|
15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
16 | |
---|
17 | % requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended |
---|
18 | |
---|
19 | \documentclass[twoside,11pt]{article} |
---|
20 | |
---|
21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
22 | |
---|
23 | % Latex packages used in the document. |
---|
24 | \usepackage[T1]{fontenc} % allow Latin1 (extended ASCII) characters |
---|
25 | \usepackage{textcomp} |
---|
26 | \usepackage[latin1]{inputenc} |
---|
27 | |
---|
28 | \usepackage{fullpage,times,comment} |
---|
29 | \usepackage{epic,eepic} |
---|
30 | \usepackage{upquote} % switch curled `'" to straight |
---|
31 | \usepackage{calc} |
---|
32 | \usepackage{xspace} |
---|
33 | \usepackage{graphicx} |
---|
34 | \usepackage{varioref} % extended references |
---|
35 | \usepackage{listings} % format program code |
---|
36 | \usepackage[flushmargin]{footmisc} % support label/reference in footnote |
---|
37 | \usepackage{latexsym} % \Box glyph |
---|
38 | \usepackage{mathptmx} % better math font with "times" |
---|
39 | \usepackage[usenames]{color} |
---|
40 | \usepackage[pagewise]{lineno} |
---|
41 | \renewcommand{\linenumberfont}{\scriptsize\sffamily} |
---|
42 | \input{common} % bespoke macros used in the document |
---|
43 | \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} |
---|
44 | \usepackage{breakurl} |
---|
45 | \renewcommand{\UrlFont}{\small\sf} |
---|
46 | |
---|
47 | \setlength{\topmargin}{-0.45in} % move running title into header |
---|
48 | \setlength{\headsep}{0.25in} |
---|
49 | |
---|
50 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
51 | |
---|
52 | \CFADefaultStyle % use default CFA format-style |
---|
53 | |
---|
54 | % inline code ©...© (copyright symbol) emacs: C-q M-) |
---|
55 | % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. |
---|
56 | % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_ |
---|
57 | % green highlighting ¢...¢ (cent symbol) emacs: C-q M-" |
---|
58 | % LaTex escape §...§ (section symbol) emacs: C-q M-' |
---|
59 | % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ |
---|
60 | % math escape $...$ (dollar symbol) |
---|
61 | |
---|
62 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
63 | |
---|
64 | % Names used in the document. |
---|
65 | \newcommand{\Version}{\input{../../version}} |
---|
66 | \newcommand{\CS}{C\raisebox{-0.9ex}{\large$^\sharp$}\xspace} |
---|
67 | |
---|
68 | \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}} |
---|
69 | \newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}} |
---|
70 | \newcommand{\R}[1]{\Textbf{#1}} |
---|
71 | \newcommand{\B}[1]{{\Textbf[blue]{#1}}} |
---|
72 | \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} |
---|
73 | |
---|
74 | \newsavebox{\LstBox} |
---|
75 | |
---|
76 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
77 | |
---|
78 | \setcounter{secnumdepth}{3} % number subsubsections |
---|
79 | \setcounter{tocdepth}{3} % subsubsections in table of contents |
---|
80 | \makeindex |
---|
81 | |
---|
82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
83 | |
---|
84 | \title{\Huge |
---|
85 | \vspace*{1in} |
---|
86 | \CFA (\CFL) User Manual \\ |
---|
87 | Version 1.0 \\ |
---|
88 | \vspace*{0.25in} |
---|
89 | \huge``describe not prescribe'' |
---|
90 | \vspace*{1in} |
---|
91 | }% title |
---|
92 | |
---|
93 | \author{\huge |
---|
94 | Peter A. Buhr and ... |
---|
95 | }% author |
---|
96 | |
---|
97 | \date{ |
---|
98 | DRAFT \\ \today |
---|
99 | }% date |
---|
100 | |
---|
101 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
102 | |
---|
103 | \begin{document} |
---|
104 | \pagestyle{headings} |
---|
105 | % changed after setting pagestyle |
---|
106 | \renewcommand{\sectionmark}[1]{\markboth{\thesection\quad #1}{\thesection\quad #1}} |
---|
107 | \renewcommand{\subsectionmark}[1]{\markboth{\thesubsection\quad #1}{\thesubsection\quad #1}} |
---|
108 | \pagenumbering{roman} |
---|
109 | \linenumbers % comment out to turn off line numbering |
---|
110 | |
---|
111 | \maketitle |
---|
112 | \thispagestyle{empty} |
---|
113 | \vspace*{\fill} |
---|
114 | \noindent |
---|
115 | \copyright\,2016 \CFA Project \\ \\ |
---|
116 | \noindent |
---|
117 | This work is licensed under the Creative Commons Attribution 4.0 International License. |
---|
118 | To view a copy of this license, visit {\small\url{http://creativecommons.org/licenses/by/4.0}}. |
---|
119 | \vspace*{1in} |
---|
120 | |
---|
121 | \clearpage |
---|
122 | \thispagestyle{plain} |
---|
123 | \pdfbookmark[1]{Contents}{section} |
---|
124 | \tableofcontents |
---|
125 | |
---|
126 | \clearpage |
---|
127 | \thispagestyle{plain} |
---|
128 | \pagenumbering{arabic} |
---|
129 | |
---|
130 | |
---|
131 | \section{Introduction} |
---|
132 | |
---|
133 | \CFA\footnote{Pronounced ``C-for-all'', and written \CFA, CFA, or \CFL.} is a modern general-purpose programming-language, designed as an evolutionary step forward from the C programming language. |
---|
134 | The syntax of the \CFA language builds from C, and should look immediately familiar to C/\Index*[C++]{\CC} programmers. |
---|
135 | % Any language feature that is not described here can be assumed to be using the standard C11 syntax. |
---|
136 | \CFA adds many modern programming-language features that directly lead to increased \emph{safety} and \emph{productivity}, while maintaining interoperability with existing C programs and achieving C performance. |
---|
137 | Like C, \CFA is a statically typed, procedural language with a low-overhead runtime, meaning there is no global garbage-collection. |
---|
138 | The primary new features include parametric-polymorphic routines and types, exceptions, concurrency, and modules. |
---|
139 | |
---|
140 | One of the main design philosophies of \CFA is to ``describe not prescribe'', which means \CFA tries to provide a pathway from low-level C programming to high-level \CFA programming, but it does not force programmers to ``do the right thing''. |
---|
141 | Programmers can cautiously add \CFA extensions to their C programs in any order and at any time to incrementally move towards safer, higher-level programming features. |
---|
142 | A programmer is always free to reach back to C from \CFA for any reason, and in many cases, new \CFA features have a fallback to a C mechanism. |
---|
143 | There is no notion or requirement for rewriting a legacy C program in \CFA; |
---|
144 | instead, a programmer evolves an existing C program into \CFA by incrementally incorporating \CFA features. |
---|
145 | New programs can be written in \CFA using a combination of C and \CFA features. |
---|
146 | \Index*[C++]{\CC} had a similar goal 30 years ago, but has struggled over the intervening time to incorporate modern programming-language features because of early design choices. |
---|
147 | \CFA has 30 years of hindsight and a clean starting point. |
---|
148 | |
---|
149 | Like \Index*[C++]{\CC}, there may be both an old and new ways to achieve the same effect. |
---|
150 | For example, the following programs compare the \CFA and C I/O mechanisms. |
---|
151 | \begin{quote2} |
---|
152 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
153 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
154 | \begin{lstlisting} |
---|
155 | #include <fstream> |
---|
156 | int main( void ) { |
---|
157 | int x = 0, y = 1, z = 2; |
---|
158 | ®sout | x | y | z | endl;® |
---|
159 | } |
---|
160 | \end{lstlisting} |
---|
161 | & |
---|
162 | \begin{lstlisting} |
---|
163 | #include <stdio.h> |
---|
164 | int main( void ) { |
---|
165 | int x = 0, y = 1, z = 2; |
---|
166 | ®printf( "%d %d %d\n", x, y, z );® |
---|
167 | } |
---|
168 | \end{lstlisting} |
---|
169 | \end{tabular} |
---|
170 | \end{quote2} |
---|
171 | Both programs output the same result. |
---|
172 | While the \CFA I/O looks similar to the \Index*[C++]{\CC} output style, there are important differences, such as automatic spacing between variables as in \Index*{Python} (see also~\VRef{s:IOLibrary}). |
---|
173 | |
---|
174 | This document is a user manual for the \CFA programming language, targeted at \CFA programmers. |
---|
175 | Implementers may refer to the \CFA Programming Language Specification for details about the language syntax and semantics. |
---|
176 | In its current state, this document covers the intended core features of the language. |
---|
177 | Changes to the syntax and additional features are expected to be included in later revisions. |
---|
178 | % For additional information, see \url{http://wiki.do-lang.org}. |
---|
179 | |
---|
180 | |
---|
181 | \section{History} |
---|
182 | |
---|
183 | The \CFA project started with K-W C~\cite{Buhr94a,Till89}, which extended C with new declaration syntax, multiple return values from routines, and extended assignment capabilities using the notion of tuples. |
---|
184 | (See~\cite{Werther96} for some similar work, but for \Index*[C++]{\CC}.) |
---|
185 | The original \CFA project~\cite{Ditchfield92} extended the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC} approach of object-oriented extensions to the C type-system. |
---|
186 | A first implementation of the core Cforall language was created~\cite{Bilson03,Esteves04}, but at the time there was little interesting in extending C, so work did not continue. |
---|
187 | As the saying goes, ``What goes around, comes around.'', and there is now renewed interest in the C programming language because of legacy code-bases, so the \CFA project has been restarted. |
---|
188 | |
---|
189 | |
---|
190 | \section{Why fix C?} |
---|
191 | |
---|
192 | Even with all its problems, C is a very popular programming language because it allows writing software at virtually any level in a computer system without restriction. |
---|
193 | For system programming, where direct access to hardware and dealing with real-time issues is a requirement, C is usually the language of choice. |
---|
194 | As well, there are millions of lines of C legacy code, forming the base for many software development projects (especially on UNIX systems). |
---|
195 | The TIOBE index (\url{http://www.tiobe.com/tiobe_index}) for March 2016 shows programming-language popularity, with \Index*{Java} 20.5\%, C 14.5\%, \Index*[C++]{\CC} 6.7\%, \CS 4.3\%, \Index*{Python} 4.3\%, and all other programming languages below 3\%. |
---|
196 | As well, for 30 years, C has been the number 1 and 2 most popular programming language: |
---|
197 | \begin{center} |
---|
198 | \setlength{\tabcolsep}{1.5ex} |
---|
199 | \begin{tabular}{@{}r|c|c|c|c|c|c|c@{}} |
---|
200 | Ranking & 2016 & 2011 & 2006 & 2001 & 1996 & 1991 & 1986 \\ |
---|
201 | \hline |
---|
202 | Java & 1 & 1 & 1 & 3 & 29 & - & - \\ |
---|
203 | \hline |
---|
204 | \R{C} & \R{2} & \R{2} & \R{2} & \R{1} & \R{1} & \R{1} & \R{1} \\ |
---|
205 | \hline |
---|
206 | \CC & 3 & 3 & 3 & 2 & 2 & 2 & 7 \\ |
---|
207 | \end{tabular} |
---|
208 | \end{center} |
---|
209 | Hence, C is still an extremely important programming language, with double the usage of \Index*[C++]{\CC}, where \CC itself is largely C code. |
---|
210 | Finally, love it or hate it, C has been an important and influential part of computer science for 40 years and it appears it will continue to be for many more years. |
---|
211 | Unfortunately, C has too many problems and omissions to make it an acceptable programming language for modern needs. |
---|
212 | |
---|
213 | The goal of this project is to engineer modern language features into C in an evolutionary rather than revolutionary way. |
---|
214 | \CC~\cite{c++,ANSI14:C++} is an example of a similar project; |
---|
215 | however, it largely extended the language, and did not address many existing problems.\footnote{% |
---|
216 | Two important existing problems addressed were changing the type of character literals from ©int© to ©char© and enumerator from ©int© to the type of its enumerators.} |
---|
217 | \Index*{Fortran}~\cite{Fortran08}, \Index*{Ada}~\cite{Ada12}, and \Index*{Cobol}~\cite{Cobol14} are examples of programming languages that took an evolutionary approach, where modern language features (\eg objects, concurrency) are added and problems fixed within the framework of the existing language. |
---|
218 | \Index*{Java}~\cite{Java8}, \Index*{Go}~\cite{Go}, \Index*{Rust}~\cite{Rust} and \Index*{D}~\cite{D} are examples of the revolutionary approach for modernizing C/\CC, resulting in a new language rather than an extension of the descendent. |
---|
219 | These languages have different syntax and semantics from C, and do not interoperate directly with C, largely because of garbage collection. |
---|
220 | As a result, there is a significant learning curve to move to these languages, and C legacy-code must be rewritten. |
---|
221 | These costs can be prohibitive for many companies with a large software base in C/\CC, and a significant number of programmers requiring retraining to a new programming language. |
---|
222 | |
---|
223 | The result of this project is a language that is largely backwards compatible with C11~\cite{C11}, but fixing some of the well known C problems and containing many modern language features. |
---|
224 | Without significant extension to the C programming language, it is becoming unable to cope with the needs of modern programming problems and programmers; |
---|
225 | as a result, it will fade into disuse. |
---|
226 | Considering the large body of existing C code and programmers, there is significant impetus to ensure C is transformed into a modern programming language. |
---|
227 | While C11 made a few simple extensions to the language, nothing was added to address existing problems in the language or to augment the language with modern language features. |
---|
228 | While some may argue that modern language features may make C complex and inefficient, it is clear a language without modern capabilities is insufficient for the advanced programming problems existing today. |
---|
229 | |
---|
230 | |
---|
231 | \section{Interoperability} |
---|
232 | \label{s:Interoperability} |
---|
233 | |
---|
234 | \CFA is designed to integrate well with existing C programs and libraries. |
---|
235 | The most important feature of interoperability is to use the same calling conventions, so there is no overhead to call existing C routines. |
---|
236 | This feature allows users of \CFA to take advantage of the existing panoply of C libraries from inside their \CFA code. |
---|
237 | In fact, one of the biggest issues for any new programming language is establishing a minimum level of library code to support a large body of activities. |
---|
238 | Language developers often state that adequate library support takes more work than designing and implementing the language itself. |
---|
239 | Like \Index*[C++]{\CC}, \CFA starts with immediate access to all exiting C libraries, and in many cases, can easily wrap library routines with simpler and safer interfaces, at very low cost. |
---|
240 | Hence, \CFA begins by leveraging the large repository of C libraries with little cost. |
---|
241 | |
---|
242 | However, it is necessary to differentiate between C and \CFA code because of name overloading, as for \CC. |
---|
243 | For example, the C math-library provides the following routines for computing the absolute value of the basic types: ©abs©, ©labs©, ©llabs©, ©fabs©, ©fabsf©, ©fabsl©, ©cabsf©, ©cabs©, and ©cabsl©. |
---|
244 | Whereas, \CFA wraps each of these routines into ones with the common name ©abs©: |
---|
245 | \begin{lstlisting} |
---|
246 | char abs( char ); |
---|
247 | extern "C" { |
---|
248 | int abs( int ); §\C{// use default C routine for int}§ |
---|
249 | } // extern "C" |
---|
250 | long int abs( long int ); |
---|
251 | long long int abs( long long int ); |
---|
252 | float abs( float ); |
---|
253 | double abs( double ); |
---|
254 | long double abs( long double ); |
---|
255 | float _Complex abs( float _Complex ); |
---|
256 | double _Complex abs( double _Complex ); |
---|
257 | long double _Complex abs( long double _Complex ); |
---|
258 | \end{lstlisting} |
---|
259 | The problem is the name clash between the library routine ©abs© and the \CFA names ©abs©. |
---|
260 | Hence, names appearing in an ©extern "C"© block have \newterm*{C linkage}. |
---|
261 | Then overloading polymorphism uses a mechanism called \newterm{name mangling}\index{mangling!name} to create unique names that are different from C names, which are not mangled. |
---|
262 | Hence, there is the same need as in \CC, to know if a name is a C or \CFA name, so it can be correctly formed. |
---|
263 | There is no way around this problem, other than C's approach of creating unique names for each pairing of operation and type. |
---|
264 | This example strongly illustrates a core idea in \CFA: \emph{the power of a name}. |
---|
265 | The name ``©abs©'' evokes the notion of absolute value, and many mathematical types provide the notion of absolute value. |
---|
266 | Hence, knowing the name ©abs© should be sufficient to apply it to any type where it is applicable. |
---|
267 | The time savings and safety of using one name uniformly versus $N$ unique names should not be underestimated. |
---|
268 | |
---|
269 | |
---|
270 | \section[Compiling CFA Program]{Compiling \CFA Program} |
---|
271 | |
---|
272 | The command ©cfa© is used to compile \CFA program(s), and is based on the GNU \Indexc{gcc} command, \eg: |
---|
273 | \begin{lstlisting} |
---|
274 | cfa§\indexc{cfa}\index{compilation!cfa@©cfa©}§ [ gcc-options ] C/§\CFA§-files [ assembler/loader-files ] |
---|
275 | \end{lstlisting} |
---|
276 | \CFA programs having the following ©gcc© flags turned on: |
---|
277 | \begin{description} |
---|
278 | \item |
---|
279 | \Indexc{-std=gnu99}\index{compilation option!-std=gnu99@{©-std=gnu99©}} |
---|
280 | The 1999 C standard plus GNU extensions. |
---|
281 | \item |
---|
282 | \Indexc{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{©-fgnu89-inline©}} |
---|
283 | Use the traditional GNU semantics for inline routines in C99 mode, which allows inline routines in header files. |
---|
284 | \end{description} |
---|
285 | The following new \CFA options are available: |
---|
286 | \begin{description} |
---|
287 | \item |
---|
288 | \Indexc{-CFA}\index{compilation option!-CFA@©-CFA©} |
---|
289 | 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. |
---|
290 | The generated code started with the standard \CFA prelude. |
---|
291 | |
---|
292 | \item |
---|
293 | \Indexc{-debug}\index{compilation option!-debug@©-debug©} |
---|
294 | The program is linked with the debugging version of the runtime system. |
---|
295 | The debug version performs runtime checks to help during the debugging phase of a \CFA program, but substantially slows the execution of the program. |
---|
296 | The runtime checks should only be removed after the program is completely debugged. |
---|
297 | \textbf{This option is the default.} |
---|
298 | |
---|
299 | \item |
---|
300 | \Indexc{-nodebug}\index{compilation option!-nodebug@©-nodebug©} |
---|
301 | The program is linked with the non-debugging version of the runtime system, so the execution of the program is faster. |
---|
302 | \Emph{However, no runtime checks or ©assert©s are performed so errors usually result in abnormal program termination.} |
---|
303 | |
---|
304 | \item |
---|
305 | \Indexc{-help}\index{compilation option!-help@©-help©} |
---|
306 | Information about the set of \CFA compilation flags is printed. |
---|
307 | |
---|
308 | \item |
---|
309 | \Indexc{-nohelp}\index{compilation option!-nohelp@©-nohelp©} |
---|
310 | Information about the set of \CFA compilation flags is not printed. |
---|
311 | \textbf{This option is the default.} |
---|
312 | |
---|
313 | \item |
---|
314 | \Indexc{-quiet}\index{compilation option!-quiet@©-quiet©} |
---|
315 | The \CFA compilation message is not printed at the beginning of a compilation. |
---|
316 | |
---|
317 | \item |
---|
318 | \Indexc{-noquiet}\index{compilation option!-noquiet@©-noquiet©} |
---|
319 | The \CFA compilation message is printed at the beginning of a compilation. |
---|
320 | \textbf{This option is the default.} |
---|
321 | |
---|
322 | \item |
---|
323 | \Indexc{-no-include-stdhdr}\index{compilation option!-no-include-stdhdr@©-no-include-stdhdr©} |
---|
324 | Do not supply ©extern "C"© wrappers for \Celeven standard include files (see~\VRef{s:StandardHeaders}). |
---|
325 | \textbf{This option is \emph{not} the default.} |
---|
326 | \end{description} |
---|
327 | |
---|
328 | The following preprocessor variables are available: |
---|
329 | \begin{description} |
---|
330 | \item |
---|
331 | \Indexc{__CFA_MAJOR__}\index{preprocessor variables!__CFA__@{©__CFA__©}} |
---|
332 | is available during preprocessing and its value is the major \Index{version number} of \CFA.\footnote{ |
---|
333 | The C preprocessor allows only integer values in a preprocessor variable so a value like ``\Version'' is not allowed. |
---|
334 | Hence, the need to have three variables for the major, minor and patch version number.} |
---|
335 | |
---|
336 | \item |
---|
337 | \Indexc{__CFA_MINOR__}\index{preprocessor variables!__CFA_MINOR__@{©__CFA_MINOR__©}} |
---|
338 | is available during preprocessing and its value is the minor \Index{version number} of \CFA. |
---|
339 | |
---|
340 | \item |
---|
341 | \Indexc{__CFA_PATCH__}\index{preprocessor variables!__CFA_PATCH__@©__CFA_PATCH__©} |
---|
342 | is available during preprocessing and its value is the patch \Index{level number} of \CFA. |
---|
343 | |
---|
344 | \item |
---|
345 | \Indexc{__CFA__}\index{preprocessor variables!__CFA__@©__CFA__©}, |
---|
346 | \Indexc{__CFORALL__}\index{preprocessor variables!__CFORALL__@©__CFORALL__©} and |
---|
347 | \Indexc{__cforall}\index{preprocessor variables!__cforall@©__cforall©} |
---|
348 | are always available during preprocessing and have no value. |
---|
349 | \end{description} |
---|
350 | These preprocessor variables allow conditional compilation of programs that must work differently in these situations. |
---|
351 | For example, to toggle between C and \CFA extensions, using the following: |
---|
352 | \begin{lstlisting} |
---|
353 | #ifndef __CFORALL__ |
---|
354 | #include <stdio.h> §\C{// C header file}§ |
---|
355 | #else |
---|
356 | #include <fstream> §\C{// \CFA header file}§ |
---|
357 | #endif |
---|
358 | \end{lstlisting} |
---|
359 | which conditionally includes the correct header file, if the program is compiled using \Indexc{gcc} or \Indexc{cfa}. |
---|
360 | |
---|
361 | |
---|
362 | \section{Underscores in Constants} |
---|
363 | |
---|
364 | Numeric constants are extended to allow \Index{underscore}s within constants\index{constant!underscore}, \eg: |
---|
365 | \begin{lstlisting} |
---|
366 | 2®_®147®_®483®_®648; §\C{// decimal constant}§ |
---|
367 | 56_ul; §\C{// decimal unsigned long constant}§ |
---|
368 | 0_377; §\C{// octal constant}§ |
---|
369 | 0x_ff_ff; §\C{// hexadecimal constant}§ |
---|
370 | 0x_ef3d_aa5c; §\C{// hexadecimal constant}§ |
---|
371 | 3.141_592_654; §\C{// floating point constant}§ |
---|
372 | 10_e_+1_00; §\C{// floating point constant}§ |
---|
373 | 0x_ff_ff_p_3; §\C{// hexadecimal floating point}§ |
---|
374 | 0x_1.ffff_ffff_p_128_l; §\C{// hexadecimal floating point long constant}§ |
---|
375 | L_"\x_ff_ee"; §\C{// wide character constant}§ |
---|
376 | \end{lstlisting} |
---|
377 | The rules for placement of underscores is as follows: |
---|
378 | \begin{enumerate} |
---|
379 | \item |
---|
380 | A sequence of underscores is disallowed, \eg ©12__34© is invalid. |
---|
381 | \item |
---|
382 | Underscores may only appear within a sequence of digits (regardless of the digit radix). |
---|
383 | In other words, an underscore cannot start or end a sequence of digits, \eg ©_1©, ©1_© and ©_1_© are invalid (actually, the 1st and 3rd examples are identifier names). |
---|
384 | \item |
---|
385 | A numeric prefix may end with an underscore; |
---|
386 | a numeric infix may begin and/or end with an underscore; |
---|
387 | a numeric suffix may begin with an underscore. |
---|
388 | For example, the octal ©0© or hexadecimal ©0x© prefix may end with an underscore ©0_377© or ©0x_ff©; |
---|
389 | the exponent infix ©E© may start or end with an underscore ©1.0_E10©, ©1.0E_10© or ©1.0_E_10©; |
---|
390 | the type suffixes ©U©, ©L©, etc. may start with an underscore ©1_U©, ©1_ll© or ©1.0E10_f©. |
---|
391 | \end{enumerate} |
---|
392 | It is significantly easier to read and enter long constants when they are broken up into smaller groupings (most cultures use comma or period among digits for the same purpose). |
---|
393 | This extension is backwards compatible, matches with the use of underscore in variable names, and appears in \Index*{Ada} and \Index*{Java} 8. |
---|
394 | |
---|
395 | |
---|
396 | \section{Declarations} |
---|
397 | \label{s:Declarations} |
---|
398 | |
---|
399 | C declaration syntax is notoriously confusing and error prone. |
---|
400 | For example, many C programmers are confused by a declaration as simple as: |
---|
401 | \begin{quote2} |
---|
402 | \begin{tabular}{@{}ll@{}} |
---|
403 | \begin{lstlisting} |
---|
404 | int *x[5] |
---|
405 | \end{lstlisting} |
---|
406 | & |
---|
407 | \raisebox{-0.75\totalheight}{\input{Cdecl}} |
---|
408 | \end{tabular} |
---|
409 | \end{quote2} |
---|
410 | Is this an array of 5 pointers to integers or a \Index{pointer} to an array of 5 integers? |
---|
411 | The fact this declaration is unclear to many C programmers means there are \Index{productivity} and \Index{safety} issues even for basic programs. |
---|
412 | Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site. |
---|
413 | For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way: |
---|
414 | \begin{lstlisting} |
---|
415 | int (*f())[5] {...}; §\C{}§ |
---|
416 | ... (*f())[3] += 1; |
---|
417 | \end{lstlisting} |
---|
418 | Essentially, the return type is wrapped around the routine name in successive layers (like an onion). |
---|
419 | While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice. |
---|
420 | |
---|
421 | \CFA provides its own type, variable and routine declarations, using a different syntax. |
---|
422 | The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type. |
---|
423 | In the following example, \R{red} is for the base type and \B{blue} is for the qualifiers. |
---|
424 | The \CFA declarations move the qualifiers to the left of the base type, i.e., move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type. |
---|
425 | \begin{quote2} |
---|
426 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
427 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
428 | \begin{lstlisting} |
---|
429 | ß[5] *ß ®int® x1; |
---|
430 | ß* [5]ß ®int® x2; |
---|
431 | ß[* [5] int]ß f®( int p )®; |
---|
432 | \end{lstlisting} |
---|
433 | & |
---|
434 | \begin{lstlisting} |
---|
435 | ®int® ß*ß x1 ß[5]ß; |
---|
436 | ®int® ß(*ßx2ß)[5]ß; |
---|
437 | ßint (*ßf®( int p )®ß)[5]ß; |
---|
438 | \end{lstlisting} |
---|
439 | \end{tabular} |
---|
440 | \end{quote2} |
---|
441 | The only exception is bit field specification, which always appear to the right of the base type. |
---|
442 | % Specifically, the character ©*© is used to indicate a pointer, square brackets ©[©\,©]© are used to represent an array or function return value, and parentheses ©()© are used to indicate a routine parameter. |
---|
443 | However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. |
---|
444 | For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows: |
---|
445 | \begin{quote2} |
---|
446 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
447 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
448 | \begin{lstlisting} |
---|
449 | ®*® int x, y; |
---|
450 | \end{lstlisting} |
---|
451 | & |
---|
452 | \begin{lstlisting} |
---|
453 | int ®*®x, ®*®y; |
---|
454 | \end{lstlisting} |
---|
455 | \end{tabular} |
---|
456 | \end{quote2} |
---|
457 | The downside of this semantics is the need to separate regular and \Index{pointer} declarations: |
---|
458 | \begin{quote2} |
---|
459 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
460 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
461 | \begin{lstlisting} |
---|
462 | ®*® int x; |
---|
463 | int y; |
---|
464 | \end{lstlisting} |
---|
465 | & |
---|
466 | \begin{lstlisting} |
---|
467 | int ®*®x, y; |
---|
468 | |
---|
469 | \end{lstlisting} |
---|
470 | \end{tabular} |
---|
471 | \end{quote2} |
---|
472 | which is \Index{prescribing} a safety benefit. |
---|
473 | Other examples are: |
---|
474 | \begin{quote2} |
---|
475 | \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} |
---|
476 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ |
---|
477 | \begin{lstlisting} |
---|
478 | [ 5 ] int z; |
---|
479 | [ 5 ] * char w; |
---|
480 | * [ 5 ] double v; |
---|
481 | struct s { |
---|
482 | int f0:3; |
---|
483 | * int f1; |
---|
484 | [ 5 ] * int f2; |
---|
485 | }; |
---|
486 | \end{lstlisting} |
---|
487 | & |
---|
488 | \begin{lstlisting} |
---|
489 | int z[ 5 ]; |
---|
490 | char *w[ 5 ]; |
---|
491 | double (*v)[ 5 ]; |
---|
492 | struct s { |
---|
493 | int f0:3; |
---|
494 | int *f1; |
---|
495 | int *f2[ 5 ] |
---|
496 | }; |
---|
497 | \end{lstlisting} |
---|
498 | & |
---|
499 | \begin{lstlisting} |
---|
500 | // array of 5 integers |
---|
501 | // array of 5 pointers to char |
---|
502 | // pointer to array of 5 doubles |
---|
503 | |
---|
504 | // common bit field syntax |
---|
505 | |
---|
506 | |
---|
507 | |
---|
508 | \end{lstlisting} |
---|
509 | \end{tabular} |
---|
510 | \end{quote2} |
---|
511 | |
---|
512 | All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg: |
---|
513 | \begin{quote2} |
---|
514 | \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} |
---|
515 | \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\ |
---|
516 | \begin{lstlisting} |
---|
517 | const * const int x; |
---|
518 | const * [ 5 ] const int y; |
---|
519 | \end{lstlisting} |
---|
520 | & |
---|
521 | \begin{lstlisting} |
---|
522 | int const * const x; |
---|
523 | const int (* const y)[ 5 ] |
---|
524 | \end{lstlisting} |
---|
525 | & |
---|
526 | \begin{lstlisting} |
---|
527 | // const pointer to const integer |
---|
528 | // const pointer to array of 5 const integers |
---|
529 | \end{lstlisting} |
---|
530 | \end{tabular} |
---|
531 | \end{quote2} |
---|
532 | All declaration qualifiers, \eg ©extern©, ©static©, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier} |
---|
533 | The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg: |
---|
534 | \begin{quote2} |
---|
535 | \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} |
---|
536 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ |
---|
537 | \begin{lstlisting} |
---|
538 | extern [ 5 ] int x; |
---|
539 | static * const int y; |
---|
540 | \end{lstlisting} |
---|
541 | & |
---|
542 | \begin{lstlisting} |
---|
543 | int extern x[ 5 ]; |
---|
544 | const int static *y; |
---|
545 | \end{lstlisting} |
---|
546 | & |
---|
547 | \begin{lstlisting} |
---|
548 | // externally visible array of 5 integers |
---|
549 | // internally visible pointer to constant int |
---|
550 | \end{lstlisting} |
---|
551 | \end{tabular} |
---|
552 | \end{quote2} |
---|
553 | |
---|
554 | Unsupported are K\&R C declarations where the base type defaults to ©int©, if no type is specified,\footnote{ |
---|
555 | At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each structure declaration and type name~\cite[\S~6.7.2(2)]{C11}} |
---|
556 | \eg: |
---|
557 | \begin{lstlisting} |
---|
558 | x; §\C{// int x}§ |
---|
559 | *y; §\C{// int *y}§ |
---|
560 | f( p1, p2 ); §\C{// int f( int p1, int p2 );}§ |
---|
561 | f( p1, p2 ) {} §\C{// int f( int p1, int p2 ) {}}§ |
---|
562 | \end{lstlisting} |
---|
563 | |
---|
564 | Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration. |
---|
565 | Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style. |
---|
566 | Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX systems. |
---|
567 | |
---|
568 | |
---|
569 | \section{Pointer / Reference} |
---|
570 | |
---|
571 | C provides a \newterm{pointer type}; |
---|
572 | \CFA adds a \newterm{reference type}. |
---|
573 | Both types contain an \newterm{address}, which is normally a location in memory. |
---|
574 | Special addresses are used to denote certain states or access co-processor memory. |
---|
575 | By convention, no variable is placed at address 0, so addresses like 0, 1, 2, 3 are often used to denote no-value or other special states. |
---|
576 | Often dereferencing a special state causes a \Index{memory fault}, so checking is necessary during execution. |
---|
577 | If the programming language assigns addresses, a program's execution is \Index{sound}, i.e., all addresses are to valid memory locations. |
---|
578 | C allows programmers to assign addresses, so there is the potential for incorrect addresses, both inside and outside of the computer address-space. |
---|
579 | |
---|
580 | Program variables are implicit pointers to memory locations generated by the compiler and automatically dereferenced, as in: |
---|
581 | \begin{quote2} |
---|
582 | \begin{tabular}{@{}lll@{}} |
---|
583 | \begin{lstlisting} |
---|
584 | int x; |
---|
585 | x = 3; |
---|
586 | int y; |
---|
587 | y = x; |
---|
588 | \end{lstlisting} |
---|
589 | & |
---|
590 | \raisebox{-0.45\totalheight}{\input{pointer1}} |
---|
591 | & |
---|
592 | \begin{lstlisting} |
---|
593 | int * ®const® x = (int *)100 |
---|
594 | *x = 3; // implicit dereference |
---|
595 | int * ®const® y = (int *)104; |
---|
596 | *y = *x; // implicit dereference |
---|
597 | \end{lstlisting} |
---|
598 | \end{tabular} |
---|
599 | \end{quote2} |
---|
600 | where the right example is how the compiler logically interprets the variables in the left example. |
---|
601 | Since a variable name only points to one location during its lifetime, it is an \Index{immutable} \Index{pointer}; |
---|
602 | hence, variables ©x© and ©y© are constant pointers in the compiler interpretation. |
---|
603 | In general, variable addresses are stored in instructions instead of loaded independently, so an instruction fetch implicitly loads a variable's address. |
---|
604 | \begin{quote2} |
---|
605 | \begin{tabular}{@{}l|l@{}} |
---|
606 | \begin{lstlisting} |
---|
607 | lda r1,100 // load address of x |
---|
608 | ld r2,(r1) // load value of x |
---|
609 | lda r3,104 // load address of y |
---|
610 | st r2,(r3) // store x into y |
---|
611 | \end{lstlisting} |
---|
612 | & |
---|
613 | \begin{lstlisting} |
---|
614 | |
---|
615 | ld r2,(100) // load value of x |
---|
616 | |
---|
617 | st r2,(104) // store x into y |
---|
618 | \end{lstlisting} |
---|
619 | \end{tabular} |
---|
620 | \end{quote2} |
---|
621 | Finally, the immutable nature of a variable's address and the fact that there is no storage for a variable address means pointer assignment\index{pointer!assignment}\index{assignment!pointer} is impossible. |
---|
622 | Therefore, the expression ©x = y© only has one meaning, ©*x = *y©, i.e., manipulate values, which is why explicitly writing the dereferences is unnecessary even though it occurs implicitly as part of instruction decoding. |
---|
623 | |
---|
624 | A \Index{pointer}/\Index{reference} is a generalization of a variable name, i.e., a mutable address that can point to more than one memory location during its lifetime. |
---|
625 | (Similarly, an integer variable can contain multiple integer literals during its lifetime versus an integer constant representing a single literal during its lifetime and may not occupy storage as the literal is embedded directly into instructions.) |
---|
626 | Hence, a pointer occupies memory to store its current address, and the pointer's value is loaded by dereferencing, \eg: |
---|
627 | \begin{quote2} |
---|
628 | \begin{tabular}{@{}ll@{}} |
---|
629 | \begin{lstlisting} |
---|
630 | int x, y, ®*® p1, ®*® p2, ®**® p3; |
---|
631 | p1 = ®&®x; // p1 points to x |
---|
632 | p2 = p1; // p2 points to x |
---|
633 | p1 = ®&®y; // p1 points to y |
---|
634 | p3 = &p2; // p3 points to p2 |
---|
635 | \end{lstlisting} |
---|
636 | & |
---|
637 | \raisebox{-0.45\totalheight}{\input{pointer2.pstex_t}} |
---|
638 | \end{tabular} |
---|
639 | \end{quote2} |
---|
640 | |
---|
641 | Notice, an address has a duality\index{address!duality}: a location in memory or the value at that location. |
---|
642 | In many cases, a compiler might be able to infer the meaning: |
---|
643 | \begin{lstlisting} |
---|
644 | p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§ |
---|
645 | \end{lstlisting} |
---|
646 | because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation. |
---|
647 | \Index*{Algol68}~\cite{Algol68} inferences pointer dereferencing to select the best meaning for each pointer usage. |
---|
648 | However, in C, the following cases are ambiguous, especially with pointer arithmetic: |
---|
649 | \begin{lstlisting} |
---|
650 | p1 = p2; §\C{// p1 = p2\ \ or\ \ *p1 = *p2}§ |
---|
651 | p1 = p1 + 1; §\C{// p1 = p1 + 1\ \ or\ \ *p1 = *p1 + 1}§ |
---|
652 | \end{lstlisting} |
---|
653 | |
---|
654 | Most languages pick one meaning as the default and the programmer explicitly indicates the other meaning to resolve the address-duality ambiguity\index{address! ambiguity}. |
---|
655 | In C, the default meaning for pointers is to manipulate the pointer's address and the pointed-to value is explicitly accessed by the dereference operator ©*©. |
---|
656 | \begin{lstlisting} |
---|
657 | p1 = p2; §\C{// pointer address assignment}§ |
---|
658 | *p1 = *p1 + 1; §\C{// pointed-to value assignment / operation}§ |
---|
659 | \end{lstlisting} |
---|
660 | which works well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©). |
---|
661 | |
---|
662 | However, in most other situations, the pointed-to value is requested more often than the pointer address. |
---|
663 | \begin{lstlisting} |
---|
664 | *p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15); |
---|
665 | \end{lstlisting} |
---|
666 | In this case, it is tedious to explicitly write the dereferencing, and error prone when pointer arithmetic is allowed. |
---|
667 | It is better to have the compiler generate the dereferencing and have no implicit pointer arithmetic: |
---|
668 | \begin{lstlisting} |
---|
669 | p2 = ((p1 + p2) * (p3 - p1)) / (p3 - 15); |
---|
670 | \end{lstlisting} |
---|
671 | |
---|
672 | To switch the default meaning for an address requires a new kind of pointer, called a \newterm{reference} denoted by ©&©. |
---|
673 | \begin{lstlisting} |
---|
674 | int x, y, ®&® r1, ®&® r2, ®&&® r3; |
---|
675 | ®&®r1 = &x; §\C{// r1 points to x}§ |
---|
676 | ®&®r2 = &r1; §\C{// r2 points to x}§ |
---|
677 | ®&®r1 = &y; §\C{// r1 points to y}§ |
---|
678 | ®&&®r3 = ®&®&r2; §\C{// r3 points to r2}§ |
---|
679 | r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§ |
---|
680 | \end{lstlisting} |
---|
681 | Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer example. |
---|
682 | Hence, a reference behaves like the variable name for the current variable it is pointing-to. |
---|
683 | The simplest way to understand a reference is to imagine the compiler inserting a dereference operator before the reference variable for each reference qualifier in a declaration, \eg: |
---|
684 | \begin{lstlisting} |
---|
685 | r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); |
---|
686 | \end{lstlisting} |
---|
687 | is rewritten as: |
---|
688 | \begin{lstlisting} |
---|
689 | ®*®r2 = ((®*®r1 + ®*®r2) ®*® (®**®r3 - ®*®r1)) / (®**®r3 - 15); |
---|
690 | \end{lstlisting} |
---|
691 | When a reference operation appears beside a dereference operation, \eg ©&*©, they cancel out.\footnote{ |
---|
692 | The unary ©&© operator yields the address of its operand. |
---|
693 | If the operand has type ``type'', the result has type ``pointer to type''. |
---|
694 | If the operand is the result of a unary ©*© operator, neither that operator nor the ©&© operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.~\cite[\S~6.5.3.2--3]{C11}} |
---|
695 | Hence, assigning to a reference requires the address of the reference variable (\Index{lvalue}): |
---|
696 | \begin{lstlisting} |
---|
697 | (&®*®)r1 = &x; §\C{// (\&*) cancel giving variable r1 not variable pointed-to by r1}§ |
---|
698 | \end{lstlisting} |
---|
699 | Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}): |
---|
700 | \begin{lstlisting} |
---|
701 | (&(&®*®)®*®)r3 = &(&®*®)r2; §\C{// (\&*) cancel giving address of r2, (\&(\&*)*) cancel giving variable r3}§ |
---|
702 | \end{lstlisting} |
---|
703 | Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth, and pointer and reference values are interchangeable because both contain addresses. |
---|
704 | \begin{lstlisting} |
---|
705 | int x, *p1 = &x, **p2 = &p1, ***p3 = &p2, |
---|
706 | &r1 = x, &&r2 = r1, &&&r3 = r2; |
---|
707 | ***p3 = 3; §\C{// change x}§ |
---|
708 | r3 = 3; §\C{// change x, ***r3}§ |
---|
709 | **p3 = ...; §\C{// change p1}§ |
---|
710 | &r3 = ...; §\C{// change r1, (\&*)**r3, 1 cancellation}§ |
---|
711 | *p3 = ...; §\C{// change p2}§ |
---|
712 | &&r3 = ...; §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§ |
---|
713 | &&&r3 = p3; §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§ |
---|
714 | \end{lstlisting} |
---|
715 | Finally, implicit dereferencing and cancellation are a static (compilation) phenomenon not a dynamic one. |
---|
716 | That is, all implicit dereferencing and any cancellation is carried out prior to the start of the program, so reference performance is equivalent to pointer performance. |
---|
717 | A programmer selects a pointer or reference type solely on whether the address is dereferenced frequently or infrequently, which dictates the amount of direct aid from the compiler; |
---|
718 | otherwise, everything else is equal. |
---|
719 | |
---|
720 | Interestingly, \Index*[C++]{\CC} deals with the address duality by making the pointed-to value the default, and prevent\-ing changes to the reference address, which eliminates half of the duality. |
---|
721 | \Index*{Java} deals with the address duality by making address assignment the default and requiring field assignment (direct or indirect via methods), i.e., there is no builtin bit-wise or method-wise assignment, which eliminates half of the duality. |
---|
722 | |
---|
723 | As for a pointer, a reference may have qualifiers: |
---|
724 | \begin{lstlisting} |
---|
725 | const int cx = 5; §\C{// cannot change cx;}§ |
---|
726 | const int & cr = cx; §\C{// cannot change what cr points to}§ |
---|
727 | ®&®cr = &cx; §\C{// can change cr}§ |
---|
728 | cr = 7; §\C{// error, cannot change cx}§ |
---|
729 | int & const rc = x; §\C{// must be initialized, \CC reference}§ |
---|
730 | ®&®rc = &x; §\C{// error, cannot change rc}§ |
---|
731 | const int & const crc = cx; §\C{// must be initialized, \CC reference}§ |
---|
732 | crc = 7; §\C{// error, cannot change cx}§ |
---|
733 | ®&®crc = &cx; §\C{// error, cannot change crc}§ |
---|
734 | \end{lstlisting} |
---|
735 | Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be ©0© unless an arbitrary pointer is assigned to the reference}, \eg: |
---|
736 | \begin{lstlisting} |
---|
737 | int & const r = *0; §\C{// where 0 is the int * zero}§ |
---|
738 | \end{lstlisting} |
---|
739 | Otherwise, the compiler is managing the addresses for type ©& const© not the programmer, and by a programming discipline of only using references with references, address errors can be prevented. |
---|
740 | Finally, the position of the ©const© qualifier \emph{after} the pointer/reference qualifier causes confuse for C programmers. |
---|
741 | The ©const© qualifier cannot be moved before the pointer/reference qualifier for C style-declarations; |
---|
742 | \CFA-style declarations attempt to address this issue: |
---|
743 | \begin{quote2} |
---|
744 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
745 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
746 | \begin{lstlisting} |
---|
747 | ®const® * ®const® * const int ccp; |
---|
748 | ®const® & ®const® & const int ccr; |
---|
749 | \end{lstlisting} |
---|
750 | & |
---|
751 | \begin{lstlisting} |
---|
752 | const int * ®const® * ®const® ccp; |
---|
753 | |
---|
754 | \end{lstlisting} |
---|
755 | \end{tabular} |
---|
756 | \end{quote2} |
---|
757 | where the \CFA declaration is read left-to-right (see \VRef{s:Declarations}). |
---|
758 | |
---|
759 | \Index{Initialization} is different than \Index{assignment} because initialization occurs on the empty (uninitialized) storage on an object, while assignment occurs on possibly initialized storage of an object. |
---|
760 | There are three initialization contexts in \CFA: declaration initialization, argument/parameter binding, return/temporary binding. |
---|
761 | For reference initialization (like pointer), the initializing value must be an address (\Index{lvalue}) not a value (\Index{rvalue}). |
---|
762 | \begin{lstlisting} |
---|
763 | int * p = &x; §\C{// both \&x and x are possible interpretations}§ |
---|
764 | int & r = x; §\C{// x unlikely interpretation, because of auto-dereferencing}§ |
---|
765 | \end{lstlisting} |
---|
766 | Hence, the compiler implicitly inserts a reference operator, ©&©, before the initialization expression. |
---|
767 | Similarly, when a reference is used for a parameter/return type, the call-site argument does not require a reference operator. |
---|
768 | \begin{lstlisting} |
---|
769 | int & f( int & rp ); §\C{// reference parameter and return}§ |
---|
770 | z = f( x ) + f( y ); §\C{// reference operator added, temporaries needed for call results}§ |
---|
771 | \end{lstlisting} |
---|
772 | Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©rp© can be locally reassigned within ©f©. |
---|
773 | Since ©?+?© takes its arguments by value, the references returned from ©f© are used to initialize compiler generated temporaries with value semantics that copy from the references. |
---|
774 | |
---|
775 | When a pointer/reference parameter has a ©const© value (immutable), it is possible to pass literals and expressions. |
---|
776 | \begin{lstlisting} |
---|
777 | void f( ®const® int & crp ); |
---|
778 | void g( ®const® int * cpp ); |
---|
779 | f( 3 ); g( &3 ); |
---|
780 | f( x + y ); g( &(x + y) ); |
---|
781 | \end{lstlisting} |
---|
782 | Here, the compiler passes the address to the literal 3 or the temporary for the expression ©x + y©, knowing the argument cannot be changed through the parameter. |
---|
783 | (The ©&© is necessary for the pointer parameter to make the types match, and is a common requirement for a C programmer.) |
---|
784 | \CFA \emph{extends} this semantics to a mutable pointer/reference parameter, and the compiler implicitly creates the necessary temporary (copying the argument), which is subsequently pointed-to by the reference parameter and can be changed. |
---|
785 | \begin{lstlisting} |
---|
786 | void f( int & rp ); |
---|
787 | void g( int * pp ); |
---|
788 | f( 3 ); g( &3 ); §\C{// compiler implicit generates temporaries}§ |
---|
789 | f( x + y ); g( &(x + y) ); §\C{// compiler implicit generates temporaries}§ |
---|
790 | \end{lstlisting} |
---|
791 | Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{ |
---|
792 | This conversion attempts to address the \newterm{const hell} problem, when the innocent addition of a ©const© qualifier causes a cascade of type failures, requiring an unknown number of additional ©const© qualifiers, until it is discovered a ©const© qualifier cannot be added and all the ©const© qualifiers must be removed.} |
---|
793 | The implicit conversion allows seamless calls to any routine without having to explicitly name/copy the literal/expression to allow the call. |
---|
794 | |
---|
795 | While \CFA attempts to handle pointers and references in a uniform, symmetric manner, C handles routine variables in an inconsistent way: a routine variable is both a pointer and a reference (particle and wave). |
---|
796 | \begin{lstlisting} |
---|
797 | void f( int p ) {...} |
---|
798 | void (*fp)( int ) = &f; §\C{// pointer initialization}§ |
---|
799 | void (*fp)( int ) = f; §\C{// reference initialization}§ |
---|
800 | (*fp)(3); §\C{// pointer invocation}§ |
---|
801 | fp(3); §\C{// reference invocation}§ |
---|
802 | \end{lstlisting} |
---|
803 | A routine variable is best described by a ©const© reference: |
---|
804 | \begin{lstlisting} |
---|
805 | const void (&fp)( int ) = f; |
---|
806 | fp( 3 ); |
---|
807 | fp = ... §\C{// error, cannot change code}§ |
---|
808 | &fp = ...; §\C{// changing routine reference}§ |
---|
809 | \end{lstlisting} |
---|
810 | because the value of the routine variable is a routine literal, i.e., the routine code is normally immutable during execution.\footnote{ |
---|
811 | Dynamic code rewriting is possible but only in special circumstances.} |
---|
812 | \CFA allows this additional use of references for routine variables in an attempt to give a more consistent meaning for them. |
---|
813 | |
---|
814 | |
---|
815 | \section{Backquote Identifiers} |
---|
816 | \label{s:BackquoteIdentifiers} |
---|
817 | |
---|
818 | \CFA accommodates keyword clashes by syntactic transformations using the \CFA backquote escape-mechanism: |
---|
819 | \begin{lstlisting} |
---|
820 | int `otype` = 3; // make keyword an identifier |
---|
821 | double `choose` = 3.5; |
---|
822 | \end{lstlisting} |
---|
823 | Programs can be converted easily by enclosing keyword identifiers in backquotes, and the backquotes can be removed later when the identifier name is changed to an non-keyword name. |
---|
824 | Clashes in C header files (see~\VRef{s:StandardHeaders}) can be handled automatically using the preprocessor, ©#include_next© and ©-I filename©: |
---|
825 | \begin{lstlisting} |
---|
826 | // include file uses the CFA keyword "otype". |
---|
827 | #if ! defined( otype ) // nesting ? |
---|
828 | #define otype `otype` |
---|
829 | #define __CFA_BFD_H__ |
---|
830 | #endif // ! otype |
---|
831 | |
---|
832 | #include_next <bfd.h> // must have internal check for multiple expansion |
---|
833 | |
---|
834 | #if defined( otype ) && defined( __CFA_BFD_H__ ) // reset only if set |
---|
835 | #undef otype |
---|
836 | #undef __CFA_BFD_H__ |
---|
837 | #endif // otype && __CFA_BFD_H__ |
---|
838 | \end{lstlisting} |
---|
839 | |
---|
840 | |
---|
841 | \section{Type Operators} |
---|
842 | |
---|
843 | The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©: |
---|
844 | \begin{quote2} |
---|
845 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
846 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
847 | \begin{lstlisting} |
---|
848 | y = (®* int®)x; |
---|
849 | i = sizeof(®[ 5 ] * int®); |
---|
850 | \end{lstlisting} |
---|
851 | & |
---|
852 | \begin{lstlisting} |
---|
853 | y = (®int *®)x; |
---|
854 | i = sizeof(®int *[ 5 ]®); |
---|
855 | \end{lstlisting} |
---|
856 | \end{tabular} |
---|
857 | \end{quote2} |
---|
858 | |
---|
859 | |
---|
860 | \section{Routine Definition} |
---|
861 | |
---|
862 | \CFA also supports a new syntax for routine definition, as well as ISO C and K\&R routine syntax. |
---|
863 | The point of the new syntax is to allow returning multiple values from a routine~\cite{Galletly96,CLU}, \eg: |
---|
864 | \begin{lstlisting} |
---|
865 | ®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) { |
---|
866 | §\emph{routine body}§ |
---|
867 | } |
---|
868 | \end{lstlisting} |
---|
869 | where routine ©f© has three output (return values) and three input parameters. |
---|
870 | Existing C syntax cannot be extended with multiple return types because it is impossible to embed a single routine name within multiple return type specifications. |
---|
871 | |
---|
872 | In detail, the brackets, ©[]©, enclose the result type, where each return value is named and that name is a local variable of the particular return type.\footnote{ |
---|
873 | \Index*{Michael Tiemann}, with help from \Index*{Doug Lea}, provided named return values in g++, circa 1989.} |
---|
874 | The value of each local return variable is automatically returned at routine termination. |
---|
875 | Declaration qualifiers can only appear at the start of a routine definition, \eg: |
---|
876 | \begin{lstlisting} |
---|
877 | ®extern® [ int x ] g( int y ) {§\,§} |
---|
878 | \end{lstlisting} |
---|
879 | Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified; |
---|
880 | 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: |
---|
881 | \begin{lstlisting} |
---|
882 | [§\,§] g(); §\C{// no input or output parameters}§ |
---|
883 | [ void ] g( void ); §\C{// no input or output parameters}§ |
---|
884 | \end{lstlisting} |
---|
885 | |
---|
886 | Routine f is called as follows: |
---|
887 | \begin{lstlisting} |
---|
888 | [ i, j, ch ] = f( 3, 'a', ch ); |
---|
889 | \end{lstlisting} |
---|
890 | The list of return values from f and the grouping on the left-hand side of the assignment is called a \newterm{return list} and discussed in Section 12. |
---|
891 | |
---|
892 | \CFA style declarations cannot be used to declare parameters for K\&R style routine definitions because of the following ambiguity: |
---|
893 | \begin{lstlisting} |
---|
894 | int (*f(x))[ 5 ] int x; {} |
---|
895 | \end{lstlisting} |
---|
896 | The string ``©int (*f(x))[ 5 ]©'' declares a K\&R style routine of type returning a pointer to an array of 5 integers, while the string ``©[ 5 ] int x©'' declares a \CFA style parameter x of type array of 5 integers. |
---|
897 | Since the strings overlap starting with the open bracket, ©[©, there is an ambiguous interpretation for the string. |
---|
898 | As well, \CFA-style declarations cannot be used to declare parameters for C-style routine-definitions because of the following ambiguity: |
---|
899 | \begin{lstlisting} |
---|
900 | typedef int foo; |
---|
901 | int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§ |
---|
902 | \end{lstlisting} |
---|
903 | The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo. |
---|
904 | The redefinition of a type name in a parameter list is the only context in C where the character ©*© can appear to the left of a type name, and \CFA relies on all type qualifier characters appearing to the right of the type name. |
---|
905 | The inability to use \CFA declarations in these two contexts is probably a blessing because it precludes programmers from arbitrarily switching between declarations forms within a declaration contexts. |
---|
906 | |
---|
907 | C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg: |
---|
908 | \begin{lstlisting} |
---|
909 | [ int ] f( * int, int * ); §\C{// returns an integer, accepts 2 pointers to integers}§ |
---|
910 | [ * int, int * ] f( int ); §\C{// returns 2 pointers to integers, accepts an integer}§ |
---|
911 | \end{lstlisting} |
---|
912 | The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in: |
---|
913 | \begin{lstlisting} |
---|
914 | #define ptoa( n, d ) int (*n)[ d ] |
---|
915 | int f( ptoa( p, 5 ) ) ... §\C{// expands to int f( int (*p)[ 5 ] )}§ |
---|
916 | [ int ] f( ptoa( p, 5 ) ) ... §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§ |
---|
917 | \end{lstlisting} |
---|
918 | Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms. |
---|
919 | |
---|
920 | |
---|
921 | \subsection{Named Return Values} |
---|
922 | |
---|
923 | \Index{Named return values} handle the case where it is necessary to define a local variable whose value is then returned in a ©return© statement, as in: |
---|
924 | \begin{lstlisting} |
---|
925 | int f() { |
---|
926 | int x; |
---|
927 | ... x = 0; ... x = y; ... |
---|
928 | return x; |
---|
929 | } |
---|
930 | \end{lstlisting} |
---|
931 | Because the value in the return variable is automatically returned when a \CFA routine terminates, the ©return© statement \emph{does not} contain an expression, as in: |
---|
932 | \newline |
---|
933 | \begin{minipage}{\linewidth} |
---|
934 | \begin{lstlisting} |
---|
935 | ®[ int x, int y ]® f() { |
---|
936 | int z; |
---|
937 | ... x = 0; ... y = z; ... |
---|
938 | ®return;® §\C{// implicitly return x, y}§ |
---|
939 | } |
---|
940 | \end{lstlisting} |
---|
941 | \end{minipage} |
---|
942 | \newline |
---|
943 | When the return is encountered, the current values of ©x© and ©y© are returned to the calling routine. |
---|
944 | As well, ``falling off the end'' of a routine without a ©return© statement is permitted, as in: |
---|
945 | \begin{lstlisting} |
---|
946 | [ int x, int y ] f() { |
---|
947 | ... |
---|
948 | } §\C{// implicitly return x, y}§ |
---|
949 | \end{lstlisting} |
---|
950 | In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered. |
---|
951 | |
---|
952 | |
---|
953 | \subsection{Routine Prototype} |
---|
954 | |
---|
955 | The syntax of the new routine prototype declaration follows directly from the new routine definition syntax; |
---|
956 | as well, parameter names are optional, \eg: |
---|
957 | \begin{lstlisting} |
---|
958 | [ int x ] f (); §\C{// returning int with no parameters}§ |
---|
959 | [ * int ] g (int y); §\C{// returning pointer to int with int parameter}§ |
---|
960 | [ ] h (int,char); §\C{// returning no result with int and char parameters}§ |
---|
961 | [ * int,int ] j (int); §\C{// returning pointer to int and int, with int parameter}§ |
---|
962 | \end{lstlisting} |
---|
963 | This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa). |
---|
964 | It is possible to declare multiple routine-prototypes in a single declaration, but the entire type specification is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg: |
---|
965 | \begin{quote2} |
---|
966 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
967 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
968 | \begin{lstlisting} |
---|
969 | [ int ] f(int), g; |
---|
970 | \end{lstlisting} |
---|
971 | & |
---|
972 | \begin{lstlisting} |
---|
973 | int f(int), g(int); |
---|
974 | \end{lstlisting} |
---|
975 | \end{tabular} |
---|
976 | \end{quote2} |
---|
977 | Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg: |
---|
978 | \begin{lstlisting} |
---|
979 | extern [ int ] f (int); |
---|
980 | static [ int ] g (int); |
---|
981 | \end{lstlisting} |
---|
982 | |
---|
983 | |
---|
984 | \section{Routine Pointers} |
---|
985 | |
---|
986 | The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg: |
---|
987 | \begin{lstlisting} |
---|
988 | * [ int x ] () fp; §\C{// pointer to routine returning int with no parameters}§ |
---|
989 | * [ * int ] (int y) gp; §\C{// pointer to routine returning pointer to int with int parameter}§ |
---|
990 | * [ ] (int,char) hp; §\C{// pointer to routine returning no result with int and char parameters}§ |
---|
991 | * [ * int,int ] (int) jp; §\C{// pointer to routine returning pointer to int and int, with int parameter}§ |
---|
992 | \end{lstlisting} |
---|
993 | While parameter names are optional, \emph{a routine name cannot be specified}; |
---|
994 | for example, the following is incorrect: |
---|
995 | \begin{lstlisting} |
---|
996 | * [ int x ] f () fp; §\C{// routine name "f" is not allowed}§ |
---|
997 | \end{lstlisting} |
---|
998 | |
---|
999 | |
---|
1000 | \section{Named and Default Arguments} |
---|
1001 | |
---|
1002 | Named and default arguments~\cite{Hardgrave76}\footnote{ |
---|
1003 | Francez~\cite{Francez77} proposed a further extension to the named-parameter passing style, which specifies what type of communication (by value, by reference, by name) the argument is passed to the routine.} |
---|
1004 | are two mechanisms to simplify routine call. |
---|
1005 | Both mechanisms are discussed with respect to \CFA. |
---|
1006 | \begin{description} |
---|
1007 | \item[Named (or Keyword) Arguments:] |
---|
1008 | provide the ability to specify an argument to a routine call using the parameter name rather than the position of the parameter. |
---|
1009 | For example, given the routine: |
---|
1010 | \begin{lstlisting} |
---|
1011 | void p( int x, int y, int z ) {...} |
---|
1012 | \end{lstlisting} |
---|
1013 | a positional call is: |
---|
1014 | \begin{lstlisting} |
---|
1015 | p( 4, 7, 3 ); |
---|
1016 | \end{lstlisting} |
---|
1017 | whereas a named (keyword) call may be: |
---|
1018 | \begin{lstlisting} |
---|
1019 | p( z : 3, x : 4, y : 7 ); §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§ |
---|
1020 | \end{lstlisting} |
---|
1021 | Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters. |
---|
1022 | The compiler rewrites a named call into a positional call. |
---|
1023 | The advantages of named parameters are: |
---|
1024 | \begin{itemize} |
---|
1025 | \item |
---|
1026 | Remembering the names of the parameters may be easier than the order in the routine definition. |
---|
1027 | \item |
---|
1028 | Parameter names provide documentation at the call site (assuming the names are descriptive). |
---|
1029 | \item |
---|
1030 | Changes can be made to the order or number of parameters without affecting the call (although the call must still be recompiled). |
---|
1031 | \end{itemize} |
---|
1032 | |
---|
1033 | Unfortunately, named arguments do not work in C-style programming-languages because a routine prototype is not required to specify parameter names, nor do the names in the prototype have to match with the actual definition. |
---|
1034 | For example, the following routine prototypes and definition are all valid. |
---|
1035 | \begin{lstlisting} |
---|
1036 | void p( int, int, int ); §\C{// equivalent prototypes}§ |
---|
1037 | void p( int x, int y, int z ); |
---|
1038 | void p( int y, int x, int z ); |
---|
1039 | void p( int z, int y, int x ); |
---|
1040 | void p( int q, int r, int s ) {} §\C{// match with this definition}§ |
---|
1041 | \end{lstlisting} |
---|
1042 | Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming. |
---|
1043 | Alternatively, prototype definitions can be eliminated by using a two-pass compilation, and implicitly creating header files for exports. |
---|
1044 | The former is easy to do, while the latter is more complex. |
---|
1045 | |
---|
1046 | Furthermore, named arguments do not work well in a \CFA-style programming-languages because they potentially introduces a new criteria for type matching. |
---|
1047 | For example, it is technically possible to disambiguate between these two overloaded definitions of ©f© based on named arguments at the call site: |
---|
1048 | \begin{lstlisting} |
---|
1049 | int f( int i, int j ); |
---|
1050 | int f( int x, double y ); |
---|
1051 | |
---|
1052 | f( j : 3, i : 4 ); §\C{// 1st f}§ |
---|
1053 | f( x : 7, y : 8.1 ); §\C{// 2nd f}§ |
---|
1054 | f( 4, 5 ); §\C{// ambiguous call}§ |
---|
1055 | \end{lstlisting} |
---|
1056 | However, named arguments compound routine resolution in conjunction with conversions: |
---|
1057 | \begin{lstlisting} |
---|
1058 | f( i : 3, 5.7 ); §\C{// ambiguous call ?}§ |
---|
1059 | \end{lstlisting} |
---|
1060 | Depending on the cost associated with named arguments, this call could be resolvable or ambiguous. |
---|
1061 | Adding named argument into the routine resolution algorithm does not seem worth the complexity. |
---|
1062 | Therefore, \CFA does \emph{not} attempt to support named arguments. |
---|
1063 | |
---|
1064 | \item[Default Arguments] |
---|
1065 | provide the ability to associate a default value with a parameter so it can be optionally specified in the argument list. |
---|
1066 | For example, given the routine: |
---|
1067 | \begin{lstlisting} |
---|
1068 | void p( int x = 1, int y = 2, int z = 3 ) {...} |
---|
1069 | \end{lstlisting} |
---|
1070 | the allowable positional calls are: |
---|
1071 | \begin{lstlisting} |
---|
1072 | p(); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§ |
---|
1073 | p( 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§ |
---|
1074 | p( 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§ |
---|
1075 | p( 4, 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§ |
---|
1076 | // empty arguments |
---|
1077 | p( , 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§ |
---|
1078 | p( 4, , 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§ |
---|
1079 | p( 4, 4, ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§ |
---|
1080 | p( 4, , ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§ |
---|
1081 | p( , 4, ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§ |
---|
1082 | p( , , 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§ |
---|
1083 | p( , , ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§ |
---|
1084 | \end{lstlisting} |
---|
1085 | Here the missing arguments are inserted from the default values in the parameter list. |
---|
1086 | The compiler rewrites missing default values into explicit positional arguments. |
---|
1087 | The advantages of default values are: |
---|
1088 | \begin{itemize} |
---|
1089 | \item |
---|
1090 | Routines with a large number of parameters are often very generalized, giving a programmer a number of different options on how a computation is performed. |
---|
1091 | For many of these kinds of routines, there are standard or default settings that work for the majority of computations. |
---|
1092 | Without default values for parameters, a programmer is forced to specify these common values all the time, resulting in long argument lists that are error prone. |
---|
1093 | \item |
---|
1094 | When a routine's interface is augmented with new parameters, it extends the interface providing generalizability\footnote{ |
---|
1095 | ``It should be possible for the implementor of an abstraction to increase its generality. |
---|
1096 | So long as the modified abstraction is a generalization of the original, existing uses of the abstraction will not require change. |
---|
1097 | It might be possible to modify an abstraction in a manner which is not a generalization without affecting existing uses, but, without inspecting the modules in which the uses occur, this possibility cannot be determined. |
---|
1098 | This criterion precludes the addition of parameters, unless these parameters have default or inferred values that are valid for all possible existing applications.''~\cite[p.~128]{Cormack90}} |
---|
1099 | (somewhat like the generalization provided by inheritance for classes). |
---|
1100 | That is, all existing calls are still valid, although the call must still be recompiled. |
---|
1101 | \end{itemize} |
---|
1102 | The only disadvantage of default arguments is that unintentional omission of an argument may not result in a compiler-time error. |
---|
1103 | Instead, a default value is used, which may not be the programmer's intent. |
---|
1104 | |
---|
1105 | Default values may only appear in a prototype versus definition context: |
---|
1106 | \begin{lstlisting} |
---|
1107 | void p( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§ |
---|
1108 | void p( int, int = 2, int = 3 ); §\C{// prototype: allowed}§ |
---|
1109 | void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: not allowed}§ |
---|
1110 | \end{lstlisting} |
---|
1111 | The reason for this restriction is to allow separate compilation. |
---|
1112 | Multiple prototypes with different default values is an error. |
---|
1113 | \end{description} |
---|
1114 | |
---|
1115 | Ellipse (``...'') arguments present problems when used with default arguments. |
---|
1116 | The conflict occurs because both named and ellipse arguments must appear after positional arguments, giving two possibilities: |
---|
1117 | \begin{lstlisting} |
---|
1118 | p( /* positional */, ... , /* named */ ); |
---|
1119 | p( /* positional */, /* named */, ... ); |
---|
1120 | \end{lstlisting} |
---|
1121 | While it is possible to implement both approaches, the first possibly is more complex than the second, \eg: |
---|
1122 | \begin{lstlisting} |
---|
1123 | p( int x, int y, int z, ... ); |
---|
1124 | p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ |
---|
1125 | p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ |
---|
1126 | \end{lstlisting} |
---|
1127 | In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin. |
---|
1128 | Hence, this approach seems significantly more difficult, and hence, confusing and error prone. |
---|
1129 | In the second call, the named arguments separate the positional and ellipse arguments, making it trivial to read the call. |
---|
1130 | |
---|
1131 | The problem is exacerbated with default arguments, \eg: |
---|
1132 | \begin{lstlisting} |
---|
1133 | void p( int x, int y = 2, int z = 3... ); |
---|
1134 | p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ |
---|
1135 | p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ |
---|
1136 | \end{lstlisting} |
---|
1137 | The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments; |
---|
1138 | therefore, argument 5 subsequently conflicts with the named argument z : 3. |
---|
1139 | In the second call, the default value for y is implicitly inserted after argument 1 and the named arguments separate the positional and ellipse arguments, making it trivial to read the call. |
---|
1140 | For these reasons, \CFA requires named arguments before ellipse arguments. |
---|
1141 | Finally, while ellipse arguments are needed for a small set of existing C routines, like printf, the extended \CFA type system largely eliminates the need for ellipse arguments (see Section 24), making much of this discussion moot. |
---|
1142 | |
---|
1143 | Default arguments and overloading (see Section 24) are complementary. |
---|
1144 | While in theory default arguments can be simulated with overloading, as in: |
---|
1145 | \begin{quote2} |
---|
1146 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
1147 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}} & \multicolumn{1}{c}{\textbf{overloading}} \\ |
---|
1148 | \begin{lstlisting} |
---|
1149 | void p( int x, int y = 2, int z = 3 ) {...} |
---|
1150 | |
---|
1151 | |
---|
1152 | \end{lstlisting} |
---|
1153 | & |
---|
1154 | \begin{lstlisting} |
---|
1155 | void p( int x, int y, int z ) {...} |
---|
1156 | void p( int x ) { p( x, 2, 3 ); } |
---|
1157 | void p( int x, int y ) { p( x, y, 3 ); } |
---|
1158 | \end{lstlisting} |
---|
1159 | \end{tabular} |
---|
1160 | \end{quote2} |
---|
1161 | the number of required overloaded routines is linear in the number of default values, which is unacceptable growth. |
---|
1162 | In general, overloading should only be used over default arguments if the body of the routine is significantly different. |
---|
1163 | Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as: |
---|
1164 | \begin{lstlisting} |
---|
1165 | p( 1, /* default */, 5 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§ |
---|
1166 | \end{lstlisting} |
---|
1167 | |
---|
1168 | Given the \CFA restrictions above, both named and default arguments are backwards compatible. |
---|
1169 | \Index*[C++]{\CC} only supports default arguments; |
---|
1170 | \Index*{Ada} supports both named and default arguments. |
---|
1171 | |
---|
1172 | |
---|
1173 | \section{Type/Routine Nesting} |
---|
1174 | |
---|
1175 | Nesting of types and routines is useful for controlling name visibility (\newterm{name hiding}). |
---|
1176 | |
---|
1177 | |
---|
1178 | \subsection{Type Nesting} |
---|
1179 | |
---|
1180 | \CFA allows \Index{type nesting}, and type qualification of the nested typres (see \VRef[Figure]{f:TypeNestingQualification}), where as C hoists\index{type hoisting} (refactors) nested types into the enclosing scope and has no type qualification. |
---|
1181 | \begin{figure} |
---|
1182 | \centering |
---|
1183 | \begin{tabular}{@{}l@{\hspace{3em}}l|l@{}} |
---|
1184 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}} & \multicolumn{1}{c}{\textbf{C Implicit Hoisting}} & \multicolumn{1}{|c}{\textbf{\CFA}} \\ |
---|
1185 | \hline |
---|
1186 | \begin{lstlisting} |
---|
1187 | struct S { |
---|
1188 | enum C { R, G, B }; |
---|
1189 | struct T { |
---|
1190 | union U { int i, j; }; |
---|
1191 | enum C c; |
---|
1192 | short int i, j; |
---|
1193 | }; |
---|
1194 | struct T t; |
---|
1195 | } s; |
---|
1196 | |
---|
1197 | int fred() { |
---|
1198 | s.t.c = R; |
---|
1199 | struct T t = { R, 1, 2 }; |
---|
1200 | enum C c; |
---|
1201 | union U u; |
---|
1202 | } |
---|
1203 | \end{lstlisting} |
---|
1204 | & |
---|
1205 | \begin{lstlisting} |
---|
1206 | enum C { R, G, B }; |
---|
1207 | union U { int i, j; }; |
---|
1208 | struct T { |
---|
1209 | enum C c; |
---|
1210 | short int i, j; |
---|
1211 | }; |
---|
1212 | struct S { |
---|
1213 | struct T t; |
---|
1214 | } s; |
---|
1215 | |
---|
1216 | |
---|
1217 | |
---|
1218 | |
---|
1219 | |
---|
1220 | |
---|
1221 | |
---|
1222 | \end{lstlisting} |
---|
1223 | & |
---|
1224 | \begin{lstlisting} |
---|
1225 | struct S { |
---|
1226 | enum C { R, G, B }; |
---|
1227 | struct T { |
---|
1228 | union U { int i, j; }; |
---|
1229 | enum C c; |
---|
1230 | short int i, j; |
---|
1231 | }; |
---|
1232 | struct T t; |
---|
1233 | } s; |
---|
1234 | |
---|
1235 | int fred() { |
---|
1236 | s.t.c = ®S.®R; // type qualification |
---|
1237 | struct ®S.®T t = { ®S.®R, 1, 2 }; |
---|
1238 | enum ®S.®C c; |
---|
1239 | union ®S.T.®U u; |
---|
1240 | } |
---|
1241 | \end{lstlisting} |
---|
1242 | \end{tabular} |
---|
1243 | \caption{Type Nesting / Qualification} |
---|
1244 | \label{f:TypeNestingQualification} |
---|
1245 | \end{figure} |
---|
1246 | In the left example in C, types ©C©, ©U© and ©T© are implicitly hoisted outside of type ©S© into the containing block scope. |
---|
1247 | In the right example in \CFA, the types are not hoisted and accessed using the field-selection operator ``©.©'' for type qualification, as does \Index*{Java}, rather than the \CC type-selection operator ``©::©''. |
---|
1248 | |
---|
1249 | |
---|
1250 | \subsection{Routine Nesting} |
---|
1251 | |
---|
1252 | While \CFA does not provide object programming by putting routines into structures, it does rely heavily on locally nested routines to redefine operations at or close to a call site. |
---|
1253 | For example, the C quick-sort is wrapped into the following polymorphic \CFA routine: |
---|
1254 | \begin{lstlisting} |
---|
1255 | forall( otype T | { int ?<?( T, T ); } ) |
---|
1256 | void qsort( const T * arr, size_t dimension ); |
---|
1257 | \end{lstlisting} |
---|
1258 | which can be used to sort in ascending and descending order by locally redefining the less-than operator into greater-than. |
---|
1259 | \begin{lstlisting} |
---|
1260 | const unsigned int size = 5; |
---|
1261 | int ia[size]; |
---|
1262 | ... §\C{// assign values to array ia}§ |
---|
1263 | qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§ |
---|
1264 | { |
---|
1265 | ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§ |
---|
1266 | qsort( ia, size ); §\C{// sort descending order by local redefinition}§ |
---|
1267 | } |
---|
1268 | \end{lstlisting} |
---|
1269 | |
---|
1270 | Nested routines are not first-class, meaning a nested routine cannot be returned if it has references to variables in its enclosing blocks; |
---|
1271 | the only exception is references to the external block of the translation unit, as these variables persist for the duration of the program. |
---|
1272 | The following program in undefined in \CFA (and Indexc{gcc}) |
---|
1273 | \begin{lstlisting} |
---|
1274 | [* [int]( int )] foo() { §\C{// int (*foo())( int )}§ |
---|
1275 | int ®i® = 7; |
---|
1276 | int bar( int p ) { |
---|
1277 | ®i® += 1; §\C{// dependent on local variable}§ |
---|
1278 | sout | ®i® | endl; |
---|
1279 | } |
---|
1280 | return bar; §\C{// undefined because of local dependence}§ |
---|
1281 | } |
---|
1282 | int main() { |
---|
1283 | * [int](int) fp = foo(); §\C{// int (*fp)(int)}§ |
---|
1284 | sout | fp( 3 ) | endl; |
---|
1285 | } |
---|
1286 | \end{lstlisting} |
---|
1287 | because |
---|
1288 | |
---|
1289 | Currently, there are no \Index{lambda} expressions, i.e., unnamed routines because routine names are very important to properly select the correct routine. |
---|
1290 | |
---|
1291 | |
---|
1292 | \section{Lexical List} |
---|
1293 | |
---|
1294 | In C and \CFA, lists of elements appear in several contexts, such as the parameter list for a routine call. |
---|
1295 | (More contexts are added shortly.) |
---|
1296 | A list of such elements is called a \newterm{lexical list}. |
---|
1297 | The general syntax of a lexical list is: |
---|
1298 | \begin{lstlisting} |
---|
1299 | [ §\emph{exprlist}§ ] |
---|
1300 | \end{lstlisting} |
---|
1301 | where ©$\emph{exprlist}$© is a list of one or more expressions separated by commas. |
---|
1302 | The brackets, ©[]©, allow differentiating between lexical lists and expressions containing the C comma operator. |
---|
1303 | The following are examples of lexical lists: |
---|
1304 | \begin{lstlisting} |
---|
1305 | [ x, y, z ] |
---|
1306 | [ 2 ] |
---|
1307 | [ v+w, x*y, 3.14159, f() ] |
---|
1308 | \end{lstlisting} |
---|
1309 | Tuples are permitted to contain sub-tuples (i.e., nesting), such as ©[ [ 14, 21 ], 9 ]©, which is a 2-element tuple whose first element is itself a tuple. |
---|
1310 | Note, a tuple is not a record (structure); |
---|
1311 | a record denotes a single value with substructure, whereas a tuple is multiple values with no substructure (see flattening coercion in Section 12.1). |
---|
1312 | In essence, tuples are largely a compile time phenomenon, having little or no runtime presence. |
---|
1313 | |
---|
1314 | Tuples can be organized into compile-time tuple variables; |
---|
1315 | these variables are of \newterm{tuple type}. |
---|
1316 | Tuple variables and types can be used anywhere lists of conventional variables and types can be used. |
---|
1317 | The general syntax of a tuple type is: |
---|
1318 | \begin{lstlisting} |
---|
1319 | [ §\emph{typelist}§ ] |
---|
1320 | \end{lstlisting} |
---|
1321 | where ©$\emph{typelist}$© is a list of one or more legal \CFA or C type specifications separated by commas, which may include other tuple type specifications. |
---|
1322 | Examples of tuple types include: |
---|
1323 | \begin{lstlisting} |
---|
1324 | [ unsigned int, char ] |
---|
1325 | [ double, double, double ] |
---|
1326 | [ * int, int * ] §\C{// mix of CFA and ANSI}§ |
---|
1327 | [ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ] |
---|
1328 | \end{lstlisting} |
---|
1329 | Like tuples, tuple types may be nested, such as ©[ [ int, int ], int ]©, which is a 2-element tuple type whose first element is itself a tuple type. |
---|
1330 | |
---|
1331 | Examples of declarations using tuple types are: |
---|
1332 | \begin{lstlisting} |
---|
1333 | [ int, int ] x; §\C{// 2 element tuple, each element of type int}§ |
---|
1334 | * [ char, char ] y; §\C{// pointer to a 2 element tuple}§ |
---|
1335 | [ [ int, int ] ] z ([ int, int ]); |
---|
1336 | \end{lstlisting} |
---|
1337 | The last example declares an external routine that expects a 2 element tuple as an input parameter and returns a 2 element tuple as its result. |
---|
1338 | |
---|
1339 | As mentioned, tuples can appear in contexts requiring a list of value, such as an argument list of a routine call. |
---|
1340 | In unambiguous situations, the tuple brackets may be omitted, \eg a tuple that appears as an argument may have its |
---|
1341 | square brackets omitted for convenience; therefore, the following routine invocations are equivalent: |
---|
1342 | \begin{lstlisting} |
---|
1343 | f( [ 1, x+2, fred() ] ); |
---|
1344 | f( 1, x+2, fred() ); |
---|
1345 | \end{lstlisting} |
---|
1346 | Also, a tuple or a tuple variable may be used to supply all or part of an argument list for a routine expecting multiple input parameters or for a routine expecting a tuple as an input parameter. |
---|
1347 | For example, the following are all legal: |
---|
1348 | \begin{lstlisting} |
---|
1349 | [ int, int ] w1; |
---|
1350 | [ int, int, int ] w2; |
---|
1351 | [ void ] f (int, int, int); /* three input parameters of type int */ |
---|
1352 | [ void ] g ([ int, int, int ]); /* 3 element tuple as input */ |
---|
1353 | f( [ 1, 2, 3 ] ); |
---|
1354 | f( w1, 3 ); |
---|
1355 | f( 1, w1 ); |
---|
1356 | f( w2 ); |
---|
1357 | g( [ 1, 2, 3 ] ); |
---|
1358 | g( w1, 3 ); |
---|
1359 | g( 1, w1 ); |
---|
1360 | g( w2 ); |
---|
1361 | \end{lstlisting} |
---|
1362 | Note, in all cases 3 arguments are supplied even though the syntax may appear to supply less than 3. As mentioned, a |
---|
1363 | tuple does not have structure like a record; a tuple is simply converted into a list of components. |
---|
1364 | \begin{rationale} |
---|
1365 | The present implementation of \CFA does not support nested routine calls when the inner routine returns multiple values; i.e., a statement such as ©g( f() )© is not supported. |
---|
1366 | Using a temporary variable to store the results of the inner routine and then passing this variable to the outer routine works, however. |
---|
1367 | \end{rationale} |
---|
1368 | |
---|
1369 | A tuple can contain a C comma expression, provided the expression containing the comma operator is enclosed in parentheses. |
---|
1370 | For instance, the following tuples are equivalent: |
---|
1371 | \begin{lstlisting} |
---|
1372 | [ 1, 3, 5 ] |
---|
1373 | [ 1, (2, 3), 5 ] |
---|
1374 | \end{lstlisting} |
---|
1375 | The second element of the second tuple is the expression (2, 3), which yields the result 3. |
---|
1376 | This requirement is the same as for comma expressions in argument lists. |
---|
1377 | |
---|
1378 | Type qualifiers, i.e., const and volatile, may modify a tuple type. |
---|
1379 | The meaning is the same as for a type qualifier modifying an aggregate type [Int99, x 6.5.2.3(7),x 6.7.3(11)], i.e., the qualifier is distributed across all of the types in the tuple, \eg: |
---|
1380 | \begin{lstlisting} |
---|
1381 | const volatile [ int, float, const int ] x; |
---|
1382 | \end{lstlisting} |
---|
1383 | is equivalent to: |
---|
1384 | \begin{lstlisting} |
---|
1385 | [ const volatile int, const volatile float, const volatile int ] x; |
---|
1386 | \end{lstlisting} |
---|
1387 | Declaration qualifiers can only appear at the start of a \CFA tuple declaration4, \eg: |
---|
1388 | \begin{lstlisting} |
---|
1389 | extern [ int, int ] w1; |
---|
1390 | static [ int, int, int ] w2; |
---|
1391 | \end{lstlisting} |
---|
1392 | \begin{rationale} |
---|
1393 | Unfortunately, C's syntax for subscripts precluded treating them as tuples. |
---|
1394 | The C subscript list has the form ©[i][j]...© and not ©[i, j, ...]©. |
---|
1395 | Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[g()]© always means a single subscript value because there is only one set of brackets. |
---|
1396 | Fixing this requires a major change to C because the syntactic form ©M[i, j, k]© already has a particular meaning: ©i, j, k© is a comma expression. |
---|
1397 | \end{rationale} |
---|
1398 | |
---|
1399 | |
---|
1400 | \subsection{Tuple Coercions} |
---|
1401 | |
---|
1402 | There are four coercions that can be performed on tuples and tuple variables: closing, opening, flattening and structuring. |
---|
1403 | In addition, the coercion of dereferencing can be performed on a tuple variable to yield its value(s), as for other variables. |
---|
1404 | A \newterm{closing coercion} takes a set of values and converts it into a tuple value, which is a contiguous set of values, as in: |
---|
1405 | \begin{lstlisting} |
---|
1406 | [ int, int, int, int ] w; |
---|
1407 | w = [ 1, 2, 3, 4 ]; |
---|
1408 | \end{lstlisting} |
---|
1409 | First the right-hand tuple is closed into a tuple value and then the tuple value is assigned. |
---|
1410 | |
---|
1411 | An \newterm{opening coercion} is the opposite of closing; a tuple value is converted into a tuple of values, as in: |
---|
1412 | \begin{lstlisting} |
---|
1413 | [ a, b, c, d ] = w |
---|
1414 | \end{lstlisting} |
---|
1415 | ©w© is implicitly opened to yield a tuple of four values, which are then assigned individually. |
---|
1416 | |
---|
1417 | A \newterm{flattening coercion} coerces a nested tuple, i.e., a tuple with one or more components, which are themselves tuples, into a flattened tuple, which is a tuple whose components are not tuples, as in: |
---|
1418 | \begin{lstlisting} |
---|
1419 | [ a, b, c, d ] = [ 1, [ 2, 3 ], 4 ]; |
---|
1420 | \end{lstlisting} |
---|
1421 | First the right-hand tuple is flattened and then the values are assigned individually. |
---|
1422 | Flattening is also performed on tuple types. |
---|
1423 | For example, the type ©[ int, [ int, int ], int ]© can be coerced, using flattening, into the type ©[ int, int, int, int ]©. |
---|
1424 | |
---|
1425 | A \newterm{structuring coercion} is the opposite of flattening; |
---|
1426 | a tuple is structured into a more complex nested tuple. |
---|
1427 | For example, structuring the tuple ©[ 1, 2, 3, 4 ]© into the tuple ©[ 1, [ 2, 3 ], 4 ]© or the tuple type ©[ int, int, int, int ]© into the tuple type ©[ int, [ int, int ], int ]©. |
---|
1428 | In the following example, the last assignment illustrates all the tuple coercions: |
---|
1429 | \begin{lstlisting} |
---|
1430 | [ int, int, int, int ] w = [ 1, 2, 3, 4 ]; |
---|
1431 | int x = 5; |
---|
1432 | [ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§ |
---|
1433 | \end{lstlisting} |
---|
1434 | Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values; |
---|
1435 | therefore, the right-hand tuple is now the tuple ©[ [ 1, 2, 3, 4 ], 5 ]©. |
---|
1436 | This tuple is then flattened, yielding ©[ 1, 2, 3, 4, 5 ]©, which is structured into ©[ 1, [ 2, 3, 4, 5 ] ]© to match the tuple type of the left-hand side. |
---|
1437 | The tuple ©[ 2, 3, 4, 5 ]© is then closed to create a tuple value. |
---|
1438 | Finally, ©x© is assigned ©1© and ©w© is assigned the tuple value using multiple assignment (see Section 14). |
---|
1439 | \begin{rationale} |
---|
1440 | A possible additional language extension is to use the structuring coercion for tuples to initialize a complex record with a tuple. |
---|
1441 | \end{rationale} |
---|
1442 | |
---|
1443 | |
---|
1444 | \section{Mass Assignment} |
---|
1445 | |
---|
1446 | \CFA permits assignment to several variables at once using mass assignment~\cite{CLU}. |
---|
1447 | Mass assignment has the following form: |
---|
1448 | \begin{lstlisting} |
---|
1449 | [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = §\emph{expr}§; |
---|
1450 | \end{lstlisting} |
---|
1451 | \index{lvalue} |
---|
1452 | 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. |
---|
1453 | ©$\emph{expr}$© is any standard arithmetic expression. |
---|
1454 | Clearly, the types of the entities being assigned must be type compatible with the value of the expression. |
---|
1455 | |
---|
1456 | Mass assignment has parallel semantics, \eg the statement: |
---|
1457 | \begin{lstlisting} |
---|
1458 | [ x, y, z ] = 1.5; |
---|
1459 | \end{lstlisting} |
---|
1460 | is equivalent to: |
---|
1461 | \begin{lstlisting} |
---|
1462 | x = 1.5; y = 1.5; z = 1.5; |
---|
1463 | \end{lstlisting} |
---|
1464 | This semantics is not the same as the following in C: |
---|
1465 | \begin{lstlisting} |
---|
1466 | x = y = z = 1.5; |
---|
1467 | \end{lstlisting} |
---|
1468 | as conversions between intermediate assignments may lose information. |
---|
1469 | A more complex example is: |
---|
1470 | \begin{lstlisting} |
---|
1471 | [ i, y[i], z ] = a + b; |
---|
1472 | \end{lstlisting} |
---|
1473 | which is equivalent to: |
---|
1474 | \begin{lstlisting} |
---|
1475 | t = a + b; |
---|
1476 | a1 = &i; a2 = &y[i]; a3 = &z; |
---|
1477 | *a1 = t; *a2 = t; *a3 = t; |
---|
1478 | \end{lstlisting} |
---|
1479 | The temporary ©t© is necessary to store the value of the expression to eliminate conversion issues. |
---|
1480 | The temporaries for the addresses are needed so that locations on the left-hand side do not change as the values are assigned. |
---|
1481 | In this case, ©y[i]© uses the previous value of ©i© and not the new value set at the beginning of the mass assignment. |
---|
1482 | |
---|
1483 | |
---|
1484 | \section{Multiple Assignment} |
---|
1485 | |
---|
1486 | \CFA also supports the assignment of several values at once, known as multiple assignment~\cite{CLU,Galletly96}. |
---|
1487 | Multiple assignment has the following form: |
---|
1488 | \begin{lstlisting} |
---|
1489 | [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = [ §\emph{expr}§, ... , §\emph{expr}§ ]; |
---|
1490 | \end{lstlisting} |
---|
1491 | \index{lvalue} |
---|
1492 | The left-hand side is a tuple of \emph{lvalues}, and the right-hand side is a tuple of \emph{expr}s. |
---|
1493 | 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. |
---|
1494 | An example of multiple assignment is: |
---|
1495 | \begin{lstlisting} |
---|
1496 | [ x, y, z ] = [ 1, 2, 3 ]; |
---|
1497 | \end{lstlisting} |
---|
1498 | Here, the values ©1©, ©2© and ©3© are assigned, respectively, to the variables ©x©, ©y© and ©z©. |
---|
1499 | A more complex example is: |
---|
1500 | \begin{lstlisting} |
---|
1501 | [ i, y[ i ], z ] = [ 1, i, a + b ]; |
---|
1502 | \end{lstlisting} |
---|
1503 | Here, the values ©1©, ©i© and ©a + b© are assigned to the variables ©i©, ©y[i]© and ©z©, respectively. |
---|
1504 | Note, the parallel semantics of |
---|
1505 | multiple assignment ensures: |
---|
1506 | \begin{lstlisting} |
---|
1507 | [ x, y ] = [ y, x ]; |
---|
1508 | \end{lstlisting} |
---|
1509 | correctly interchanges (swaps) the values stored in ©x© and ©y©. |
---|
1510 | The following cases are errors: |
---|
1511 | \begin{lstlisting} |
---|
1512 | [ a, b, c ] = [ 1, 2, 3, 4 ]; |
---|
1513 | [ a, b, c ] = [ 1, 2 ]; |
---|
1514 | \end{lstlisting} |
---|
1515 | because the number of entities in the left-hand tuple is unequal with the right-hand tuple. |
---|
1516 | |
---|
1517 | As for all tuple contexts in C, side effects should not be used because C does not define an ordering for the evaluation of the elements of a tuple; |
---|
1518 | both these examples produce indeterminate results: |
---|
1519 | \begin{lstlisting} |
---|
1520 | f( x++, x++ ); §\C{// C routine call with side effects in arguments}§ |
---|
1521 | [ v1, v2 ] = [ x++, x++ ]; §\C{// side effects in righthand side of multiple assignment}§ |
---|
1522 | \end{lstlisting} |
---|
1523 | |
---|
1524 | |
---|
1525 | \section{Cascade Assignment} |
---|
1526 | |
---|
1527 | As in C, \CFA mass and multiple assignments can be cascaded, producing cascade assignment. |
---|
1528 | Cascade assignment has the following form: |
---|
1529 | \begin{lstlisting} |
---|
1530 | §\emph{tuple}§ = §\emph{tuple}§ = ... = §\emph{tuple}§; |
---|
1531 | \end{lstlisting} |
---|
1532 | and it has the same parallel semantics as for mass and multiple assignment. |
---|
1533 | Some examples of cascade assignment are: |
---|
1534 | \begin{lstlisting} |
---|
1535 | x1 = y1 = x2 = y2 = 0; |
---|
1536 | [ x1, y1 ] = [ x2, y2 ] = [ x3, y3 ]; |
---|
1537 | [ x1, y1 ] = [ x2, y2 ] = 0; |
---|
1538 | [ x1, y1 ] = z = 0; |
---|
1539 | \end{lstlisting} |
---|
1540 | As in C, the rightmost assignment is performed first, i.e., assignment parses right to left. |
---|
1541 | |
---|
1542 | |
---|
1543 | \section{Unnamed Structure Fields} |
---|
1544 | |
---|
1545 | C requires each field of a structure to have a name, except for a bit field associated with a basic type, \eg: |
---|
1546 | \begin{lstlisting} |
---|
1547 | struct { |
---|
1548 | int f1; §\C{// named field}§ |
---|
1549 | int f2 : 4; §\C{// named field with bit field size}§ |
---|
1550 | int : 3; §\C{// unnamed field for basic type with bit field size}§ |
---|
1551 | int ; §\C{// disallowed, unnamed field}§ |
---|
1552 | int *; §\C{// disallowed, unnamed field}§ |
---|
1553 | int (*)(int); §\C{// disallowed, unnamed field}§ |
---|
1554 | }; |
---|
1555 | \end{lstlisting} |
---|
1556 | This requirement is relaxed by making the field name optional for all field declarations; therefore, all the field declarations in the example are allowed. |
---|
1557 | As for unnamed bit fields, an unnamed field is used for padding a structure to a particular size. |
---|
1558 | A list of unnamed fields is also supported, \eg: |
---|
1559 | \begin{lstlisting} |
---|
1560 | struct { |
---|
1561 | int , , ; §\C{// 3 unnamed fields}§ |
---|
1562 | } |
---|
1563 | \end{lstlisting} |
---|
1564 | |
---|
1565 | |
---|
1566 | \section{Field Tuples} |
---|
1567 | |
---|
1568 | Tuples may be used to select multiple fields of a record by field name. |
---|
1569 | Its general form is: |
---|
1570 | \begin{lstlisting} |
---|
1571 | §\emph{expr}§ . [ §\emph{fieldlist}§ ] |
---|
1572 | §\emph{expr}§ -> [ §\emph{fieldlist}§ ] |
---|
1573 | \end{lstlisting} |
---|
1574 | \emph{expr} is any expression yielding a value of type record, \eg ©struct©, ©union©. |
---|
1575 | Each element of \emph{ fieldlist} is an element of the record specified by \emph{expr}. |
---|
1576 | A record-field tuple may be used anywhere a tuple can be used. An example of the use of a record-field tuple is |
---|
1577 | the following: |
---|
1578 | \begin{lstlisting} |
---|
1579 | struct s { |
---|
1580 | int f1, f2; |
---|
1581 | char f3; |
---|
1582 | double f4; |
---|
1583 | } v; |
---|
1584 | v.[ f3, f1, f2 ] = ['x', 11, 17 ]; §\C{// equivalent to v.f3 = 'x', v.f1 = 11, v.f2 = 17}§ |
---|
1585 | f( v.[ f3, f1, f2 ] ); §\C{// equivalent to f( v.f3, v.f1, v.f2 )}§ |
---|
1586 | \end{lstlisting} |
---|
1587 | Note, the fields appearing in a record-field tuple may be specified in any order; |
---|
1588 | also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple. |
---|
1589 | |
---|
1590 | If a field of a ©struct© is itself another ©struct©, multiple fields of this subrecord can be specified using a nested record-field tuple, as in the following example: |
---|
1591 | \begin{lstlisting} |
---|
1592 | struct inner { |
---|
1593 | int f2, f3; |
---|
1594 | }; |
---|
1595 | struct outer { |
---|
1596 | int f1; |
---|
1597 | struct inner i; |
---|
1598 | double f4; |
---|
1599 | } o; |
---|
1600 | |
---|
1601 | o.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ]; |
---|
1602 | \end{lstlisting} |
---|
1603 | |
---|
1604 | |
---|
1605 | \section{Labelled Continue / Break} |
---|
1606 | |
---|
1607 | While C provides ©continue© and ©break© statements for altering control flow, both are restricted to one level of nesting for a particular control structure. |
---|
1608 | Unfortunately, this restriction forces programmers to use ©goto© to achieve the equivalent control-flow for more than one level of nesting. |
---|
1609 | To prevent having to switch to the ©goto©, \CFA extends the ©continue©\index{continue@©continue©}\index{continue@©continue©!labelled}\index{labelled!continue@©continue©} and ©break©\index{break@©break©}\index{break@©break©!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85,Java}. |
---|
1610 | For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do© statement; |
---|
1611 | for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement. |
---|
1612 | |
---|
1613 | The following example shows the labelled ©continue© specifying which control structure is the target for the next loop iteration: |
---|
1614 | \begin{quote2} |
---|
1615 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
1616 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
1617 | \begin{lstlisting} |
---|
1618 | ®L1:® do { |
---|
1619 | ®L2:® while ( ... ) { |
---|
1620 | ®L3:® for ( ... ) { |
---|
1621 | ... continue ®L1®; ... // continue do |
---|
1622 | ... continue ®L2®; ... // continue while |
---|
1623 | ... continue ®L3®; ... // continue for |
---|
1624 | } // for |
---|
1625 | } // while |
---|
1626 | } while ( ... ); |
---|
1627 | \end{lstlisting} |
---|
1628 | & |
---|
1629 | \begin{lstlisting} |
---|
1630 | do { |
---|
1631 | while ( ... ) { |
---|
1632 | for ( ... ) { |
---|
1633 | ... goto L1; ... |
---|
1634 | ... goto L2; ... |
---|
1635 | ... goto L3; ... |
---|
1636 | L3: ; } |
---|
1637 | L2: ; } |
---|
1638 | L1: ; } while ( ... ); |
---|
1639 | \end{lstlisting} |
---|
1640 | \end{tabular} |
---|
1641 | \end{quote2} |
---|
1642 | The innermost loop has three restart points, which cause the next loop iteration to begin. |
---|
1643 | |
---|
1644 | The following example shows the labelled ©break© specifying which control structure is the target for exit: |
---|
1645 | \begin{quote2} |
---|
1646 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
1647 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ |
---|
1648 | \begin{lstlisting} |
---|
1649 | ®L1:® { |
---|
1650 | ... §declarations§ ... |
---|
1651 | ®L2:® switch ( ... ) { |
---|
1652 | case 3: |
---|
1653 | ®L3:® if ( ... ) { |
---|
1654 | ®L4:® for ( ... ) { |
---|
1655 | ... break ®L1®; ... // exit compound statement |
---|
1656 | ... break ®L2®; ... // exit switch |
---|
1657 | ... break ®L3®; ... // exit if |
---|
1658 | ... break ®L4®; ... // exit loop |
---|
1659 | } // for |
---|
1660 | } else { |
---|
1661 | ... break ®L3®; ... // exit if |
---|
1662 | } // if |
---|
1663 | } // switch |
---|
1664 | } // compound |
---|
1665 | \end{lstlisting} |
---|
1666 | & |
---|
1667 | \begin{lstlisting} |
---|
1668 | { |
---|
1669 | ... §declarations§ ... |
---|
1670 | switch ( ... ) { |
---|
1671 | case 3: |
---|
1672 | if ( ... ) { |
---|
1673 | for ( ... ) { |
---|
1674 | ... goto L1; ... |
---|
1675 | ... goto L2; ... |
---|
1676 | ... goto L3; ... |
---|
1677 | ... goto L4; ... |
---|
1678 | } L4: ; |
---|
1679 | } else { |
---|
1680 | ... goto L3; ... |
---|
1681 | } L3: ; |
---|
1682 | } L2: ; |
---|
1683 | } L1: ; |
---|
1684 | \end{lstlisting} |
---|
1685 | \end{tabular} |
---|
1686 | \end{quote2} |
---|
1687 | The innermost loop has four exit points, which cause termination of one or more of the four \Index{nested control structure}s. |
---|
1688 | |
---|
1689 | Both ©continue© and ©break© with target labels are simply a ©goto©\index{goto@©goto©!restricted} restricted in the following ways: |
---|
1690 | \begin{itemize} |
---|
1691 | \item |
---|
1692 | They cannot be used to create a loop. |
---|
1693 | This means that only the looping construct can be used to create a loop. |
---|
1694 | This restriction is important since all situations that can result in repeated execution of statements in a program are clearly delineated. |
---|
1695 | \item |
---|
1696 | Since they always transfer out of containing control structures, they cannot be used to branch into a control structure. |
---|
1697 | \end{itemize} |
---|
1698 | The advantage of the labelled ©continue©/©break© is allowing static multi-level exits without having to use the ©goto© statement and tying control flow to the target control structure rather than an arbitrary point in a program. |
---|
1699 | Furthermore, the location of the label at the \emph{beginning} of the target control structure informs the reader that complex control-flow is occurring in the body of the control structure. |
---|
1700 | With ©goto©, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader. |
---|
1701 | Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs. |
---|
1702 | The implicit targets of the current ©continue© and ©break©, i.e., the closest enclosing loop or ©switch©, change as certain constructs are added or removed. |
---|
1703 | |
---|
1704 | |
---|
1705 | \section{Switch Statement} |
---|
1706 | |
---|
1707 | C allows a number of questionable forms for the ©switch© statement: |
---|
1708 | \begin{enumerate} |
---|
1709 | \item |
---|
1710 | By default, the end of a ©case© clause\footnote{ |
---|
1711 | In this section, the term \emph{case clause} refers to either a ©case© or ©default© clause.} |
---|
1712 | \emph{falls through} to the next ©case© clause in the ©switch© statement; |
---|
1713 | to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©: |
---|
1714 | \begin{lstlisting} |
---|
1715 | switch ( i ) { |
---|
1716 | case 1: |
---|
1717 | ... |
---|
1718 | // fall-through |
---|
1719 | case 2: |
---|
1720 | ... |
---|
1721 | break; // exit switch statement |
---|
1722 | } |
---|
1723 | \end{lstlisting} |
---|
1724 | The ability to fall-through to the next clause \emph{is} a useful form of control flow, specifically when a sequence of case actions compound: |
---|
1725 | \begin{quote2} |
---|
1726 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
1727 | \begin{lstlisting} |
---|
1728 | switch ( argc ) { |
---|
1729 | case 3: |
---|
1730 | // open output file |
---|
1731 | // fall-through |
---|
1732 | case 2: |
---|
1733 | // open input file |
---|
1734 | break; // exit switch statement |
---|
1735 | default: |
---|
1736 | // usage message |
---|
1737 | } |
---|
1738 | \end{lstlisting} |
---|
1739 | & |
---|
1740 | \begin{lstlisting} |
---|
1741 | |
---|
1742 | if ( argc == 3 ) { |
---|
1743 | // open output file |
---|
1744 | ®// open input file |
---|
1745 | ®} else if ( argc == 2 ) { |
---|
1746 | ®// open input file |
---|
1747 | |
---|
1748 | ®} else { |
---|
1749 | // usage message |
---|
1750 | } |
---|
1751 | \end{lstlisting} |
---|
1752 | \end{tabular} |
---|
1753 | \end{quote2} |
---|
1754 | In this example, case 2 is always done if case 3 is done. |
---|
1755 | This control flow is difficult to simulate with if statements or a ©switch© statement without fall-through as code must be duplicated or placed in a separate routine. |
---|
1756 | C also uses fall-through to handle multiple case-values resulting in the same action: |
---|
1757 | \begin{lstlisting} |
---|
1758 | switch ( i ) { |
---|
1759 | case 1: case 3: case 5: // odd values |
---|
1760 | // same action |
---|
1761 | break; |
---|
1762 | case 2: case 4: case 6: // even values |
---|
1763 | // same action |
---|
1764 | break; |
---|
1765 | } |
---|
1766 | \end{lstlisting} |
---|
1767 | However, this situation is handled in other languages without fall-through by allowing a list of case values. |
---|
1768 | While fall-through itself is not a problem, the problem occurs when fall-through is the default, as this semantics is unintuitive to many programmers and is different from virtually all other programming languages with a ©switch© statement. |
---|
1769 | Hence, default fall-through semantics results in a large number of programming errors as programmers often forget the ©break© statement at the end of a ©case© clause, resulting in inadvertent fall-through. |
---|
1770 | |
---|
1771 | \item |
---|
1772 | It is possible to place ©case© clauses on statements nested \emph{within} the body of the ©switch© statement: |
---|
1773 | \begin{lstlisting} |
---|
1774 | switch ( i ) { |
---|
1775 | case 0: |
---|
1776 | if ( j < k ) { |
---|
1777 | ... |
---|
1778 | ®case 1:® // transfer into "if" statement |
---|
1779 | ... |
---|
1780 | } // if |
---|
1781 | case 2: |
---|
1782 | while ( j < 5 ) { |
---|
1783 | ... |
---|
1784 | ®case 3:® // transfer into "while" statement |
---|
1785 | ... |
---|
1786 | } // while |
---|
1787 | } // switch |
---|
1788 | \end{lstlisting} |
---|
1789 | The problem with this usage is branching into control structures, which is known to cause both comprehension and technical difficulties. |
---|
1790 | The comprehension problem occurs from the inability to determine how control reaches a particular point due to the number of branches leading to it. |
---|
1791 | The technical problem results from the inability to ensure allocation and initialization of variables when blocks are not entered at the beginning. |
---|
1792 | Often transferring into a block can bypass variable declaration and/or its initialization, which results in subsequent errors. |
---|
1793 | There are virtually no positive arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it. |
---|
1794 | Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}: |
---|
1795 | \begin{lstlisting} |
---|
1796 | register int n = (count + 7) / 8; |
---|
1797 | switch ( count % 8 ) { |
---|
1798 | case 0: do{ *to = *from++; |
---|
1799 | case 7: *to = *from++; |
---|
1800 | case 6: *to = *from++; |
---|
1801 | case 5: *to = *from++; |
---|
1802 | case 4: *to = *from++; |
---|
1803 | case 3: *to = *from++; |
---|
1804 | case 2: *to = *from++; |
---|
1805 | case 1: *to = *from++; |
---|
1806 | } while ( --n > 0 ); |
---|
1807 | } |
---|
1808 | \end{lstlisting} |
---|
1809 | which unrolls a loop N times (N = 8 above) and uses the ©switch© statement to deal with any iterations not a multiple of N. |
---|
1810 | While efficient, this sort of special purpose usage is questionable: |
---|
1811 | \begin{quote} |
---|
1812 | Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and revulsion at this |
---|
1813 | discovery.~\cite{Duff83} |
---|
1814 | \end{quote} |
---|
1815 | \item |
---|
1816 | It is possible to place the ©default© clause anywhere in the list of labelled clauses for a ©switch© statement, rather than only at the end. |
---|
1817 | Virtually all programming languages with a ©switch© statement require the ©default© clause to appear last in the case-clause list. |
---|
1818 | The logic for this semantics is that after checking all the ©case© clauses without success, the ©default© clause is selected; |
---|
1819 | hence, physically placing the ©default© clause at the end of the ©case© clause list matches with this semantics. |
---|
1820 | This physical placement can be compared to the physical placement of an ©else© clause at the end of a series of connected ©if©/©else© statements. |
---|
1821 | |
---|
1822 | \item |
---|
1823 | It is possible to place unreachable code at the start of a ©switch© statement, as in: |
---|
1824 | \begin{lstlisting} |
---|
1825 | switch ( x ) { |
---|
1826 | ®int y = 1;® §\C{// unreachable initialization}§ |
---|
1827 | ®x = 7;® §\C{// unreachable code without label/branch}§ |
---|
1828 | case 3: ... |
---|
1829 | ... |
---|
1830 | ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§ |
---|
1831 | z = 2; |
---|
1832 | case 3: |
---|
1833 | ®x = z;® §\C{// without fall through, z is uninitialized}§ |
---|
1834 | } |
---|
1835 | \end{lstlisting} |
---|
1836 | While the declaration of the local variable ©y© is useful with a scope across all ©case© clauses, the initialization for such a variable is defined to never be executed because control always transfers over it. |
---|
1837 | Furthermore, any statements before the first ©case© clause can only be executed if labelled and transferred to using a ©goto©, either from outside or inside of the ©switch©, both of which are problematic. |
---|
1838 | As well, the declaration of ©z© cannot occur after the ©case© because a label can only be attached to a statement, and without a fall through to case 3, ©z© is uninitialized. |
---|
1839 | The key observation is that the ©switch© statement branches into control structure, i.e., there are multiple entry points into its statement body. |
---|
1840 | \end{enumerate} |
---|
1841 | |
---|
1842 | Before discussing potential language changes to deal with these problems, it is worth observing that in a typical C program: |
---|
1843 | \begin{itemize} |
---|
1844 | \item |
---|
1845 | the number of ©switch© statements is small, |
---|
1846 | \item |
---|
1847 | most ©switch© statements are well formed (i.e., no \Index*{Duff's device}), |
---|
1848 | \item |
---|
1849 | the ©default© clause is usually written as the last case-clause, |
---|
1850 | \item |
---|
1851 | and there is only a medium amount of fall-through from one ©case© clause to the next, and most of these result from a list of case values executing common code, rather than a sequence of case actions that compound. |
---|
1852 | \end{itemize} |
---|
1853 | These observations help to put the \CFA changes to the ©switch© into perspective. |
---|
1854 | \begin{enumerate} |
---|
1855 | \item |
---|
1856 | Eliminating default fall-through has the greatest potential for affecting existing code. |
---|
1857 | However, even if fall-through is removed, most ©switch© statements would continue to work because of the explicit transfers already present at the end of each ©case© clause, the common placement of the ©default© clause at the end of the case list, and the most common use of fall-through, i.e., a list of ©case© clauses executing common code, \eg: |
---|
1858 | \begin{lstlisting} |
---|
1859 | case 1: case 2: case 3: ... |
---|
1860 | \end{lstlisting} |
---|
1861 | still works. |
---|
1862 | Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments. |
---|
1863 | Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, e.g.: |
---|
1864 | \begin{lstlisting} |
---|
1865 | ®choose® ( i ) { |
---|
1866 | case 1: case 2: case 3: |
---|
1867 | ... |
---|
1868 | ®// implicit end of switch (break) |
---|
1869 | ®case 5: |
---|
1870 | ... |
---|
1871 | ®fallthru®; §\C{// explicit fall through}§ |
---|
1872 | case 7: |
---|
1873 | ... |
---|
1874 | ®break® §\C{// explicit end of switch}§ |
---|
1875 | default: |
---|
1876 | j = 3; |
---|
1877 | } |
---|
1878 | \end{lstlisting} |
---|
1879 | Like the ©switch© statement, the ©choose© statement retains the fall-through semantics for a list of ©case© clauses; |
---|
1880 | the implicit ©break© is applied only at the end of the \emph{statements} following a ©case© clause. |
---|
1881 | The explicit ©fallthru© is retained because it is a C-idiom most C programmers expect, and its absence might discourage programmers from using the ©choose© statement. |
---|
1882 | As well, allowing an explicit ©break© from the ©choose© is a carry over from the ©switch© statement, and expected by C programmers. |
---|
1883 | \item |
---|
1884 | \Index*{Duff's device} is eliminated from both ©switch© and ©choose© statements, and only invalidates a small amount of very questionable code. |
---|
1885 | Hence, the ©case© clause must appear at the same nesting level as the ©switch©/©choose© body, as is done in most other programming languages with ©switch© statements. |
---|
1886 | \item |
---|
1887 | The issue of ©default© at locations other than at the end of the cause clause can be solved by using good programming style, and there are a few reasonable situations involving fall-through where the ©default© clause needs to appear is locations other than at the end. |
---|
1888 | Therefore, no change is made for this issue. |
---|
1889 | \item |
---|
1890 | Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and associated initialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{ |
---|
1891 | Essentially, these declarations are hoisted before the ©switch©/©choose© statement and both declarations and statement are surrounded by a compound statement.} and precluding statements before the first ©case© clause. |
---|
1892 | Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound. |
---|
1893 | \begin{lstlisting} |
---|
1894 | switch ( x ) { |
---|
1895 | ®int i = 0;® §\C{// allowed only at start}§ |
---|
1896 | case 0: |
---|
1897 | ... |
---|
1898 | ®int j = 0;® §\C{// disallowed}§ |
---|
1899 | case 1: |
---|
1900 | { |
---|
1901 | ®int k = 0;® §\C{// allowed at different nesting levels}§ |
---|
1902 | ... |
---|
1903 | } |
---|
1904 | ... |
---|
1905 | } |
---|
1906 | \end{lstlisting} |
---|
1907 | \end{enumerate} |
---|
1908 | |
---|
1909 | |
---|
1910 | \section{Case Clause} |
---|
1911 | |
---|
1912 | C restricts the ©case© clause of a ©switch© statement to a single value. |
---|
1913 | For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values. |
---|
1914 | Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C. |
---|
1915 | Therefore, the ©case© clause is extended with a list of values, as in: |
---|
1916 | \begin{quote2} |
---|
1917 | \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} |
---|
1918 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ |
---|
1919 | \begin{lstlisting} |
---|
1920 | switch ( i ) { |
---|
1921 | case ®1, 3, 5®: |
---|
1922 | ... |
---|
1923 | case ®2, 4, 6®: |
---|
1924 | ... |
---|
1925 | } |
---|
1926 | \end{lstlisting} |
---|
1927 | & |
---|
1928 | \begin{lstlisting} |
---|
1929 | switch ( i ) { |
---|
1930 | case 1: case 3 : case 5: |
---|
1931 | ... |
---|
1932 | case 2: case 4 : case 6: |
---|
1933 | ... |
---|
1934 | } |
---|
1935 | \end{lstlisting} |
---|
1936 | & |
---|
1937 | \begin{lstlisting} |
---|
1938 | |
---|
1939 | // odd values |
---|
1940 | |
---|
1941 | // even values |
---|
1942 | |
---|
1943 | |
---|
1944 | \end{lstlisting} |
---|
1945 | \end{tabular} |
---|
1946 | \end{quote2} |
---|
1947 | In addition, two forms of subranges are allowed to specify case values: a new \CFA form and an existing GNU C form.\footnote{ |
---|
1948 | The GNU C form \emph{requires} spaces around the ellipse.} |
---|
1949 | \begin{quote2} |
---|
1950 | \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} |
---|
1951 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{GNU C}} \\ |
---|
1952 | \begin{lstlisting} |
---|
1953 | switch ( i ) { |
---|
1954 | case ®1~5:® |
---|
1955 | ... |
---|
1956 | case ®10~15:® |
---|
1957 | ... |
---|
1958 | } |
---|
1959 | \end{lstlisting} |
---|
1960 | & |
---|
1961 | \begin{lstlisting} |
---|
1962 | switch ( i ) |
---|
1963 | case ®1 ... 5®: |
---|
1964 | ... |
---|
1965 | case ®10 ... 15®: |
---|
1966 | ... |
---|
1967 | } |
---|
1968 | \end{lstlisting} |
---|
1969 | & |
---|
1970 | \begin{lstlisting} |
---|
1971 | |
---|
1972 | // 1, 2, 3, 4, 5 |
---|
1973 | |
---|
1974 | // 10, 11, 12, 13, 14, 15 |
---|
1975 | |
---|
1976 | |
---|
1977 | \end{lstlisting} |
---|
1978 | \end{tabular} |
---|
1979 | \end{quote2} |
---|
1980 | Lists of subranges are also allowed. |
---|
1981 | \begin{lstlisting} |
---|
1982 | case ®1~5, 12~21, 35~42®: |
---|
1983 | \end{lstlisting} |
---|
1984 | |
---|
1985 | |
---|
1986 | \section{Exception Handling} |
---|
1987 | |
---|
1988 | Exception handling provides two mechanism: change of control flow from a raise to a handler, and communication from the raise to the handler. |
---|
1989 | \begin{lstlisting} |
---|
1990 | exception void h( int i ); |
---|
1991 | exception int h( int i, double d ); |
---|
1992 | |
---|
1993 | void f(...) { |
---|
1994 | ... throw h( 3 ); |
---|
1995 | ... i = resume h( 3, 5.1 ); |
---|
1996 | } |
---|
1997 | |
---|
1998 | try { |
---|
1999 | f(...); |
---|
2000 | } catch h( int w ) { |
---|
2001 | // reset |
---|
2002 | } resume h( int p, double x ) { |
---|
2003 | return 17; // recover |
---|
2004 | } finally { |
---|
2005 | } |
---|
2006 | \end{lstlisting} |
---|
2007 | So the type raised would be the mangled name of the exception prototype and that name would be matched at the handler clauses by comparing the strings. |
---|
2008 | The arguments for the call would have to be packed in a message and unpacked at handler clause and then a call made to the handler. |
---|
2009 | |
---|
2010 | |
---|
2011 | \section{Types} |
---|
2012 | |
---|
2013 | \subsection{Type Definitions} |
---|
2014 | |
---|
2015 | \CFA allows users to define new types using the keyword type. |
---|
2016 | |
---|
2017 | \begin{lstlisting} |
---|
2018 | // SensorValue is a distinct type and represented as an int |
---|
2019 | type SensorValue = int; |
---|
2020 | \end{lstlisting} |
---|
2021 | |
---|
2022 | A type definition is different from a typedef in C because a typedef just creates an alias for a type, while Do.s type definition creates a distinct type. |
---|
2023 | This means that users can define distinct function overloads for the new type (see Overloading for more information). |
---|
2024 | For example: |
---|
2025 | |
---|
2026 | \begin{lstlisting} |
---|
2027 | type SensorValue = int; |
---|
2028 | void printValue(int v) {...} |
---|
2029 | void printValue(SensorValue v) {...} |
---|
2030 | void process(int v) {...} |
---|
2031 | |
---|
2032 | SensorValue s = ...; |
---|
2033 | |
---|
2034 | printValue(s); // calls version with SensorValue argument |
---|
2035 | |
---|
2036 | printValue((int) s); // calls version with int argument |
---|
2037 | |
---|
2038 | process(s); // implicit conversion to int |
---|
2039 | \end{lstlisting} |
---|
2040 | |
---|
2041 | If SensorValue was defined with a typedef, then these two print functions would not have unique signatures. |
---|
2042 | This can be very useful to create a distinct type that has the same representation as another type. |
---|
2043 | |
---|
2044 | The compiler will assume it can safely convert from the old type to the new type, implicitly. |
---|
2045 | Users may override this and define a function that must be called to convert from one type to another. |
---|
2046 | |
---|
2047 | \begin{lstlisting} |
---|
2048 | type SensorValue = int; |
---|
2049 | // ()? is the overloaded conversion operator identifier |
---|
2050 | // This function converts an int to a SensorValue |
---|
2051 | SensorValue ()?(int val) { |
---|
2052 | ... |
---|
2053 | } |
---|
2054 | void process(int v) {...} |
---|
2055 | |
---|
2056 | SensorValue s = ...; |
---|
2057 | process(s); // implicit call to conversion operator |
---|
2058 | \end{lstlisting} |
---|
2059 | |
---|
2060 | In many cases, it is not desired for the compiler to do this implicit conversion. |
---|
2061 | To avoid that, the user can use the explicit modifier on the conversion operator. |
---|
2062 | Any places where the conversion is needed but not explicit (with a cast), will result in a compile-time error. |
---|
2063 | |
---|
2064 | \begin{lstlisting} |
---|
2065 | type SensorValue = int; |
---|
2066 | |
---|
2067 | // conversion from int to SensorValue; must be explicit |
---|
2068 | explicit SensorValue ()?(int val) { |
---|
2069 | ... |
---|
2070 | } |
---|
2071 | |
---|
2072 | void process(int v) {...} |
---|
2073 | |
---|
2074 | SensorValue s = ...; |
---|
2075 | process(s); // implicit cast to int: compile-time error |
---|
2076 | process((int) s); // explicit cast to int: calls conversion func |
---|
2077 | \end{lstlisting} |
---|
2078 | |
---|
2079 | The conversion may not require any code, but still need to be explicit; in that case, the syntax can be simplified to: |
---|
2080 | \begin{lstlisting} |
---|
2081 | type SensorValue = int; |
---|
2082 | explicit SensorValue ()?(int); |
---|
2083 | void process(int v) {...} |
---|
2084 | |
---|
2085 | SensorValue s = ...; |
---|
2086 | process(s); // compile-time error |
---|
2087 | process((int) s); // type is converted, no function is called |
---|
2088 | \end{lstlisting} |
---|
2089 | |
---|
2090 | |
---|
2091 | \subsection{Structures} |
---|
2092 | |
---|
2093 | Structures in \CFA are basically the same as structures in C. |
---|
2094 | A structure is defined with the same syntax as in C. |
---|
2095 | When referring to a structure in \CFA, users may omit the struct keyword. |
---|
2096 | \begin{lstlisting} |
---|
2097 | struct Point { |
---|
2098 | double x; |
---|
2099 | double y; |
---|
2100 | }; |
---|
2101 | |
---|
2102 | Point p = {0.0, 0.0}; |
---|
2103 | \end{lstlisting} |
---|
2104 | |
---|
2105 | \CFA does not support inheritance among types, but instead uses composition to enable reuse of structure fields. |
---|
2106 | Composition is achieved by embedding one type into another. |
---|
2107 | When type A is embedded in type B, an object with type B may be used as an object of type A, and the fields of type A are directly accessible. |
---|
2108 | Embedding types is achieved using anonymous members. |
---|
2109 | For example, using Point from above: |
---|
2110 | \begin{lstlisting} |
---|
2111 | void foo(Point p); |
---|
2112 | |
---|
2113 | struct ColoredPoint { |
---|
2114 | Point; // anonymous member (no identifier) |
---|
2115 | int Color; |
---|
2116 | }; |
---|
2117 | ... |
---|
2118 | ColoredPoint cp = ...; |
---|
2119 | cp.x = 10.3; // x from Point is accessed directly |
---|
2120 | cp.color = 0x33aaff; // color is accessed normally |
---|
2121 | foo(cp); // cp can be used directly as a Point |
---|
2122 | \end{lstlisting} |
---|
2123 | |
---|
2124 | |
---|
2125 | \subsection{Constructors and Destructors} |
---|
2126 | |
---|
2127 | \CFA supports C initialization of structures, but it also adds constructors for more advanced initialization. |
---|
2128 | Additionally, \CFA adds destructors that are called when a variable is de-allocated (variable goes out of scope or object is deleted). |
---|
2129 | These functions take a reference to the structure as a parameter (see References for more information). |
---|
2130 | |
---|
2131 | \begin{figure} |
---|
2132 | \begin{lstlisting} |
---|
2133 | struct Widget { |
---|
2134 | int id; |
---|
2135 | float size; |
---|
2136 | Parts *optionalParts; |
---|
2137 | }; |
---|
2138 | |
---|
2139 | // ?{} is the constructor operator identifier |
---|
2140 | // The first argument is a reference to the type to initialize |
---|
2141 | // Subsequent arguments can be specified for initialization |
---|
2142 | |
---|
2143 | void ?{}(Widget &w) { // default constructor |
---|
2144 | w.id = -1; |
---|
2145 | w.size = 0.0; |
---|
2146 | w.optionalParts = 0; |
---|
2147 | } |
---|
2148 | |
---|
2149 | // constructor with values (does not need to include all fields) |
---|
2150 | void ?{}(Widget &w, int id, float size) { |
---|
2151 | w.id = id; |
---|
2152 | w.size = size; |
---|
2153 | w.optionalParts = 0; |
---|
2154 | } |
---|
2155 | |
---|
2156 | // ^? is the destructor operator identifier |
---|
2157 | void ^?(Widget &w) { // destructor |
---|
2158 | w.id = 0; |
---|
2159 | w.size = 0.0; |
---|
2160 | if (w.optionalParts != 0) { |
---|
2161 | // This is the only pointer to optionalParts, free it |
---|
2162 | free(w.optionalParts); |
---|
2163 | w.optionalParts = 0; |
---|
2164 | } |
---|
2165 | } |
---|
2166 | |
---|
2167 | Widget baz; // reserve space only |
---|
2168 | Widget foo{}; // calls default constructor |
---|
2169 | Widget bar{23, 2.45}; // calls constructor with values |
---|
2170 | baz{24, 0.91}; // calls constructor with values |
---|
2171 | ?{}(baz, 24, 0.91}; // explicit call to constructor |
---|
2172 | ^bar; // explicit call to destructor |
---|
2173 | ^?(bar); // explicit call to destructor |
---|
2174 | \end{lstlisting} |
---|
2175 | \caption{Constructors and Destructors} |
---|
2176 | \end{figure} |
---|
2177 | |
---|
2178 | |
---|
2179 | \begin{comment} |
---|
2180 | \section{References} |
---|
2181 | |
---|
2182 | |
---|
2183 | By introducing references in parameter types, users are given an easy way to pass a value by reference, without the need for NULL pointer checks. |
---|
2184 | In structures, a reference can replace a pointer to an object that should always have a valid value. |
---|
2185 | When a structure contains a reference, all of its constructors must initialize the reference and all instances of this structure must initialize it upon definition. |
---|
2186 | |
---|
2187 | The syntax for using references in \CFA is the same as \CC with the exception of reference initialization. |
---|
2188 | Use ©&© to specify a reference, and access references just like regular objects, not like pointers (use dot notation to access fields). |
---|
2189 | When initializing a reference, \CFA uses a different syntax which differentiates reference initialization from assignment to a reference. |
---|
2190 | The ©&© is used on both sides of the expression to clarify that the address of the reference is being set to the address of the variable to which it refers. |
---|
2191 | \end{comment} |
---|
2192 | |
---|
2193 | |
---|
2194 | \section{Overloading} |
---|
2195 | |
---|
2196 | Overloading refers to the capability of a programmer to define and use multiple objects in a program with the same name. |
---|
2197 | In \CFA, a declaration may overload declarations from outer scopes with the same name, instead of hiding them as is the case in C. |
---|
2198 | This may cause identical C and \CFA programs to behave differently. |
---|
2199 | The compiler selects the appropriate object (overload resolution) based on context information at the place where it is used. |
---|
2200 | Overloading allows programmers to give functions with different signatures but similar semantics the same name, simplifying the interface to users. |
---|
2201 | Disadvantages of overloading are that it can be used to give functions with different semantics the same name, causing confusion, or that the compiler may resolve to a different function from what the programmer expected. |
---|
2202 | \CFA allows overloading of functions, operators, variables, and even the constants 0 and 1. |
---|
2203 | |
---|
2204 | The compiler follows some overload resolution rules to determine the best interpretation of all of these overloads. |
---|
2205 | The best valid interpretations are the valid interpretations that use the fewest unsafe conversions. |
---|
2206 | Of these, the best are those where the functions and objects involved are the least polymorphic. |
---|
2207 | Of these, the best have the lowest total conversion cost, including all implicit conversions in the argument expressions. |
---|
2208 | Of these, the best have the highest total conversion cost for the implicit conversions (if any) applied to the argument expressions. |
---|
2209 | If there is no single best valid interpretation, or if the best valid interpretation is ambiguous, then the resulting interpretation is ambiguous. |
---|
2210 | For details about type inference and overload resolution, please see the \CFA Language Specification. |
---|
2211 | \begin{lstlisting} |
---|
2212 | int foo(int a, int b) { |
---|
2213 | float sum = 0.0; |
---|
2214 | float special = 1.0; |
---|
2215 | { |
---|
2216 | int sum = 0; |
---|
2217 | // both the float and int versions of sum are available |
---|
2218 | float special = 4.0; |
---|
2219 | // this inner special hides the outer version |
---|
2220 | ... |
---|
2221 | } |
---|
2222 | ... |
---|
2223 | } |
---|
2224 | \end{lstlisting} |
---|
2225 | |
---|
2226 | |
---|
2227 | \subsection{Overloaded Constant} |
---|
2228 | |
---|
2229 | The constants 0 and 1 have special meaning. |
---|
2230 | In \CFA, as in C, all scalar types can be incremented and |
---|
2231 | decremented, which is defined in terms of adding or subtracting 1. |
---|
2232 | The operations ©&&©, ©||©, and ©!© can be applied to any scalar arguments and are defined in terms of comparison against 0 (ex. ©(a && b)© becomes ©(a != 0 && b != 0)©). |
---|
2233 | |
---|
2234 | 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. |
---|
2235 | 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. |
---|
2236 | Defining special constants for a user-defined type is more efficient than defining a conversion to the type from ©_Bool©. |
---|
2237 | |
---|
2238 | Why just 0 and 1? Why not other integers? No other integers have special status in C. |
---|
2239 | A facility that let programmers declare specific constants..const Rational 12., for instance. would not be much of an improvement. |
---|
2240 | Some facility for defining the creation of values of programmer-defined types from arbitrary integer tokens would be needed. |
---|
2241 | The complexity of such a feature does not seem worth the gain. |
---|
2242 | |
---|
2243 | For example, to define the constants for a complex type, the programmer would define the following: |
---|
2244 | |
---|
2245 | \begin{lstlisting} |
---|
2246 | struct Complex { |
---|
2247 | double real; |
---|
2248 | double imaginary; |
---|
2249 | } |
---|
2250 | |
---|
2251 | const Complex 0 = {0, 0}; |
---|
2252 | const Complex 1 = {1, 0}; |
---|
2253 | ... |
---|
2254 | |
---|
2255 | Complex a = 0; |
---|
2256 | ... |
---|
2257 | |
---|
2258 | a++; |
---|
2259 | ... |
---|
2260 | if (a) { // same as if (a == 0) |
---|
2261 | ... |
---|
2262 | } |
---|
2263 | \end{lstlisting} |
---|
2264 | |
---|
2265 | |
---|
2266 | \subsection{Variable Overloading} |
---|
2267 | |
---|
2268 | The overload rules of \CFA allow a programmer to define multiple variables with the same name, but different types. |
---|
2269 | Allowing overloading of variable names enables programmers to use the same name across multiple types, simplifying naming conventions and is compatible with the other overloading that is allowed. |
---|
2270 | For example, a developer may want to do the following: |
---|
2271 | \begin{lstlisting} |
---|
2272 | int pi = 3; |
---|
2273 | float pi = 3.14; |
---|
2274 | char pi = .p.; |
---|
2275 | \end{lstlisting} |
---|
2276 | |
---|
2277 | |
---|
2278 | \subsection{Function Overloading} |
---|
2279 | |
---|
2280 | Overloaded functions in \CFA are resolved based on the number and type of arguments, type of return value, and the level of specialization required (specialized functions are preferred over generic). |
---|
2281 | |
---|
2282 | The examples below give some basic intuition about how the resolution works. |
---|
2283 | \begin{lstlisting} |
---|
2284 | // Choose the one with less conversions |
---|
2285 | int doSomething(int value) {...} // option 1 |
---|
2286 | int doSomething(short value) {...} // option 2 |
---|
2287 | |
---|
2288 | int a, b = 4; |
---|
2289 | short c = 2; |
---|
2290 | |
---|
2291 | a = doSomething(b); // chooses option 1 |
---|
2292 | a = doSomething(c); // chooses option 2 |
---|
2293 | |
---|
2294 | // Choose the specialized version over the generic |
---|
2295 | |
---|
2296 | generic(type T) |
---|
2297 | T bar(T rhs, T lhs) {...} // option 3 |
---|
2298 | float bar(float rhs, float lhs){...} // option 4 |
---|
2299 | float a, b, c; |
---|
2300 | double d, e, f; |
---|
2301 | c = bar(a, b); // chooses option 4 |
---|
2302 | |
---|
2303 | // specialization is preferred over unsafe conversions |
---|
2304 | |
---|
2305 | f = bar(d, e); // chooses option 5 |
---|
2306 | \end{lstlisting} |
---|
2307 | |
---|
2308 | |
---|
2309 | \subsection{Operator Overloading} |
---|
2310 | |
---|
2311 | \CFA also allows operators to be overloaded, to simplify the use of user-defined types. |
---|
2312 | Overloading the operators allows the users to use the same syntax for their custom types that they use for built-in types, increasing readability and improving productivity. |
---|
2313 | \CFA uses the following special identifiers to name overloaded operators: |
---|
2314 | |
---|
2315 | \begin{table}[hbt] |
---|
2316 | \hfil |
---|
2317 | \begin{tabular}[t]{ll} |
---|
2318 | %identifier & operation \\ \hline |
---|
2319 | ©?[?]© & subscripting \impl{?[?]}\\ |
---|
2320 | ©?()© & function call \impl{?()}\\ |
---|
2321 | ©?++© & postfix increment \impl{?++}\\ |
---|
2322 | ©?--© & postfix decrement \impl{?--}\\ |
---|
2323 | ©++?© & prefix increment \impl{++?}\\ |
---|
2324 | ©--?© & prefix decrement \impl{--?}\\ |
---|
2325 | ©*?© & dereference \impl{*?}\\ |
---|
2326 | ©+?© & unary plus \impl{+?}\\ |
---|
2327 | ©-?© & arithmetic negation \impl{-?}\\ |
---|
2328 | ©~?© & bitwise negation \impl{~?}\\ |
---|
2329 | ©!?© & logical complement \impl{"!?}\\ |
---|
2330 | ©?*?© & multiplication \impl{?*?}\\ |
---|
2331 | ©?/?© & division \impl{?/?}\\ |
---|
2332 | \end{tabular}\hfil |
---|
2333 | \begin{tabular}[t]{ll} |
---|
2334 | %identifier & operation \\ \hline |
---|
2335 | ©?%?© & remainder \impl{?%?}\\ |
---|
2336 | ©?+?© & addition \impl{?+?}\\ |
---|
2337 | ©?-?© & subtraction \impl{?-?}\\ |
---|
2338 | ©?<<?© & left shift \impl{?<<?}\\ |
---|
2339 | ©?>>?© & right shift \impl{?>>?}\\ |
---|
2340 | ©?<?© & less than \impl{?<?}\\ |
---|
2341 | ©?<=?© & less than or equal \impl{?<=?}\\ |
---|
2342 | ©?>=?© & greater than or equal \impl{?>=?}\\ |
---|
2343 | ©?>?© & greater than \impl{?>?}\\ |
---|
2344 | ©?==?© & equality \impl{?==?}\\ |
---|
2345 | ©?!=?© & inequality \impl{?"!=?}\\ |
---|
2346 | ©?&?© & bitwise AND \impl{?&?}\\ |
---|
2347 | \end{tabular}\hfil |
---|
2348 | \begin{tabular}[t]{ll} |
---|
2349 | %identifier & operation \\ \hline |
---|
2350 | ©?^?© & exclusive OR \impl{?^?}\\ |
---|
2351 | ©?|?© & inclusive OR \impl{?"|?}\\ |
---|
2352 | ©?=?© & simple assignment \impl{?=?}\\ |
---|
2353 | ©?*=?© & multiplication assignment \impl{?*=?}\\ |
---|
2354 | ©?/=?© & division assignment \impl{?/=?}\\ |
---|
2355 | ©?%=?© & remainder assignment \impl{?%=?}\\ |
---|
2356 | ©?+=?© & addition assignment \impl{?+=?}\\ |
---|
2357 | ©?-=?© & subtraction assignment \impl{?-=?}\\ |
---|
2358 | ©?<<=?© & left-shift assignment \impl{?<<=?}\\ |
---|
2359 | ©?>>=?© & right-shift assignment \impl{?>>=?}\\ |
---|
2360 | ©?&=?© & bitwise AND assignment \impl{?&=?}\\ |
---|
2361 | ©?^=?© & exclusive OR assignment \impl{?^=?}\\ |
---|
2362 | ©?|=?© & inclusive OR assignment \impl{?"|=?}\\ |
---|
2363 | \end{tabular} |
---|
2364 | \hfil |
---|
2365 | \caption{Operator Identifiers} |
---|
2366 | \label{opids} |
---|
2367 | \end{table} |
---|
2368 | |
---|
2369 | These identifiers are defined such that the question marks in the name identify the location of the operands. |
---|
2370 | These operands represent the parameters to the functions, and define how the operands are mapped to the function call. |
---|
2371 | For example, ©a + b© becomes ©?+?(a, b)©. |
---|
2372 | |
---|
2373 | In the example below, a new type, myComplex, is defined with an overloaded constructor, + operator, and string operator. |
---|
2374 | These operators are called using the normal C syntax. |
---|
2375 | |
---|
2376 | \begin{lstlisting} |
---|
2377 | type Complex = struct { // define a Complex type |
---|
2378 | double real; |
---|
2379 | double imag; |
---|
2380 | } |
---|
2381 | |
---|
2382 | // Constructor with default values |
---|
2383 | |
---|
2384 | void ?{}(Complex &c, double real = 0.0, double imag = 0.0) { |
---|
2385 | c.real = real; |
---|
2386 | c.imag = imag; |
---|
2387 | } |
---|
2388 | |
---|
2389 | Complex ?+?(Complex lhs, Complex rhs) { |
---|
2390 | Complex sum; |
---|
2391 | sum.real = lhs.real + rhs.real; |
---|
2392 | sum.imag = lhs.imag + rhs.imag; |
---|
2393 | return sum; |
---|
2394 | } |
---|
2395 | |
---|
2396 | String ()?(const Complex c) { |
---|
2397 | // use the string conversions for the structure members |
---|
2398 | return (String)c.real + . + . + (String)c.imag + .i.; |
---|
2399 | } |
---|
2400 | ... |
---|
2401 | |
---|
2402 | Complex a, b, c = {1.0}; // constructor for c w/ default imag |
---|
2403 | ... |
---|
2404 | c = a + b; |
---|
2405 | print(.sum = . + c); |
---|
2406 | \end{lstlisting} |
---|
2407 | |
---|
2408 | |
---|
2409 | \section{Auto Type-Inferencing} |
---|
2410 | |
---|
2411 | Auto type-inferencing occurs in a declaration where a variable's type is inferred from its initialization expression type. |
---|
2412 | \begin{quote2} |
---|
2413 | \begin{tabular}{@{}l@{\hspace{3em}}ll@{}} |
---|
2414 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CC}} & \multicolumn{1}{c}{Indexc{gcc}} \\ |
---|
2415 | \begin{lstlisting} |
---|
2416 | |
---|
2417 | auto j = 3.0 * 4; |
---|
2418 | int i; |
---|
2419 | auto k = i; |
---|
2420 | \end{lstlisting} |
---|
2421 | & |
---|
2422 | \begin{lstlisting} |
---|
2423 | #define expr 3.0 * i |
---|
2424 | typeof(expr) j = expr; |
---|
2425 | int i; |
---|
2426 | typeof(i) k = i; |
---|
2427 | \end{lstlisting} |
---|
2428 | & |
---|
2429 | \begin{lstlisting} |
---|
2430 | |
---|
2431 | // use type of initialization expression |
---|
2432 | |
---|
2433 | // use type of primary variable |
---|
2434 | \end{lstlisting} |
---|
2435 | \end{tabular} |
---|
2436 | \end{quote2} |
---|
2437 | The two important capabilities are: |
---|
2438 | \begin{itemize} |
---|
2439 | \item |
---|
2440 | preventing having to determine or write out long generic types, |
---|
2441 | \item |
---|
2442 | ensure secondary variables, related to a primary variable, always have the same type. |
---|
2443 | \end{itemize} |
---|
2444 | |
---|
2445 | In \CFA, ©typedef© provides a mechanism to alias long type names with short ones, both globally and locally, but not eliminate the use of the short name. |
---|
2446 | \Indexc{gcc} provides ©typeof© to declare a secondary variable from a primary variable. |
---|
2447 | \CFA also relies heavily on the specification of the left-hand side of assignment for type inferencing, so in many cases it is crucial to specify the type of the left-hand side to select the correct type of the right-hand expression. |
---|
2448 | Only for overloaded routines with the same return type is variable type-inferencing possible. |
---|
2449 | Finally, ©auto© presents the programming problem of tracking down a type when the type is actually needed. |
---|
2450 | For example, given |
---|
2451 | \begin{lstlisting} |
---|
2452 | auto j = ®...® |
---|
2453 | \end{lstlisting} |
---|
2454 | and the need to write a routine to compute using ©j© |
---|
2455 | \begin{lstlisting} |
---|
2456 | void rtn( ®...® parm ); |
---|
2457 | rtn( j ); |
---|
2458 | \end{lstlisting} |
---|
2459 | A programmer must work backwards to determine the type of ©j©'s initialization expression, reconstructing the possibly long generic type-name. |
---|
2460 | In this situation, having the type name or a short alias is very useful. |
---|
2461 | |
---|
2462 | There is also the conundrum in type inferencing of when to \emph{\Index{brand}} a type. |
---|
2463 | That is, when is the type of the variable more important than the type of its initialization expression. |
---|
2464 | For example, if a change is made in an initialization expression, it can cause hundreds or thousands of cascading type changes and/or errors. |
---|
2465 | At some point, a programmer wants the type of the variable to remain constant and the expression to be in error when it changes. |
---|
2466 | |
---|
2467 | Given ©typedef© and ©typeof© in \CFA, and the strong need to use the type of left-hand side in inferencing, auto type-inferencing is not supported at this time. |
---|
2468 | Should a significant need arise, this feature can be revisited. |
---|
2469 | |
---|
2470 | |
---|
2471 | \section{Generics} |
---|
2472 | |
---|
2473 | \CFA supports parametric polymorphism to allow users to define generic functions and types. |
---|
2474 | Generics allow programmers to use type variables in place of concrete types so that the code can be reused with multiple types. |
---|
2475 | The type parameters can be restricted to satisfy a set of constraints. |
---|
2476 | This enables \CFA to build fully compiled generic functions and types, unlike other languages like \Index*[C++]{\CC} where templates are expanded or must be explicitly instantiated. |
---|
2477 | |
---|
2478 | |
---|
2479 | \subsection{Generic Functions} |
---|
2480 | |
---|
2481 | Generic functions in \CFA are similar to template functions in \Index*[C++]{\CC}, and will sometimes be expanded into specialized versions, just like in \CC. |
---|
2482 | The difference, however, is that generic functions in \CFA can also be separately compiled, using function pointers for callers to pass in all needed functionality for the given type. |
---|
2483 | This means that compiled libraries can contain generic functions that can be used by programs linked with them (statically or dynamically). |
---|
2484 | Another advantage over \CC templates is unlike templates, generic functions are statically checked, even without being instantiated. |
---|
2485 | |
---|
2486 | A simple example of using Do.s parametric polymorphism to create a generic swap function would look like this: |
---|
2487 | |
---|
2488 | \begin{lstlisting} |
---|
2489 | generic(type T) |
---|
2490 | void swap(T &a, T &b) { |
---|
2491 | T tmp = a; |
---|
2492 | a = b; |
---|
2493 | b = a; |
---|
2494 | } |
---|
2495 | |
---|
2496 | int a, b; |
---|
2497 | swap(a, b); |
---|
2498 | |
---|
2499 | Point p1, p2; |
---|
2500 | swap(p1, p2); |
---|
2501 | \end{lstlisting} |
---|
2502 | |
---|
2503 | Here, instead of specifying types for the parameters a and b, the function has a generic type parameter, type T. |
---|
2504 | This function can be called with any type, and the compiler will handle generating the proper code for that type, using call site inference to determine the appropriate value for T. |
---|
2505 | |
---|
2506 | |
---|
2507 | \subsection{Bounded Quantification} |
---|
2508 | |
---|
2509 | Some generic functions only work (or make sense) for any type that satisfies a given property. |
---|
2510 | For example, here is a function to pick the minimum of two values of some type. |
---|
2511 | \begin{lstlisting} |
---|
2512 | generic (type T | bool ?<?(T, T) ) |
---|
2513 | |
---|
2514 | T min(T a, T b) { |
---|
2515 | return a < b ? a : b; |
---|
2516 | } |
---|
2517 | \end{lstlisting} |
---|
2518 | |
---|
2519 | It only makes sense to call min with values of a type that has an ordering: a way to decide whether one value is less than another. |
---|
2520 | The ordering function used here is the less than operator, <. |
---|
2521 | The syntax used to reference the operator is discussed in further detail in Operator Overloading. |
---|
2522 | In \CFA, this assertion on the type of a generic is written as the bound, (type T | bool ?<?(T, T)). |
---|
2523 | The \CFA compiler enforces that minis only called with types for which the less than operator is defined, and reports a compile-time error otherwise. |
---|
2524 | |
---|
2525 | Bounds can also involve multiple types, and multiple requirements, as shown below: |
---|
2526 | \begin{lstlisting} |
---|
2527 | generic (type T, type U | { T foo(T, U); U bar(U); }) |
---|
2528 | |
---|
2529 | T baz(T t, U u) { |
---|
2530 | return foo(t, bar(u)); |
---|
2531 | } |
---|
2532 | \end{lstlisting} |
---|
2533 | |
---|
2534 | |
---|
2535 | \subsection{Interfaces} |
---|
2536 | |
---|
2537 | Type bounds as shown above are not very informative, merely requiring that a function exists with the right name and type. |
---|
2538 | Suppose you try to call a polymorphic function and \CFA gives you an error that int combine(int, int) is not defined. |
---|
2539 | Can you define it? What is it supposed to do? Perhaps it should compute the sum, or the bitwise and, or the maximum, or the least common multiple; or perhaps it's an operation that can't be defined for integers. |
---|
2540 | The function signature doesn't say. |
---|
2541 | |
---|
2542 | Interfaces gather together a set of function signatures under a common name, which solves two problems. |
---|
2543 | First, an interface name can be used in type bounds instead of function signatures. |
---|
2544 | This avoids repetition when a bound is used in many functions. |
---|
2545 | Second, interfaces explicitly document the existence of a commonly used set of functionality, making programs easier to understand. |
---|
2546 | \begin{lstlisting} |
---|
2547 | generic (type T) |
---|
2548 | interface Orderable { |
---|
2549 | bool ?<?(T, T); |
---|
2550 | }; |
---|
2551 | |
---|
2552 | generic (type T | Orderable(T)) |
---|
2553 | T min(T a, T b) { |
---|
2554 | return a < b ? a : b; |
---|
2555 | } |
---|
2556 | \end{lstlisting} |
---|
2557 | |
---|
2558 | This definition of the interface Orderable makes the generic function min easier to read and understand. |
---|
2559 | Orderable can also be reused for other generic functions, max for example. |
---|
2560 | Interfaces can also build on top of other interfaces. |
---|
2561 | For example: |
---|
2562 | \begin{lstlisting} |
---|
2563 | generic (type T | Orderable(T) |
---|
2564 | interface FooBarable { |
---|
2565 | int foo(T, T); |
---|
2566 | int Bar(T, T); |
---|
2567 | }; |
---|
2568 | \end{lstlisting} |
---|
2569 | |
---|
2570 | The FooBarable interface specifies all of the bounds of the Orderable interface, plus the additional bounds specified in its definition. |
---|
2571 | A type does not need to specify that it satisfies any interface, the compiler can figure this out at compile time. |
---|
2572 | For example, there is no need to add some special syntax to show that a type implements the Orderable interface, just define a ?<? operator and it is satisfied. |
---|
2573 | |
---|
2574 | |
---|
2575 | \subsection{Generic Typedefs} |
---|
2576 | |
---|
2577 | Type synonyms can be defined generically using the typedef keyword together with a generic type annotation. |
---|
2578 | These can be used to abbreviate complicated type expressions, especially in generic code. |
---|
2579 | \begin{lstlisting} |
---|
2580 | // typedef the generic function pointers for later use |
---|
2581 | |
---|
2582 | generic(type T) |
---|
2583 | typedef int (*predicate)(T); |
---|
2584 | generic(type Captured, type T) |
---|
2585 | typedef void (*callback)(Captured, T); |
---|
2586 | |
---|
2587 | generic(type T) |
---|
2588 | void find(int length, T *array, |
---|
2589 | predicate(T) p, callback(void *, T)f) { |
---|
2590 | int i; |
---|
2591 | for (i = 0; i < length; i++) |
---|
2592 | if (p(array[i])) f(NULL, array[i]); |
---|
2593 | } |
---|
2594 | \end{lstlisting} |
---|
2595 | |
---|
2596 | |
---|
2597 | \subsection{Generic Types} |
---|
2598 | |
---|
2599 | Generic types are defined using the same mechanisms as those described above for generic functions. |
---|
2600 | This feature allows users to create types that have one or more fields that use generic parameters as types, similar to a template classes in \Index*[C++]{\CC}. |
---|
2601 | For example, to make a generic linked list, a placeholder is created for the type of the elements, so that the specific type of the elements in the list need not be specified when defining the list. |
---|
2602 | In C, something like this would have to be done using void pointers and unsafe casting. |
---|
2603 | As in generic functions, Do.s generic types are different from \CC templates in that they can be fully compiled, while \CC templates are more like macro expansions. |
---|
2604 | This means that a \CFA generic type from a compiled library can be used with any type that satisfies the bounds. |
---|
2605 | |
---|
2606 | The syntax for defining a generic type looks very similar to that of a generic function. |
---|
2607 | Generic types support bounds and interfaces, using the same syntax as generic functions. |
---|
2608 | \begin{lstlisting} |
---|
2609 | generic (type T) |
---|
2610 | struct LinkedListElem { |
---|
2611 | T elem; |
---|
2612 | LinkedListElem(T) *next; |
---|
2613 | }; |
---|
2614 | |
---|
2615 | LinkedListElem *++?(LinkedListElem **elem) { |
---|
2616 | return *elem = elem->next; |
---|
2617 | } |
---|
2618 | |
---|
2619 | generic (type T) |
---|
2620 | struct LinkedList { |
---|
2621 | LinkedListElem(T) *head; |
---|
2622 | unsigned int size; |
---|
2623 | } |
---|
2624 | |
---|
2625 | generic (type T | bool ?==?(T, T)) |
---|
2626 | bool contains(LinkedList(T) *list, T elem) { |
---|
2627 | for(LinkedListElem *iter = list->head; iter != 0; ++iter) { |
---|
2628 | if (iter->elem == elem) return true; |
---|
2629 | } |
---|
2630 | return false; |
---|
2631 | } |
---|
2632 | \end{lstlisting} |
---|
2633 | |
---|
2634 | |
---|
2635 | \section{Safety} |
---|
2636 | |
---|
2637 | Safety, along with productivity, is a key goal of Do. |
---|
2638 | This section discusses the safety features that have been included in \CFA to help programmers create more stable, reliable, and secure code. |
---|
2639 | |
---|
2640 | |
---|
2641 | \subsection{Exceptions} |
---|
2642 | |
---|
2643 | \CFA introduces support for exceptions as an easier way to recover from exceptional conditions that may be detected within a block of code. |
---|
2644 | In C, developers can use error codes and special return values to report to a caller that an error occurred in a function. |
---|
2645 | The major problem with error codes is that they can be easily ignored by the caller. |
---|
2646 | Failure to properly check for errors can result in the caller making incorrect assumptions about the current state or about the return value that are very likely to result in errors later on in the program, making the source of the problem more difficult to find when debugging. |
---|
2647 | An unhandled exception on the other hand will cause a crash, revealing the original source of the erroneous state. |
---|
2648 | |
---|
2649 | Exceptions in \CFA allow a different type of control flow. |
---|
2650 | Throwing an exception terminates execution of the current block, invokes the destructors of variables that are local to the block, and propagates the exception to the parent block. |
---|
2651 | The exception is immediately re-thrown from the parent block unless it is caught as described below. |
---|
2652 | \CFA uses keywords similar to \Index*[C++]{\CC} for exception handling. |
---|
2653 | An exception is thrown using a throw statement, which accepts one argument. |
---|
2654 | |
---|
2655 | \begin{lstlisting} |
---|
2656 | ... |
---|
2657 | |
---|
2658 | throw 13; |
---|
2659 | |
---|
2660 | ... |
---|
2661 | \end{lstlisting} |
---|
2662 | |
---|
2663 | An exception can be caught using a catch statement, which specifies the type of the exception it can catch. |
---|
2664 | A catch is specified immediately after a guarded block to signify that it can catch an exception from that block. |
---|
2665 | A guarded block is specified using the try keyword, followed by a block of code inside of curly braces. |
---|
2666 | |
---|
2667 | \begin{lstlisting} |
---|
2668 | ... |
---|
2669 | |
---|
2670 | try { |
---|
2671 | throw 13; |
---|
2672 | } |
---|
2673 | catch(int e) { |
---|
2674 | printf(.caught an exception: %d\n., e); |
---|
2675 | } |
---|
2676 | \end{lstlisting} |
---|
2677 | |
---|
2678 | |
---|
2679 | \subsection{Memory Management} |
---|
2680 | |
---|
2681 | |
---|
2682 | \subsubsection{Manual Memory Management} |
---|
2683 | |
---|
2684 | Using malloc and free to dynamically allocate memory exposes several potential, and common, errors. |
---|
2685 | First, malloc breaks type safety because it returns a pointer to void. |
---|
2686 | There is no relationship between the type that the returned pointer is cast to, and the amount of memory allocated. |
---|
2687 | This problem is solved with a type-safe malloc. |
---|
2688 | Do.s type-safe malloc does not take any arguments for size. |
---|
2689 | Instead, it infers the type based on the return value, and then allocates space for the inferred type. |
---|
2690 | |
---|
2691 | \begin{lstlisting} |
---|
2692 | float *f = malloc(); // allocates the size of a float |
---|
2693 | |
---|
2694 | struct S { |
---|
2695 | int i, j, k; |
---|
2696 | }; |
---|
2697 | |
---|
2698 | struct S *s = malloc(); // allocates the size of a struct S |
---|
2699 | \end{lstlisting} |
---|
2700 | |
---|
2701 | In addition to the improved malloc, \CFA also provides a technique for combining allocation and initialization into one step, using the new function. |
---|
2702 | For all constructors defined for a given type (see Operator Overloading), a corresponding call to new can be used to allocate and construct that type. |
---|
2703 | |
---|
2704 | \begin{lstlisting} |
---|
2705 | type Complex = struct { |
---|
2706 | float real; |
---|
2707 | float imag; |
---|
2708 | }; |
---|
2709 | |
---|
2710 | // default constructor |
---|
2711 | |
---|
2712 | void ?{}(Complex &c) { |
---|
2713 | c.real = 0.0; |
---|
2714 | c.imag = 0.0; |
---|
2715 | } |
---|
2716 | |
---|
2717 | |
---|
2718 | |
---|
2719 | // 2 parameter constructor |
---|
2720 | |
---|
2721 | void ?{}(Complex &c, float real, float imag) { |
---|
2722 | c.real = real; |
---|
2723 | c.imag = imag; |
---|
2724 | } |
---|
2725 | |
---|
2726 | |
---|
2727 | int main() { |
---|
2728 | Complex c1; // No constructor is called |
---|
2729 | Complex c2{}; // Default constructor called |
---|
2730 | Complex c3{1.0, -1.0}; // 2 parameter constructor is called |
---|
2731 | |
---|
2732 | Complex *p1 = malloc(); // allocate |
---|
2733 | Complex *p2 = new(); // allocate + default constructor |
---|
2734 | Complex *p3 = new(0.5, 1.0); // allocate + 2 param constructor |
---|
2735 | } |
---|
2736 | |
---|
2737 | \end{lstlisting} |
---|
2738 | |
---|
2739 | |
---|
2740 | \subsubsection{Automatic Memory Management} |
---|
2741 | |
---|
2742 | \CFA may also support automatic memory management to further improve safety. |
---|
2743 | If the compiler can insert all of the code needed to manage dynamically allocated memory (automatic reference counting), then developers can avoid problems with dangling pointers, double frees, memory leaks, etc. |
---|
2744 | This feature requires further investigation. |
---|
2745 | \CFA will not have a garbage collector, but might use some kind of region-based memory management. |
---|
2746 | |
---|
2747 | |
---|
2748 | \subsection{Unsafe C Constructs} |
---|
2749 | |
---|
2750 | C programmers are able to access all of the low-level tricks that are sometimes needed for close-to-the-hardware programming. |
---|
2751 | Some of these practices however are often error-prone and difficult to read and maintain. |
---|
2752 | Since \CFA is designed to be safer than C, such constructs are disallowed in \CFA code. |
---|
2753 | If a programmer wants to use one of these unsafe C constructs, the unsafe code must be contained in a C linkage block (see Interoperability), which will be compiled like C code. |
---|
2754 | This block means that the user is telling the tools, .I know this is unsafe, but I.m going to do it anyway.. |
---|
2755 | |
---|
2756 | The exact set of unsafe C constructs that will be disallowed in \CFA has not yet been decided, but is sure to include pointer arithmetic, pointer casting, etc. |
---|
2757 | Once the full set is decided, the rules will be listed here. |
---|
2758 | |
---|
2759 | |
---|
2760 | \section{Syntactic Anomalies} |
---|
2761 | |
---|
2762 | The number 0 and 1 are treated specially in \CFA, and can be redefined as variables. |
---|
2763 | One syntactic anomaly is when a field in an structure is names 0 or 1: |
---|
2764 | \begin{lstlisting} |
---|
2765 | struct S { |
---|
2766 | int 0, 1; |
---|
2767 | } s; |
---|
2768 | \end{lstlisting} |
---|
2769 | The problem occurs in accessing these fields using the selection operation ``©.©'': |
---|
2770 | \begin{lstlisting} |
---|
2771 | s.0 = 0; // ambiguity with floating constant .0 |
---|
2772 | s.1 = 1; // ambiguity with floating constant .1 |
---|
2773 | \end{lstlisting} |
---|
2774 | To make this work, a space is required after the field selection: |
---|
2775 | \begin{lstlisting} |
---|
2776 | ®s.§\textvisiblespace§0® = 0; |
---|
2777 | ®s.§\textvisiblespace§1® = 1; |
---|
2778 | \end{lstlisting} |
---|
2779 | While this syntax is awkward, it is unlikely many programmers will name fields of a structure 0 or 1. |
---|
2780 | Like the \Index*[C++]{\CC} lexical problem with closing template-syntax, e.g, ©Foo<Bar<int®>>®©, this issue can be solved with a more powerful lexer/parser. |
---|
2781 | |
---|
2782 | There are several ambiguous cases with operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be lexed as ©*©/©?*?© or ©*?©/©*?©. |
---|
2783 | Since it is common practise to put a unary operator juxtaposed to an identifier, \eg ©*i©, users will be annoyed if they cannot do this with respect to operator identifiers. |
---|
2784 | Even with this special hack, there are 5 general cases that cannot be handled. |
---|
2785 | The first case is for the function-call identifier ©?()©: |
---|
2786 | \begin{lstlisting} |
---|
2787 | int *§\textvisiblespace§?()(); // declaration: space required after '*' |
---|
2788 | *§\textvisiblespace§?()(); // expression: space required after '*' |
---|
2789 | \end{lstlisting} |
---|
2790 | Without the space, the string ©*?()© is ambiguous without N character look ahead; |
---|
2791 | it requires scanning ahead to determine if there is a ©'('©, which is the start of an argument/parameter list. |
---|
2792 | |
---|
2793 | The 4 remaining cases occur in expressions: |
---|
2794 | \begin{lstlisting} |
---|
2795 | i++§\textvisiblespace§?i:0; // space required before '?' |
---|
2796 | i--§\textvisiblespace§?i:0; // space required before '?' |
---|
2797 | i§\textvisiblespace§?++i:0; // space required after '?' |
---|
2798 | i§\textvisiblespace§?--i:0; // space required after '?' |
---|
2799 | \end{lstlisting} |
---|
2800 | In the first two cases, the string ©i++?© is ambiguous, where this string can be lexed as ©i© / ©++?© or ©i++© / ©?©; |
---|
2801 | it requires scanning ahead to determine if there is a ©'('©, which is the start of an argument list. |
---|
2802 | In the second two cases, the string ©?++x© is ambiguous, where this string can be lexed as ©?++© / ©x© or ©?© / y©++x©; |
---|
2803 | it requires scanning ahead to determine if there is a ©'('©, which is the start of an argument list. |
---|
2804 | |
---|
2805 | |
---|
2806 | \section{Concurrency} |
---|
2807 | |
---|
2808 | Today's processors for nearly all use cases, ranging from embedded systems to large cloud computing servers, are composed of multiple cores, often heterogeneous. |
---|
2809 | As machines grow in complexity, it becomes more difficult for a program to make the most use of the hardware available. |
---|
2810 | \CFA includes built-in concurrency features to enable high performance and improve programmer productivity on these multi-/many-core machines. |
---|
2811 | |
---|
2812 | Concurrency support in \CFA is implemented on top of a highly efficient runtime system of light-weight, M:N, user level threads. |
---|
2813 | The model integrates concurrency features into the language by making the structure type the core unit of concurrency. |
---|
2814 | All communication occurs through method calls, where data is sent via method arguments, and received via the return value. |
---|
2815 | This enables a very familiar interface to all programmers, even those with no parallel programming experience. |
---|
2816 | It also allows the compiler to do static type checking of all communication, a very important safety feature. |
---|
2817 | This controlled communication with type safety has some similarities with channels in \Index*{Go}, and can actually implement |
---|
2818 | channels exactly, as well as create additional communication patterns that channels cannot. |
---|
2819 | Mutex objects, monitors, are used to contain mutual exclusion within an object and synchronization across concurrent threads. |
---|
2820 | |
---|
2821 | Three new keywords are added to support these features: |
---|
2822 | |
---|
2823 | monitor creates a structure with implicit locking when accessing fields |
---|
2824 | |
---|
2825 | mutex implies use of a monitor requiring the implicit locking |
---|
2826 | |
---|
2827 | task creates a type with implicit locking, separate stack, and a thread |
---|
2828 | |
---|
2829 | |
---|
2830 | \subsection{Monitors} |
---|
2831 | |
---|
2832 | A monitor is a structure in \CFA which includes implicit locking of its fields. |
---|
2833 | Users of a monitor interact with it just like any structure, but the compiler handles code as needed to ensure mutual exclusion. |
---|
2834 | An example of the definition of a monitor is shown here: |
---|
2835 | \begin{lstlisting} |
---|
2836 | type Account = monitor { |
---|
2837 | const unsigned long number; // account number |
---|
2838 | float balance; // account balance |
---|
2839 | }; |
---|
2840 | \end{lstlisting} |
---|
2841 | |
---|
2842 | Since a monitor structure includes an implicit locking mechanism, it does not make sense to copy a monitor; |
---|
2843 | it is always passed by reference. |
---|
2844 | Users can specify to the compiler whether or not a function will require mutual exclusion of the monitor using the mutex modifier on the parameter. |
---|
2845 | When mutex is specified, the compiler inserts locking before executing the body of the function, and unlocking after the body. |
---|
2846 | This means that a function requiring mutual exclusion could block if the lock is already held by another thread. |
---|
2847 | Blocking on a monitor lock does not block the kernel thread, it simply blocks the user thread, which yields its kernel thread while waiting to obtain the lock. |
---|
2848 | If multiple mutex parameters are specified, they will be locked in parameter order (\ie first parameter is locked first) and unlocked in the |
---|
2849 | reverse order. |
---|
2850 | \begin{lstlisting} |
---|
2851 | // This function accesses a constant field, it does not require |
---|
2852 | // mutual exclusion |
---|
2853 | |
---|
2854 | export unsigned long getAccountNumber(Account &a) { |
---|
2855 | return a.number; |
---|
2856 | } |
---|
2857 | |
---|
2858 | // This function accesses and modifies a shared field; it |
---|
2859 | // requires mutual exclusion |
---|
2860 | |
---|
2861 | export float withdrawal(mutex Account &a, float amount) { |
---|
2862 | a.balance -= amount; |
---|
2863 | return a.balance; |
---|
2864 | } |
---|
2865 | \end{lstlisting} |
---|
2866 | |
---|
2867 | Often, one function using a monitor will call another function using that same monitor. |
---|
2868 | If both require mutual exclusion, then the thread would be waiting for itself to release the lock when it calls the inner function. |
---|
2869 | This situation is resolved by allowing recursive entry (reentrant locks), meaning that if the lock is already held by the caller, it can be locked again. |
---|
2870 | It will still be unlocked the same number of times. |
---|
2871 | An example of this situation is shown below: |
---|
2872 | |
---|
2873 | \begin{lstlisting} |
---|
2874 | // deleting a job from a worker requires mutual exclusion |
---|
2875 | |
---|
2876 | void deleteJob(mutex Worker &w, Job &j) { |
---|
2877 | ... |
---|
2878 | } |
---|
2879 | |
---|
2880 | // transferring requires mutual exclusion and calls deleteJob |
---|
2881 | |
---|
2882 | void transferJob(mutex Worker &from, Worker &to) { |
---|
2883 | ... |
---|
2884 | deleteJob(j); |
---|
2885 | ... |
---|
2886 | } |
---|
2887 | \end{lstlisting} |
---|
2888 | |
---|
2889 | |
---|
2890 | \subsection{Tasks} |
---|
2891 | |
---|
2892 | \CFA also provides a simple mechanism for creating and utilizing user level threads. |
---|
2893 | A task provides mutual exclusion like a monitor, and also has its own execution state and a thread of control. |
---|
2894 | Similar to a monitor, a task is defined like a structure: |
---|
2895 | \begin{lstlisting} |
---|
2896 | type Adder = task { |
---|
2897 | int *row; |
---|
2898 | int size; |
---|
2899 | int &subtotal; |
---|
2900 | } |
---|
2901 | \end{lstlisting} |
---|
2902 | |
---|
2903 | A task may define a constructor, which will be called upon allocation and run on the caller.s thread. |
---|
2904 | A destructor may also be defined, which is called at de-allocation (when a dynamic object is deleted or when a local object goes out of scope). |
---|
2905 | After a task is allocated and initialized, its thread is spawned implicitly and begins executing in its function call method. |
---|
2906 | All tasks must define this function call method, with a void return value and no additional parameters, or the compiler will report an error. |
---|
2907 | Below are example functions for the above Adder task, and its usage to sum up a matrix on multiple threads. |
---|
2908 | (Note that this example is designed to display the syntax and functionality, not the best method to solve this problem) |
---|
2909 | \begin{lstlisting} |
---|
2910 | void ?{}(Adder &a, int r[], int s, int &st) { // constructor |
---|
2911 | a.row = r; |
---|
2912 | a.size = s; |
---|
2913 | a.subtotal = st; |
---|
2914 | } |
---|
2915 | |
---|
2916 | // implicitly spawn thread and begin execution here |
---|
2917 | |
---|
2918 | void ?()(Adder &a) { |
---|
2919 | int c; |
---|
2920 | subtotal = 0; |
---|
2921 | for (c=0; c<a.size; ++c) { |
---|
2922 | subtotal += row[c]; |
---|
2923 | } |
---|
2924 | } |
---|
2925 | |
---|
2926 | int main() { |
---|
2927 | const int rows = 100, cols = 1000000; |
---|
2928 | int matrix[rows][cols]; |
---|
2929 | int subtotals[rows]; |
---|
2930 | int total = 0; |
---|
2931 | int r; |
---|
2932 | |
---|
2933 | { // create a new scope here for our adders |
---|
2934 | Adder adders[rows]; |
---|
2935 | // read in the matrix |
---|
2936 | ... |
---|
2937 | for (r=0; r<rows; ++r) { |
---|
2938 | // tasks are initialized on this thread |
---|
2939 | Adders[r] = {matrix[r], cols, subtotals[r]}; |
---|
2940 | Adders[r](); // spawn thread and begin execution |
---|
2941 | } |
---|
2942 | } // adders go out of scope; block here until they all finish |
---|
2943 | total += subtotals[r]; |
---|
2944 | printf(.total is %d\n., total); |
---|
2945 | } |
---|
2946 | \end{lstlisting} |
---|
2947 | |
---|
2948 | |
---|
2949 | \subsection{Cooperative Scheduling} |
---|
2950 | |
---|
2951 | Tasks in \CFA are cooperatively scheduled, meaning that a task will not be interrupted by another task, except at specific yield points. |
---|
2952 | In Listing 31, there are no yield points, so each task runs to completion with no interruptions. |
---|
2953 | Places where a task could yield include waiting for a lock (explicitly or implicitly), waiting for I/O, or waiting for a specific function (or one of a set of functions) to be called. |
---|
2954 | This last option is introduced with the yield function. yield is used to indicate that this task should yield its thread until the specified function is called. |
---|
2955 | For example, the code below defines a monitor that maintains a generic list. |
---|
2956 | When a task tries to pop from the list, but it is empty, the task should yield until another task puts something into the list, with the push function. |
---|
2957 | Similarly, when a task tries to push something onto the list, but it is full, it will yield until another task frees some space with the pop function. |
---|
2958 | |
---|
2959 | \begin{lstlisting} |
---|
2960 | // type T is used as a generic type for all definitions inside |
---|
2961 | // the curly brackets |
---|
2962 | |
---|
2963 | generic(type T) { |
---|
2964 | type Channel = monitor { |
---|
2965 | List(T) list; // list is a simple generic list type |
---|
2966 | }; |
---|
2967 | |
---|
2968 | T pop(mutex &Channel(T) ch) { |
---|
2969 | if (ch.list.empty()) { |
---|
2970 | // yield until push is called for this channel |
---|
2971 | yield(push); |
---|
2972 | } |
---|
2973 | return ch.list.pop(); |
---|
2974 | } |
---|
2975 | |
---|
2976 | void push(mutex &Channel(T)ch, T val) { |
---|
2977 | if (ch.list.full()) { |
---|
2978 | // yield until pop is called for this channel |
---|
2979 | yield(pop); |
---|
2980 | } |
---|
2981 | ch.list.push(val); |
---|
2982 | } |
---|
2983 | } |
---|
2984 | \end{lstlisting} |
---|
2985 | |
---|
2986 | A task can also yield indefinitely by calling yield with no arguments. |
---|
2987 | This will tell the scheduler to yield this task until it is resumed by some other task. |
---|
2988 | A task can resume another task by using its functional call operator. |
---|
2989 | The code below shows a simple ping-pong example, where two tasks yield back and forth to each other using these methods. |
---|
2990 | |
---|
2991 | \begin{lstlisting} |
---|
2992 | type Ping = task { |
---|
2993 | Pong *partner; |
---|
2994 | }; |
---|
2995 | |
---|
2996 | void ?{}(Ping &p, Pong *partner = 0) { |
---|
2997 | p.partner = partner; |
---|
2998 | } |
---|
2999 | |
---|
3000 | void ?()(Ping &p) { |
---|
3001 | for(;;) { // loop forever |
---|
3002 | printf(.ping\n.); |
---|
3003 | partner(); // resumes the partner task |
---|
3004 | yield(); // yields this task |
---|
3005 | } |
---|
3006 | } |
---|
3007 | |
---|
3008 | type Pong = task { |
---|
3009 | Ping *partner; |
---|
3010 | }; |
---|
3011 | |
---|
3012 | void ?{}(Pong &p, Ping *partner = 0) { |
---|
3013 | p.partner = partner; |
---|
3014 | } |
---|
3015 | |
---|
3016 | void ?()(Pong &p) { |
---|
3017 | for(;;) { // loop forever |
---|
3018 | yield(); // yields this task |
---|
3019 | printf(.pong/n.); |
---|
3020 | partner(); // resumes the partner task |
---|
3021 | } |
---|
3022 | } |
---|
3023 | |
---|
3024 | void main() { |
---|
3025 | Ping ping; // allocate ping |
---|
3026 | Pong pong{ping}; // allocate, initialize, and start pong |
---|
3027 | Ping{pong}; // initialize and start ping |
---|
3028 | } |
---|
3029 | \end{lstlisting} |
---|
3030 | |
---|
3031 | The same functionality can be accomplished by providing functions to be called by the partner task. |
---|
3032 | \begin{lstlisting} |
---|
3033 | type Pingpong = task { |
---|
3034 | String msg; |
---|
3035 | Pingpong *partner; |
---|
3036 | }; |
---|
3037 | |
---|
3038 | void ?{}(Pingpong &p, String msg, Pingpong *partner = 0) { |
---|
3039 | p.msg = msg; |
---|
3040 | p.partner = partner; |
---|
3041 | } |
---|
3042 | |
---|
3043 | void ?()(Pingpong &p) { |
---|
3044 | for(;;) { |
---|
3045 | yield(go); |
---|
3046 | } |
---|
3047 | } |
---|
3048 | |
---|
3049 | void go(Pingpong &p) { |
---|
3050 | print(.%(p.msg)\n.); |
---|
3051 | go(p.partner); |
---|
3052 | } |
---|
3053 | |
---|
3054 | void main() { |
---|
3055 | Pingpong ping = {.ping.}; |
---|
3056 | Pingpong pong = {.pong., ping}; |
---|
3057 | ping.partner = pong; |
---|
3058 | go(ping); |
---|
3059 | } |
---|
3060 | \end{lstlisting} |
---|
3061 | |
---|
3062 | |
---|
3063 | \section{Modules and Packages } |
---|
3064 | |
---|
3065 | \begin{comment} |
---|
3066 | High-level encapsulation is useful for organizing code into reusable units, and accelerating compilation speed. |
---|
3067 | \CFA provides a convenient mechanism for creating, building and sharing groups of functionality that enhances productivity and improves compile time. |
---|
3068 | |
---|
3069 | There are two levels of encapsulation in \CFA, module and package. |
---|
3070 | A module is a logical grouping of functionality that can be easily pulled into another project, much like a module in \Index*{Python} or a package in \Index*{Go}. |
---|
3071 | A module forms a namespace to limit the visibility and prevent naming conflicts of variables. |
---|
3072 | Furthermore, a module is an independent translation unit, which can be compiled separately to accelerate the compilation speed. |
---|
3073 | |
---|
3074 | A package is a physical grouping of one or more modules that is used for code distribution and version management. |
---|
3075 | Package is also the level of granularity at which dependences are managed. |
---|
3076 | A package is similar to the Crate in \Index*{Rust}. |
---|
3077 | |
---|
3078 | |
---|
3079 | \subsection{No Declarations, No Header Files} |
---|
3080 | |
---|
3081 | In C and \Index*[C++]{\CC}, it is necessary to declare or define every global variable, global function, and type before it is used in each file. |
---|
3082 | Header files and a preprocessor are normally used to avoid repeating code. |
---|
3083 | Thus, many variables, functions, and types are described twice, which exposes an opportunity for errors and causes additional maintenance work. |
---|
3084 | Instead of following this model, the \CFA tools can extract all of the same information from the code automatically. |
---|
3085 | This information is then stored in the object files for each module, in a format that can quickly be read by the compiler, and stored at the top of the file, for quick access. |
---|
3086 | In addition to the user productivity improvements, this simple change also improves compile time, by saving the information in a simple machine readable format, instead of making the compiler parse the same information over and over from a header file. |
---|
3087 | This seems like a minor change, but according to (Pike, \Index*{Go} at Google: Language Design in the Service of Software Engineering), this simple change can cause massive reductions in compile time. |
---|
3088 | |
---|
3089 | In \CFA, multiple definitions are not necessary. |
---|
3090 | Within a module, all of the module's global definitions are visible throughout the module. |
---|
3091 | For example, the following code compiles, even though ©isOdd© was not declared before being called: |
---|
3092 | \begin{lstlisting} |
---|
3093 | bool isEven(unsigned int x) { |
---|
3094 | if (x == 0) return true; |
---|
3095 | else return !isOdd(x); |
---|
3096 | } |
---|
3097 | |
---|
3098 | bool isOdd(unsigned int x) { |
---|
3099 | if (x == 1) return true; |
---|
3100 | else return !isEven(x - 2); |
---|
3101 | } |
---|
3102 | \end{lstlisting} |
---|
3103 | |
---|
3104 | Header files in C are used to expose the declarations from a library, so that they can be used externally. |
---|
3105 | With \CFA, this functionality is replaced with module exports, discussed below. |
---|
3106 | When building a \CFA module which needs to be callable from C code, users can use the tools to generate a header file suitable for including in these C files with all of the needed declarations. |
---|
3107 | |
---|
3108 | In order to interoperate with existing C code, \CFA files can still include header files, the contents of which will be enclosed in a C linkage section to indicate C calling conventions (see Interoperability for more information). |
---|
3109 | |
---|
3110 | |
---|
3111 | \subsection{Modules} |
---|
3112 | |
---|
3113 | A module typically contains a set of related types and methods, with some objects accessible from outside the package, and some limited to use inside the module. |
---|
3114 | These modules can then be easily shared and reused in multiple projects. |
---|
3115 | As modules are intended to be distributed for reuse, they should generally have stable, well-defined interfaces. |
---|
3116 | |
---|
3117 | \CFA adds the following keywords to express the module systems: module, export, import, as. |
---|
3118 | |
---|
3119 | |
---|
3120 | \subsubsection{Module Declaration} |
---|
3121 | |
---|
3122 | The syntax to declare a module is module moduleName;. |
---|
3123 | |
---|
3124 | The module declaration must be at the beginning of a file, and each file can only belong to one module. |
---|
3125 | If there is no module declaration at the beginning of a file, the file belongs to the global module. |
---|
3126 | A module can span several files. |
---|
3127 | By convention, a module and the files belonging to the module have additional mapping relationship which is described in the Do-Lang Tooling documentation. |
---|
3128 | |
---|
3129 | The moduleName follows the same rules of a variable name, except that it can use slash "/" to indicate the module/sub-module relationship. |
---|
3130 | For example, container/vector is a valid module name, where container is the parent module name, and vector is the sub-module under container. |
---|
3131 | |
---|
3132 | Only the interfaces of a module are visible from outside, when the module is imported. export is a type decorator to declare a module interface. |
---|
3133 | A method, a global variable or a type can be declared as a module interface. |
---|
3134 | Types defined in a module and referenced by an exported function or a variable must be exported, too. |
---|
3135 | |
---|
3136 | The following code is a simple module declaration example. |
---|
3137 | \begin{lstlisting} |
---|
3138 | module M; |
---|
3139 | |
---|
3140 | //visible outside module M |
---|
3141 | |
---|
3142 | export int f(int i) { return i + 1; } |
---|
3143 | export double aCounter; |
---|
3144 | |
---|
3145 | //not visible outside module M |
---|
3146 | |
---|
3147 | int g(int i) { return i - 1; } |
---|
3148 | |
---|
3149 | double bCounter; |
---|
3150 | \end{lstlisting} |
---|
3151 | |
---|
3152 | export module moduleName; can be use to re-export all the visible (exported) names in moduleName from the current module. |
---|
3153 | |
---|
3154 | |
---|
3155 | \subsubsection{Module Import} |
---|
3156 | |
---|
3157 | The syntax to import a module is import moduleName; or import moduleName as anotherName;. |
---|
3158 | One package cannot be imported with both of the two types of syntax in one file. |
---|
3159 | A package imported in one file will only be visible in this file. |
---|
3160 | For example, two files, A and B belong to the same module. |
---|
3161 | If file A imports another module, M, the exported names in M are not visible in file B. |
---|
3162 | |
---|
3163 | All of the exported names are visible in the file that imports the module. |
---|
3164 | The exported names can be accessed within a namespace based on the module name in the first syntax (ex moduleName.foo). |
---|
3165 | If moduleName has several elements separated by '/' to describe a sub-module (ex. import container/vector;), the last element in the moduleName is used as the namespace to access the visible names in that module (ex vector.add(...);). |
---|
3166 | The as keyword is used to confine the imported names in a unique namespace (ex. anotherName.foo). anotherName must be a valid identifier (same rules as a variable name) which means it cannot have '/' in it. |
---|
3167 | Conflicts in namespaces will be reported by the compiler. |
---|
3168 | The second method can be used to solve conflicting name problems. |
---|
3169 | The following code snippets show the two situations. |
---|
3170 | |
---|
3171 | \begin{lstlisting} |
---|
3172 | module util/counter; |
---|
3173 | export int f(int i) { return i+1; } |
---|
3174 | |
---|
3175 | import util/counter; |
---|
3176 | |
---|
3177 | int main() { |
---|
3178 | return counter.f(200); // f() from the package counter |
---|
3179 | } |
---|
3180 | |
---|
3181 | import util/counter as ct; |
---|
3182 | int main() { |
---|
3183 | return ct.f(200); // f() from the package counter |
---|
3184 | } |
---|
3185 | \end{lstlisting} |
---|
3186 | |
---|
3187 | |
---|
3188 | Additionally, using the .as. syntax, a user can force the compiler to add the imported names into the current namespace using .as ..With these module rules, the following module definitions and imports can be achieved without any problem. |
---|
3189 | |
---|
3190 | \begin{lstlisting} |
---|
3191 | module M1; |
---|
3192 | export int f(int i) { return i+1;} // visible outside |
---|
3193 | |
---|
3194 | int g(int i) { return i-1;} // not visible outside |
---|
3195 | |
---|
3196 | module M2; |
---|
3197 | int f(int i) { return i * 2; } // not visible outside |
---|
3198 | export int g(int g) { return i / 2; } // visible outside |
---|
3199 | |
---|
3200 | import M1 as .; |
---|
3201 | |
---|
3202 | import M2 as .; |
---|
3203 | |
---|
3204 | |
---|
3205 | int main() { |
---|
3206 | return f(3) + g(4); //f() from M1 and g() from M2; |
---|
3207 | } |
---|
3208 | \end{lstlisting} |
---|
3209 | |
---|
3210 | |
---|
3211 | \subsubsection{Sub-Module and Module Aggregation} |
---|
3212 | |
---|
3213 | Several modules can be organized in a parent module and sub-modules relationship. |
---|
3214 | The sub-module names are based on hierarchical naming, and use slash, "/", to indicate the relationship. |
---|
3215 | For example, std/vector and std/io are sub-modules of module std. |
---|
3216 | The exported names in a sub-module are NOT visible if the parent module is imported, which means the exported names in the sub-module are |
---|
3217 | not implicitly exported in the parent module. |
---|
3218 | |
---|
3219 | Aggregation is a mechanism to support components and simplified importing. |
---|
3220 | The mechanism is not based on naming but based on manual declaration. |
---|
3221 | For example, the following is the aggregated sequence module. |
---|
3222 | The export {...} is syntactic sugar for many lines of export module aModule;. |
---|
3223 | If an aggregated module is imported, all the included modules in the aggregation are imported. |
---|
3224 | |
---|
3225 | \begin{lstlisting} |
---|
3226 | module std/sequence; |
---|
3227 | |
---|
3228 | export { |
---|
3229 | module std/vector; |
---|
3230 | module std/list; |
---|
3231 | module std/array; |
---|
3232 | module std/deque; |
---|
3233 | module std/forward_list; |
---|
3234 | module std/queue; |
---|
3235 | module std/stack; |
---|
3236 | }; |
---|
3237 | \end{lstlisting} |
---|
3238 | |
---|
3239 | After importing the aggregated module, each individual name is still contained in the original name space. |
---|
3240 | For example, vector.add() and list.add() should be used to reference the add methods if there are add methods in both the vector module and the list module. |
---|
3241 | |
---|
3242 | |
---|
3243 | \subsubsection{Import from Repository} |
---|
3244 | |
---|
3245 | When a module is imported, the tools locate the module in the one of the accessible package paths (defined by command line flag or environment variable). |
---|
3246 | The tools also support retrieving modules of a package from external repositories. |
---|
3247 | See Listing 40: Package directory structure |
---|
3248 | |
---|
3249 | |
---|
3250 | \subsubsection{Package Import} |
---|
3251 | |
---|
3252 | Because packages are the places where the building tool looks for modules, there is no code required in the \CFA source file to import a package. |
---|
3253 | In order to use modules in a package, the programmer needs to guide the building tool to locate the right package by 1) Adding the package's parent path into \$DOPATH; |
---|
3254 | or 2) Adding the package dependence into the current project's Do.prj. |
---|
3255 | More details about locating a module in a package are explained in the next section. |
---|
3256 | |
---|
3257 | |
---|
3258 | \subsubsection{Package Versioning} |
---|
3259 | |
---|
3260 | A package must have a version number. |
---|
3261 | The version number is a string. |
---|
3262 | For example "1.0", "1.a", "A1", and "1ec5fab753eb979d3886a491845b8ae152d58c8f" are all valid version numbers. |
---|
3263 | By convention, a package is stored in a directory named packageName-packageVersion. |
---|
3264 | For example, the util package with version 1.1 is stored in a directory named util-1.1. |
---|
3265 | |
---|
3266 | The project description file can optionally specify the version of the package used in the current project. |
---|
3267 | If not defined, because the version number is a string, and all the different versions for the same package will be sorted in increasing order, the package with the largest version number will be used in the compilation. |
---|
3268 | The builder tool will record the specific package version used in the build in the project's "Do.lock" file to enable fully repeatable builds. |
---|
3269 | |
---|
3270 | |
---|
3271 | \subsection{Module and Package Organization} |
---|
3272 | |
---|
3273 | \CFA has two level of encapsulations, module and package. |
---|
3274 | This section explains the object model of modules, packages and other language concepts. |
---|
3275 | It also explains how programmers should organize their code, and the method used by the build tools to locate packages, and import modules for compilation. |
---|
3276 | |
---|
3277 | |
---|
3278 | \subsubsection{Object Model} |
---|
3279 | |
---|
3280 | There are several concepts in Do. |
---|
3281 | \begin{itemize} |
---|
3282 | \item |
---|
3283 | File: a \CFA source file |
---|
3284 | \item |
---|
3285 | Module: a container to organize a set of related types and methods; It has a module name, and several interfaces visible from outside |
---|
3286 | \item |
---|
3287 | Package: a container to organize modules for distribution; It has attributes like name, author, |
---|
3288 | version, dependences, etc. |
---|
3289 | \item |
---|
3290 | Project: a working set for a \CFA project; It has attributes like name, author, version, dependences, etc. |
---|
3291 | \end{itemize} |
---|
3292 | |
---|
3293 | The following rules summarize the object model of all the above concepts: |
---|
3294 | \begin{itemize} |
---|
3295 | \item |
---|
3296 | A module contains one or more files |
---|
3297 | \begin{itemize} |
---|
3298 | \item |
---|
3299 | One file can only belong to one module |
---|
3300 | \item |
---|
3301 | A module has its name and interfaces exported |
---|
3302 | \item |
---|
3303 | A file without a module declaration at the beginning belongs to the global module |
---|
3304 | \item |
---|
3305 | \end{itemize} |
---|
3306 | |
---|
3307 | \item |
---|
3308 | A package contains one or more modules |
---|
3309 | \begin{itemize} |
---|
3310 | \item |
---|
3311 | A package has additional meta info described in Do.prj file |
---|
3312 | \item |
---|
3313 | A package may be dependent on other packages. |
---|
3314 | \end{itemize} |
---|
3315 | |
---|
3316 | \item |
---|
3317 | A project contains one or more modules in its source code |
---|
3318 | \begin{itemize} |
---|
3319 | \item |
---|
3320 | A project has additional meta info described in Do.prj file |
---|
3321 | \item |
---|
3322 | A project may be dependent on other packages |
---|
3323 | \item |
---|
3324 | A project can be transformed into a package for distribution |
---|
3325 | \item |
---|
3326 | A project can generate one or more executable binaries |
---|
3327 | \end{itemize} |
---|
3328 | \end{itemize} |
---|
3329 | |
---|
3330 | |
---|
3331 | \subsubsection{Module File Organization} |
---|
3332 | |
---|
3333 | The rules of this section are the conventions to organize module files in one package. |
---|
3334 | |
---|
3335 | The file location of a module in a package must match the module/submodule naming hierarchy. |
---|
3336 | The names separated by slash "/" must match the directory levels. |
---|
3337 | If only one file is used to implement one module, there is no need to put the module implementation file inside a sub-directory. |
---|
3338 | The file can be put inside its parent module's sub-directory with the sub module's name as the file name. |
---|
3339 | |
---|
3340 | Here is an example of a package, util. |
---|
3341 | \begin{lstlisting} |
---|
3342 | + util |
---|
3343 | Do.prj #package description file |
---|
3344 | heap.do #Case 1: module heap; |
---|
3345 | list.do #Case 1: mdoule list; |
---|
3346 | ring.do #Case 1: module ring; |
---|
3347 | + string #Case 2 |
---|
3348 | impl1.do #module string; |
---|
3349 | + std |
---|
3350 | vector.do |
---|
3351 | list.do |
---|
3352 | + array #Case 3 |
---|
3353 | array1.do #module std/array; |
---|
3354 | array2.do #module std/array; |
---|
3355 | sequence.do #Case 4, module std/sequence; |
---|
3356 | test.do #Case 5 |
---|
3357 | \end{lstlisting} |
---|
3358 | |
---|
3359 | \begin{itemize} |
---|
3360 | \item |
---|
3361 | Case 1: Each individual file implements a module |
---|
3362 | \item |
---|
3363 | Case 2: Put the implementation of a module under the sub-directory, but there is only one file |
---|
3364 | \item |
---|
3365 | Case 3: Put the implementation of a module under the sub-directory; There are several files to |
---|
3366 | implement one module |
---|
3367 | \item |
---|
3368 | Case 4: One file to express one aggregation |
---|
3369 | \item |
---|
3370 | Case 5: The file does not belong to any module; It is used for testing purpose |
---|
3371 | \end{itemize} |
---|
3372 | |
---|
3373 | The example only uses source code, ".do" files, to show the module file organization. |
---|
3374 | Other module packaging formats, like binary, must also follow the same rules. |
---|
3375 | |
---|
3376 | |
---|
3377 | \subsection{Module File Format} |
---|
3378 | |
---|
3379 | \CFA supports different types of module file formats. |
---|
3380 | |
---|
3381 | \begin{itemize} |
---|
3382 | \item |
---|
3383 | Pure source code format: The files should be organized following the previous section's definition. |
---|
3384 | \item |
---|
3385 | IR format (TBD): The \CFA compiler IR format, similar to the source code format |
---|
3386 | \item |
---|
3387 | Binary format, including ".a" static library or ".so" dynamic linkage library |
---|
3388 | \begin{itemize} |
---|
3389 | \item |
---|
3390 | The file's name must match the right level's module name defined in the previous section |
---|
3391 | \item |
---|
3392 | E.g. "util.so" includes all modules for the package util. |
---|
3393 | \item |
---|
3394 | E.g. "string.so" under the package directory to include files belonging to "module string;" |
---|
3395 | \end{itemize} |
---|
3396 | \item. |
---|
3397 | Archive format |
---|
3398 | \begin{itemize} |
---|
3399 | \item |
---|
3400 | The archive is named as ".dar", and is a zip archive of the source code or the binary for a package |
---|
3401 | \item |
---|
3402 | E.g. "util.dar" is the whole package for util package including the package direction file |
---|
3403 | \end{itemize} |
---|
3404 | \item |
---|
3405 | Hybrid format |
---|
3406 | \begin{itemize} |
---|
3407 | \item |
---|
3408 | A package can be distributed partly in source code, partly in binary format, and/or packaged in the archive format |
---|
3409 | \item |
---|
3410 | The only limitation is that the names of the files must match the module location names defined in previous section |
---|
3411 | \end{itemize} |
---|
3412 | \end{itemize} |
---|
3413 | Package and Module Locating and the \CFA Language Tooling documentation for more details. |
---|
3414 | |
---|
3415 | |
---|
3416 | \subsection{Packages} |
---|
3417 | |
---|
3418 | A package is synonymous with a library in other languages. |
---|
3419 | The intent of the package level encapsulation is to facilitate code distribution, version control, and dependence management. |
---|
3420 | A package is a physical grouping of one or more modules in a directory (an archive file for a directory). |
---|
3421 | The concept of a package is the convention for grouping code, and the contract between the language and the building tool to search for imported modules. |
---|
3422 | |
---|
3423 | |
---|
3424 | \subsubsection{Package Definition} |
---|
3425 | |
---|
3426 | A package is defined by putting a project description file, Do.prj, with one or more modules into a directory. |
---|
3427 | This project description file contains the package's meta data, including package name, author, version, dependences, etc. |
---|
3428 | It should be in the root of the package directory. |
---|
3429 | |
---|
3430 | The modules in the package could be either source code, or compiled binary format. |
---|
3431 | The location of the module files should follow the module name's path. |
---|
3432 | |
---|
3433 | Here is a simple example of the directory structure of a package, core. |
---|
3434 | It contains a module std and several sub-modules under std. |
---|
3435 | \begin{lstlisting} |
---|
3436 | + core |
---|
3437 | Do.prj |
---|
3438 | + std |
---|
3439 | + io |
---|
3440 | file.do # module std/io/file; |
---|
3441 | network.do #module std/io/network; |
---|
3442 | + container |
---|
3443 | vector.do #module std/container/vector; |
---|
3444 | list.do #module std/container/list; |
---|
3445 | \end{lstlisting} |
---|
3446 | |
---|
3447 | |
---|
3448 | \subsubsection{Package Import} |
---|
3449 | |
---|
3450 | Because packages are the places where the building tool looks for modules, there is no code required in the \CFA source file to import a package. |
---|
3451 | In order to use modules in a package, the programmer needs to guide the building tool to locate the right package by 1) Adding the package's parent path into \$DOPATH; or 2) Adding the package dependence into the current project's Do.prj. |
---|
3452 | More details about locating a module in a package are explained in the next section. |
---|
3453 | |
---|
3454 | |
---|
3455 | \subsubsection{Package Versioning} |
---|
3456 | |
---|
3457 | A package must have a version number. |
---|
3458 | The version number is a string. |
---|
3459 | For example "1.0", "1.a", "A1", and "1ec5fab753eb979d3886a491845b8ae152d58c8f" are all valid version numbers. |
---|
3460 | By convention, a package is stored in a directory named packageName-packageVersion. |
---|
3461 | For example, the util package with version 1.1 is stored in a directory named util-1.1. |
---|
3462 | |
---|
3463 | The project description file can optionally specify the version of the package used in the current project. |
---|
3464 | If not defined, because the version number is a string, and all the different versions for the same package will be sorted in increasing order, the package with the largest version number will be used in the compilation. |
---|
3465 | The builder tool will record the specific package version used in the build in the project's "Do.lock" file to enable fully repeatable builds. |
---|
3466 | |
---|
3467 | |
---|
3468 | \subsection{Module and Package Organization} |
---|
3469 | |
---|
3470 | \CFA has two level of encapsulations, module and package. |
---|
3471 | This section explains the object model of modules, packages and other language concepts. |
---|
3472 | It also explains how programmers should organize their code, and the method used by the build tools to locate packages, and import modules for compilation. |
---|
3473 | |
---|
3474 | |
---|
3475 | \subsubsection{Object Model} |
---|
3476 | |
---|
3477 | There are several concepts in Do. |
---|
3478 | \begin{itemize} |
---|
3479 | \item |
---|
3480 | File: a \CFA source file |
---|
3481 | \item |
---|
3482 | Module: a container to organize a set of related types and methods; It has a module name, and several interfaces visible from outside |
---|
3483 | \item |
---|
3484 | Package: a container to organize modules for distribution; It has attributes like name, author, version, dependences, etc. |
---|
3485 | \item |
---|
3486 | Project: a working set for a \CFA project; It has attributes like name, author, version, dependences, etc. |
---|
3487 | \end{itemize} |
---|
3488 | |
---|
3489 | The following rules summarize the object model of all the above concepts: |
---|
3490 | \begin{itemize} |
---|
3491 | \item |
---|
3492 | A module contains one or more files |
---|
3493 | \begin{itemize} |
---|
3494 | \item |
---|
3495 | One file can only belong to one module |
---|
3496 | \item |
---|
3497 | A module has its name and interfaces exported |
---|
3498 | \item |
---|
3499 | A file without a module declaration at the beginning belongs to the global module |
---|
3500 | \end{itemize} |
---|
3501 | \item |
---|
3502 | A package contains one or more modules |
---|
3503 | \begin{itemize} |
---|
3504 | \item |
---|
3505 | A package has additional meta info described in Do.prj file |
---|
3506 | \item |
---|
3507 | A package may be dependent on other packages. |
---|
3508 | \end{itemize} |
---|
3509 | \item |
---|
3510 | A project contains one or more modules in its source code |
---|
3511 | \begin{itemize} |
---|
3512 | \item |
---|
3513 | A project has additional meta info described in Do.prj file |
---|
3514 | \item |
---|
3515 | A project may be dependent on other packages |
---|
3516 | \item |
---|
3517 | A project can be transformed into a package for distribution |
---|
3518 | \item |
---|
3519 | A project can generate one or more executable binaries |
---|
3520 | \end{itemize} |
---|
3521 | \end{itemize} |
---|
3522 | |
---|
3523 | |
---|
3524 | \subsubsection{Module File Organization} |
---|
3525 | |
---|
3526 | The rules of this section are the conventions to organize module files in one package. |
---|
3527 | |
---|
3528 | The file location of a module in a package must match the module/submodule naming hierarchy. |
---|
3529 | The names separated by slash "/" must match the directory levels. |
---|
3530 | If only one file is used to implement one module, there is no need to put the module implementation file inside a sub-directory. |
---|
3531 | The file can be put inside its parent module's sub-directory with the sub module's name as the file name. |
---|
3532 | |
---|
3533 | Here is an example of a package, util. |
---|
3534 | \begin{lstlisting} |
---|
3535 | + util |
---|
3536 | Do.prj #package description file |
---|
3537 | heap.do #Case 1: module heap; |
---|
3538 | list.do #Case 1: mdoule list; |
---|
3539 | ring.do #Case 1: module ring; |
---|
3540 | + string #Case 2 |
---|
3541 | impl1.do #module string; |
---|
3542 | + std |
---|
3543 | vector.do |
---|
3544 | list.do |
---|
3545 | + array #Case 3 |
---|
3546 | array1.do #module std/array; |
---|
3547 | array2.do #module std/array; |
---|
3548 | sequence.do #Case 4, module std/sequence; |
---|
3549 | test.do #Case 5 |
---|
3550 | \end{lstlisting} |
---|
3551 | |
---|
3552 | |
---|
3553 | \begin{itemize} |
---|
3554 | \item |
---|
3555 | Case 1: Each individual file implements a module |
---|
3556 | \item |
---|
3557 | Case 2: Put the implementation of a module under the sub-directory, but there is only one file |
---|
3558 | \item |
---|
3559 | Case 3: Put the implementation of a module under the sub-directory; There are several files to implement one module |
---|
3560 | \item |
---|
3561 | Case 4: One file to express one aggregation |
---|
3562 | \item |
---|
3563 | Case 5: The file does not belong to any module; It is used for testing purpose |
---|
3564 | \end{itemize} |
---|
3565 | |
---|
3566 | The example only uses source code, ".do" files, to show the module file organization. |
---|
3567 | Other module packaging formats, like binary, must also follow the same rules. |
---|
3568 | |
---|
3569 | |
---|
3570 | \subsubsection{Module File Format} |
---|
3571 | |
---|
3572 | \CFA supports different types of module file formats. |
---|
3573 | |
---|
3574 | \begin{itemize} |
---|
3575 | \item |
---|
3576 | Pure source code format: The files should be organized following the previous section's definition. |
---|
3577 | \item |
---|
3578 | IR format (TBD): The \CFA compiler IR format, similar to the source code format |
---|
3579 | \item |
---|
3580 | Binary format, including ".a" static library or ".so" dynamic linkage library |
---|
3581 | \begin{itemize} |
---|
3582 | \item |
---|
3583 | The file's name must match the right level's module name defined in the previous section |
---|
3584 | \item |
---|
3585 | E.g. "util.so" includes all modules for the package util. |
---|
3586 | \item |
---|
3587 | E.g. "string.so" under the package directory to include files belonging to "module string;" |
---|
3588 | \end{itemize} |
---|
3589 | \item |
---|
3590 | Archive format |
---|
3591 | \begin{itemize} |
---|
3592 | \item |
---|
3593 | The archive is named as ".dar", and is a zip archive of the source code or the binary for a package |
---|
3594 | \item |
---|
3595 | E.g. "util.dar" is the whole package for util package including the package direction file |
---|
3596 | \end{itemize} |
---|
3597 | \item |
---|
3598 | Hybrid format |
---|
3599 | \begin{itemize} |
---|
3600 | \item |
---|
3601 | A package can be distributed partly in source code, partly in binary format, and/or packaged in the archive format |
---|
3602 | \item |
---|
3603 | The only limitation is that the names of the files must match the module location names defined in previous section |
---|
3604 | \end{itemize} |
---|
3605 | \end{itemize} |
---|
3606 | |
---|
3607 | |
---|
3608 | \subsection{Package and Module Locating} |
---|
3609 | |
---|
3610 | The high-level build tools provided by \CFA will handle finding a package in your local filesystem or retrieving it from a repository if necessary, building it if necessary, and linking with it. |
---|
3611 | If a programmer prefers, one can directly call the compiler, docc to build the source files and create and link to static libraries. |
---|
3612 | |
---|
3613 | When a source file imports a module, the \CFA build tool and docc compiler will locate the module according to the following order: |
---|
3614 | |
---|
3615 | \begin{enumerate} |
---|
3616 | \item |
---|
3617 | This source file's directory tree, which is typically the project's src directory |
---|
3618 | \item |
---|
3619 | All of the dependent packages (in a directory or in an archive file) under the current \CFA project's pkg directory |
---|
3620 | \item |
---|
3621 | The dependent packages (in a directory or in an archive file) inside the paths defined in the DOPATH environment variable |
---|
3622 | \item |
---|
3623 | The dependent packages (in a directory or in an archive file) inside the global \CFA SDK installation's pkg directory |
---|
3624 | \item |
---|
3625 | If one dependent package is still not found, the builder tool will automatically retrieve it from the repository defined in the SDK installation's configuration, and store it in the SDK's pkg directory |
---|
3626 | \end{enumerate} |
---|
3627 | |
---|
3628 | The module found first in a package will shadow the modules with the same name in the later packages in the search sequence. |
---|
3629 | |
---|
3630 | |
---|
3631 | \subsubsection{Dependent Package} |
---|
3632 | |
---|
3633 | Dependent packages are those packages containing modules that the current project's source code will import from. |
---|
3634 | Dependent packages are defined implicitly or explicitly in one \CFA project. |
---|
3635 | All of the packages under the current project's pkg directory are implicitly dependent packages. |
---|
3636 | For others, the dependent packages must be defined in the project's Do.prj file. |
---|
3637 | |
---|
3638 | |
---|
3639 | \subsubsection{Package and Module Locating Example} |
---|
3640 | |
---|
3641 | \begin{lstlisting} |
---|
3642 | # A project's source code tree |
---|
3643 | |
---|
3644 | -------------------------------------- |
---|
3645 | |
---|
3646 | + testProject |
---|
3647 | Do.prj |
---|
3648 | + src |
---|
3649 | main.do |
---|
3650 | + pkg |
---|
3651 | + security-1.1 |
---|
3652 | Do.prj |
---|
3653 | security.do #module security |
---|
3654 | |
---|
3655 | -------------------------------------- |
---|
3656 | |
---|
3657 | # Do.prj |
---|
3658 | |
---|
3659 | -------------------------------------- |
---|
3660 | |
---|
3661 | [dependences] |
---|
3662 | std |
---|
3663 | util = "0.2" |
---|
3664 | |
---|
3665 | -------------------------------------- |
---|
3666 | |
---|
3667 | # main.do |
---|
3668 | |
---|
3669 | --------------------------------------- |
---|
3670 | |
---|
3671 | import security; |
---|
3672 | import std/vector; |
---|
3673 | import container; |
---|
3674 | |
---|
3675 | ---------------------------------------- |
---|
3676 | \end{lstlisting} |
---|
3677 | |
---|
3678 | |
---|
3679 | \begin{lstlisting} |
---|
3680 | # pkg directory's source code tree |
---|
3681 | |
---|
3682 | ----------------------------------------- |
---|
3683 | |
---|
3684 | + pkg |
---|
3685 | + std-1.0 |
---|
3686 | Do.prj |
---|
3687 | vector.do #module std/vector; |
---|
3688 | queue.do #module std/queue; |
---|
3689 | + std-1.1 |
---|
3690 | Do.prj |
---|
3691 | vector.do #module std/vector; |
---|
3692 | queue.do #module std/queue; |
---|
3693 | list.do #module std/list; |
---|
3694 | + util-0.1 |
---|
3695 | Do.prj |
---|
3696 | container.do #module container; |
---|
3697 | + security-1.0 |
---|
3698 | security.do #module security; |
---|
3699 | ------------------------------------------ |
---|
3700 | \end{lstlisting} |
---|
3701 | |
---|
3702 | |
---|
3703 | During the compiling of main.do file import security; |
---|
3704 | The security module appears in both the local security-1.1 package, and the global security-1.0 package. |
---|
3705 | According to the locating sequence, the local security module in security-1.1 will be used. |
---|
3706 | And because the security-1.1 package is under local's pkg directory. |
---|
3707 | No dependence description is required in the project Do.prj file. |
---|
3708 | |
---|
3709 | import std/vector; |
---|
3710 | |
---|
3711 | The std/vector package appears in two different versions' packages in the global path and the project dependence doesn't specify the version. std-1.1 is used in this case. |
---|
3712 | |
---|
3713 | import container; |
---|
3714 | |
---|
3715 | The Do.prj specifies the version 0.2 should be used to locate container module from util package but only version 0.1 is available in the local file system. |
---|
3716 | The builder tool then will try to retrieve it from the web and store it in the global pkg directory. |
---|
3717 | After that, the container module from the newly downloaded package will be used in the compilation. |
---|
3718 | \end{comment} |
---|
3719 | |
---|
3720 | |
---|
3721 | \section{Comparison with Other Languages} |
---|
3722 | |
---|
3723 | \CFA is one of many languages that attempts to improve upon C. |
---|
3724 | In developing \CFA, many other languages were consulted for ideas, constructs, and syntax. |
---|
3725 | Therefore, it is important to show how these languages each compare with Do. |
---|
3726 | In this section, \CFA is compared with what the writers of this document consider to be the closest competitors of Do: \Index*[C++]{\CC}, \Index*{Go}, \Index*{Rust}, and \Index*{D}. |
---|
3727 | |
---|
3728 | |
---|
3729 | \subsection[Comparing Key Features of CFA]{Comparing Key Features of \CFA} |
---|
3730 | |
---|
3731 | |
---|
3732 | {% local change to lstlising to reduce font size |
---|
3733 | |
---|
3734 | |
---|
3735 | \lstset{basicstyle=\linespread{0.9}\sf\relsize{-2}} |
---|
3736 | |
---|
3737 | |
---|
3738 | \subsubsection{Constructors and Destructors} |
---|
3739 | |
---|
3740 | \begin{flushleft} |
---|
3741 | \begin{tabular}{@{}l|l|l|l@{}} |
---|
3742 | \multicolumn{1}{c|}{\textbf{\CFA}} & \multicolumn{1}{c|}{\textbf{\CC}} & \multicolumn{1}{c|}{\textbf{Go}} & \multicolumn{1}{c}{\textbf{Rust}} \\ |
---|
3743 | \hline |
---|
3744 | \begin{lstlisting} |
---|
3745 | struct Line { |
---|
3746 | float lnth; |
---|
3747 | } |
---|
3748 | // default constructor |
---|
3749 | void ?{}( Line * l ) { |
---|
3750 | l->lnth = 0.0; |
---|
3751 | sout | "default" | endl; |
---|
3752 | } |
---|
3753 | |
---|
3754 | |
---|
3755 | // constructor with length |
---|
3756 | void ?{}( Line * l, float lnth ) { |
---|
3757 | l->lnth = lnth; |
---|
3758 | sout | "lnth" | l->lnth | endl; |
---|
3759 | |
---|
3760 | } |
---|
3761 | |
---|
3762 | // destructor |
---|
3763 | void ^?() { |
---|
3764 | sout | "destroyed" | endl; |
---|
3765 | l.lnth = 0.0; |
---|
3766 | } |
---|
3767 | |
---|
3768 | // usage |
---|
3769 | Line line1; |
---|
3770 | Line line2 = { 3.4 }; |
---|
3771 | \end{lstlisting} |
---|
3772 | & |
---|
3773 | \begin{lstlisting}[language=C++] |
---|
3774 | class Line { |
---|
3775 | float lnth; |
---|
3776 | |
---|
3777 | // default constructor |
---|
3778 | Line() { |
---|
3779 | cout << "default" << endl; |
---|
3780 | lnth = 0.0; |
---|
3781 | } |
---|
3782 | |
---|
3783 | |
---|
3784 | // constructor with lnth |
---|
3785 | Line( float l ) { |
---|
3786 | cout << "length " << length |
---|
3787 | << endl; |
---|
3788 | length = l; |
---|
3789 | } |
---|
3790 | |
---|
3791 | // destructor |
---|
3792 | ~Line() { |
---|
3793 | cout << "destroyed" << endl; |
---|
3794 | length = 0.0; |
---|
3795 | } |
---|
3796 | } |
---|
3797 | // usage |
---|
3798 | Line line1; |
---|
3799 | Line line2( 3.4 ); |
---|
3800 | \end{lstlisting} |
---|
3801 | & |
---|
3802 | \begin{lstlisting}[language=Golang] |
---|
3803 | type Line struct { |
---|
3804 | length float32 |
---|
3805 | } |
---|
3806 | // default constructor |
---|
3807 | func makeLine() Line { |
---|
3808 | fmt.PrintLn( "default" ) |
---|
3809 | return Line{0.0} |
---|
3810 | } |
---|
3811 | |
---|
3812 | |
---|
3813 | // constructor with length |
---|
3814 | func makeLine( length float32 ) Line { |
---|
3815 | fmt.Printf( "length %v", length ) |
---|
3816 | |
---|
3817 | return Line{length} |
---|
3818 | } |
---|
3819 | |
---|
3820 | // no destructor |
---|
3821 | |
---|
3822 | |
---|
3823 | |
---|
3824 | |
---|
3825 | |
---|
3826 | // usage |
---|
3827 | line1 := makeLine() |
---|
3828 | line2 := makeLine( 3.4 ) |
---|
3829 | \end{lstlisting} |
---|
3830 | & |
---|
3831 | \begin{lstlisting} |
---|
3832 | struct Line { |
---|
3833 | length: f32 |
---|
3834 | } |
---|
3835 | // default constructor |
---|
3836 | impl Default for Line { |
---|
3837 | fn default () -> Line { |
---|
3838 | println!( "default" ); |
---|
3839 | Line{ length: 0.0 } |
---|
3840 | } |
---|
3841 | } |
---|
3842 | // constructor with length |
---|
3843 | impl Line { |
---|
3844 | fn make( len: f32 ) -> Line { |
---|
3845 | println!( "length: {}", len ); |
---|
3846 | Line{ length: len } |
---|
3847 | } |
---|
3848 | } |
---|
3849 | // destructor |
---|
3850 | impl Drop for Line { |
---|
3851 | fn drop( &mut self ) { |
---|
3852 | self.length = 0.0 |
---|
3853 | } |
---|
3854 | } |
---|
3855 | // usage |
---|
3856 | let line1:Line = Default::default(); |
---|
3857 | Line line2( 3.4 ); |
---|
3858 | \end{lstlisting} |
---|
3859 | \end{tabular} |
---|
3860 | \end{flushleft} |
---|
3861 | |
---|
3862 | |
---|
3863 | \subsubsection{Operator Overloading} |
---|
3864 | |
---|
3865 | \begin{flushleft} |
---|
3866 | \begin{tabular}{@{}l|l|l|l@{}} |
---|
3867 | \multicolumn{1}{c|}{\textbf{\CFA}} & \multicolumn{1}{c|}{\textbf{\CC}} & \multicolumn{1}{c|}{\textbf{Go}} & \multicolumn{1}{c}{\textbf{Rust}} \\ |
---|
3868 | \hline |
---|
3869 | \begin{lstlisting} |
---|
3870 | struct Cpx { |
---|
3871 | double re, im; |
---|
3872 | }; |
---|
3873 | // overload addition operator |
---|
3874 | Cpx ?+?( Cpx l, const Cpx r ) { |
---|
3875 | return (Cpx){l.re+l.im, l.im+r.im}; |
---|
3876 | } |
---|
3877 | Cpx a, b, c; |
---|
3878 | c = a + b; |
---|
3879 | \end{lstlisting} |
---|
3880 | & |
---|
3881 | \begin{lstlisting} |
---|
3882 | struct Cpx { |
---|
3883 | double re, im; |
---|
3884 | }; |
---|
3885 | // overload addition operator |
---|
3886 | Cpx operator+( Cpx l, const Cpx r ) { |
---|
3887 | return (Cpx){l.re+l.im, l.im+r.im}; |
---|
3888 | } |
---|
3889 | Cpx a, b, c; |
---|
3890 | c = a + b; |
---|
3891 | \end{lstlisting} |
---|
3892 | & |
---|
3893 | \begin{lstlisting} |
---|
3894 | // no operator overloading |
---|
3895 | |
---|
3896 | |
---|
3897 | |
---|
3898 | |
---|
3899 | |
---|
3900 | |
---|
3901 | |
---|
3902 | \end{lstlisting} |
---|
3903 | & |
---|
3904 | \begin{lstlisting} |
---|
3905 | struct Cpx { |
---|
3906 | re: f32, |
---|
3907 | im: f32 |
---|
3908 | } |
---|
3909 | // overload addition operator |
---|
3910 | impl Add for Cpx { |
---|
3911 | type Output = Cpx |
---|
3912 | fn add(self, r: Cpx) -> Cpx { |
---|
3913 | let mut res = Cpx{re: 0.0, im: 0.0}; |
---|
3914 | res.re = self.re + r.re; |
---|
3915 | res.im = self.im + r.im; |
---|
3916 | return res |
---|
3917 | } |
---|
3918 | } |
---|
3919 | let (a, b, mut c) = ...; |
---|
3920 | c = a + b |
---|
3921 | \end{lstlisting} |
---|
3922 | \end{tabular} |
---|
3923 | \end{flushleft} |
---|
3924 | |
---|
3925 | |
---|
3926 | \subsubsection{Calling C Functions} |
---|
3927 | |
---|
3928 | \begin{flushleft} |
---|
3929 | \begin{tabular}{@{}l|l|l@{}} |
---|
3930 | \multicolumn{1}{c|}{\textbf{\CFA/\CC}} & \multicolumn{1}{c|}{\textbf{Go}} & \multicolumn{1}{c}{\textbf{Rust}} \\ |
---|
3931 | \hline |
---|
3932 | \begin{lstlisting}[boxpos=t] |
---|
3933 | extern "C" { |
---|
3934 | #include <sys/types.h> |
---|
3935 | #include <sys/stat.h> |
---|
3936 | #include <unistd.h> |
---|
3937 | } |
---|
3938 | size_t fileSize( const char *path ) { |
---|
3939 | struct stat s; |
---|
3940 | stat(path, &s); |
---|
3941 | return s.st_size; |
---|
3942 | } |
---|
3943 | \end{lstlisting} |
---|
3944 | & |
---|
3945 | \begin{lstlisting}[boxpos=t] |
---|
3946 | /* |
---|
3947 | #cgo |
---|
3948 | #include <sys/types.h> |
---|
3949 | #include <sys/stat.h> |
---|
3950 | #include <unistd.h> |
---|
3951 | */ |
---|
3952 | import "C" |
---|
3953 | import "unsafe" |
---|
3954 | |
---|
3955 | func fileSize(path string) C.size_t { |
---|
3956 | var buf C.struct_stat |
---|
3957 | c_string := C.CString(path) |
---|
3958 | C.stat(p, &buf) |
---|
3959 | C.free(unsafe.Pointer(c_string)) |
---|
3960 | return buf._st_size |
---|
3961 | } |
---|
3962 | \end{lstlisting} |
---|
3963 | & |
---|
3964 | \begin{lstlisting}[boxpos=t] |
---|
3965 | use libc::{c_int, size_t}; |
---|
3966 | // translated from sys/stat.h |
---|
3967 | #[repr(C)] |
---|
3968 | struct stat_t { |
---|
3969 | ... |
---|
3970 | st_size: size_t, |
---|
3971 | ... |
---|
3972 | } |
---|
3973 | #[link(name = "libc")] |
---|
3974 | extern { |
---|
3975 | fn stat(path: *const u8, |
---|
3976 | buf: *mut stat_t) -> c_int; |
---|
3977 | } |
---|
3978 | fn fileSize(path: *const u8) -> size_t |
---|
3979 | { |
---|
3980 | unsafe { |
---|
3981 | let mut buf: stat_t = uninit(); |
---|
3982 | stat(path, &mut buf); |
---|
3983 | buf.st_size |
---|
3984 | } |
---|
3985 | } |
---|
3986 | \end{lstlisting} |
---|
3987 | \end{tabular} |
---|
3988 | \end{flushleft} |
---|
3989 | |
---|
3990 | |
---|
3991 | \subsubsection{Generic Functions} |
---|
3992 | |
---|
3993 | \begin{flushleft} |
---|
3994 | \begin{tabular}{@{}l|l|l|l@{}} |
---|
3995 | \multicolumn{1}{c|}{\textbf{\CFA}} & \multicolumn{1}{c|}{\textbf{\CC}} & \multicolumn{1}{c|}{\textbf{Go}} & \multicolumn{1}{c}{\textbf{Rust}} \\ |
---|
3996 | \hline |
---|
3997 | \begin{lstlisting} |
---|
3998 | generic(type T, type N | |
---|
3999 | { int ?<?(N, N); }) |
---|
4000 | T *maximize(N (*f)(const T&), |
---|
4001 | int n, T *a) { |
---|
4002 | T *bestX = NULL; |
---|
4003 | N bestN; |
---|
4004 | for (int i = 0; i < n; i++) { |
---|
4005 | N curN = f(a[i]); |
---|
4006 | if (bestX == NULL || |
---|
4007 | curN > bestN) { |
---|
4008 | bestX = &a[i]; bestN = curN; |
---|
4009 | } |
---|
4010 | } |
---|
4011 | return bestX; |
---|
4012 | } |
---|
4013 | |
---|
4014 | string *longest(int n, string *p) |
---|
4015 | { |
---|
4016 | return maximize(length, n, p); |
---|
4017 | } |
---|
4018 | \end{lstlisting} |
---|
4019 | & |
---|
4020 | \begin{lstlisting} |
---|
4021 | template<typename T, typename F> |
---|
4022 | T *maximize(const F &f, |
---|
4023 | int n, T *a) { |
---|
4024 | typedef decltype(f(a[0])) N; |
---|
4025 | T *bestX = NULL; |
---|
4026 | N bestN; |
---|
4027 | for (int i = 0; i < n; i++) { |
---|
4028 | N curN = f(a[i]); |
---|
4029 | if (bestX == NULL || curN > bestN) |
---|
4030 | { |
---|
4031 | bestX = &a[i]; bestN = curN; |
---|
4032 | } |
---|
4033 | } |
---|
4034 | return bestX; |
---|
4035 | } |
---|
4036 | |
---|
4037 | string *longest(int n, string *p) { |
---|
4038 | return maximize( |
---|
4039 | [](const string &s) { |
---|
4040 | return s.length(); |
---|
4041 | }, n, p); |
---|
4042 | } |
---|
4043 | \end{lstlisting} |
---|
4044 | & |
---|
4045 | \begin{lstlisting} |
---|
4046 | // Go does not support generics! |
---|
4047 | func maximize( |
---|
4048 | gt func(interface{}, interface{}) bool, |
---|
4049 | f func(interface{}) interface{}, |
---|
4050 | a []interface{}) interface{} { |
---|
4051 | var bestX interface{} = nil |
---|
4052 | var bestN interface{} = nil |
---|
4053 | for _, x := range a { |
---|
4054 | curN := f(x) |
---|
4055 | if bestX == nil || gt(curN, bestN) |
---|
4056 | { |
---|
4057 | bestN = curN |
---|
4058 | bestX = x |
---|
4059 | } |
---|
4060 | } |
---|
4061 | return bestX |
---|
4062 | } |
---|
4063 | |
---|
4064 | func longest( |
---|
4065 | a []interface{}) interface{} { |
---|
4066 | return maximize( |
---|
4067 | func(a, b interface{}) bool { |
---|
4068 | return a.(int) > b.(int) }, |
---|
4069 | func(s interface{}) interface{} { |
---|
4070 | return len(s.(string)) }, |
---|
4071 | a).(string) |
---|
4072 | } |
---|
4073 | \end{lstlisting} |
---|
4074 | & |
---|
4075 | \begin{lstlisting} |
---|
4076 | use std::cmp::Ordering; |
---|
4077 | |
---|
4078 | fn maximize<N: Ord + Copy, T, F: |
---|
4079 | Fn(&T) -> N>(f: F, a: &Vec<T>) -> |
---|
4080 | Option<&T> { |
---|
4081 | let mut best_x: Option<&T> = None; |
---|
4082 | let mut best_n: Option<N> = None; |
---|
4083 | for x in a { |
---|
4084 | let n = f(x); |
---|
4085 | if (match best_n { None => true, |
---|
4086 | Some(bn) => |
---|
4087 | n.cmp(&bn) == Ordering::Greater }) |
---|
4088 | { |
---|
4089 | best_x = Some(x); |
---|
4090 | best_n = Some(n); |
---|
4091 | } |
---|
4092 | } |
---|
4093 | return best_x |
---|
4094 | } |
---|
4095 | |
---|
4096 | fn longest(a: &Vec<String>) -> |
---|
4097 | Option<&String> { |
---|
4098 | return |
---|
4099 | maximize(|x: &String| x.len(), a) |
---|
4100 | } |
---|
4101 | \end{lstlisting} |
---|
4102 | \end{tabular} |
---|
4103 | \end{flushleft} |
---|
4104 | |
---|
4105 | |
---|
4106 | \begin{comment} |
---|
4107 | \subsubsection{Modules / Packages} |
---|
4108 | |
---|
4109 | \begin{lstlisting} |
---|
4110 | \CFA |
---|
4111 | \CC |
---|
4112 | |
---|
4113 | |
---|
4114 | module example/M; |
---|
4115 | |
---|
4116 | export int inc(int val) { |
---|
4117 | return val + 1; |
---|
4118 | } |
---|
4119 | |
---|
4120 | |
---|
4121 | |
---|
4122 | |
---|
4123 | -------------------------------------- |
---|
4124 | //Use the module in another file |
---|
4125 | import example/M; |
---|
4126 | int main() { |
---|
4127 | print(M.inc(100)); |
---|
4128 | return 0; |
---|
4129 | } |
---|
4130 | // Using \CC17 module proposal |
---|
4131 | |
---|
4132 | module example.M; |
---|
4133 | |
---|
4134 | export { |
---|
4135 | int inc(int val); |
---|
4136 | } |
---|
4137 | |
---|
4138 | int inc(inv val) { |
---|
4139 | return val + 1; |
---|
4140 | } |
---|
4141 | -------------------------------------- |
---|
4142 | // Use the module in another file |
---|
4143 | import example.M; |
---|
4144 | int main() { |
---|
4145 | cout << inc(100) << endl; |
---|
4146 | return 0; |
---|
4147 | } |
---|
4148 | |
---|
4149 | Go |
---|
4150 | Rust |
---|
4151 | package example/M; |
---|
4152 | |
---|
4153 | func Inc(val int32) int32 { |
---|
4154 | // Capitalization indicates exported |
---|
4155 | return val + 100 |
---|
4156 | } |
---|
4157 | |
---|
4158 | |
---|
4159 | -------------------------------------- |
---|
4160 | //Use the package in another file |
---|
4161 | package main |
---|
4162 | import .fmt. |
---|
4163 | import "example/M" |
---|
4164 | |
---|
4165 | func main() int32 { |
---|
4166 | fmt.Printf(.%v., M.Inc(100)) |
---|
4167 | } |
---|
4168 | pub mod example { |
---|
4169 | pub mod M { |
---|
4170 | pub inc(val i32) -> i32 { |
---|
4171 | return val + 100; |
---|
4172 | } |
---|
4173 | } |
---|
4174 | } |
---|
4175 | |
---|
4176 | -------------------------------------- |
---|
4177 | //Use the module in another file |
---|
4178 | use example::M; |
---|
4179 | |
---|
4180 | |
---|
4181 | |
---|
4182 | fn main() { |
---|
4183 | println!(.{}., M::inc(100)); |
---|
4184 | } |
---|
4185 | \end{lstlisting} |
---|
4186 | \end{comment} |
---|
4187 | |
---|
4188 | |
---|
4189 | \subsubsection{Parallel Tasks} |
---|
4190 | |
---|
4191 | \begin{flushleft} |
---|
4192 | \begin{tabular}{@{}l|l|l|l@{}} |
---|
4193 | \multicolumn{1}{c|}{\textbf{\CFA}} & \multicolumn{1}{c|}{\textbf{\CC}} & \multicolumn{1}{c|}{\textbf{Go}} & \multicolumn{1}{c}{\textbf{Rust}} \\ |
---|
4194 | \hline |
---|
4195 | \begin{lstlisting} |
---|
4196 | task Nonzero { |
---|
4197 | int *data; |
---|
4198 | int start; |
---|
4199 | int end; |
---|
4200 | int* res; |
---|
4201 | }; |
---|
4202 | |
---|
4203 | void ?{}(Nonzero &a, int d[], int s, |
---|
4204 | int e, int* subres) { |
---|
4205 | // constructor |
---|
4206 | a.data = d; |
---|
4207 | a.start = s; |
---|
4208 | a.end = e; |
---|
4209 | a.res = subres; |
---|
4210 | } |
---|
4211 | |
---|
4212 | // implicitly spawn thread here |
---|
4213 | void ?()(NonzeroCounter &a) { |
---|
4214 | int i; |
---|
4215 | int nonzero = 0; |
---|
4216 | for (i=start; c<end; ++i) { |
---|
4217 | if(a.data[i]!=0){ nonzero++;} |
---|
4218 | } |
---|
4219 | *a.res = nonzero; |
---|
4220 | } |
---|
4221 | |
---|
4222 | int main() { |
---|
4223 | int sz = ... |
---|
4224 | int data[sz] = ...; |
---|
4225 | int r1 = 0, r2=0; |
---|
4226 | int res; |
---|
4227 | { // create a scope for Nonzero |
---|
4228 | Nonzero n1{data, 0, sz/2, &n1}; |
---|
4229 | Nonzero n2{data, sz/2, sz, &n2}; |
---|
4230 | n1();//spawn |
---|
4231 | n2();//spawn |
---|
4232 | } |
---|
4233 | res = r1+r2; |
---|
4234 | return res; |
---|
4235 | } |
---|
4236 | \end{lstlisting} |
---|
4237 | & |
---|
4238 | \begin{lstlisting} |
---|
4239 | #include <thread> |
---|
4240 | #include <mutex> |
---|
4241 | |
---|
4242 | std::mutex m; |
---|
4243 | |
---|
4244 | |
---|
4245 | |
---|
4246 | |
---|
4247 | |
---|
4248 | |
---|
4249 | |
---|
4250 | |
---|
4251 | |
---|
4252 | |
---|
4253 | |
---|
4254 | |
---|
4255 | void task(const vector<int>&v, |
---|
4256 | int* res, size_t s, |
---|
4257 | size_t e) { |
---|
4258 | int non_zero = 0; |
---|
4259 | for(size_t i = s; i < e; ++i){ |
---|
4260 | if(v[i]!=0) { non_zero++;} |
---|
4261 | } |
---|
4262 | std::unique_lock<mutex> lck {m}; |
---|
4263 | *res += non_zero; |
---|
4264 | } |
---|
4265 | |
---|
4266 | int main() { |
---|
4267 | vector<int> data = ...; //data |
---|
4268 | int res = 0; |
---|
4269 | std::thread t1 {task, ref(data), |
---|
4270 | &res, 0, |
---|
4271 | data.size()/2}; |
---|
4272 | std::thread t2 {task, ref(data), |
---|
4273 | &res, data.size()/2, |
---|
4274 | data.size()}; |
---|
4275 | t1.join(); |
---|
4276 | t2.join(); |
---|
4277 | return res; |
---|
4278 | } |
---|
4279 | \end{lstlisting} |
---|
4280 | & |
---|
4281 | \begin{lstlisting} |
---|
4282 | package main |
---|
4283 | |
---|
4284 | import "fmt" |
---|
4285 | |
---|
4286 | func nonzero(data []int, c chan int) { |
---|
4287 | nz := 0 |
---|
4288 | for _, v:=range data { |
---|
4289 | if(v!=0) { nz := nz+1 } |
---|
4290 | } |
---|
4291 | c <- nz |
---|
4292 | } |
---|
4293 | |
---|
4294 | func main() { |
---|
4295 | sz := ... |
---|
4296 | data := make([]int, sz) |
---|
4297 | ... // data init |
---|
4298 | go nonzero(data[:len(data)/2], c) |
---|
4299 | go nonzero(data[len(data)/2:], c) |
---|
4300 | n1, n2 := <-c, <-c |
---|
4301 | res := n1 + n2 |
---|
4302 | fmt.Println(res) |
---|
4303 | } |
---|
4304 | \end{lstlisting} |
---|
4305 | & |
---|
4306 | \begin{lstlisting} |
---|
4307 | use std::thread; |
---|
4308 | use std::sync:mpsc::channel; |
---|
4309 | |
---|
4310 | fn main() { |
---|
4311 | let sz = ...; |
---|
4312 | let mut data:Vec<i32> = |
---|
4313 | Vec::with_capacity(sz as usize); |
---|
4314 | ... //init data |
---|
4315 | let (tx, rx) = channel(); |
---|
4316 | for i in 0..1 { |
---|
4317 | let tx = tx.clone(); |
---|
4318 | let data = data.clone() |
---|
4319 | thread::spawn(move|| { |
---|
4320 | let mut nz := 0; |
---|
4321 | let mut s = 0; |
---|
4322 | let mut e = sz / 2; |
---|
4323 | if i == 1 { |
---|
4324 | s = sz/2; |
---|
4325 | e = data.len(); |
---|
4326 | } |
---|
4327 | for i in s..(e - 1) { |
---|
4328 | if data[i] != 0 ( |
---|
4329 | nz = nz + 1 |
---|
4330 | } |
---|
4331 | } |
---|
4332 | tx.send(nz).unwrap(); |
---|
4333 | }); |
---|
4334 | } |
---|
4335 | let res = rx.recv().unwrap() + |
---|
4336 | rx.recv().unwrap(); |
---|
4337 | println!(.{}., res); |
---|
4338 | } |
---|
4339 | \end{lstlisting} |
---|
4340 | \end{tabular} |
---|
4341 | \end{flushleft} |
---|
4342 | |
---|
4343 | }% local change to lstlising to reduce font size |
---|
4344 | |
---|
4345 | |
---|
4346 | \subsection{Summary of Language Comparison} |
---|
4347 | |
---|
4348 | |
---|
4349 | \subsubsection[C++]{\CC} |
---|
4350 | |
---|
4351 | \Index*[C++]{\CC} is a general-purpose programming language. |
---|
4352 | It has imperative, object-oriented and generic programming features, while also providing facilities for low-level memory manipulation. (Wikipedia) |
---|
4353 | |
---|
4354 | The primary focus of \CC seems to be adding object-oriented programming to C, and this is the primary difference between \CC and Do. |
---|
4355 | \CC uses classes to encapsulate data and the functions that operate on that data, and to hide the internal representation of the data. |
---|
4356 | \CFA uses modules instead to perform these same tasks. |
---|
4357 | Classes in \CC also enable inheritance among types. |
---|
4358 | Instead of inheritance, \CFA embraces composition and interfaces to achieve the same goals with more flexibility. |
---|
4359 | There are many studies and articles comparing inheritance and composition (or is-a versus has-a relationships), so we will not go into more detail here (Venners, 1998) (Pike, \Index*{Go} at Google: Language Design in the Service of Software Engineering , 2012). |
---|
4360 | |
---|
4361 | Overloading in \CFA is very similar to overloading in \CC, with the exception of the additional use, in \CFA, of the return type to differentiate between overloaded functions. |
---|
4362 | References and exceptions in \CFA are heavily based on the same features from \CC. |
---|
4363 | The mechanism for interoperating with C code in \CFA is also borrowed from \CC. |
---|
4364 | |
---|
4365 | Both \CFA and \CC provide generics, and the syntax is quite similar. |
---|
4366 | The key difference between the two, is that in \CC templates are expanded at compile time for each type for which the template is instantiated, while in \CFA, function pointers are used to make the generic fully compilable. |
---|
4367 | This means that a generic function can be defined in a compiled library, and still be used as expected from source. |
---|
4368 | |
---|
4369 | |
---|
4370 | \subsubsection{Go} |
---|
4371 | |
---|
4372 | \Index*{Go}, also commonly referred to as golang, is a programming language developed at Google in 2007 [.]. |
---|
4373 | It is a statically typed language with syntax loosely derived from that of C, adding garbage collection, type |
---|
4374 | safety, some structural typing capabilities, additional built-in types such as variable-length arrays and key-value maps, and a large standard library. (Wikipedia) |
---|
4375 | |
---|
4376 | Go and \CFA differ significantly in syntax and implementation, but the underlying core concepts of the two languages are aligned. |
---|
4377 | Both Go and \CFA use composition and interfaces as opposed to inheritance to enable encapsulation and abstraction. |
---|
4378 | Both languages (along with their tooling ecosystem) provide a simple packaging mechanism for building units of code for easy sharing and reuse. |
---|
4379 | Both languages also include built-in light weight, user level threading concurrency features that attempt to simplify the effort and thought process required for writing parallel programs while maintaining high performance. |
---|
4380 | |
---|
4381 | Go has a significant runtime which handles the scheduling of its light weight threads, and performs garbage collection, among other tasks. |
---|
4382 | \CFA uses a cooperative scheduling algorithm for its tasks, and uses automatic reference counting to enable advanced memory management without garbage collection. |
---|
4383 | This results in Go requiring significant overhead to interface with C libraries while \CFA has no overhead. |
---|
4384 | |
---|
4385 | |
---|
4386 | \subsubsection{Rust} |
---|
4387 | |
---|
4388 | \Index*{Rust} is a general-purpose, multi-paradigm, compiled programming language developed by Mozilla Research. |
---|
4389 | It is designed to be a "safe, concurrent, practical language", supporting pure-functional, concurrent-actor[dubious . discuss][citation needed], imperative-procedural, and object-oriented styles. |
---|
4390 | |
---|
4391 | The primary focus of Rust is in safety, especially in concurrent programs. |
---|
4392 | To enforce a high level of safety, Rust has added ownership as a core feature of the language to guarantee memory safety. |
---|
4393 | This safety comes at the cost of a difficult learning curve, a change in the thought model of the program, and often some runtime overhead. |
---|
4394 | |
---|
4395 | Aside from those key differences, Rust and \CFA also have several similarities. |
---|
4396 | Both languages support no overhead interoperability with C and have minimal runtimes. |
---|
4397 | Both languages support inheritance and polymorphism through the use of interfaces (traits). |
---|
4398 | |
---|
4399 | |
---|
4400 | \subsubsection{D} |
---|
4401 | |
---|
4402 | The \Index*{D} programming language is an object-oriented, imperative, multi-paradigm system programming |
---|
4403 | language created by Walter Bright of Digital Mars and released in 2001. [.] |
---|
4404 | Though it originated as a re-engineering of \CC, D is a distinct language, having redesigned some core \CC features while also taking inspiration from other languages, notably \Index*{Java}, \Index*{Python}, Ruby, C\#, and Eiffel. |
---|
4405 | |
---|
4406 | D and \CFA both start with C and add productivity features. |
---|
4407 | The obvious difference is that D uses classes and inheritance while \CFA uses composition and interfaces. |
---|
4408 | D is closer to \CFA than \CC since it is limited to single inheritance and also supports interfaces. |
---|
4409 | Like \CC, and unlike \CFA, D uses garbage collection and has compile-time expanded templates. |
---|
4410 | D does not have any built-in concurrency constructs in the |
---|
4411 | language, though it does have a standard library for concurrency which includes the low-level primitives for concurrency. |
---|
4412 | |
---|
4413 | |
---|
4414 | \appendix |
---|
4415 | |
---|
4416 | |
---|
4417 | \section{Incompatible} |
---|
4418 | |
---|
4419 | The following incompatibles exist between \CFA and C, and are similar to Annex C for \CC~\cite{ANSI14:C++}. |
---|
4420 | |
---|
4421 | \begin{enumerate} |
---|
4422 | \item |
---|
4423 | \begin{description} |
---|
4424 | \item[Change:] add new keywords \\ |
---|
4425 | New keywords are added to \CFA (see~\VRef{s:NewKeywords}). |
---|
4426 | \item[Rationale:] keywords added to implement new semantics of \CFA. |
---|
4427 | \item[Effect on original feature:] change to semantics of well-defined feature. \\ |
---|
4428 | Any ISO C programs using these keywords as identifiers are invalid \CFA programs. |
---|
4429 | \item[Difficulty of converting:] keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism (see~\VRef{s:BackquoteIdentifiers}): |
---|
4430 | \item[How widely used:] clashes among new \CFA keywords and existing identifiers are rare. |
---|
4431 | \end{description} |
---|
4432 | |
---|
4433 | \item |
---|
4434 | \begin{description} |
---|
4435 | \item[Change:] type of character literal ©int© to ©char© to allow more intuitive overloading: |
---|
4436 | \begin{lstlisting} |
---|
4437 | int rtn( int i ); |
---|
4438 | int rtn( char c ); |
---|
4439 | rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§ |
---|
4440 | \end{lstlisting} |
---|
4441 | \item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first. |
---|
4442 | In particular, output of ©char© variable now print a character rather than the decimal ASCII value of the character. |
---|
4443 | \begin{lstlisting} |
---|
4444 | sout | 'x' | " " | (int)'x' | endl; |
---|
4445 | x 120 |
---|
4446 | \end{lstlisting} |
---|
4447 | Having to cast ©'x'© to ©char© is non-intuitive. |
---|
4448 | \item[Effect on original feature:] change to semantics of well-defined feature that depend on: |
---|
4449 | \begin{lstlisting} |
---|
4450 | sizeof( 'x' ) == sizeof( int ) |
---|
4451 | \end{lstlisting} |
---|
4452 | no long work the same in \CFA programs. |
---|
4453 | \item[Difficulty of converting:] simple |
---|
4454 | \item[How widely used:] programs that depend upon ©sizeof( 'x' )© are rare and can be changed to ©sizeof(char)©. |
---|
4455 | \end{description} |
---|
4456 | |
---|
4457 | \item |
---|
4458 | \begin{description} |
---|
4459 | \item[Change:] make string literals ©const©: |
---|
4460 | \begin{lstlisting} |
---|
4461 | char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§ |
---|
4462 | char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§ |
---|
4463 | \end{lstlisting} |
---|
4464 | The type of a string literal is changed from ©[] char© to ©const [] char©. |
---|
4465 | Similarly, the type of a wide string literal is changed from ©[] wchar_t© to ©const [] wchar_t©. |
---|
4466 | \item[Rationale:] This change is a safety issue: |
---|
4467 | \begin{lstlisting} |
---|
4468 | char * p = "abc"; |
---|
4469 | p[0] = 'w'; §\C{// segment fault or change constant literal}§ |
---|
4470 | \end{lstlisting} |
---|
4471 | The same problem occurs when passing a string literal to a routine that changes its argument. |
---|
4472 | \item[Effect on original feature:] change to semantics of well-defined feature. |
---|
4473 | \item[Difficulty of converting:] simple syntactic transformation, because string literals can be converted to ©char *©. |
---|
4474 | \item[How widely used:] programs that have a legitimate reason to treat string literals as pointers to potentially modifiable memory are rare. |
---|
4475 | \end{description} |
---|
4476 | |
---|
4477 | \item |
---|
4478 | \begin{description} |
---|
4479 | \item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope: |
---|
4480 | \begin{lstlisting} |
---|
4481 | int i; §\C{// forward definition}§ |
---|
4482 | int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§ |
---|
4483 | int i = 0; §\C{// definition}§ |
---|
4484 | \end{lstlisting} |
---|
4485 | is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed. |
---|
4486 | This change makes it impossible to define mutually referential file-local static objects, if initializers are restricted to the syntactic forms of C. For example, |
---|
4487 | \begin{lstlisting} |
---|
4488 | struct X { int i; struct X *next; }; |
---|
4489 | static struct X a; §\C{// forward definition}§ |
---|
4490 | static struct X b = { 0, ®&a® }; §\C{// forward reference, valid in C, invalid in \CFA}§ |
---|
4491 | static struct X a = { 1, &b }; §\C{// definition}§ |
---|
4492 | \end{lstlisting} |
---|
4493 | \item[Rationale:] avoids having different initialization rules for builtin types and userdefined types. |
---|
4494 | \item[Effect on original feature:] change to semantics of well-defined feature. |
---|
4495 | \item[Difficulty of converting:] the initializer for one of a set of mutually-referential file-local static objects must invoke a routine call to achieve the initialization. |
---|
4496 | \item[How widely used:] seldom |
---|
4497 | \end{description} |
---|
4498 | |
---|
4499 | \item |
---|
4500 | \begin{description} |
---|
4501 | \item[Change:] have ©struct© introduce a scope for nested types: |
---|
4502 | \begin{lstlisting} |
---|
4503 | enum ®Colour® { R, G, B, Y, C, M }; |
---|
4504 | struct Person { |
---|
4505 | enum ®Colour® { R, G, B }; §\C{// nested type}§ |
---|
4506 | struct Face { §\C{// nested type}§ |
---|
4507 | ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§ |
---|
4508 | }; |
---|
4509 | ß.ß®Colour® shirt; §\C{// type defined outside (top level)}§ |
---|
4510 | ®Colour® pants; §\C{// type defined same level}§ |
---|
4511 | Face looks[10]; §\C{// type defined same level}§ |
---|
4512 | }; |
---|
4513 | ®Colour® c = R; §\C{// type/enum defined same level}§ |
---|
4514 | Personß.ß®Colour® pc = Personß.ßR; §\C{// type/enum defined inside}§ |
---|
4515 | Personß.ßFace pretty; §\C{// type defined inside}§ |
---|
4516 | \end{lstlisting} |
---|
4517 | In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, i.e., the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing. |
---|
4518 | \CFA is C \emph{incompatible} on this issue, and provides semantics similar to \Index*[C++]{\CC}. |
---|
4519 | Nested types are not hoisted and can be referenced using the field selection operator ``©.©'', unlike the \CC scope-resolution operator ``©::©''. |
---|
4520 | \item[Rationale:] ©struct© scope is crucial to \CFA as an information structuring and hiding mechanism. |
---|
4521 | \item[Effect on original feature:] change to semantics of well-defined feature. |
---|
4522 | \item[Difficulty of converting:] Semantic transformation. |
---|
4523 | \item[How widely used:] C programs rarely have nest types because they are equivalent to the hoisted version. |
---|
4524 | \end{description} |
---|
4525 | |
---|
4526 | \item |
---|
4527 | \begin{description} |
---|
4528 | \item[Change:] In C++, the name of a nested class is local to its enclosing class. |
---|
4529 | \item[Rationale:] C++ classes have member functions which require that classes establish scopes. |
---|
4530 | \item[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: |
---|
4531 | \begin{lstlisting} |
---|
4532 | struct Y; §\C{// struct Y and struct X are at the same scope}§ |
---|
4533 | struct X { |
---|
4534 | struct Y { /* ... */ } y; |
---|
4535 | }; |
---|
4536 | \end{lstlisting} |
---|
4537 | 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. |
---|
4538 | Note: this is a consequence of the difference in scope rules, which is documented in 3.3. |
---|
4539 | \item[How widely used:] Seldom. |
---|
4540 | \end{description} |
---|
4541 | |
---|
4542 | \item |
---|
4543 | \begin{description} |
---|
4544 | \item[Change:] comma expression is disallowed as subscript |
---|
4545 | \item[Rationale:] safety issue to prevent subscripting error for multidimensional arrays: ©x[i,j]© instead of ©x[i][j]©, and this syntactic form then taken by \CFA for new style arrays. |
---|
4546 | \item[Effect on original feature:] change to semantics of well-defined feature. |
---|
4547 | \item[Difficulty of converting:] semantic transformation of ©x[i,j]© to ©x[(i,j)]© |
---|
4548 | \item[How widely used:] seldom. |
---|
4549 | \end{description} |
---|
4550 | \end{enumerate} |
---|
4551 | |
---|
4552 | |
---|
4553 | \section{New Keywords} |
---|
4554 | \label{s:NewKeywords} |
---|
4555 | |
---|
4556 | \begin{quote2} |
---|
4557 | \begin{tabular}{lll} |
---|
4558 | ©catch© & ©fallthrough© & ©otype© \\ |
---|
4559 | ©catchResume© & ©fallthru© & ©throw© \\ |
---|
4560 | ©choose© & ©finally© & ©throwResume© \\ |
---|
4561 | ©disable© & ©forall© & ©trait© \\ |
---|
4562 | ©dtype© & ©ftype© & ©try© \\ |
---|
4563 | ©enable© & ©lvalue© & \\ |
---|
4564 | \end{tabular} |
---|
4565 | \end{quote2} |
---|
4566 | |
---|
4567 | |
---|
4568 | \section{Standard Headers} |
---|
4569 | \label{s:StandardHeaders} |
---|
4570 | |
---|
4571 | C prescribes the following standard header-files~\cite[\S~7.1.2]{C11}: |
---|
4572 | \begin{quote2} |
---|
4573 | \begin{minipage}{\linewidth} |
---|
4574 | \begin{tabular}{lll} |
---|
4575 | assert.h & math.h & stdlib.h \\ |
---|
4576 | complex.h & setjmp.h & stdnoreturn.h \\ |
---|
4577 | ctype.h & signal.h & string.h \\ |
---|
4578 | errno.h & stdalign.h & tgmath.h \\ |
---|
4579 | fenv.h & stdarg.h & threads.h \\ |
---|
4580 | float.h & stdatomic.h & time.h \\ |
---|
4581 | inttypes.h & stdbool.h & uchar.h \\ |
---|
4582 | iso646.h & stddef.h & wchar.h \\ |
---|
4583 | limits.h & stdint.h & wctype.h \\ |
---|
4584 | locale.h & stdio.h & unistd.h\footnote{\CFA extension} |
---|
4585 | \end{tabular} |
---|
4586 | \end{minipage} |
---|
4587 | \end{quote2} |
---|
4588 | For the prescribed head-files, \CFA implicitly wraps their includes in an ©extern "C"©; |
---|
4589 | hence, names in these include files are not mangled\index{mangling!name} (see~\VRef{s:Interoperability}). |
---|
4590 | All other C header files must be explicitly wrapped in ©extern "C"© to prevent name mangling. |
---|
4591 | |
---|
4592 | |
---|
4593 | \section{I/O Library} |
---|
4594 | \label{s:IOLibrary} |
---|
4595 | \index{input/output library} |
---|
4596 | |
---|
4597 | The goal for the \CFA I/O is to make I/O as simple as possible in the common cases, while fully supporting polymorphism and user defined types in a consistent way. |
---|
4598 | The common case is printing out a sequence of variables separated by whitespace. |
---|
4599 | \begin{quote2} |
---|
4600 | \begin{tabular}{@{}l@{\hspace{3em}}l@{}} |
---|
4601 | \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ |
---|
4602 | \begin{lstlisting} |
---|
4603 | int x = 0, y = 1, z = 2; |
---|
4604 | ®sout® ®|® x ®|® y ®|® z ®| endl®; |
---|
4605 | \end{lstlisting} |
---|
4606 | & |
---|
4607 | \begin{lstlisting} |
---|
4608 | |
---|
4609 | cout << x << " " << y << " " << z << endl; |
---|
4610 | \end{lstlisting} |
---|
4611 | \end{tabular} |
---|
4612 | \end{quote2} |
---|
4613 | The \CFA form has half as many characters as the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators. |
---|
4614 | |
---|
4615 | The logical-or operator is used because it is the lowest-priority overloadable operator, other than assignment. |
---|
4616 | Therefore, fewer output expressions require parenthesis. |
---|
4617 | \begin{quote2} |
---|
4618 | \begin{tabular}{@{}ll@{}} |
---|
4619 | \textbf{\CFA:} |
---|
4620 | & |
---|
4621 | \begin{lstlisting} |
---|
4622 | sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl; |
---|
4623 | \end{lstlisting} |
---|
4624 | \\ |
---|
4625 | \textbf{\CC:} |
---|
4626 | & |
---|
4627 | \begin{lstlisting} |
---|
4628 | cout << x * 3 << y + 1 << (z << 2) << (x == y) << (x | y) << (x || y) << (x > z ? 1 : 2) << endl; |
---|
4629 | \end{lstlisting} |
---|
4630 | \end{tabular} |
---|
4631 | \end{quote2} |
---|
4632 | Finally, the logical-or operator has a link with the Shell pipe-operator for moving data, although data flows in the opposite direction. |
---|
4633 | |
---|
4634 | The implicit separator\index{I/O separator} character (space/blank) is a separator not a terminator. |
---|
4635 | The rules for implicitly adding the separator are: |
---|
4636 | \begin{enumerate} |
---|
4637 | \item |
---|
4638 | A separator does not appear at the start or end of a line. |
---|
4639 | \begin{lstlisting}[belowskip=0pt] |
---|
4640 | sout | 1 | 2 | 3 | endl; |
---|
4641 | \end{lstlisting} |
---|
4642 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4643 | 1 2 3 |
---|
4644 | \end{lstlisting} |
---|
4645 | \item |
---|
4646 | A separator does not appear before or after a character literal or variable. |
---|
4647 | \begin{lstlisting} |
---|
4648 | sout | '1' | '2' | '3' | endl; |
---|
4649 | 123 |
---|
4650 | \end{lstlisting} |
---|
4651 | \item |
---|
4652 | A separator does not appear before or after a null (empty) C string |
---|
4653 | \begin{lstlisting} |
---|
4654 | sout | 1 | "" | 2 | "" | 3 | endl; |
---|
4655 | 123 |
---|
4656 | \end{lstlisting} |
---|
4657 | which is a local mechanism to disable insertion of the separator character. |
---|
4658 | \item |
---|
4659 | A separator does not appear before a C string starting with the (extended) \Index{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off]@([{$£¥¡¿«@ |
---|
4660 | %$ |
---|
4661 | \begin{lstlisting}[mathescape=off] |
---|
4662 | sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x $" | 4 | "x £" | 5 | "x ¥" | 6 | "x ¡" | 7 |
---|
4663 | | "x ¿" | 8 | "x «" | 9 | endl; |
---|
4664 | \end{lstlisting} |
---|
4665 | %$ |
---|
4666 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4667 | x (1 x [2 x {3 x $4 x £5 x ¥6 x ¡7 x ¿8 x «9 |
---|
4668 | \end{lstlisting} |
---|
4669 | %$ |
---|
4670 | \item |
---|
4671 | A seperator does not appear after a C string ending with the (extended) \Index{ASCII}\index{ASCII!extended} characters: ©,.:;!?)]}%¢»© |
---|
4672 | \begin{lstlisting}[belowskip=0pt] |
---|
4673 | sout | 1 | ", x" | 2 | ". x" | 3 | ": x" | 4 | "; x" | 5 | "! x" | 6 | "? x" | 7 |
---|
4674 | | ") x" | 8 | "] x" | 9 | "} x" | 10 | "% x" | 11 | "¢ x" | 12 | "» x" | endl; |
---|
4675 | \end{lstlisting} |
---|
4676 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4677 | 1, x 2. x 3: x 4; x 5! x 6? x 7) x 8] x 9} x 10% x 11¢ 12» |
---|
4678 | \end{lstlisting} |
---|
4679 | \item |
---|
4680 | 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@ |
---|
4681 | \begin{lstlisting}[belowskip=0pt] |
---|
4682 | sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x" | "x " | 4 | " x" | "x\t" | 1 | "\tx" | endl; |
---|
4683 | \end{lstlisting} |
---|
4684 | \begin{lstlisting}[mathescape=off,showspaces=true,showtabs=true,aboveskip=0pt,belowskip=0pt] |
---|
4685 | x`1`x'2'x"3"x x 4 x x 1 x |
---|
4686 | \end{lstlisting} |
---|
4687 | \end{enumerate} |
---|
4688 | The following \CC-style \Index{manipulator}s allow further control over implicit seperation. |
---|
4689 | \begin{lstlisting}[mathescape=off,belowskip=0pt] |
---|
4690 | sout | sepOn | 1 | 2 | 3 | sepOn | endl; §\C{// separator at start of line}§ |
---|
4691 | \end{lstlisting} |
---|
4692 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4693 | 1 2 3 |
---|
4694 | \end{lstlisting} |
---|
4695 | \begin{lstlisting}[mathescape=off,aboveskip=0pt,belowskip=0pt] |
---|
4696 | sout | 1 | sepOff | 2 | 3 | endl; §\C{// turn off implicit separator temporarily}§ |
---|
4697 | \end{lstlisting} |
---|
4698 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4699 | 12 3 |
---|
4700 | \end{lstlisting} |
---|
4701 | \begin{lstlisting}[mathescape=off,aboveskip=0pt,belowskip=0pt] |
---|
4702 | sout | sepDisable | 1 | 2 | 3 | endl; §\C{// turn off implicit separation, affects all subsequent prints}§ |
---|
4703 | \end{lstlisting} |
---|
4704 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4705 | 123 |
---|
4706 | \end{lstlisting} |
---|
4707 | \begin{lstlisting}[mathescape=off,aboveskip=0pt,belowskip=0pt] |
---|
4708 | sout | 1 | sepOn | 2 | 3 | endl; §\C{// turn on implicit separator temporarily}§ |
---|
4709 | \end{lstlisting} |
---|
4710 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4711 | 1 23 |
---|
4712 | \end{lstlisting} |
---|
4713 | \begin{lstlisting}[mathescape=off,aboveskip=0pt,belowskip=0pt] |
---|
4714 | sout | sepEnable | 1 | 2 | 3 | endl; §\C{// turn on implicit separation, affects all subsequent prints}§ |
---|
4715 | \end{lstlisting} |
---|
4716 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] |
---|
4717 | 1 2 3 |
---|
4718 | \end{lstlisting} |
---|
4719 | \begin{lstlisting}[mathescape=off,aboveskip=0pt,aboveskip=0pt,belowskip=0pt] |
---|
4720 | sepSet( sout, ", $" ); §\C{// change separator from " " to ", \$"}§ |
---|
4721 | sout | 1 | 2 | 3 | endl; |
---|
4722 | \end{lstlisting} |
---|
4723 | %$ |
---|
4724 | \begin{lstlisting}[mathescape=off,showspaces=true,aboveskip=0pt] |
---|
4725 | 1, $2, $3 |
---|
4726 | \end{lstlisting} |
---|
4727 | %$ |
---|
4728 | \begin{comment} |
---|
4729 | #include <fstream> |
---|
4730 | |
---|
4731 | int main() { |
---|
4732 | int x = 3, y = 5, z = 7; |
---|
4733 | sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl; |
---|
4734 | sout | 1 | 2 | 3 | endl; |
---|
4735 | sout | '1' | '2' | '3' | endl; |
---|
4736 | sout | 1 | "" | 2 | "" | 3 | endl; |
---|
4737 | sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x $" | 4 | "x £" | 5 | "x ¥" | 6 | "x ¡" | 7 | "x ¿" | 8 | "x «" | 9 | endl; |
---|
4738 | sout | 1 | ", x" | 2 | ". x" | 3 | ": x" | 4 | "; x" | 5 | "! x" | 6 | "? x" | 7 | ") x" | 8 | "] x" | 9 | "} x" |
---|
4739 | | 10 | "% x" | 11 | "¢ x" | 12 | "» x" | endl; |
---|
4740 | sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x" | "x " | 4 | " x" | "x\t" | 1 | "\tx" | endl; |
---|
4741 | sout | sepOn | 1 | 2 | 3 | sepOn | endl; // separator at start of line |
---|
4742 | sout | 1 | sepOff | 2 | 3 | endl; // turn off implicit separator temporarily |
---|
4743 | sout | sepDisable | 1 | 2 | 3 | endl; // turn off implicit separation, affects all subsequent prints |
---|
4744 | sout | 1 | sepOn | 2 | 3 | endl; // turn on implicit separator temporarily |
---|
4745 | sout | sepEnable | 1 | 2 | 3 | endl; // turn on implicit separation, affects all subsequent prints |
---|
4746 | sepSet( sout, ", $" ); // change separator from " " to ", $" |
---|
4747 | sout | 1 | 2 | 3 | endl; |
---|
4748 | |
---|
4749 | } |
---|
4750 | |
---|
4751 | // Local Variables: // |
---|
4752 | // tab-width: 4 // |
---|
4753 | // End: // |
---|
4754 | \end{comment} |
---|
4755 | %$ |
---|
4756 | |
---|
4757 | |
---|
4758 | \section{Standard Library} |
---|
4759 | \label{s:StandardLibrary} |
---|
4760 | |
---|
4761 | The goal of the \CFA standard-library is to wrap many of the existing C library-routines that are explicitly polymorphic into implicitly polymorphic versions. |
---|
4762 | |
---|
4763 | |
---|
4764 | \subsection{malloc} |
---|
4765 | |
---|
4766 | \leavevmode |
---|
4767 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4768 | forall( otype T ) T * malloc( void );§\indexc{malloc}§ |
---|
4769 | forall( otype T ) T * malloc( char fill ); |
---|
4770 | forall( otype T ) T * malloc( T * ptr, size_t size ); |
---|
4771 | forall( otype T ) T * malloc( T * ptr, size_t size, unsigned char fill ); |
---|
4772 | forall( otype T ) T * calloc( size_t nmemb );§\indexc{calloc}§ |
---|
4773 | forall( otype T ) T * realloc( T * ptr, size_t size );§\indexc{ato}§ |
---|
4774 | forall( otype T ) T * realloc( T * ptr, size_t size, unsigned char fill ); |
---|
4775 | |
---|
4776 | forall( otype T ) T * aligned_alloc( size_t alignment );§\indexc{ato}§ |
---|
4777 | forall( otype T ) T * memalign( size_t alignment ); // deprecated |
---|
4778 | forall( otype T ) int posix_memalign( T ** ptr, size_t alignment ); |
---|
4779 | |
---|
4780 | forall( otype T ) T * memset( T * ptr, unsigned char fill ); // use default value '\0' for fill |
---|
4781 | forall( otype T ) T * memset( T * ptr ); // remove when default value available |
---|
4782 | \end{lstlisting} |
---|
4783 | |
---|
4784 | |
---|
4785 | \subsection{ato / strto} |
---|
4786 | |
---|
4787 | \leavevmode |
---|
4788 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4789 | int ato( const char * ptr );§\indexc{ato}§ |
---|
4790 | unsigned int ato( const char * ptr ); |
---|
4791 | long int ato( const char * ptr ); |
---|
4792 | unsigned long int ato( const char * ptr ); |
---|
4793 | long long int ato( const char * ptr ); |
---|
4794 | unsigned long long int ato( const char * ptr ); |
---|
4795 | float ato( const char * ptr ); |
---|
4796 | double ato( const char * ptr ); |
---|
4797 | long double ato( const char * ptr ); |
---|
4798 | float _Complex ato( const char * ptr ); |
---|
4799 | double _Complex ato( const char * ptr ); |
---|
4800 | long double _Complex ato( const char * ptr ); |
---|
4801 | |
---|
4802 | int strto( const char * sptr, char ** eptr, int base ); |
---|
4803 | unsigned int strto( const char * sptr, char ** eptr, int base ); |
---|
4804 | long int strto( const char * sptr, char ** eptr, int base ); |
---|
4805 | unsigned long int strto( const char * sptr, char ** eptr, int base ); |
---|
4806 | long long int strto( const char * sptr, char ** eptr, int base ); |
---|
4807 | unsigned long long int strto( const char * sptr, char ** eptr, int base ); |
---|
4808 | float strto( const char * sptr, char ** eptr ); |
---|
4809 | double strto( const char * sptr, char ** eptr ); |
---|
4810 | long double strto( const char * sptr, char ** eptr ); |
---|
4811 | float _Complex strto( const char * sptr, char ** eptr ); |
---|
4812 | double _Complex strto( const char * sptr, char ** eptr ); |
---|
4813 | long double _Complex strto( const char * sptr, char ** eptr ); |
---|
4814 | \end{lstlisting} |
---|
4815 | |
---|
4816 | |
---|
4817 | \subsection{bsearch / qsort} |
---|
4818 | |
---|
4819 | \leavevmode |
---|
4820 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4821 | forall( otype T | { int ?<?( T, T ); } ) |
---|
4822 | T * bsearch( const T key, const T * arr, size_t dimension );§\indexc{bsearch}§ |
---|
4823 | |
---|
4824 | forall( otype T | { int ?<?( T, T ); } ) |
---|
4825 | void qsort( const T * arr, size_t dimension );§\indexc{qsort}§ |
---|
4826 | \end{lstlisting} |
---|
4827 | |
---|
4828 | |
---|
4829 | \subsection{abs} |
---|
4830 | |
---|
4831 | \leavevmode |
---|
4832 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4833 | char abs( char );§\indexc{abs}§ |
---|
4834 | int abs( int ); |
---|
4835 | long int abs( long int ); |
---|
4836 | long long int abs( long long int ); |
---|
4837 | float abs( float ); |
---|
4838 | double abs( double ); |
---|
4839 | long double abs( long double ); |
---|
4840 | float abs( float _Complex ); |
---|
4841 | double abs( double _Complex ); |
---|
4842 | long double abs( long double _Complex ); |
---|
4843 | \end{lstlisting} |
---|
4844 | |
---|
4845 | |
---|
4846 | \subsection{random} |
---|
4847 | |
---|
4848 | \leavevmode |
---|
4849 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4850 | void rand48seed( long int s );§\indexc{rand48seed}§ |
---|
4851 | char rand48();§\indexc{rand48}§ |
---|
4852 | int rand48(); |
---|
4853 | unsigned int rand48(); |
---|
4854 | long int rand48(); |
---|
4855 | unsigned long int rand48(); |
---|
4856 | float rand48(); |
---|
4857 | double rand48(); |
---|
4858 | float _Complex rand48(); |
---|
4859 | double _Complex rand48(); |
---|
4860 | long double _Complex rand48(); |
---|
4861 | \end{lstlisting} |
---|
4862 | |
---|
4863 | |
---|
4864 | \subsection{min / max / clamp / swap} |
---|
4865 | |
---|
4866 | \leavevmode |
---|
4867 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4868 | forall( otype T | { int ?<?( T, T ); } ) |
---|
4869 | T min( const T t1, const T t2 );§\indexc{min}§ |
---|
4870 | |
---|
4871 | forall( otype T | { int ?>?( T, T ); } ) |
---|
4872 | T max( const T t1, const T t2 );§\indexc{max}§ |
---|
4873 | |
---|
4874 | forall( otype T | { T min( T, T ); T max( T, T ); } ) |
---|
4875 | T clamp( T value, T min_val, T max_val );§\indexc{clamp}§ |
---|
4876 | |
---|
4877 | forall( otype T ) |
---|
4878 | void swap( T * t1, T * t2 );§\indexc{swap}§ |
---|
4879 | \end{lstlisting} |
---|
4880 | |
---|
4881 | |
---|
4882 | \section{Math Library} |
---|
4883 | \label{s:Math Library} |
---|
4884 | |
---|
4885 | 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. |
---|
4886 | |
---|
4887 | |
---|
4888 | \subsection{General} |
---|
4889 | |
---|
4890 | \leavevmode |
---|
4891 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4892 | float fabs( float );§\indexc{fabs}§ |
---|
4893 | double fabs( double ); |
---|
4894 | long double fabs( long double ); |
---|
4895 | float cabs( float _Complex ); |
---|
4896 | double cabs( double _Complex ); |
---|
4897 | long double cabs( long double _Complex ); |
---|
4898 | |
---|
4899 | float ?%?( float, float );§\indexc{fmod}§ |
---|
4900 | float fmod( float, float ); |
---|
4901 | double ?%?( double, double ); |
---|
4902 | double fmod( double, double ); |
---|
4903 | long double ?%?( long double, long double ); |
---|
4904 | long double fmod( long double, long double ); |
---|
4905 | |
---|
4906 | float remainder( float, float );§\indexc{remainder}§ |
---|
4907 | double remainder( double, double ); |
---|
4908 | long double remainder( long double, long double ); |
---|
4909 | |
---|
4910 | [ int, float ] remquo( float, float );§\indexc{remquo}§ |
---|
4911 | float remquo( float, float, int * ); |
---|
4912 | [ int, double ] remquo( double, double ); |
---|
4913 | double remquo( double, double, int * ); |
---|
4914 | [ int, long double ] remquo( long double, long double ); |
---|
4915 | long double remquo( long double, long double, int * ); |
---|
4916 | |
---|
4917 | [ int, float ] div( float, float ); // alternative name for remquo |
---|
4918 | float div( float, float, int * );§\indexc{div}§ |
---|
4919 | [ int, double ] div( double, double ); |
---|
4920 | double div( double, double, int * ); |
---|
4921 | [ int, long double ] div( long double, long double ); |
---|
4922 | long double div( long double, long double, int * ); |
---|
4923 | |
---|
4924 | float fma( float, float, float );§\indexc{fma}§ |
---|
4925 | double fma( double, double, double ); |
---|
4926 | long double fma( long double, long double, long double ); |
---|
4927 | |
---|
4928 | float fdim( float, float );§\indexc{fdim}§ |
---|
4929 | double fdim( double, double ); |
---|
4930 | long double fdim( long double, long double ); |
---|
4931 | |
---|
4932 | float nan( const char * );§\indexc{nan}§ |
---|
4933 | double nan( const char * ); |
---|
4934 | long double nan( const char * ); |
---|
4935 | \end{lstlisting} |
---|
4936 | |
---|
4937 | |
---|
4938 | \subsection{Exponential} |
---|
4939 | |
---|
4940 | \leavevmode |
---|
4941 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4942 | float exp( float );§\indexc{exp}§ |
---|
4943 | double exp( double ); |
---|
4944 | long double exp( long double ); |
---|
4945 | float _Complex exp( float _Complex ); |
---|
4946 | double _Complex exp( double _Complex ); |
---|
4947 | long double _Complex exp( long double _Complex ); |
---|
4948 | |
---|
4949 | float exp2( float );§\indexc{exp2}§ |
---|
4950 | double exp2( double ); |
---|
4951 | long double exp2( long double ); |
---|
4952 | float _Complex exp2( float _Complex ); |
---|
4953 | double _Complex exp2( double _Complex ); |
---|
4954 | long double _Complex exp2( long double _Complex ); |
---|
4955 | |
---|
4956 | float expm1( float );§\indexc{expm1}§ |
---|
4957 | double expm1( double ); |
---|
4958 | long double expm1( long double ); |
---|
4959 | |
---|
4960 | float log( float );§\indexc{log}§ |
---|
4961 | double log( double ); |
---|
4962 | long double log( long double ); |
---|
4963 | float _Complex log( float _Complex ); |
---|
4964 | double _Complex log( double _Complex ); |
---|
4965 | long double _Complex log( long double _Complex ); |
---|
4966 | |
---|
4967 | float log2( float );§\indexc{log2}§ |
---|
4968 | double log2( double ); |
---|
4969 | long double log2( long double ); |
---|
4970 | float _Complex log2( float _Complex ); |
---|
4971 | double _Complex log2( double _Complex ); |
---|
4972 | long double _Complex log2( long double _Complex ); |
---|
4973 | |
---|
4974 | float log10( float );§\indexc{log10}§ |
---|
4975 | double log10( double ); |
---|
4976 | long double log10( long double ); |
---|
4977 | float _Complex log10( float _Complex ); |
---|
4978 | double _Complex log10( double _Complex ); |
---|
4979 | long double _Complex log10( long double _Complex ); |
---|
4980 | |
---|
4981 | float log1p( float );§\indexc{log1p}§ |
---|
4982 | double log1p( double ); |
---|
4983 | long double log1p( long double ); |
---|
4984 | |
---|
4985 | int ilogb( float );§\indexc{ilogb}§ |
---|
4986 | int ilogb( double ); |
---|
4987 | int ilogb( long double ); |
---|
4988 | |
---|
4989 | float logb( float );§\indexc{logb}§ |
---|
4990 | double logb( double ); |
---|
4991 | long double logb( long double ); |
---|
4992 | \end{lstlisting} |
---|
4993 | |
---|
4994 | |
---|
4995 | \subsection{Power} |
---|
4996 | |
---|
4997 | \leavevmode |
---|
4998 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
4999 | float sqrt( float );§\indexc{sqrt}§ |
---|
5000 | double sqrt( double ); |
---|
5001 | long double sqrt( long double ); |
---|
5002 | float _Complex sqrt( float _Complex ); |
---|
5003 | double _Complex sqrt( double _Complex ); |
---|
5004 | long double _Complex sqrt( long double _Complex ); |
---|
5005 | |
---|
5006 | float cbrt( float );§\indexc{cbrt}§ |
---|
5007 | double cbrt( double ); |
---|
5008 | long double cbrt( long double ); |
---|
5009 | |
---|
5010 | float hypot( float, float );§\indexc{hypot}§ |
---|
5011 | double hypot( double, double ); |
---|
5012 | long double hypot( long double, long double ); |
---|
5013 | |
---|
5014 | float pow( float, float );§\indexc{pow}§ |
---|
5015 | double pow( double, double ); |
---|
5016 | long double pow( long double, long double ); |
---|
5017 | float _Complex pow( float _Complex, float _Complex ); |
---|
5018 | double _Complex pow( double _Complex, double _Complex ); |
---|
5019 | long double _Complex pow( long double _Complex, long double _Complex ); |
---|
5020 | \end{lstlisting} |
---|
5021 | |
---|
5022 | |
---|
5023 | \subsection{Trigonometric} |
---|
5024 | |
---|
5025 | \leavevmode |
---|
5026 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
5027 | float sin( float );§\indexc{sin}§ |
---|
5028 | double sin( double ); |
---|
5029 | long double sin( long double ); |
---|
5030 | float _Complex sin( float _Complex ); |
---|
5031 | double _Complex sin( double _Complex ); |
---|
5032 | long double _Complex sin( long double _Complex ); |
---|
5033 | |
---|
5034 | float cos( float );§\indexc{cos}§ |
---|
5035 | double cos( double ); |
---|
5036 | long double cos( long double ); |
---|
5037 | float _Complex cos( float _Complex ); |
---|
5038 | double _Complex cos( double _Complex ); |
---|
5039 | long double _Complex cos( long double _Complex ); |
---|
5040 | |
---|
5041 | float tan( float );§\indexc{tan}§ |
---|
5042 | double tan( double ); |
---|
5043 | long double tan( long double ); |
---|
5044 | float _Complex tan( float _Complex ); |
---|
5045 | double _Complex tan( double _Complex ); |
---|
5046 | long double _Complex tan( long double _Complex ); |
---|
5047 | |
---|
5048 | float asin( float );§\indexc{asin}§ |
---|
5049 | double asin( double ); |
---|
5050 | long double asin( long double ); |
---|
5051 | float _Complex asin( float _Complex ); |
---|
5052 | double _Complex asin( double _Complex ); |
---|
5053 | long double _Complex asin( long double _Complex ); |
---|
5054 | |
---|
5055 | float acos( float );§\indexc{acos}§ |
---|
5056 | double acos( double ); |
---|
5057 | long double acos( long double ); |
---|
5058 | float _Complex acos( float _Complex ); |
---|
5059 | double _Complex acos( double _Complex ); |
---|
5060 | long double _Complex acos( long double _Complex ); |
---|
5061 | |
---|
5062 | float atan( float );§\indexc{atan}§ |
---|
5063 | double atan( double ); |
---|
5064 | long double atan( long double ); |
---|
5065 | float _Complex atan( float _Complex ); |
---|
5066 | double _Complex atan( double _Complex ); |
---|
5067 | long double _Complex atan( long double _Complex ); |
---|
5068 | |
---|
5069 | float atan2( float, float );§\indexc{atan2}§ |
---|
5070 | double atan2( double, double ); |
---|
5071 | long double atan2( long double, long double ); |
---|
5072 | |
---|
5073 | float atan( float, float ); // alternative name for atan2 |
---|
5074 | double atan( double, double );§\indexc{atan}§ |
---|
5075 | long double atan( long double, long double ); |
---|
5076 | \end{lstlisting} |
---|
5077 | |
---|
5078 | |
---|
5079 | \subsection{Hyperbolic} |
---|
5080 | |
---|
5081 | \leavevmode |
---|
5082 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
5083 | float sinh( float );§\indexc{sinh}§ |
---|
5084 | double sinh( double ); |
---|
5085 | long double sinh( long double ); |
---|
5086 | float _Complex sinh( float _Complex ); |
---|
5087 | double _Complex sinh( double _Complex ); |
---|
5088 | long double _Complex sinh( long double _Complex ); |
---|
5089 | |
---|
5090 | float cosh( float );§\indexc{cosh}§ |
---|
5091 | double cosh( double ); |
---|
5092 | long double cosh( long double ); |
---|
5093 | float _Complex cosh( float _Complex ); |
---|
5094 | double _Complex cosh( double _Complex ); |
---|
5095 | long double _Complex cosh( long double _Complex ); |
---|
5096 | |
---|
5097 | float tanh( float );§\indexc{tanh}§ |
---|
5098 | double tanh( double ); |
---|
5099 | long double tanh( long double ); |
---|
5100 | float _Complex tanh( float _Complex ); |
---|
5101 | double _Complex tanh( double _Complex ); |
---|
5102 | long double _Complex tanh( long double _Complex ); |
---|
5103 | |
---|
5104 | float asinh( float );§\indexc{asinh}§ |
---|
5105 | double asinh( double ); |
---|
5106 | long double asinh( long double ); |
---|
5107 | float _Complex asinh( float _Complex ); |
---|
5108 | double _Complex asinh( double _Complex ); |
---|
5109 | long double _Complex asinh( long double _Complex ); |
---|
5110 | |
---|
5111 | float acosh( float );§\indexc{acosh}§ |
---|
5112 | double acosh( double ); |
---|
5113 | long double acosh( long double ); |
---|
5114 | float _Complex acosh( float _Complex ); |
---|
5115 | double _Complex acosh( double _Complex ); |
---|
5116 | long double _Complex acosh( long double _Complex ); |
---|
5117 | |
---|
5118 | float atanh( float );§\indexc{atanh}§ |
---|
5119 | double atanh( double ); |
---|
5120 | long double atanh( long double ); |
---|
5121 | float _Complex atanh( float _Complex ); |
---|
5122 | double _Complex atanh( double _Complex ); |
---|
5123 | long double _Complex atanh( long double _Complex ); |
---|
5124 | \end{lstlisting} |
---|
5125 | |
---|
5126 | |
---|
5127 | \subsection{Error / Gamma} |
---|
5128 | |
---|
5129 | \leavevmode |
---|
5130 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
5131 | float erf( float );§\indexc{erf}§ |
---|
5132 | double erf( double ); |
---|
5133 | long double erf( long double ); |
---|
5134 | float _Complex erf( float _Complex ); |
---|
5135 | double _Complex erf( double _Complex ); |
---|
5136 | long double _Complex erf( long double _Complex ); |
---|
5137 | |
---|
5138 | float erfc( float );§\indexc{erfc}§ |
---|
5139 | double erfc( double ); |
---|
5140 | long double erfc( long double ); |
---|
5141 | float _Complex erfc( float _Complex ); |
---|
5142 | double _Complex erfc( double _Complex ); |
---|
5143 | long double _Complex erfc( long double _Complex ); |
---|
5144 | |
---|
5145 | float lgamma( float );§\indexc{lgamma}§ |
---|
5146 | double lgamma( double ); |
---|
5147 | long double lgamma( long double ); |
---|
5148 | float lgamma( float, int * ); |
---|
5149 | double lgamma( double, int * ); |
---|
5150 | long double lgamma( long double, int * ); |
---|
5151 | |
---|
5152 | float tgamma( float );§\indexc{tgamma}§ |
---|
5153 | double tgamma( double ); |
---|
5154 | long double tgamma( long double ); |
---|
5155 | \end{lstlisting} |
---|
5156 | |
---|
5157 | |
---|
5158 | \subsection{Nearest Integer} |
---|
5159 | |
---|
5160 | \leavevmode |
---|
5161 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
5162 | float floor( float );§\indexc{floor}§ |
---|
5163 | double floor( double ); |
---|
5164 | long double floor( long double ); |
---|
5165 | |
---|
5166 | float ceil( float );§\indexc{ceil}§ |
---|
5167 | double ceil( double ); |
---|
5168 | long double ceil( long double ); |
---|
5169 | |
---|
5170 | float trunc( float );§\indexc{trunc}§ |
---|
5171 | double trunc( double ); |
---|
5172 | long double trunc( long double ); |
---|
5173 | |
---|
5174 | float rint( float );§\indexc{rint}§ |
---|
5175 | long double rint( long double ); |
---|
5176 | long int rint( float ); |
---|
5177 | long int rint( double ); |
---|
5178 | long int rint( long double ); |
---|
5179 | long long int rint( float ); |
---|
5180 | long long int rint( double ); |
---|
5181 | long long int rint( long double ); |
---|
5182 | |
---|
5183 | long int lrint( float );§\indexc{lrint}§ |
---|
5184 | long int lrint( double ); |
---|
5185 | long int lrint( long double ); |
---|
5186 | long long int llrint( float ); |
---|
5187 | long long int llrint( double ); |
---|
5188 | long long int llrint( long double ); |
---|
5189 | |
---|
5190 | float nearbyint( float );§\indexc{nearbyint}§ |
---|
5191 | double nearbyint( double ); |
---|
5192 | long double nearbyint( long double ); |
---|
5193 | |
---|
5194 | float round( float );§\indexc{round}§ |
---|
5195 | long double round( long double ); |
---|
5196 | long int round( float ); |
---|
5197 | long int round( double ); |
---|
5198 | long int round( long double ); |
---|
5199 | long long int round( float ); |
---|
5200 | long long int round( double ); |
---|
5201 | long long int round( long double ); |
---|
5202 | |
---|
5203 | long int lround( float );§\indexc{lround}§ |
---|
5204 | long int lround( double ); |
---|
5205 | long int lround( long double ); |
---|
5206 | long long int llround( float ); |
---|
5207 | long long int llround( double ); |
---|
5208 | long long int llround( long double ); |
---|
5209 | \end{lstlisting} |
---|
5210 | |
---|
5211 | |
---|
5212 | \subsection{Manipulation} |
---|
5213 | |
---|
5214 | \leavevmode |
---|
5215 | \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] |
---|
5216 | float copysign( float, float );§\indexc{copysign}§ |
---|
5217 | double copysign( double, double ); |
---|
5218 | long double copysign( long double, long double ); |
---|
5219 | |
---|
5220 | float frexp( float, int * );§\indexc{frexp}§ |
---|
5221 | double frexp( double, int * ); |
---|
5222 | long double frexp( long double, int * ); |
---|
5223 | |
---|
5224 | float ldexp( float, int );§\indexc{ldexp}§ |
---|
5225 | double ldexp( double, int ); |
---|
5226 | long double ldexp( long double, int ); |
---|
5227 | |
---|
5228 | [ float, float ] modf( float );§\indexc{modf}§ |
---|
5229 | float modf( float, float * ); |
---|
5230 | [ double, double ] modf( double ); |
---|
5231 | double modf( double, double * ); |
---|
5232 | [ long double, long double ] modf( long double ); |
---|
5233 | long double modf( long double, long double * ); |
---|
5234 | |
---|
5235 | float nextafter( float, float );§\indexc{nextafter}§ |
---|
5236 | double nextafter( double, double ); |
---|
5237 | long double nextafter( long double, long double ); |
---|
5238 | |
---|
5239 | float nexttoward( float, long double );§\indexc{nexttoward}§ |
---|
5240 | double nexttoward( double, long double ); |
---|
5241 | long double nexttoward( long double, long double ); |
---|
5242 | |
---|
5243 | float scalbn( float, int );§\indexc{scalbn}§ |
---|
5244 | double scalbn( double, int ); |
---|
5245 | long double scalbn( long double, int ); |
---|
5246 | |
---|
5247 | float scalbln( float, long int );§\indexc{scalbln}§ |
---|
5248 | double scalbln( double, long int ); |
---|
5249 | long double scalbln( long double, long int ); |
---|
5250 | \end{lstlisting} |
---|
5251 | |
---|
5252 | |
---|
5253 | \section{Rational Numbers} |
---|
5254 | \label{s:RationalNumbers} |
---|
5255 | |
---|
5256 | Rational numbers are numbers written as a ratio, \ie as a fraction, where the numerator (top number) and the denominator (bottom number) are whole numbers. |
---|
5257 | When creating and computing with rational numbers, results are constantly reduced to keep the numerator and denominator as small as possible. |
---|
5258 | |
---|
5259 | \begin{lstlisting}[belowskip=0pt] |
---|
5260 | // implementation |
---|
5261 | struct Rational {§\indexc{Rational}§ |
---|
5262 | long int numerator, denominator; // invariant: denominator > 0 |
---|
5263 | }; // Rational |
---|
5264 | |
---|
5265 | // constants |
---|
5266 | extern struct Rational 0; |
---|
5267 | extern struct Rational 1; |
---|
5268 | |
---|
5269 | // constructors |
---|
5270 | Rational rational(); |
---|
5271 | Rational rational( long int n ); |
---|
5272 | Rational rational( long int n, long int d ); |
---|
5273 | |
---|
5274 | // getter/setter for numerator/denominator |
---|
5275 | long int numerator( Rational r ); |
---|
5276 | long int numerator( Rational r, long int n ); |
---|
5277 | long int denominator( Rational r ); |
---|
5278 | long int denominator( Rational r, long int d ); |
---|
5279 | |
---|
5280 | // comparison |
---|
5281 | int ?==?( Rational l, Rational r ); |
---|
5282 | int ?!=?( Rational l, Rational r ); |
---|
5283 | int ?<?( Rational l, Rational r ); |
---|
5284 | int ?<=?( Rational l, Rational r ); |
---|
5285 | int ?>?( Rational l, Rational r ); |
---|
5286 | int ?>=?( Rational l, Rational r ); |
---|
5287 | |
---|
5288 | // arithmetic |
---|
5289 | Rational -?( Rational r ); |
---|
5290 | Rational ?+?( Rational l, Rational r ); |
---|
5291 | Rational ?-?( Rational l, Rational r ); |
---|
5292 | Rational ?*?( Rational l, Rational r ); |
---|
5293 | Rational ?/?( Rational l, Rational r ); |
---|
5294 | |
---|
5295 | // conversion |
---|
5296 | double widen( Rational r ); |
---|
5297 | Rational narrow( double f, long int md ); |
---|
5298 | |
---|
5299 | // I/O |
---|
5300 | forall( dtype istype | istream( istype ) ) istype * ?|?( istype *, Rational * ); |
---|
5301 | forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, Rational ); |
---|
5302 | \end{lstlisting} |
---|
5303 | |
---|
5304 | |
---|
5305 | \bibliographystyle{plain} |
---|
5306 | \bibliography{cfa} |
---|
5307 | |
---|
5308 | |
---|
5309 | \addcontentsline{toc}{section}{\indexname} % add index name to table of contents |
---|
5310 | \begin{theindex} |
---|
5311 | Italic page numbers give the location of the main entry for the referenced term. |
---|
5312 | Plain page numbers denote uses of the indexed term. |
---|
5313 | Entries for grammar non-terminals are italicized. |
---|
5314 | A typewriter font is used for grammar terminals and program identifiers. |
---|
5315 | \indexspace |
---|
5316 | \input{user.ind} |
---|
5317 | \end{theindex} |
---|
5318 | |
---|
5319 | |
---|
5320 | \end{document} |
---|
5321 | |
---|
5322 | % Local Variables: % |
---|
5323 | % tab-width: 4 % |
---|
5324 | % fill-column: 100 % |
---|
5325 | % compile-command: "make" % |
---|
5326 | % End: % |
---|