- Timestamp:
- Apr 28, 2021, 4:56:50 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 8d66610
- Parents:
- feacef9 (diff), b7fd2db6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- doc
- Files:
-
- 17 added
- 3 deleted
- 19 edited
- 1 moved
-
LaTeXmacros/lstlang.sty (modified) (2 diffs)
-
bibliography/pl.bib (modified) (2 diffs)
-
theses/andrew_beach_MMath/Makefile (modified) (5 diffs)
-
theses/andrew_beach_MMath/exception-hierarchy.fig (added)
-
theses/andrew_beach_MMath/existing.tex (modified) (12 diffs)
-
theses/andrew_beach_MMath/features.tex (modified) (17 diffs)
-
theses/andrew_beach_MMath/future.tex (modified) (1 diff)
-
theses/andrew_beach_MMath/implement.tex (modified) (21 diffs)
-
theses/andrew_beach_MMath/stack-marking.fig (added)
-
theses/andrew_beach_MMath/thesis-frontpgs.tex (deleted)
-
theses/andrew_beach_MMath/thesis.tex (deleted)
-
theses/andrew_beach_MMath/uw-ethesis.cls (deleted)
-
theses/andrew_beach_MMath/uw-ethesis.tex (modified) (5 diffs)
-
theses/mubeen_zulfiqar_MMath/.gitignore (added)
-
theses/mubeen_zulfiqar_MMath/AllocDS1.fig (added)
-
theses/mubeen_zulfiqar_MMath/AllocDS2.fig (added)
-
theses/mubeen_zulfiqar_MMath/Makefile (added)
-
theses/mubeen_zulfiqar_MMath/allocator.tex (added)
-
theses/mubeen_zulfiqar_MMath/background.tex (added)
-
theses/mubeen_zulfiqar_MMath/benchmarks.tex (added)
-
theses/mubeen_zulfiqar_MMath/conclusion.tex (added)
-
theses/mubeen_zulfiqar_MMath/intro.tex (added)
-
theses/mubeen_zulfiqar_MMath/thesis.tex (added)
-
theses/mubeen_zulfiqar_MMath/uw-ethesis-frontpgs.tex (added)
-
theses/mubeen_zulfiqar_MMath/uw-ethesis.bib (moved) (moved from doc/theses/andrew_beach_MMath/thesis.bib ) (2 diffs)
-
theses/mubeen_zulfiqar_MMath/uw-ethesis.tex (added)
-
theses/thierry_delisle_PhD/code/readyQ_proto/dynamic_entropy.hpp (added)
-
theses/thierry_delisle_PhD/code/readyQ_proto/links.hpp (modified) (1 diff)
-
theses/thierry_delisle_PhD/code/readyQ_proto/links2.hpp (added)
-
theses/thierry_delisle_PhD/code/readyQ_proto/ntmove.cpp (added)
-
theses/thierry_delisle_PhD/code/readyQ_proto/processor_list.hpp (modified) (5 diffs)
-
theses/thierry_delisle_PhD/code/readyQ_proto/processor_list_good.cpp (modified) (1 diff)
-
theses/thierry_delisle_PhD/code/readyQ_proto/randbit.cpp (modified) (1 diff)
-
theses/thierry_delisle_PhD/code/readyQ_proto/relaxed_list.cpp (modified) (11 diffs)
-
theses/thierry_delisle_PhD/code/readyQ_proto/snzi-packed.hpp (modified) (2 diffs)
-
theses/thierry_delisle_PhD/code/readyQ_proto/snzi.hpp (modified) (1 diff)
-
theses/thierry_delisle_PhD/code/readyQ_proto/utils.hpp (modified) (4 diffs)
-
theses/thierry_delisle_PhD/code/readyQ_proto/work_stealing.hpp (modified) (7 diffs)
-
user/figures/Cdecl.fig (modified) (3 diffs)
-
user/user.tex (modified) (140 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/lstlang.sty
rfeacef9 r5407cdc 8 8 %% Created On : Sat May 13 16:34:42 2017 9 9 %% Last Modified By : Peter A. Buhr 10 %% Last Modified On : Wed Sep 23 22:40:04 202011 %% Update Count : 2 410 %% Last Modified On : Wed Feb 17 09:21:15 2021 11 %% Update Count : 27 12 12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 13 … … 113 113 morekeywords={ 114 114 _Alignas, _Alignof, __alignof, __alignof__, asm, __asm, __asm__, __attribute, __attribute__, 115 auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,116 coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally, 115 auto, basetypeof, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__, 116 coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally, fixup, 117 117 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__, 118 118 inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or, 119 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, thread,120 _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,119 otype, restrict, __restrict, __restrict__, recover, report, __signed, __signed__, _Static_assert, suspend, 120 thread, _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__, 121 121 virtual, __volatile, __volatile__, waitfor, when, with, zero_t, 122 122 }, -
doc/bibliography/pl.bib
rfeacef9 r5407cdc 1797 1797 } 1798 1798 1799 @article{Delisle2 0,1799 @article{Delisle21, 1800 1800 keywords = {concurrency, Cforall}, 1801 1801 contributer = {pabuhr@plg}, 1802 1802 author = {Thierry Delisle and Peter A. Buhr}, 1803 1803 title = {Advanced Control-flow and Concurrency in \textsf{C}$\mathbf{\forall}$}, 1804 year = 2020,1805 1804 journal = spe, 1806 pages = {1-38}, 1807 note = {\href{https://doi-org.proxy.lib.uwaterloo.ca/10.1002/spe.2925}{https://\-doi-org.proxy.lib.uwaterloo.ca/\-10.1002/\-spe.2925}}, 1808 note = {}, 1805 month = may, 1806 year = 2021, 1807 volume = 51, 1808 number = 5, 1809 pages = {1005-1042}, 1810 note = {\href{https://onlinelibrary.wiley.com/doi/10.1002/spe.2925}{https://\-onlinelibrary.wiley.com/\-doi/\-10.1002/\-spe.2925}}, 1809 1811 } 1810 1812 … … 3300 3302 month = jan, 3301 3303 address = {Waterloo, Ontario, Canada, N2L 3G1}, 3302 note = {\ textsf{http://uwspace.uwaterloo.ca/\-bitstream/\-10012/\-3501/\-1/\-Thesis.pdf}},3304 note = {\href{http://uwspace.uwaterloo.ca/bitstream/10012/3501/1/Thesis.pdf}{http://\-uwspace.uwaterloo.ca/\-bitstream/\-10012/\-3501/\-1/\-Thesis.pdf}}, 3303 3305 } 3304 3306 -
doc/theses/andrew_beach_MMath/Makefile
rfeacef9 r5407cdc 4 4 BUILD=out 5 5 TEXSRC=$(wildcard *.tex) 6 FIGSRC=$(wildcard *.fig) 6 7 BIBSRC=$(wildcard *.bib) 7 8 STYSRC=$(wildcard *.sty) … … 13 14 BASE= ${DOC:%.pdf=%} 14 15 16 RAWSRC=${TEXSRC} ${BIBSRC} ${STYSRC} ${CLSSRC} 17 FIGTEX=${FIGSRC:%.fig=${BUILD}/%.tex} 18 15 19 ### Special Rules: 16 20 … … 18 22 19 23 ### Commands: 20 LATEX=TEXINPUTS=${TEXLIB} pdflatex -halt-on-error -output-directory=${BUILD}24 LATEX=TEXINPUTS=${TEXLIB} latex -halt-on-error -output-directory=${BUILD} 21 25 BIBTEX=BIBINPUTS=${BIBLIB} bibtex 22 26 GLOSSARY=INDEXSTYLE=${BUILD} makeglossaries-lite … … 26 30 all: ${DOC} 27 31 28 ${BUILD}/${DOC}: ${TEXSRC} ${BIBSRC} ${STYSRC} ${CLSSRC} Makefile | ${BUILD} 32 # The main rule, it does all the tex/latex processing. 33 ${BUILD}/${BASE}.dvi: ${RAWSRC} ${FIGTEX} Makefile | ${BUILD} 29 34 ${LATEX} ${BASE} 30 35 ${BIBTEX} ${BUILD}/${BASE} … … 33 38 ${LATEX} ${BASE} 34 39 35 ${DOC}: ${BUILD}/${DOC} 36 cp $< $@ 40 # Convert xfig output to tex. (Generates \special declarations.) 41 ${FIGTEX}: ${BUILD}/%.tex: %.fig | ${BUILD} 42 fig2dev -L eepic $< > $@ 43 44 # Step through dvi & postscript to handle xfig specials. 45 %.pdf : ${BUILD}/%.dvi 46 dvipdf $^ $@ 37 47 38 48 ${BUILD}: -
doc/theses/andrew_beach_MMath/existing.tex
rfeacef9 r5407cdc 14 14 \section{Overloading and \lstinline{extern}} 15 15 \CFA has extensive overloading, allowing multiple definitions of the same name 16 to be defined .~\cite{Moss18}16 to be defined~\cite{Moss18}. 17 17 \begin{cfa} 18 18 char i; int i; double i; $\C[3.75in]{// variable overload}$ … … 46 46 pointers using the ampersand (@&@) instead of the pointer asterisk (@*@). \CFA 47 47 references may also be mutable or non-mutable. If mutable, a reference variable 48 may be assigned tousing the address-of operator (@&@), which converts the48 may be assigned using the address-of operator (@&@), which converts the 49 49 reference to a pointer. 50 50 \begin{cfa} … … 58 58 \section{Constructors and Destructors} 59 59 60 Both constructors and destructors are operators, which means they are just60 Both constructors and destructors are operators, which means they are 61 61 functions with special operator names rather than type names in \Cpp. The 62 62 special operator names may be used to call the functions explicitly (not … … 64 64 65 65 In general, operator names in \CFA are constructed by bracketing an operator 66 token with @?@, which indicates wherethe arguments. For example, infixed66 token with @?@, which indicates the position of the arguments. For example, infixed 67 67 multiplication is @?*?@ while prefix dereference is @*?@. This syntax make it 68 68 easy to tell the difference between prefix operations (such as @++?@) and … … 89 89 definition, \CFA creates a default and copy constructor, destructor and 90 90 assignment (like \Cpp). It is possible to define constructors/destructors for 91 basic and existing types .91 basic and existing types (unlike \Cpp). 92 92 93 93 \section{Polymorphism} … … 120 120 do_once(value); 121 121 } 122 void do_once( inti) { ... } // provide assertion123 inti;122 void do_once(@int@ i) { ... } // provide assertion 123 @int@ i; 124 124 do_twice(i); // implicitly pass assertion do_once to do_twice 125 125 \end{cfa} … … 172 172 declarations instead of parameters, returns, and local variable declarations. 173 173 \begin{cfa} 174 forall(dtype T)174 forall(dtype @T@) 175 175 struct node { 176 node(T) * next; // generic linked node 177 T * data; 178 } 176 node(@T@) * next; // generic linked node 177 @T@ * data; 178 } 179 node(@int@) inode; 179 180 \end{cfa} 180 181 The generic type @node(T)@ is an example of a polymorphic-type usage. Like \Cpp 181 template susage, a polymorphic-type usage must specify a type parameter.182 template usage, a polymorphic-type usage must specify a type parameter. 182 183 183 184 There are many other polymorphism features in \CFA but these are the ones used 184 185 by the exception system. 185 186 186 \section{Con currency}187 \CFA has a number of concurrency features: @thread@, @monitor@, @mutex@188 parameters, @coroutine@ and @generator@.The two features that interact with189 the exception system are @ thread@ and @coroutine@; they and their supporting187 \section{Control Flow} 188 \CFA has a number of advanced control-flow features: @generator@, @coroutine@, @monitor@, @mutex@ parameters, and @thread@. 189 The two features that interact with 190 the exception system are @coroutine@ and @thread@; they and their supporting 190 191 constructs are described here. 191 192 … … 216 217 CountUp countup; 217 218 \end{cfa} 218 Each coroutine has @main@ function, which takes a reference to a coroutine219 Each coroutine has a @main@ function, which takes a reference to a coroutine 219 220 object and returns @void@. 220 221 \begin{cfa}[numbers=left] … … 230 231 In this function, or functions called by this function (helper functions), the 231 232 @suspend@ statement is used to return execution to the coroutine's caller 232 without terminating the coroutine .233 without terminating the coroutine's function. 233 234 234 235 A coroutine is resumed by calling the @resume@ function, \eg @resume(countup)@. … … 242 243 @resume(countup).next@. 243 244 244 \subsection{Monitor s and Mutex}245 \subsection{Monitor and Mutex Parameter} 245 246 Concurrency does not guarantee ordering; without ordering results are 246 247 non-deterministic. To claw back ordering, \CFA uses monitors and @mutex@ … … 260 261 and only one runs at a time. 261 262 262 \subsection{Thread s}263 \subsection{Thread} 263 264 Functions, generators, and coroutines are sequential so there is only a single 264 265 (but potentially sophisticated) execution path in a program. Threads introduce … … 268 269 monitors and mutex parameters. For threads to work safely with other threads, 269 270 also requires mutual exclusion in the form of a communication rendezvous, which 270 also supports internal synchronization as for mutex objects. For exceptions 271 only t he basic two basic operations are important: threadfork and join.271 also supports internal synchronization as for mutex objects. For exceptions, 272 only two basic thread operations are important: fork and join. 272 273 273 274 Threads are created like coroutines with an associated @main@ function: -
doc/theses/andrew_beach_MMath/features.tex
rfeacef9 r5407cdc 2 2 3 3 This chapter covers the design and user interface of the \CFA 4 exception-handling mechanism. 4 exception-handling mechanism (EHM). % or exception system. 5 6 We will begin with an overview of EHMs in general. It is not a strict 7 definition of all EHMs nor an exaustive list of all possible features. 8 However it does cover the most common structure and features found in them. 9 10 % We should cover what is an exception handling mechanism and what is an 11 % exception before this. Probably in the introduction. Some of this could 12 % move there. 13 \paragraph{Raise / Handle} 14 An exception operation has two main parts: raise and handle. 15 These terms are sometimes also known as throw and catch but this work uses 16 throw/catch as a particular kind of raise/handle. 17 These are the two parts that the user will write themselves and may 18 be the only two pieces of the EHM that have any syntax in the language. 19 20 \subparagraph{Raise} 21 The raise is the starting point for exception handling. It marks the beginning 22 of exception handling by \newterm{raising} an excepion, which passes it to 23 the EHM. 24 25 Some well known examples include the @throw@ statements of \Cpp and Java and 26 the \codePy{raise} statement from Python. In real systems a raise may preform 27 some other work (such as memory management) but for the purposes of this 28 overview that can be ignored. 29 30 \subparagraph{Handle} 31 The purpose of most exception operations is to run some user code to handle 32 that exception. This code is given, with some other information, in a handler. 33 34 A handler has three common features: the previously mentioned user code, a 35 region of code they cover and an exception label/condition that matches 36 certain exceptions. 37 Only raises inside the covered region and raising exceptions that match the 38 label can be handled by a given handler. 39 Different EHMs will have different rules to pick a handler 40 if multipe handlers could be used such as ``best match" or ``first found". 41 42 The @try@ statements of \Cpp, Java and Python are common examples. All three 43 also show another common feature of handlers, they are grouped by the covered 44 region. 45 46 \paragraph{Propagation} 47 After an exception is raised comes what is usually the biggest step for the 48 EHM: finding and setting up the handler. The propogation from raise to 49 handler can be broken up into three different tasks: searching for a handler, 50 matching against the handler and installing the handler. 51 52 \subparagraph{Searching} 53 The EHM begins by searching for handlers that might be used to handle 54 the exception. Searching is usually independent of the exception that was 55 thrown as it looks for handlers that have the raise site in their covered 56 region. 57 This includes handlers in the current function, as well as any in callers 58 on the stack that have the function call in their covered region. 59 60 \subparagraph{Matching} 61 Each handler found has to be matched with the raised exception. The exception 62 label defines a condition that be use used with exception and decides if 63 there is a match or not. 64 65 In languages where the first match is used this step is intertwined with 66 searching, a match check is preformed immediately after the search finds 67 a possible handler. 68 69 \subparagraph{Installing} 70 After a handler is chosen it must be made ready to run. 71 The implementation can vary widely to fit with the rest of the 72 design of the EHM. The installation step might be trivial or it could be 73 the most expensive step in handling an exception. The latter tends to be the 74 case when stack unwinding is involved. 75 76 If a matching handler is not guarantied to be found the EHM will need a 77 different course of action here in the cases where no handler matches. 78 This is only required with unchecked exceptions as checked exceptions 79 (such as in Java) can make than guaranty. 80 This different action can also be installing a handler but it is usually an 81 implicat and much more general one. 82 83 \subparagraph{Hierarchy} 84 A common way to organize exceptions is in a hierarchical structure. 85 This is especially true in object-orientated languages where the 86 exception hierarchy is a natural extension of the object hierarchy. 87 88 Consider the following hierarchy of exceptions: 89 \begin{center} 90 \input{exception-hierarchy} 91 \end{center} 92 93 A handler labelled with any given exception can handle exceptions of that 94 type or any child type of that exception. The root of the exception hierarchy 95 (here \codeC{exception}) acts as a catch-all, leaf types catch single types 96 and the exceptions in the middle can be used to catch different groups of 97 related exceptions. 98 99 This system has some notable advantages, such as multiple levels of grouping, 100 the ability for libraries to add new exception types and the isolation 101 between different sub-hierarchies. 102 This design is used in \CFA even though it is not a object-orientated 103 language using different tools to create the hierarchy. 104 105 % Could I cite the rational for the Python IO exception rework? 106 107 \paragraph{Completion} 108 After the handler has finished the entire exception operation has to complete 109 and continue executing somewhere else. This step is usually simple, 110 both logically and in its implementation, as the installation of the handler 111 is usually set up to do most of the work. 112 113 The EHM can return control to many different places, 114 the most common are after the handler definition and after the raise. 115 116 \paragraph{Communication} 117 For effective exception handling, additional information is usually passed 118 from the raise to the handler. 119 So far only communication of the exceptions' identity has been covered. 120 A common method is putting fields into the exception instance and giving the 121 handler access to them. 5 122 6 123 \section{Virtuals} 7 Virtual types and casts are not part of the exception system nor are they 8 required for an exception system. But an object-oriented style hierarchy is a 9 great way of organizing exceptions so a minimal virtual system has been added 10 to \CFA. 11 12 The pattern of a simple hierarchy was borrowed from object-oriented 13 programming was chosen for several reasons. 14 The first is that it allows new exceptions to be added in user code 15 and in libraries independently of each other. Another is it allows for 16 different levels of exception grouping (all exceptions, all IO exceptions or 17 a particular IO exception). Also it also provides a simple way of passing 18 data back and forth across the throw. 19 20 Virtual types and casts are not required for a basic exception-system but are 21 useful for advanced exception features. However, \CFA is not object-oriented so 22 there is no obvious concept of virtuals. Hence, to create advanced exception 23 features for this work, I needed to design and implement a virtual-like 24 system for \CFA. 25 26 % NOTE: Maybe we should but less of the rational here. 27 Object-oriented languages often organized exceptions into a simple hierarchy, 28 \eg Java. 29 \begin{center} 30 \setlength{\unitlength}{4000sp}% 31 \begin{picture}(1605,612)(2011,-1951) 32 \put(2100,-1411){\vector(1, 0){225}} 33 \put(3450,-1411){\vector(1, 0){225}} 34 \put(3550,-1411){\line(0,-1){225}} 35 \put(3550,-1636){\vector(1, 0){150}} 36 \put(3550,-1636){\line(0,-1){225}} 37 \put(3550,-1861){\vector(1, 0){150}} 38 \put(2025,-1490){\makebox(0,0)[rb]{\LstBasicStyle{exception}}} 39 \put(2400,-1460){\makebox(0,0)[lb]{\LstBasicStyle{arithmetic}}} 40 \put(3750,-1460){\makebox(0,0)[lb]{\LstBasicStyle{underflow}}} 41 \put(3750,-1690){\makebox(0,0)[lb]{\LstBasicStyle{overflow}}} 42 \put(3750,-1920){\makebox(0,0)[lb]{\LstBasicStyle{zerodivide}}} 43 \end{picture}% 44 \end{center} 45 The hierarchy provides the ability to handle an exception at different degrees 46 of specificity (left to right). Hence, it is possible to catch a more general 47 exception-type in higher-level code where the implementation details are 48 unknown, which reduces tight coupling to the lower-level implementation. 49 Otherwise, low-level code changes require higher-level code changes, \eg, 50 changing from raising @underflow@ to @overflow@ at the low level means changing 51 the matching catch at the high level versus catching the general @arithmetic@ 52 exception. In detail, each virtual type may have a parent and can have any 53 number of children. A type's descendants are its children and its children's 54 descendants. A type may not be its own descendant. 55 56 The exception hierarchy allows a handler (@catch@ clause) to match multiple 57 exceptions, \eg a base-type handler catches both base and derived 58 exception-types. 59 \begin{cfa} 60 try { 61 ... 62 } catch(arithmetic &) { 63 ... // handle arithmetic, underflow, overflow, zerodivide 64 } 65 \end{cfa} 66 Most exception mechanisms perform a linear search of the handlers and select 67 the first matching handler, so the order of handers is now important because 68 matching is many to one. 69 70 Each virtual type needs an associated virtual table. A virtual table is a 71 structure with fields for all the virtual members of a type. A virtual type has 72 all the virtual members of its parent and can add more. It may also update the 73 values of the virtual members and often does. 124 Virtual types and casts are not part of \CFA's EHM nor are they required for 125 any EHM. But \CFA uses a hierarchial system of exceptions and this feature 126 is leveraged to create that. 127 128 % Maybe talk about why the virtual system is so minimal. 129 % Created for but not a part of the exception system. 130 131 The virtual system supports multiple ``trees" of types. Each tree is 132 a simple hierarchy with a single root type. Each type in a tree has exactly 133 one parent -- except for the root type which has zero parents -- and any 134 number of children. 135 Any type that belongs to any of these trees is called a virtual type. 136 137 % A type's ancestors are its parent and its parent's ancestors. 138 % The root type has no ancestors. 139 % A type's decendents are its children and its children's decendents. 140 141 Every virtual type also has a list of virtual members. Children inherit 142 their parent's list of virtual members but may add new members to it. 143 It is important to note that these are virtual members, not virtual methods 144 of object-orientated programming, and can be of any type. 145 However, since \CFA has function pointers and they are allowed, virtual 146 members can be used to mimic virtual methods. 147 148 Each virtual type has a unique id. 149 This unique id and all the virtual members are combined 150 into a virtual table type. Each virtual type has a pointer to a virtual table 151 as a hidden field. 152 153 Up until this point the virtual system is similar to ones found in 154 object-orientated languages but this where \CFA diverges. Objects encapsulate a 155 single set of behaviours in each type, universally across the entire program, 156 and indeed all programs that use that type definition. In this sense the 157 types are ``closed" and cannot be altered. 158 159 In \CFA types do not encapsulate any behaviour. Traits are local and 160 types can begin to statify a trait, stop satifying a trait or satify the same 161 trait in a different way at any lexical location in the program. 162 In this sense they are ``open" as they can change at any time. This means it 163 is implossible to pick a single set of functions that repersent the type's 164 implementation across the program. 165 166 \CFA side-steps this issue by not having a single virtual table for each 167 type. A user can define virtual tables which are filled in at their 168 declaration and given a name. Anywhere that name is visible, even if it was 169 defined locally inside a function (although that means it will not have a 170 static lifetime), it can be used. 171 Specifically, a virtual type is ``bound" to a virtual table which 172 sets the virtual members for that object. The virtual members can be accessed 173 through the object. 74 174 75 175 While much of the virtual infrastructure is created, it is currently only used … … 83 183 \Cpp syntax for special casts. Both the type of @EXPRESSION@ and @TYPE@ must be 84 184 a pointer to a virtual type. 85 The cast dynamically checks if the @EXPRESSION@ type is the same or a sub type185 The cast dynamically checks if the @EXPRESSION@ type is the same or a sub-type 86 186 of @TYPE@, and if true, returns a pointer to the 87 187 @EXPRESSION@ object, otherwise it returns @0p@ (null pointer). … … 101 201 \end{cfa} 102 202 The trait is defined over two types, the exception type and the virtual table 103 type. This should be one-to-one ,each exception type has only one virtual203 type. This should be one-to-one: each exception type has only one virtual 104 204 table type and vice versa. The only assertion in the trait is 105 205 @get_exception_vtable@, which takes a pointer of the exception type and 106 206 returns a reference to the virtual table type instance. 107 207 208 % TODO: This section, and all references to get_exception_vtable, are 209 % out-of-data. Perhaps wait until the update is finished before rewriting it. 108 210 The function @get_exception_vtable@ is actually a constant function. 109 Re cardless of the value passed in (including the null pointer) it should211 Regardless of the value passed in (including the null pointer) it should 110 212 return a reference to the virtual table instance for that type. 111 213 The reason it is a function instead of a constant is that it make type … … 119 221 % similar system I know of (except Agda's I guess) so I took it out. 120 222 121 There are two more traits for exceptions @is_termination_exception@ and 122 @is_resumption_exception@. They are defined as follows: 123 223 There are two more traits for exceptions defined as follows: 124 224 \begin{cfa} 125 225 trait is_termination_exception( … … 133 233 }; 134 234 \end{cfa} 135 136 In other words they make sure that a given type and virtual type is an 137 exception and defines one of the two default handlers. These default handlers 138 are used in the main exception handling operations \see{Exception Handling} 139 and their use will be detailed there. 140 141 However all three of these traits can be trickly to use directly. 142 There is a bit of repetition required but 235 Both traits ensure a pair of types are an exception type and its virtual table 236 and defines one of the two default handlers. The default handlers are used 237 as fallbacks and are discussed in detail in \VRef{s:ExceptionHandling}. 238 239 However, all three of these traits can be tricky to use directly. 240 While there is a bit of repetition required, 143 241 the largest issue is that the virtual table type is mangled and not in a user 144 facing way. So the re are three macros that can be used to wrap these traits145 when you need to referto the names:242 facing way. So these three macros are provided to wrap these traits to 243 simplify referring to the names: 146 244 @IS_EXCEPTION@, @IS_TERMINATION_EXCEPTION@ and @IS_RESUMPTION_EXCEPTION@. 147 245 148 All t ake one or two arguments. The first argument is the name of the149 exception type. Its unmangled and mangled form are passedto the trait.246 All three take one or two arguments. The first argument is the name of the 247 exception type. The macro passes its unmangled and mangled form to the trait. 150 248 The second (optional) argument is a parenthesized list of polymorphic 151 arguments. This argument should onlywith polymorphic exceptions and the152 list willbe passed to both types.153 In the current set-up the base name and the polymorphic arguments have to154 match so these macros can be used without losing flexability.249 arguments. This argument is only used with polymorphic exceptions and the 250 list is be passed to both types. 251 In the current set-up, the two types always have the same polymorphic 252 arguments so these macros can be used without losing flexibility. 155 253 156 254 For example consider a function that is polymorphic over types that have a … … 162 260 163 261 \section{Exception Handling} 164 \ CFA provides two kinds of exception handling, termination and resumption.165 These twin operations are the core of the exception handling mechanism and 166 are the reason for the features of exceptions.262 \label{s:ExceptionHandling} 263 \CFA provides two kinds of exception handling: termination and resumption. 264 These twin operations are the core of \CFA's exception handling mechanism. 167 265 This section will cover the general patterns shared by the two operations and 168 266 then go on to cover the details each individual operation. 169 267 170 Both operations follow the same set of steps to do their operation. They both 171 start with the user preforming a throw on an exception. 172 Then there is the search for a handler, if one is found than the exception 173 is caught and the handler is run. After that control returns to normal 174 execution. 175 268 Both operations follow the same set of steps. 269 Both start with the user preforming a raise on an exception. 270 Then the exception propogates up the stack. 271 If a handler is found the exception is caught and the handler is run. 272 After that control returns to normal execution. 176 273 If the search fails a default handler is run and then control 177 returns to normal execution immediately. That is where the default handlers 178 @defaultTermiationHandler@ and @defaultResumptionHandler@ are used. 274 returns to normal execution after the raise. 275 276 This general description covers what the two kinds have in common. 277 Differences include how propogation is preformed, where exception continues 278 after an exception is caught and handled and which default handler is run. 179 279 180 280 \subsection{Termination} 181 281 \label{s:Termination} 182 183 Termination handling is more familiar kind and used in most programming 282 Termination handling is the familiar kind and used in most programming 184 283 languages with exception handling. 185 It is dynamic, non-local goto. If a throw is successful then the stack will 186 be unwound and control will (usually) continue in a different function on 187 the call stack. They are commonly used when an error has occured and recovery 188 is impossible in the current function. 284 It is dynamic, non-local goto. If the raised exception is matched and 285 handled the stack is unwound and control will (usually) continue the function 286 on the call stack that defined the handler. 287 Termination is commonly used when an error has occurred and recovery is 288 impossible locally. 189 289 190 290 % (usually) Control can continue in the current function but then a different 191 291 % control flow construct should be used. 192 292 193 A termination throwis started with the @throw@ statement:293 A termination raise is started with the @throw@ statement: 194 294 \begin{cfa} 195 295 throw EXPRESSION; 196 296 \end{cfa} 197 297 The expression must return a reference to a termination exception, where the 198 termination exception is any type that satifies @is_termination_exception@ 199 at the call site. 200 Through \CFA's trait system the functions in the traits are passed into the 201 throw code. A new @defaultTerminationHandler@ can be defined in any scope to 298 termination exception is any type that satisfies the trait 299 @is_termination_exception@ at the call site. 300 Through \CFA's trait system the trait functions are implicity passed into the 301 throw code and the EHM. 302 A new @defaultTerminationHandler@ can be defined in any scope to 202 303 change the throw's behavior (see below). 203 304 204 The throw will copy the provided exception into managed memory. It is the 205 user's responcibility to ensure the original exception is cleaned up if the 206 stack is unwound (allocating it on the stack should be sufficient). 207 208 Then the exception system searches the stack using the copied exception. 209 It starts starts from the throw and proceeds to the base of the stack, 305 The throw will copy the provided exception into managed memory to ensure 306 the exception is not destroyed if the stack is unwound. 307 It is the user's responsibility to ensure the original exception is cleaned 308 up wheither the stack is unwound or not. Allocating it on the stack is 309 usually sufficient. 310 311 Then propogation starts with the search. \CFA uses a ``first match" rule so 312 matching is preformed with the copied exception as the search continues. 313 It starts from the throwing function and proceeds to the base of the stack, 210 314 from callee to caller. 211 315 At each stack frame, a check is made for resumption handlers defined by the … … 214 318 try { 215 319 GUARDED_BLOCK 216 } catch (EXCEPTION_TYPE$\(_1\)$ * NAME$\(_1\)$) {320 } catch (EXCEPTION_TYPE$\(_1\)$ * [NAME$\(_1\)$]) { 217 321 HANDLER_BLOCK$\(_1\)$ 218 } catch (EXCEPTION_TYPE$\(_2\)$ * NAME$\(_2\)$) {322 } catch (EXCEPTION_TYPE$\(_2\)$ * [NAME$\(_2\)$]) { 219 323 HANDLER_BLOCK$\(_2\)$ 220 324 } 221 325 \end{cfa} 222 When viewed on its own a try statement will simply exceute the statements in223 @GUARDED_BLOCK@ and when those are finished the try statement finishes.326 When viewed on its own, a try statement will simply execute the statements 327 in @GUARDED_BLOCK@ and when those are finished the try statement finishes. 224 328 225 329 However, while the guarded statements are being executed, including any 226 functions they invoke, all the handlers following the try block are now 227 or any functions invoked from those 228 statements, throws an exception, and the exception 229 is not handled by a try statement further up the stack, the termination 230 handlers are searched for a matching exception type from top to bottom. 231 232 Exception matching checks the representation of the thrown exception-type is 233 the same or a descendant type of the exception types in the handler clauses. If 234 it is the same of a descendent of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$ is 330 invoked functions, all the handlers in the statement are now on the search 331 path. If a termination exception is thrown and not handled further up the 332 stack they will be matched against the exception. 333 334 Exception matching checks the handler in each catch clause in the order 335 they appear, top to bottom. If the representation of the thrown exception type 336 is the same or a descendant of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$ 337 (if provided) is 235 338 bound to a pointer to the exception and the statements in @HANDLER_BLOCK@$_i$ 236 339 are executed. If control reaches the end of the handler, the exception is 237 340 freed and control continues after the try statement. 238 341 239 If no handler is found during the search then the default handler is run. 342 If no termination handler is found during the search then the default handler 343 (@defaultTerminationHandler@) is run. 240 344 Through \CFA's trait system the best match at the throw sight will be used. 241 345 This function is run and is passed the copied exception. After the default 242 346 handler is run control continues after the throw statement. 243 347 244 There is a global @defaultTerminationHandler@ that cancels the current stack 245 with the copied exception. However it is generic over all exception types so 246 new default handlers can be defined for different exception types and so 247 different exception types can have different default handlers. 348 There is a global @defaultTerminationHandler@ that is polymorphic over all 349 exception types. Since it is so general a more specific handler can be 350 defined and will be used for those types, effectively overriding the handler 351 for particular exception type. 352 The global default termination handler performs a cancellation 353 \see{\VRef{s:Cancellation}} on the current stack with the copied exception. 248 354 249 355 \subsection{Resumption} 250 356 \label{s:Resumption} 251 357 252 Resumption exception handling is a less common formthan termination but is253 just as old~\cite{Goodenough75} and is in some sense simpler.254 It is a dynamic, non-local function call. If the throw is successful a255 closure will be taken from up the stack and executed, after which the throwing 256 function will continue executing.257 These are most often used when an error occur ed and if the error is repaired358 Resumption exception handling is less common than termination but is 359 just as old~\cite{Goodenough75} and is simpler in many ways. 360 It is a dynamic, non-local function call. If the raised exception is 361 matched a closure will be taken from up the stack and executed, 362 after which the raising function will continue executing. 363 These are most often used when an error occurred and if the error is repaired 258 364 then the function can continue. 259 365 … … 262 368 throwResume EXPRESSION; 263 369 \end{cfa} 264 The semantics of the @throwResume@ statement are like the @throw@, but the 265 expression has return a reference a type that satifies the trait 266 @is_resumption_exception@. The assertions from this trait are available to 370 It works much the same way as the termination throw. 371 The expression must return a reference to a resumption exception, 372 where the resumption exception is any type that satisfies the trait 373 @is_resumption_exception@ at the call site. 374 The assertions from this trait are available to 267 375 the exception system while handling the exception. 268 376 269 At runtime, no copies are made. As the stack is not unwound the exception and 377 At run-time, no exception copy is made. 378 As the stack is not unwound the exception and 270 379 any values on the stack will remain in scope while the resumption is handled. 271 380 272 Then the exception system searches the stack using the provided exception. 273 It starts starts from the throw and proceeds to the base of the stack, 274 from callee to caller. 381 The EHM then begins propogation. The search starts from the raise in the 382 resuming function and proceeds to the base of the stack, from callee to caller. 275 383 At each stack frame, a check is made for resumption handlers defined by the 276 384 @catchResume@ clauses of a @try@ statement. … … 278 386 try { 279 387 GUARDED_BLOCK 280 } catchResume (EXCEPTION_TYPE$\(_1\)$ * NAME$\(_1\)$) {388 } catchResume (EXCEPTION_TYPE$\(_1\)$ * [NAME$\(_1\)$]) { 281 389 HANDLER_BLOCK$\(_1\)$ 282 } catchResume (EXCEPTION_TYPE$\(_2\)$ * NAME$\(_2\)$) {390 } catchResume (EXCEPTION_TYPE$\(_2\)$ * [NAME$\(_2\)$]) { 283 391 HANDLER_BLOCK$\(_2\)$ 284 392 } 285 393 \end{cfa} 286 If the handlers are not involved in a search this will simply execute the 287 @GUARDED_BLOCK@ and then continue to the next statement. 288 Its purpose is to add handlers onto the stack. 289 (Note, termination and resumption handlers may be intermixed in a @try@ 290 statement but the kind of throw must be the same as the handler for it to be 291 considered as a possible match.) 292 293 If a search for a resumption handler reaches a try block it will check each 294 @catchResume@ clause, top-to-bottom. 295 At each handler if the thrown exception is or is a child type of 296 @EXCEPTION_TYPE@$_i$ then the a pointer to the exception is bound to 297 @NAME@$_i$ and then @HANDLER_BLOCK@$_i$ is executed. After the block is 298 finished control will return to the @throwResume@ statement. 394 % I wonder if there would be some good central place for this. 395 Note that termination handlers and resumption handlers may be used together 396 in a single try statement, intermixing @catch@ and @catchResume@ freely. 397 Each type of handler will only interact with exceptions from the matching 398 type of raise. 399 When a try statement is executed it simply executes the statements in the 400 @GUARDED_BLOCK@ and then finishes. 401 402 However, while the guarded statements are being executed, including any 403 invoked functions, all the handlers in the statement are now on the search 404 path. If a resumption exception is reported and not handled further up the 405 stack they will be matched against the exception. 406 407 Exception matching checks the handler in each catch clause in the order 408 they appear, top to bottom. If the representation of the thrown exception type 409 is the same or a descendant of @EXCEPTION_TYPE@$_i$ then @NAME@$_i$ 410 (if provided) is bound to a pointer to the exception and the statements in 411 @HANDLER_BLOCK@$_i$ are executed. 412 If control reaches the end of the handler, execution continues after the 413 the raise statement that raised the handled exception. 299 414 300 415 Like termination, if no resumption handler is found, the default handler … … 302 417 call sight according to \CFA's overloading rules. The default handler is 303 418 passed the exception given to the throw. When the default handler finishes 304 execution continues after the throwstatement.419 execution continues after the raise statement. 305 420 306 421 There is a global @defaultResumptionHandler@ is polymorphic over all 307 422 termination exceptions and preforms a termination throw on the exception. 308 The @defaultTerminationHandler@ for that throwis matched at the original309 throwstatement (the resumption @throwResume@) and it can be customized by423 The @defaultTerminationHandler@ for that raise is matched at the original 424 raise statement (the resumption @throwResume@) and it can be customized by 310 425 introducing a new or better match as well. 311 426 312 % \subsubsection? 313 427 \subsubsection{Resumption Marking} 314 428 A key difference between resumption and termination is that resumption does 315 429 not unwind the stack. A side effect that is that when a handler is matched … … 331 445 search and match the handler in the @catchResume@ clause. This will be 332 446 call and placed on the stack on top of the try-block. The second throw then 333 throws and will sea ch the same try block and put call another instance of the447 throws and will search the same try block and put call another instance of the 334 448 same handler leading to an infinite loop. 335 449 … … 337 451 can form with multiple handlers and different exception types. 338 452 339 To prevent all of these cases we mask sections of the stack, or equvilantly 340 the try statements on the stack, so that the resumption seach skips over 341 them and continues with the next unmasked section of the stack. 342 343 A section of the stack is marked when it is searched to see if it contains 344 a handler for an exception and unmarked when that exception has been handled 345 or the search was completed without finding a handler. 346 347 % This might need a diagram. But it is an important part of the justification 348 % of the design of the traversal order. 349 \begin{verbatim} 350 throwResume2 ----------. 351 | | 352 generated from handler | 353 | | 354 handler | 355 | | 356 throwResume1 -----. : 357 | | : 358 try | : search skip 359 | | : 360 catchResume <----' : 361 | | 362 \end{verbatim} 363 364 The rules can be remembered as thinking about what would be searched in 365 termination. So when a throw happens in a handler; a termination handler 366 skips everything from the original throw to the original catch because that 367 part of the stack has been unwound, a resumption handler skips the same 368 section of stack because it has been masked. 369 A throw in a default handler will preform the same search as the original 370 throw because; for termination nothing has been unwound, for resumption 371 the mask will be the same. 372 373 The symmetry with termination is why this pattern was picked. Other patterns, 374 such as marking just the handlers that caught, also work but lack the 375 symmetry whih means there is more to remember. 453 To prevent all of these cases we mark try statements on the stack. 454 A try statement is marked when a match check is preformed with it and an 455 exception. The statement will be unmarked when the handling of that exception 456 is completed or the search completes without finding a handler. 457 While a try statement is marked its handlers are never matched, effectify 458 skipping over it to the next try statement. 459 460 \begin{center} 461 \input{stack-marking} 462 \end{center} 463 464 These rules mirror what happens with termination. 465 When a termination throw happens in a handler the search will not look at 466 any handlers from the original throw to the original catch because that 467 part of the stack has been unwound. 468 A resumption raise in the same situation wants to search the entire stack, 469 but it will not try to match the exception with try statements in the section 470 that would have been unwound as they are marked. 471 472 The symmetry between resumption termination is why this pattern was picked. 473 Other patterns, such as marking just the handlers that caught, also work but 474 lack the symmetry means there are less rules to remember. 376 475 377 476 \section{Conditional Catch} … … 379 478 condition to further control which exceptions they handle: 380 479 \begin{cfa} 381 catch (EXCEPTION_TYPE * NAME; CONDITION)480 catch (EXCEPTION_TYPE * [NAME] ; CONDITION) 382 481 \end{cfa} 383 482 First, the same semantics is used to match the exception type. Second, if the … … 387 486 matches. Otherwise, the exception search continues as if the exception type 388 487 did not match. 389 \begin{cfa} 390 try { 391 f1 = open( ... ); 392 f2 = open( ... ); 488 489 The condition matching allows finer matching by allowing the match to check 490 more kinds of information than just the exception type. 491 \begin{cfa} 492 try { 493 handle1 = open( f1, ... ); 494 handle2 = open( f2, ... ); 495 handle3 = open( f3, ... ); 393 496 ... 394 497 } catch( IOFailure * f ; fd( f ) == f1 ) { 395 // only handle IO failure for f1 396 } 397 \end{cfa} 398 Note, catching @IOFailure@, checking for @f1@ in the handler, and reraising the 399 exception if not @f1@ is different because the reraise does not examine any of 400 remaining handlers in the current try statement. 401 402 \section{Rethrowing} 403 \colour{red}{From Andrew: I recomend we talk about why the language doesn't 404 have rethrows/reraises instead.} 405 406 \label{s:Rethrowing} 498 // Only handle IO failure for f1. 499 } catch( IOFailure * f ; fd( f ) == f3 ) { 500 // Only handle IO failure for f3. 501 } 502 // Can't handle a failure relating to f2 here. 503 \end{cfa} 504 In this example the file that experianced the IO error is used to decide 505 which handler should be run, if any at all. 506 507 \begin{comment} 508 % I know I actually haven't got rid of them yet, but I'm going to try 509 % to write it as if I had and see if that makes sense: 510 \section{Reraising} 511 \label{s:Reraising} 407 512 Within the handler block or functions called from the handler block, it is 408 513 possible to reraise the most recently caught exception with @throw@ or … … 423 528 is part of an unwound stack frame. To prevent this problem, a new default 424 529 handler is generated that does a program-level abort. 530 \end{comment} 531 532 \subsection{Comparison with Reraising} 533 A more popular way to allow handlers to match in more detail is to reraise 534 the exception after it has been caught if it could not be handled here. 535 On the surface these two features seem interchangable. 536 537 If we used @throw;@ to start a termination reraise then these two statements 538 would have the same behaviour: 539 \begin{cfa} 540 try { 541 do_work_may_throw(); 542 } catch(exception_t * exc ; can_handle(exc)) { 543 handle(exc); 544 } 545 \end{cfa} 546 547 \begin{cfa} 548 try { 549 do_work_may_throw(); 550 } catch(exception_t * exc) { 551 if (can_handle(exc)) { 552 handle(exc); 553 } else { 554 throw; 555 } 556 } 557 \end{cfa} 558 If there are further handlers after this handler only the first version will 559 check them. If multiple handlers on a single try block could handle the same 560 exception the translations get more complex but they are equivilantly 561 powerful. 562 563 Until stack unwinding comes into the picture. In termination handling, a 564 conditional catch happens before the stack is unwound, but a reraise happens 565 afterwards. Normally this might only cause you to loose some debug 566 information you could get from a stack trace (and that can be side stepped 567 entirely by collecting information during the unwind). But for \CFA there is 568 another issue, if the exception isn't handled the default handler should be 569 run at the site of the original raise. 570 571 There are two problems with this: the site of the original raise doesn't 572 exist anymore and the default handler might not exist anymore. The site will 573 always be removed as part of the unwinding, often with the entirety of the 574 function it was in. The default handler could be a stack allocated nested 575 function removed during the unwind. 576 577 This means actually trying to pretend the catch didn't happening, continuing 578 the original raise instead of starting a new one, is infeasible. 579 That is the expected behaviour for most languages and we can't replicate 580 that behaviour. 425 581 426 582 \section{Finally Clauses} 583 \label{s:FinallyClauses} 427 584 Finally clauses are used to preform unconditional clean-up when leaving a 428 scope . They are placed at the end of a try statement:585 scope and are placed at the end of a try statement after any handler clauses: 429 586 \begin{cfa} 430 587 try { … … 442 599 443 600 Execution of the finally block should always finish, meaning control runs off 444 the end of the block. This requirement ensures always continues as if the 445 finally clause is not present, \ie finally is for cleanup not changing control 446 flow. Because of this requirement, local control flow out of the finally block 601 the end of the block. This requirement ensures control always continues as if 602 the finally clause is not present, \ie finally is for cleanup not changing 603 control flow. 604 Because of this requirement, local control flow out of the finally block 447 605 is forbidden. The compiler precludes any @break@, @continue@, @fallthru@ or 448 606 @return@ that causes control to leave the finally block. Other ways to leave 449 607 the finally block, such as a long jump or termination are much harder to check, 450 and at best requiring additional run-time overhead, and so are mearly608 and at best requiring additional run-time overhead, and so are only 451 609 discouraged. 452 610 453 Not all languages with exceptionshave finally clauses. Notably \Cpp does611 Not all languages with unwinding have finally clauses. Notably \Cpp does 454 612 without it as descructors serve a similar role. Although destructors and 455 613 finally clauses can be used in many of the same areas they have their own 456 614 use cases like top-level functions and lambda functions with closures. 457 615 Destructors take a bit more work to set up but are much easier to reuse while 458 finally clauses are good for once offs and can include local information. 616 finally clauses are good for one-off uses and 617 can easily include local information. 459 618 460 619 \section{Cancellation} 620 \label{s:Cancellation} 461 621 Cancellation is a stack-level abort, which can be thought of as as an 462 uncatchable termination. It unwinds the entire ty of thecurrent stack, and if622 uncatchable termination. It unwinds the entire current stack, and if 463 623 possible forwards the cancellation exception to a different stack. 464 624 … … 466 626 There is no special statement for starting a cancellation; instead the standard 467 627 library function @cancel_stack@ is called passing an exception. Unlike a 468 throw, this exception is not used in matching only to pass information about628 raise, this exception is not used in matching only to pass information about 469 629 the cause of the cancellation. 470 (This also means matching cannot fail so there is no default handler either.)471 472 After @cancel_stack@ is called the exception is copied into the exception473 handling mechanism's memory. Then the entirety ofthe current stack is630 (This also means matching cannot fail so there is no default handler.) 631 632 After @cancel_stack@ is called the exception is copied into the EHM's memory 633 and the current stack is 474 634 unwound. After that it depends one which stack is being cancelled. 475 635 \begin{description} 476 636 \item[Main Stack:] 477 637 The main stack is the one used by the program main at the start of execution, 478 and is the only stack in a sequential program. Even in a concurrent program 479 the main stack is only dependent on the environment that started the program. 480 Hence, when the main stack is cancelled there is nowhere else in the program 481 to notify. After the stack is unwound, there is a program-level abort. 638 and is the only stack in a sequential program. 639 After the main stack is unwound there is a program-level abort. 640 641 There are two reasons for this. The first is that it obviously had to do this 642 in a sequential program as there is nothing else to notify and the simplicity 643 of keeping the same behaviour in sequential and concurrent programs is good. 644 Also, even in concurrent programs there is no stack that an innate connection 645 to, so it would have be explicitly managed. 482 646 483 647 \item[Thread Stack:] 484 A thread stack is created for a @thread@ object or object that satisfies the 485 @is_thread@ trait. A thread only has two points of communication that must 486 happen: start and join. As the thread must be running to perform a 487 cancellation, it must occur after start and before join, so join is used 488 for communication here. 489 After the stack is unwound, the thread halts and waits for 490 another thread to join with it. The joining thread checks for a cancellation, 491 and if present, resumes exception @ThreadCancelled@. 492 493 There is a subtle difference between the explicit join (@join@ function) and 494 implicit join (from a destructor call). The explicit join takes the default 495 handler (@defaultResumptionHandler@) from its calling context, which is used if 496 the exception is not caught. The implicit join does a program abort instead. 497 498 This semantics is for safety. If an unwind is triggered while another unwind 499 is underway only one of them can proceed as they both want to ``consume'' the 500 stack. Letting both try to proceed leads to very undefined behaviour. 501 Both termination and cancellation involve unwinding and, since the default 502 @defaultResumptionHandler@ preforms a termination that could more easily 503 happen in an implicate join inside a destructor. So there is an error message 504 and an abort instead. 505 \todo{Perhaps have a more general disucssion of unwind collisions before 506 this point.} 507 508 The recommended way to avoid the abort is to handle the intial resumption 509 from the implicate join. If required you may put an explicate join inside a 510 finally clause to disable the check and use the local 511 @defaultResumptionHandler@ instead. 512 513 \item[Coroutine Stack:] A coroutine stack is created for a @coroutine@ object 514 or object that satisfies the @is_coroutine@ trait. A coroutine only knows of 515 two other coroutines, its starter and its last resumer. Of the two the last 516 resumer has the tightest coupling to the coroutine it activated and the most 517 up-to-date information. 518 519 Hence, cancellation of the active coroutine is forwarded to the last resumer 520 after the stack is unwound. When the resumer restarts, it resumes exception 521 @CoroutineCancelled@, which is polymorphic over the coroutine type and has a 522 pointer to the cancelled coroutine. 523 524 The resume function also has an assertion that the @defaultResumptionHandler@ 525 for the exception. So it will use the default handler like a regular throw. 648 A thread stack is created for a \CFA @thread@ object or object that satisfies 649 the @is_thread@ trait. 650 After a thread stack is unwound there exception is stored until another 651 thread attempts to join with it. Then the exception @ThreadCancelled@, 652 which stores a reference to the thread and to the exception passed to the 653 cancellation, is reported from the join. 654 There is one difference between an explicit join (with the @join@ function) 655 and an implicit join (from a destructor call). The explicit join takes the 656 default handler (@defaultResumptionHandler@) from its calling context while 657 the implicit join provides its own which does a program abort if the 658 @ThreadCancelled@ exception cannot be handled. 659 660 Communication is done at join because a thread only has to have to points of 661 communication with other threads: start and join. 662 Since a thread must be running to perform a cancellation (and cannot be 663 cancelled from another stack), the cancellation must be after start and 664 before the join. So join is the one that we will use. 665 666 % TODO: Find somewhere to discuss unwind collisions. 667 The difference between the explicit and implicit join is for safety and 668 debugging. It helps prevent unwinding collisions by avoiding throwing from 669 a destructor and prevents cascading the error across multiple threads if 670 the user is not equipped to deal with it. 671 Also you can always add an explicit join if that is the desired behaviour. 672 673 \item[Coroutine Stack:] 674 A coroutine stack is created for a @coroutine@ object or object that 675 satisfies the @is_coroutine@ trait. 676 After a coroutine stack is unwound control returns to the resume function 677 that most recently resumed it. The resume statement reports a 678 @CoroutineCancelled@ exception, which contains a references to the cancelled 679 coroutine and the exception used to cancel it. 680 The resume function also takes the @defaultResumptionHandler@ from the 681 caller's context and passes it to the internal report. 682 683 A coroutine knows of two other coroutines, its starter and its last resumer. 684 The starter has a much more distant connection while the last resumer just 685 (in terms of coroutine state) called resume on this coroutine, so the message 686 is passed to the latter. 526 687 \end{description} -
doc/theses/andrew_beach_MMath/future.tex
rfeacef9 r5407cdc 83 83 patterns to find the handler. 84 84 85 \section{Checked Exceptions} 86 Checked exceptions make exceptions part of a function's type by adding the 87 exception signature. An exception signature must declare all checked 88 exceptions that could propogate from the function (either because they were 89 raised inside the function or came from a sub-function). This improves safety 90 by making sure every checked exception is either handled or consciously 91 passed on. 92 93 However checked exceptions were never seriously considered for this project 94 for two reasons. The first is due to time constraints, even copying an 95 existing checked exception system would be pushing the remaining time and 96 trying to address the second problem would take even longer. The second 97 problem is that checked exceptions have some real usability trade-offs in 98 exchange for the increased safety. 99 100 These trade-offs are most problematic when trying to pass exceptions through 101 higher-order functions from the functions the user passed into the 102 higher-order function. There are no well known solutions to this problem 103 that were statifactory for \CFA (which carries some of C's flexability 104 over safety design) so one would have to be researched and developed. 105 106 Follow-up work might add checked exceptions to \CFA, possibly using 107 polymorphic exception signatures, a form of tunneling\cite{Zhang19} or 108 checked and unchecked raises. 109 85 110 \section{Zero-Cost Try} 86 111 \CFA does not have zero-cost try-statements because the compiler generates C -
doc/theses/andrew_beach_MMath/implement.tex
rfeacef9 r5407cdc 13 13 library. 14 14 15 \subsection{Virtual Type} 16 Virtual types only have one change to their structure, the addition of a 17 pointer to the virtual table. This is always the first field so that 18 if it is cast to a supertype the field's location is still known. 19 20 This field is set as part of all new generated constructors. 21 \todo{They only come as part exceptions and don't work.} 22 After the object is created the field is constant. 23 24 However it can be read from, internally it is just a regular field called 25 @virtual_table@. Dereferencing it gives the virtual table and access to the 26 type's virtual members. 27 15 28 \subsection{Virtual Table} 29 Every time a virtual type is defined the new virtual table type must also be 30 defined. 31 32 The unique instance is important because the address of the virtual table 33 instance is used as the identifier for the virtual type. So a pointer to the 34 virtual table and the ID for the virtual type are interchangable. 35 \todo{Unique instances might be going so we will have to talk about the new 36 system instead.} 37 38 The first step in putting it all together is to create the virtual table type. 39 The virtual table type is just a structure and can be described in terms of 40 its fields. The first field is always the parent type ID (or a pointer to 41 the parent virtual table) or 0 (the null pointer). 42 Next are other fields on the parent virtual table are repeated. 43 Finally are the fields used to store any new virtual members of the new 44 The virtual type 45 16 46 The virtual system is accessed through a private constant field inserted at the 17 47 beginning of every virtual type, called the virtual-table pointer. This field 18 48 points at a type's virtual table and is assigned during the object's 19 construction. The address of a virtual table acts as the unique identifier for49 construction. The address of a virtual table acts as the unique identifier for 20 50 the virtual type, and the first field of a virtual table is a pointer to the 21 parent virtual-table or @0p@. The remaining fields are duplicated from the51 parent virtual-table or @0p@. The remaining fields are duplicated from the 22 52 parent tables in this type's inheritance chain, followed by any fields this type 23 introduces. Parent fields are duplicated so they can be changed ( \CC24 \lstinline[language=c++]|override|), so that references to the dispatched type53 introduces. Parent fields are duplicated so they can be changed (all virtual 54 members are overridable), so that references to the dispatched type 25 55 are replaced with the current virtual type. 26 \PAB{Can you create a simple diagram of the layout?}27 56 % These are always taken by pointer or reference. 57 58 % Simple ascii diragram: 59 \begin{verbatim} 60 parent_pointer \ 61 parent_field0 | 62 ... | Same layout as parent. 63 parent_fieldN / 64 child_field0 65 ... 66 child_fieldN 67 \end{verbatim} 68 \todo{Refine the diagram} 28 69 29 70 % For each virtual type, a virtual table is constructed. This is both a new type … … 34 75 A virtual table is created when the virtual type is created. The name of the 35 76 type is created by mangling the name of the base type. The name of the instance 36 is also generated by name mangling. The fields are initialized automatically.77 is also generated by name mangling. The fields are initialized automatically. 37 78 The parent field is initialized by getting the type of the parent field and 38 79 using that to calculate the mangled name of the parent's virtual table type. … … 67 108 \begin{sloppypar} 68 109 Coroutines and threads need instances of @CoroutineCancelled@ and 69 @ThreadCancelled@ respectively to use all of their functionality. When a new110 @ThreadCancelled@ respectively to use all of their functionality. When a new 70 111 data type is declared with @coroutine@ or @thread@ the forward declaration for 71 112 the instance is created as well. The definition of the virtual table is created … … 80 121 The function is 81 122 \begin{cfa} 82 void * __cfa__virtual_cast( struct __cfa__parent_vtable const * parent, 123 void * __cfa__virtual_cast( 124 struct __cfa__parent_vtable const * parent, 83 125 struct __cfa__parent_vtable const * const * child ); 84 }85 126 \end{cfa} 86 and it is implemented in the standard library. It takes a pointer to the target 87 type's virtual table and the object pointer being cast. The function performs a 88 linear search starting at the object's virtual-table and walking through the 89 the parent pointers, checking to if it or any of its ancestors are the same as 90 the target-type virtual table-pointer. 91 92 For the generated code, a forward declaration of the virtual works as follows. 93 There is a forward declaration of @__cfa__virtual_cast@ in every \CFA file so 94 it can just be used. The object argument is the expression being cast so that 95 is just placed in the argument list. 96 97 To build the target type parameter, the compiler creates a mapping from 98 concrete type-name -- so for polymorphic types the parameters are filled in -- 99 to virtual table address. Every virtual table declaration is added to the this 100 table; repeats are ignored unless they have conflicting definitions. Note, 101 these declarations do not have to be in scope, but they should usually be 102 introduced as part of the type definition. 103 104 \PAB{I do not understood all of \VRef{s:VirtualSystem}. I think you need to 105 write more to make it clear.} 106 127 and it is implemented in the standard library. The structure reperents the 128 head of a vtable which is the pointer to the parent virtual table. The 129 @parent@ points directly at the parent type virtual table while the @child@ 130 points at the object of the (possibe) child type. 131 132 In terms of the virtual cast expression, @parent@ comes from looking up the 133 type being cast to and @child@ is the result of the expression being cast. 134 Because the complier outputs C code, some type C type casts are also used. 135 The last bit of glue is an map that saves every virtual type the compiler 136 sees. This is used to check the type used in a virtual cast is a virtual 137 type and to get its virtual table. 138 (It also checks for conflicting definitions.) 139 140 Inside the function it is a simple conditional. If the type repersented by 141 @parent@ is or is an ancestor of the type repersented by @*child@ (it 142 requires one more level of derefence to pass through the object) then @child@ 143 is returned, otherwise the null pointer is returned. 144 145 The check itself is preformed is a simple linear search. If the child 146 virtual table or any of its ancestors (which are retreved through the first 147 field of every virtual table) are the same as the parent virtual table then 148 the cast succeeds. 107 149 108 150 \section{Exceptions} … … 121 163 stack. On function entry and return, unwinding is handled directly by the code 122 164 embedded in the function. Usually, the stack-frame size is known statically 123 based on parameter and local variable declarations. For dynamically-sized165 based on parameter and local variable declarations. For dynamically-sized 124 166 local variables, a runtime computation is necessary to know the frame 125 167 size. Finally, a function's frame-size may change during execution as local … … 179 221 180 222 To use libunwind, each function must have a personality function and a Language 181 Specific Data Area (LSDA). The LSDA has the unique information for each223 Specific Data Area (LSDA). The LSDA has the unique information for each 182 224 function to tell the personality function where a function is executing, its 183 current stack frame, and what handlers should be checked. Theoretically, the225 current stack frame, and what handlers should be checked. Theoretically, the 184 226 LSDA can contain any information but conventionally it is a table with entries 185 227 representing regions of the function and what has to be done there during … … 196 238 197 239 The GCC compilation flag @-fexceptions@ causes the generation of an LSDA and 198 attaches its personality function. \PAB{to what is it attached?} However, this 199 flag only handles the cleanup attribute 240 attaches its personality function. However, this 241 flag only handles the cleanup attribute: 242 \todo{Peter: What is attached? Andrew: It uses the .cfi\_personality directive 243 and that's all I know.} 200 244 \begin{cfa} 201 245 void clean_up( int * var ) { ... } 202 int avar __attribute__(( __cleanup(clean_up) ));246 int avar __attribute__(( cleanup(clean_up) )); 203 247 \end{cfa} 204 which is used on a variable and specifies a function, \eg @clean_up@, run when 205 the variable goes out of scope. The function is passed a pointer to the object 206 so it can be used to mimic destructors. However, this feature cannot be used to 207 mimic @try@ statements. 248 which is used on a variable and specifies a function, in this case @clean_up@, 249 run when the variable goes out of scope. 250 The function is passed a pointer to the object being removed from the stack 251 so it can be used to mimic destructors. 252 However, this feature cannot be used to mimic @try@ statements as it cannot 253 control the unwinding. 208 254 209 255 \subsection{Personality Functions} 210 Personality functions have a complex interface specified by libunwind. This256 Personality functions have a complex interface specified by libunwind. This 211 257 section covers some of the important parts of the interface. 212 258 213 A personality function performs four tasks, although not all have to be214 present.259 A personality function can preform different actions depending on how it is 260 called. 215 261 \begin{lstlisting}[language=C,{moredelim=**[is][\color{red}]{@}{@}}] 216 262 typedef _Unwind_Reason_Code (*@_Unwind_Personality_Fn@) ( … … 225 271 \item 226 272 @_UA_SEARCH_PHASE@ specifies a search phase and tells the personality function 227 to check for handlers. If there is a handler in a stack frame, as defined by273 to check for handlers. If there is a handler in a stack frame, as defined by 228 274 the language, the personality function returns @_URC_HANDLER_FOUND@; otherwise 229 275 it return @_URC_CONTINUE_UNWIND@. … … 296 342 \end{cfa} 297 343 It also unwinds the stack but it does not use the search phase. Instead another 298 function, the stop function, is used to stop searching. The exception is the344 function, the stop function, is used to stop searching. The exception is the 299 345 same as the one passed to raise exception. The extra arguments are the stop 300 346 function and the stop parameter. The stop function has a similar interface as a … … 318 364 319 365 \begin{sloppypar} 320 Its arguments are the same as the paired personality function. The actions366 Its arguments are the same as the paired personality function. The actions 321 367 @_UA_CLEANUP_PHASE@ and @_UA_FORCE_UNWIND@ are always set when it is 322 368 called. Beyond the libunwind standard, both GCC and Clang add an extra action … … 343 389 strong symbol replacing the sequential version. 344 390 345 % The version of the function defined in @libcfa@ is very simple. It returns a 346 % pointer to a global static variable. With only one stack this global instance 347 % is associated with the only stack. 348 349 For coroutines, @this_exception_context@ accesses the exception context stored 350 at the base of the stack. For threads, @this_exception_context@ uses the 351 concurrency library to access the current stack of the thread or coroutine 352 being executed by the thread, and then accesses the exception context stored at 353 the base of this stack. 391 The sequential @this_exception_context@ returns a hard-coded pointer to the 392 global execption context. 393 The concurrent version adds the exception context to the data stored at the 394 base of each stack. When @this_exception_context@ is called it retrieves the 395 active stack and returns the address of the context saved there. 354 396 355 397 \section{Termination} … … 369 411 per-exception storage. 370 412 371 Exceptions are stored in variable-sized blocks. \PAB{Show a memory layout 372 figure.} The first component is a fixed sized data structure that contains the 413 [Quick ASCII diagram to get started.] 414 \begin{verbatim} 415 Fixed Header | _Unwind_Exception <- pointer target 416 | 417 | Cforall storage 418 | 419 Variable Body | the exception <- fixed offset 420 V ... 421 \end{verbatim} 422 423 Exceptions are stored in variable-sized blocks. 424 The first component is a fixed sized data structure that contains the 373 425 information for libunwind and the exception system. The second component is an 374 426 area of memory big enough to store the exception. Macros with pointer arthritic … … 388 440 exception type. The size and copy function are used immediately to copy an 389 441 exception into managed memory. After the exception is handled the free function 390 is used to clean up the exception and then the entire node is passed to free. 442 is used to clean up the exception and then the entire node is passed to free 443 so the memory can be given back to the heap. 391 444 392 445 \subsection{Try Statements and Catch Clauses} … … 399 452 library. The contents of a try block and the termination handlers are converted 400 453 into functions. These are then passed to the try terminate function and it 401 calls them. This approach puts a try statement in its own functions so that no 402 function has to deal with both termination handlers and destructors. \PAB{I do 403 not understand the previous sentence.} 404 405 This function has some custom embedded assembly that defines \emph{its} 406 personality function and LSDA. The assembly is created with handcrafted C @asm@ 407 statements, which is why there is only one version of it. The personality 408 function is structured so that it can be expanded, but currently it only 409 handles this one function. Notably, it does not handle any destructors so the 410 function is constructed so that it does need to run it. \PAB{I do not 411 understand the previous sentence.} 454 calls them. 455 Because this function is known and fixed (and not an arbitrary function that 456 happens to contain a try statement) this means the LSDA can be generated ahead 457 of time. 458 459 Both the LSDA and the personality function are set ahead of time using 460 embedded assembly. This is handcrafted using C @asm@ statements and contains 461 enough information for the single try statement the function repersents. 412 462 413 463 The three functions passed to try terminate are: … … 419 469 420 470 \item[match function:] This function is called during the search phase and 421 decides if a catch clause matches the termination exception. It is constructed471 decides if a catch clause matches the termination exception. It is constructed 422 472 from the conditional part of each handler and runs each check, top to bottom, 423 473 in turn, first checking to see if the exception type matches and then if the … … 428 478 \item[handler function:] This function handles the exception. It takes a 429 479 pointer to the exception and the handler's id and returns nothing. It is called 430 after the cleanup phase. It is constructed by stitching together the bodies of480 after the cleanup phase. It is constructed by stitching together the bodies of 431 481 each handler and dispatches to the selected handler. 432 482 \end{description} … … 434 484 can be used to create closures, functions that can refer to the state of other 435 485 functions on the stack. This approach allows the functions to refer to all the 436 variables in scope for the function containing the @try@ statement. These486 variables in scope for the function containing the @try@ statement. These 437 487 nested functions and all other functions besides @__cfaehm_try_terminate@ in 438 488 \CFA use the GCC personality function and the @-fexceptions@ flag to generate … … 455 505 handler that matches. If no handler matches then the function returns 456 506 false. Otherwise the matching handler is run; if it completes successfully, the 457 function returns true. Re resume, through the @throwResume;@ statement, cause458 the function to return true.507 function returns true. Rethrowing, through the @throwResume;@ statement, 508 causes the function to return true. 459 509 460 510 % Recursive Resumption Stuff: … … 482 532 providing zero-cost enter/exit using the LSDA. Unfortunately, there is no way 483 533 to return from a libunwind search without installing a handler or raising an 484 error. Although workarounds might be possible, they are beyond the scope of534 error. Although workarounds might be possible, they are beyond the scope of 485 535 this thesis. The current resumption implementation has simplicity in its 486 536 favour. … … 503 553 504 554 Cancellation also uses libunwind to do its stack traversal and unwinding, 505 however it uses a different primary function @_Unwind_ForcedUnwind@. Details555 however it uses a different primary function @_Unwind_ForcedUnwind@. Details 506 556 of its interface can be found in the \VRef{s:ForcedUnwind}. 507 557 … … 511 561 its main coroutine and the coroutine it is currently executing. 512 562 513 The first check is if the current thread's main and current coroutine do not 514 match, implying a coroutine cancellation; otherwise, it is a thread 515 cancellation. Otherwise it is a main thread cancellation. \PAB{Previous 516 sentence does not make sense.} 563 So if the active thread's main and current coroutine are the same. If they 564 are then the current stack is a thread stack, otherwise it is a coroutine 565 stack. If it is a thread stack then an equality check with the stored main 566 thread pointer and current thread pointer is enough to tell if the current 567 thread is the main thread or not. 517 568 518 569 However, if the threading library is not linked, the sequential execution is on -
doc/theses/andrew_beach_MMath/uw-ethesis.tex
rfeacef9 r5407cdc 74 74 % ====================================================================== 75 75 % D O C U M E N T P R E A M B L E 76 % Specify the document class, default style attributes, page dimensions, etc. 77 % For hyperlinked PDF, suitable for viewing on a computer, use this: 78 \documentclass[letterpaper,12pt,titlepage,oneside,final]{book} 79 80 % For PDF, suitable for double-sided printing, change the PrintVersion 81 % variable below to "true" and use this \documentclass line instead of the 82 % one above: 83 %\documentclass[letterpaper,12pt,titlepage,openright,twoside,final]{book} 84 85 \usepackage{etoolbox} 76 \RequirePackage{etoolbox} 77 78 % Control if this for print (set true) or will stay digital (default). 79 % Print is two sided, digital uses more colours. 80 \newtoggle{printversion} 81 %\toggletrue{printversion} 82 83 \iftoggle{printversion}{% 84 \documentclass[letterpaper,12pt,titlepage,openright,twoside,final]{book} 85 }{% 86 \documentclass[letterpaper,12pt,titlepage,oneside,final]{book} 87 } 86 88 87 89 % Some LaTeX commands I define for my own nomenclature. … … 94 96 % Anything defined here may be redefined by packages added below... 95 97 96 % This package allows if-then-else control structures. 97 \usepackage{ifthen} 98 \newboolean{PrintVersion} 99 \setboolean{PrintVersion}{false} 100 % CHANGE THIS VALUE TO "true" as necessary, to improve printed results for 101 % hard copies by overriding some options of the hyperref package, called below. 102 103 %\usepackage{nomencl} % For a nomenclature (optional; available from ctan.org) 98 % For a nomenclature (optional; available from ctan.org) 99 %\usepackage{nomencl} 104 100 % Lots of math symbols and environments 105 101 \usepackage{amsmath,amssymb,amstext} 106 % For including graphics N.B. pdftex graphics driver 107 \usepackage[pdftex]{graphicx} 102 % For including graphics (must match graphics driver) 103 \usepackage{epic,eepic} 104 \usepackage{graphicx} 108 105 % Removes large sections of the document. 109 106 \usepackage{comment} 110 107 % Adds todos (Must be included after comment.) 111 108 \usepackage{todonotes} 112 113 109 114 110 % Hyperlinks make it very easy to navigate an electronic document. … … 117 113 % Use the "hyperref" package 118 114 % N.B. HYPERREF MUST BE THE LAST PACKAGE LOADED; ADD ADDITIONAL PKGS ABOVE 119 \usepackage[pdftex,pagebackref=true]{hyperref} % with basic options 120 %\usepackage[pdftex,pagebackref=true]{hyperref} 115 \usepackage[pagebackref=true]{hyperref} 121 116 % N.B. pagebackref=true provides links back from the References to the body 122 117 % text. This can cause trouble for printing. … … 128 123 pdffitwindow=false, % window fit to page when opened 129 124 pdfstartview={FitH}, % fits the width of the page to the window 130 % pdftitle={uWaterloo\ LaTeX\ Thesis\ Template}, % title: CHANGE THIS TEXT!131 % pdfauthor={Author}, % author: CHANGE THIS TEXT! and uncomment this line132 % pdfsubject={Subject}, % subject: CHANGE THIS TEXT! and uncomment this line133 % pdfkeywords={keyword1} {key2} {key3}, % optional list of keywords134 125 pdfnewwindow=true, % links in new window 135 126 colorlinks=true, % false: boxed links; true: colored links 136 linkcolor=blue, % color of internal links137 citecolor=green, % color of links to bibliography138 filecolor=magenta, % color of file links139 urlcolor=cyan % color of external links140 127 } 141 % for improved print quality, change some hyperref options 142 \ifthenelse{\boolean{PrintVersion}}{ 143 \hypersetup{ % override some previously defined hyperref options 144 % colorlinks,% 145 citecolor=black,% 146 filecolor=black,% 147 linkcolor=black,% 148 urlcolor=black} 149 }{} % end of ifthenelse (no else) 128 \iftoggle{printversion}{ 129 \hypersetup{ 130 citecolor=black, % colour of links to bibliography 131 filecolor=black, % colour of file links 132 linkcolor=black, % colour of internal links 133 urlcolor=black, % colour of external links 134 } 135 }{ % Digital Version 136 \hypersetup{ 137 citecolor=green, 138 filecolor=magenta, 139 linkcolor=blue, 140 urlcolor=cyan, 141 } 142 } 143 144 \hypersetup{ 145 pdftitle={Exception Handling in Cforall}, 146 pdfauthor={Andrew James Beach}, 147 pdfsubject={Computer Science}, 148 pdfkeywords={programming languages} {exceptions} 149 {language design} {language implementation}, 150 } 150 151 151 152 % Exception to the rule of hyperref being the last add-on package … … 217 218 \pdfstringdefDisableCommands{\def\Cpp{C++}} 218 219 220 % Wrappers for inline code snippits. 221 \newrobustcmd*\codeCFA[1]{\lstinline[language=CFA]{#1}} 222 \newrobustcmd*\codeC[1]{\lstinline[language=C]{#1}} 223 \newrobustcmd*\codeCpp[1]{\lstinline[language=C++]{#1}} 224 \newrobustcmd*\codePy[1]{\lstinline[language=Python]{#1}} 225 219 226 % Colour text, formatted in LaTeX style instead of TeX style. 220 227 \newcommand*\colour[2]{{\color{#1}#2}} -
doc/theses/mubeen_zulfiqar_MMath/uw-ethesis.bib
rfeacef9 r5407cdc 6 6 Alexander Samarin", 7 7 title = "The \LaTeX\ Companion", 8 year = "1994",8 year = "1994", 9 9 publisher = "Addison-Wesley", 10 address = "Reading, Massachusetts"10 address = "Reading, Massachusetts" 11 11 } 12 12 … … 23 23 title = "\LaTeX\ --- A Document Preparation System", 24 24 edition = "Second", 25 year = "1994",26 publisher = "Addison-Wesley",25 year = "1994", 26 publisher = "Addison-Wesley", 27 27 address = "Reading, Massachusetts" 28 28 } -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/links.hpp
rfeacef9 r5407cdc 117 117 } 118 118 119 long long ts() const {119 unsigned long long ts() const { 120 120 return before._links.ts; 121 121 } -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/processor_list.hpp
rfeacef9 r5407cdc 39 39 while( __builtin_expect(ll.exchange(true),false) ) { 40 40 while(ll.load(std::memory_order_relaxed)) 41 asm volatile("pause");41 Pause(); 42 42 } 43 43 /* paranoid */ assert(ll); … … 93 93 && ready.compare_exchange_weak(copy, n + 1) ) 94 94 break; 95 asm volatile("pause");95 Pause(); 96 96 } 97 97 … … 133 133 // Step 1 : make sure no writer are in the middle of the critical section 134 134 while(lock.load(std::memory_order_relaxed)) 135 asm volatile("pause");135 Pause(); 136 136 137 137 // Fence needed because we don't want to start trying to acquire the lock … … 195 195 // to simply lock their own lock and enter. 196 196 while(lock.load(std::memory_order_relaxed)) 197 asm volatile("pause");197 Pause(); 198 198 199 199 // Step 2 : lock per-proc lock … … 204 204 for(uint_fast32_t i = 0; i < s; i++) { 205 205 while(data[i].lock.load(std::memory_order_relaxed)) 206 asm volatile("pause");206 Pause(); 207 207 } 208 208 -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/processor_list_good.cpp
rfeacef9 r5407cdc 21 21 target = (target - (target % total)) + total; 22 22 while(waiting < target) 23 asm volatile("pause");23 Pause(); 24 24 25 25 assert(waiting < (1ul << 60)); -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/randbit.cpp
rfeacef9 r5407cdc 123 123 target = (target - (target % total)) + total; 124 124 while(waiting < target) 125 asm volatile("pause");125 Pause(); 126 126 127 127 assert(waiting < (1ul << 60)); -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/relaxed_list.cpp
rfeacef9 r5407cdc 206 206 std::cout << "Total ops : " << ops << "(" << global.in << "i, " << global.out << "o, " << global.empty << "e)\n"; 207 207 #ifndef NO_STATS 208 LIST_VARIANT<Node>::stats_print(std::cout );208 LIST_VARIANT<Node>::stats_print(std::cout, duration); 209 209 #endif 210 210 } … … 368 368 369 369 for(Node * & node : nodes) { 370 node = list.pop(); 371 assert(node); 370 node = nullptr; 371 while(!node) { 372 node = list.pop(); 373 } 372 374 local.crc_out += node->value; 373 375 local.out++; … … 691 693 692 694 for(const auto & n : nodes) { 693 local.valmax = max(local.valmax, size_t(n.value));694 local.valmin = min(local.valmin, size_t(n.value));695 local.valmax = std::max(local.valmax, size_t(n.value)); 696 local.valmin = std::min(local.valmin, size_t(n.value)); 695 697 } 696 698 … … 773 775 try { 774 776 arg = optarg = argv[optind]; 775 nnodes = st oul(optarg, &len);777 nnodes = std::stoul(optarg, &len); 776 778 if(len != arg.size()) { throw std::invalid_argument(""); } 777 779 } catch(std::invalid_argument &) { … … 792 794 try { 793 795 arg = optarg = argv[optind]; 794 nnodes = st oul(optarg, &len);796 nnodes = std::stoul(optarg, &len); 795 797 if(len != arg.size()) { throw std::invalid_argument(""); } 796 798 } catch(std::invalid_argument &) { … … 812 814 try { 813 815 arg = optarg = argv[optind]; 814 nnodes = st oul(optarg, &len);816 nnodes = std::stoul(optarg, &len); 815 817 if(len != arg.size()) { throw std::invalid_argument(""); } 816 818 nslots = nnodes; … … 823 825 try { 824 826 arg = optarg = argv[optind]; 825 nnodes = st oul(optarg, &len);827 nnodes = std::stoul(optarg, &len); 826 828 if(len != arg.size()) { throw std::invalid_argument(""); } 827 829 } catch(std::invalid_argument &) { … … 831 833 try { 832 834 arg = optarg = argv[optind + 1]; 833 nslots = st oul(optarg, &len);835 nslots = std::stoul(optarg, &len); 834 836 if(len != arg.size()) { throw std::invalid_argument(""); } 835 837 } catch(std::invalid_argument &) { … … 884 886 case 'd': 885 887 try { 886 duration = st od(optarg, &len);888 duration = std::stod(optarg, &len); 887 889 if(len != arg.size()) { throw std::invalid_argument(""); } 888 890 } catch(std::invalid_argument &) { … … 893 895 case 't': 894 896 try { 895 nthreads = st oul(optarg, &len);897 nthreads = std::stoul(optarg, &len); 896 898 if(len != arg.size()) { throw std::invalid_argument(""); } 897 899 } catch(std::invalid_argument &) { … … 902 904 case 'q': 903 905 try { 904 nqueues = st oul(optarg, &len);906 nqueues = std::stoul(optarg, &len); 905 907 if(len != arg.size()) { throw std::invalid_argument(""); } 906 908 } catch(std::invalid_argument &) { -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/snzi-packed.hpp
rfeacef9 r5407cdc 168 168 for(int i = 0; i < width; i++) { 169 169 int idx = i % hwdith; 170 std::cout << i << " -> " << idx + width << std::endl;171 170 leafs[i].parent = &nodes[ idx ]; 172 171 } … … 174 173 for(int i = 0; i < root; i++) { 175 174 int idx = (i / 2) + hwdith; 176 std::cout << i + width << " -> " << idx + width << std::endl;177 175 nodes[i].parent = &nodes[ idx ]; 178 176 } -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/snzi.hpp
rfeacef9 r5407cdc 159 159 std::cout << "SNZI: " << depth << "x" << width << "(" << mask - 1 << ") " << (sizeof(snzi_t::node) * (root + 1)) << " bytes" << std::endl; 160 160 for(int i = 0; i < root; i++) { 161 std::cout << i << " -> " << (i / base) + width << std::endl;162 161 nodes[i].parent = &nodes[(i / base) + width]; 163 162 } -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/utils.hpp
rfeacef9 r5407cdc 11 11 #include <sys/sysinfo.h> 12 12 13 #include <x86intrin.h> 14 15 // Barrier from 16 class barrier_t { 17 public: 18 barrier_t(size_t total) 19 : waiting(0) 20 , total(total) 21 {} 22 23 void wait(unsigned) { 24 size_t target = waiting++; 25 target = (target - (target % total)) + total; 26 while(waiting < target) 27 asm volatile("pause"); 28 29 assert(waiting < (1ul << 60)); 30 } 31 32 private: 33 std::atomic<size_t> waiting; 34 size_t total; 35 }; 13 // #include <x86intrin.h> 36 14 37 15 // class Random { … … 102 80 }; 103 81 104 static inline long long rdtscl(void) { 105 unsigned int lo, hi; 106 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 107 return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 108 } 82 static inline long long int rdtscl(void) { 83 #if defined( __i386 ) || defined( __x86_64 ) 84 unsigned int lo, hi; 85 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 86 return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 87 #elif defined( __aarch64__ ) || defined( __arm__ ) 88 // https://github.com/google/benchmark/blob/v1.1.0/src/cycleclock.h#L116 89 long long int virtual_timer_value; 90 asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); 91 return virtual_timer_value; 92 #else 93 #error unsupported hardware architecture 94 #endif 95 } 96 97 #if defined( __i386 ) || defined( __x86_64 ) 98 #define Pause() __asm__ __volatile__ ( "pause" : : : ) 99 #elif defined( __ARM_ARCH ) 100 #define Pause() __asm__ __volatile__ ( "YIELD" : : : ) 101 #else 102 #error unsupported architecture 103 #endif 109 104 110 105 static inline void affinity(int tid) { … … 195 190 } 196 191 192 // Barrier from 193 class barrier_t { 194 public: 195 barrier_t(size_t total) 196 : waiting(0) 197 , total(total) 198 {} 199 200 void wait(unsigned) { 201 size_t target = waiting++; 202 target = (target - (target % total)) + total; 203 while(waiting < target) 204 Pause(); 205 206 assert(waiting < (1ul << 60)); 207 } 208 209 private: 210 std::atomic<size_t> waiting; 211 size_t total; 212 }; 213 197 214 struct spinlock_t { 198 215 std::atomic_bool ll = { false }; … … 201 218 while( __builtin_expect(ll.exchange(true),false) ) { 202 219 while(ll.load(std::memory_order_relaxed)) 203 asm volatile("pause");220 Pause(); 204 221 } 205 222 } -
doc/theses/thierry_delisle_PhD/code/readyQ_proto/work_stealing.hpp
rfeacef9 r5407cdc 6 6 #include <memory> 7 7 #include <mutex> 8 #include <thread> 8 9 #include <type_traits> 9 10 … … 11 12 #include "utils.hpp" 12 13 #include "links.hpp" 14 #include "links2.hpp" 13 15 #include "snzi.hpp" 14 16 17 // #include <x86intrin.h> 18 15 19 using namespace std; 20 21 static const long long lim = 2000; 22 static const unsigned nqueues = 2; 23 24 struct __attribute__((aligned(128))) timestamp_t { 25 volatile unsigned long long val = 0; 26 }; 27 28 template<typename node_t> 29 struct __attribute__((aligned(128))) localQ_t { 30 #ifdef NO_MPSC 31 intrusive_queue_t<node_t> list; 32 33 inline auto ts() { return list.ts(); } 34 inline auto lock() { return list.lock.lock(); } 35 inline auto try_lock() { return list.lock.try_lock(); } 36 inline auto unlock() { return list.lock.unlock(); } 37 38 inline auto push( node_t * node ) { return list.push( node ); } 39 inline auto pop() { return list.pop(); } 40 #else 41 mpsc_queue<node_t> queue = {}; 42 spinlock_t _lock = {}; 43 44 inline auto ts() { auto h = queue.head(); return h ? h->_links.ts : 0ull; } 45 inline auto lock() { return _lock.lock(); } 46 inline auto try_lock() { return _lock.try_lock(); } 47 inline auto unlock() { return _lock.unlock(); } 48 49 inline auto push( node_t * node ) { return queue.push( node ); } 50 inline auto pop() { return queue.pop(); } 51 #endif 52 53 54 }; 16 55 17 56 template<typename node_t> … … 25 64 26 65 work_stealing(unsigned _numThreads, unsigned) 27 : numThreads(_numThreads) 28 , lists(new intrusive_queue_t<node_t>[numThreads]) 29 , snzi( std::log2( numThreads / 2 ), 2 ) 66 : numThreads(_numThreads * nqueues) 67 , lists(new localQ_t<node_t>[numThreads]) 68 // , lists(new intrusive_queue_t<node_t>[numThreads]) 69 , times(new timestamp_t[numThreads]) 70 // , snzi( std::log2( numThreads / 2 ), 2 ) 30 71 31 72 { … … 40 81 __attribute__((noinline, hot)) void push(node_t * node) { 41 82 node->_links.ts = rdtscl(); 42 if( node->_links.hint > numThreads ) { 43 node->_links.hint = tls.rng.next() % numThreads; 44 tls.stat.push.nhint++; 83 // node->_links.ts = 1; 84 85 auto & list = *({ 86 unsigned i; 87 #ifdef NO_MPSC 88 do { 89 #endif 90 tls.stats.push.attempt++; 91 // unsigned r = tls.rng1.next(); 92 unsigned r = tls.it++; 93 if(tls.my_queue == outside) { 94 i = r % numThreads; 95 } else { 96 i = tls.my_queue + (r % nqueues); 97 } 98 #ifdef NO_MPSC 99 } while(!lists[i].try_lock()); 100 #endif 101 &lists[i]; 102 }); 103 104 list.push( node ); 105 #ifdef NO_MPSC 106 list.unlock(); 107 #endif 108 // tls.rng2.set_raw_state( tls.rng1.get_raw_state()); 109 // count++; 110 tls.stats.push.success++; 111 } 112 113 __attribute__((noinline, hot)) node_t * pop() { 114 if(tls.my_queue != outside) { 115 // if( tls.myfriend == outside ) { 116 // auto r = tls.rng1.next(); 117 // tls.myfriend = r % numThreads; 118 // // assert(lists[(tls.it % nqueues) + tls.my_queue].ts() >= lists[((tls.it + 1) % nqueues) + tls.my_queue].ts()); 119 // tls.mytime = std::min(lists[(tls.it % nqueues) + tls.my_queue].ts(), lists[((tls.it + 1) % nqueues) + tls.my_queue].ts()); 120 // // times[tls.myfriend].val = 0; 121 // // lists[tls.myfriend].val = 0; 122 // } 123 // // else if(times[tls.myfriend].val == 0) { 124 // // else if(lists[tls.myfriend].val == 0) { 125 // else if(times[tls.myfriend].val < tls.mytime) { 126 // // else if(times[tls.myfriend].val < lists[(tls.it % nqueues) + tls.my_queue].ts()) { 127 // node_t * n = try_pop(tls.myfriend, tls.stats.pop.help); 128 // tls.stats.help++; 129 // tls.myfriend = outside; 130 // if(n) return n; 131 // } 132 // if( tls.myfriend == outside ) { 133 // auto r = tls.rng1.next(); 134 // tls.myfriend = r % numThreads; 135 // tls.mytime = lists[((tls.it + 1) % nqueues) + tls.my_queue].ts(); 136 // } 137 // else { 138 // if(times[tls.myfriend].val + 1000 < tls.mytime) { 139 // node_t * n = try_pop(tls.myfriend, tls.stats.pop.help); 140 // tls.stats.help++; 141 // if(n) return n; 142 // } 143 // tls.myfriend = outside; 144 // } 145 146 node_t * n = local(); 147 if(n) return n; 45 148 } 46 149 47 unsigned i = node->_links.hint; 48 auto & list = lists[i]; 49 list.lock.lock(); 50 51 if(list.push( node )) { 52 snzi.arrive(i); 150 // try steal 151 for(int i = 0; i < 25; i++) { 152 node_t * n = steal(); 153 if(n) return n; 53 154 } 54 155 55 list.lock.unlock(); 56 } 57 58 __attribute__((noinline, hot)) node_t * pop() { 59 node_t * node; 60 while(true) { 61 if(!snzi.query()) { 62 return nullptr; 63 } 64 65 { 66 unsigned i = tls.my_queue; 67 auto & list = lists[i]; 68 if( list.ts() != 0 ) { 69 list.lock.lock(); 70 if((node = try_pop(i))) { 71 tls.stat.pop.local.success++; 72 break; 73 } 74 else { 75 tls.stat.pop.local.elock++; 76 } 77 } 78 else { 79 tls.stat.pop.local.espec++; 80 } 81 } 82 83 tls.stat.pop.steal.tried++; 84 85 int i = tls.rng.next() % numThreads; 86 auto & list = lists[i]; 87 if( list.ts() == 0 ) { 88 tls.stat.pop.steal.empty++; 89 continue; 90 } 91 92 if( !list.lock.try_lock() ) { 93 tls.stat.pop.steal.locked++; 94 continue; 95 } 96 97 if((node = try_pop(i))) { 98 tls.stat.pop.steal.success++; 99 break; 156 return search(); 157 } 158 159 private: 160 inline node_t * local() { 161 unsigned i = (--tls.it % nqueues) + tls.my_queue; 162 node_t * n = try_pop(i, tls.stats.pop.local); 163 if(n) return n; 164 i = (--tls.it % nqueues) + tls.my_queue; 165 return try_pop(i, tls.stats.pop.local); 166 } 167 168 inline node_t * steal() { 169 unsigned i = tls.rng2.prev() % numThreads; 170 return try_pop(i, tls.stats.pop.steal); 171 } 172 173 inline node_t * search() { 174 unsigned offset = tls.rng2.prev(); 175 for(unsigned i = 0; i < numThreads; i++) { 176 unsigned idx = (offset + i) % numThreads; 177 node_t * thrd = try_pop(idx, tls.stats.pop.search); 178 if(thrd) { 179 return thrd; 100 180 } 101 181 } 102 182 103 #if defined(READ) 104 const unsigned f = READ; 105 if(0 == (tls.it % f)) { 106 unsigned i = tls.it / f; 107 lists[i % numThreads].ts(); 108 } 109 // lists[tls.it].ts(); 110 tls.it++; 111 #endif 112 113 114 return node; 115 } 116 117 private: 118 node_t * try_pop(unsigned i) { 183 return nullptr; 184 } 185 186 private: 187 struct attempt_stat_t { 188 std::size_t attempt = { 0 }; 189 std::size_t elock = { 0 }; 190 std::size_t eempty = { 0 }; 191 std::size_t espec = { 0 }; 192 std::size_t success = { 0 }; 193 }; 194 195 node_t * try_pop(unsigned i, attempt_stat_t & stat) { 196 assert(i < numThreads); 119 197 auto & list = lists[i]; 198 stat.attempt++; 199 200 // If the list is empty, don't try 201 if(list.ts() == 0) { stat.espec++; return nullptr; } 202 203 // If we can't get the lock, move on 204 if( !list.try_lock() ) { stat.elock++; return nullptr; } 120 205 121 206 // If list is empty, unlock and retry 122 207 if( list.ts() == 0 ) { 123 list.lock.unlock(); 208 list.unlock(); 209 stat.eempty++; 124 210 return nullptr; 125 211 } 126 212 127 // Actually pop the list 128 node_t * node; 129 bool emptied; 130 std::tie(node, emptied) = list.pop(); 131 assert(node); 132 133 if(emptied) { 134 snzi.depart(i); 135 } 136 137 // Unlock and return 138 list.lock.unlock(); 139 return node; 213 auto node = list.pop(); 214 list.unlock(); 215 stat.success++; 216 #ifdef NO_MPSC 217 // times[i].val = 1; 218 times[i].val = node.first->_links.ts; 219 // lists[i].val = node.first->_links.ts; 220 return node.first; 221 #else 222 times[i].val = node->_links.ts; 223 return node; 224 #endif 140 225 } 141 226 … … 144 229 145 230 static std::atomic_uint32_t ticket; 231 static const unsigned outside = 0xFFFFFFFF; 232 233 static inline unsigned calc_preferred() { 234 unsigned t = ticket++; 235 if(t == 0) return outside; 236 unsigned i = (t - 1) * nqueues; 237 return i; 238 } 239 146 240 static __attribute__((aligned(128))) thread_local struct TLS { 147 Random rng = { int(rdtscl()) }; 148 unsigned my_queue = ticket++; 241 Random rng1 = { unsigned(std::hash<std::thread::id>{}(std::this_thread::get_id()) ^ rdtscl()) }; 242 Random rng2 = { unsigned(std::hash<std::thread::id>{}(std::this_thread::get_id()) ^ rdtscl()) }; 243 unsigned it = 0; 244 unsigned my_queue = calc_preferred(); 245 unsigned myfriend = outside; 246 unsigned long long int mytime = 0; 149 247 #if defined(READ) 150 248 unsigned it = 0; … … 152 250 struct { 153 251 struct { 154 std::size_t nhint = { 0 }; 252 std::size_t attempt = { 0 }; 253 std::size_t success = { 0 }; 155 254 } push; 156 255 struct { 157 struct { 158 std::size_t success = { 0 }; 159 std::size_t espec = { 0 }; 160 std::size_t elock = { 0 }; 161 } local; 162 struct { 163 std::size_t tried = { 0 }; 164 std::size_t locked = { 0 }; 165 std::size_t empty = { 0 }; 166 std::size_t success = { 0 }; 167 } steal; 256 attempt_stat_t help; 257 attempt_stat_t local; 258 attempt_stat_t steal; 259 attempt_stat_t search; 168 260 } pop; 169 } stat; 261 std::size_t help = { 0 }; 262 } stats; 170 263 } tls; 171 264 172 265 private: 173 266 const unsigned numThreads; 174 std::unique_ptr<intrusive_queue_t<node_t> []> lists; 175 __attribute__((aligned(64))) snzi_t snzi; 267 std::unique_ptr<localQ_t<node_t> []> lists; 268 // std::unique_ptr<intrusive_queue_t<node_t> []> lists; 269 std::unique_ptr<timestamp_t []> times; 270 __attribute__((aligned(128))) std::atomic_size_t count; 176 271 177 272 #ifndef NO_STATS … … 179 274 static struct GlobalStats { 180 275 struct { 181 std::atomic_size_t nhint = { 0 }; 276 std::atomic_size_t attempt = { 0 }; 277 std::atomic_size_t success = { 0 }; 182 278 } push; 183 279 struct { 184 280 struct { 281 std::atomic_size_t attempt = { 0 }; 282 std::atomic_size_t elock = { 0 }; 283 std::atomic_size_t eempty = { 0 }; 284 std::atomic_size_t espec = { 0 }; 185 285 std::atomic_size_t success = { 0 }; 186 std::atomic_size_t espec = { 0 }; 187 std::atomic_size_t elock = { 0 }; 286 } help; 287 struct { 288 std::atomic_size_t attempt = { 0 }; 289 std::atomic_size_t elock = { 0 }; 290 std::atomic_size_t eempty = { 0 }; 291 std::atomic_size_t espec = { 0 }; 292 std::atomic_size_t success = { 0 }; 188 293 } local; 189 294 struct { 190 std::atomic_size_t tried = { 0 }; 191 std::atomic_size_t locked = { 0 }; 192 std::atomic_size_t empty = { 0 }; 295 std::atomic_size_t attempt = { 0 }; 296 std::atomic_size_t elock = { 0 }; 297 std::atomic_size_t eempty = { 0 }; 298 std::atomic_size_t espec = { 0 }; 193 299 std::atomic_size_t success = { 0 }; 194 300 } steal; 301 struct { 302 std::atomic_size_t attempt = { 0 }; 303 std::atomic_size_t elock = { 0 }; 304 std::atomic_size_t eempty = { 0 }; 305 std::atomic_size_t espec = { 0 }; 306 std::atomic_size_t success = { 0 }; 307 } search; 195 308 } pop; 309 std::atomic_size_t help = { 0 }; 196 310 } global_stats; 197 311 198 312 public: 199 313 static void stats_tls_tally() { 200 global_stats.push.nhint += tls.stat.push.nhint; 201 global_stats.pop.local.success += tls.stat.pop.local.success; 202 global_stats.pop.local.espec += tls.stat.pop.local.espec ; 203 global_stats.pop.local.elock += tls.stat.pop.local.elock ; 204 global_stats.pop.steal.tried += tls.stat.pop.steal.tried ; 205 global_stats.pop.steal.locked += tls.stat.pop.steal.locked ; 206 global_stats.pop.steal.empty += tls.stat.pop.steal.empty ; 207 global_stats.pop.steal.success += tls.stat.pop.steal.success; 208 } 209 210 static void stats_print(std::ostream & os ) { 314 global_stats.push.attempt += tls.stats.push.attempt; 315 global_stats.push.success += tls.stats.push.success; 316 global_stats.pop.help .attempt += tls.stats.pop.help .attempt; 317 global_stats.pop.help .elock += tls.stats.pop.help .elock ; 318 global_stats.pop.help .eempty += tls.stats.pop.help .eempty ; 319 global_stats.pop.help .espec += tls.stats.pop.help .espec ; 320 global_stats.pop.help .success += tls.stats.pop.help .success; 321 global_stats.pop.local .attempt += tls.stats.pop.local .attempt; 322 global_stats.pop.local .elock += tls.stats.pop.local .elock ; 323 global_stats.pop.local .eempty += tls.stats.pop.local .eempty ; 324 global_stats.pop.local .espec += tls.stats.pop.local .espec ; 325 global_stats.pop.local .success += tls.stats.pop.local .success; 326 global_stats.pop.steal .attempt += tls.stats.pop.steal .attempt; 327 global_stats.pop.steal .elock += tls.stats.pop.steal .elock ; 328 global_stats.pop.steal .eempty += tls.stats.pop.steal .eempty ; 329 global_stats.pop.steal .espec += tls.stats.pop.steal .espec ; 330 global_stats.pop.steal .success += tls.stats.pop.steal .success; 331 global_stats.pop.search.attempt += tls.stats.pop.search.attempt; 332 global_stats.pop.search.elock += tls.stats.pop.search.elock ; 333 global_stats.pop.search.eempty += tls.stats.pop.search.eempty ; 334 global_stats.pop.search.espec += tls.stats.pop.search.espec ; 335 global_stats.pop.search.success += tls.stats.pop.search.success; 336 global_stats.help += tls.stats.help; 337 } 338 339 static void stats_print(std::ostream & os, double duration ) { 211 340 std::cout << "----- Work Stealing Stats -----" << std::endl; 212 341 213 double stealSucc = double(global_stats.pop.steal.success) / global_stats.pop.steal.tried; 214 os << "Push to new Q : " << std::setw(15) << global_stats.push.nhint << "\n"; 215 os << "Local Pop : " << std::setw(15) << global_stats.pop.local.success << "\n"; 216 os << "Steal Pop : " << std::setw(15) << global_stats.pop.steal.success << "(" << global_stats.pop.local.espec << "s, " << global_stats.pop.local.elock << "l)\n"; 217 os << "Steal Success : " << std::setw(15) << stealSucc << "(" << global_stats.pop.steal.tried << " tries)\n"; 218 os << "Steal Fails : " << std::setw(15) << global_stats.pop.steal.empty << "e, " << global_stats.pop.steal.locked << "l\n"; 342 double push_suc = (100.0 * double(global_stats.push.success) / global_stats.push.attempt); 343 double push_len = double(global_stats.push.attempt ) / global_stats.push.success; 344 os << "Push Pick : " << push_suc << " %, len " << push_len << " (" << global_stats.push.attempt << " / " << global_stats.push.success << ")\n"; 345 346 double hlp_suc = (100.0 * double(global_stats.pop.help.success) / global_stats.pop.help.attempt); 347 double hlp_len = double(global_stats.pop.help.attempt ) / global_stats.pop.help.success; 348 os << "Help : " << hlp_suc << " %, len " << hlp_len << " (" << global_stats.pop.help.attempt << " / " << global_stats.pop.help.success << ")\n"; 349 os << "Help Fail : " << global_stats.pop.help.espec << "s, " << global_stats.pop.help.eempty << "e, " << global_stats.pop.help.elock << "l\n"; 350 351 double pop_suc = (100.0 * double(global_stats.pop.local.success) / global_stats.pop.local.attempt); 352 double pop_len = double(global_stats.pop.local.attempt ) / global_stats.pop.local.success; 353 os << "Local : " << pop_suc << " %, len " << pop_len << " (" << global_stats.pop.local.attempt << " / " << global_stats.pop.local.success << ")\n"; 354 os << "Local Fail : " << global_stats.pop.local.espec << "s, " << global_stats.pop.local.eempty << "e, " << global_stats.pop.local.elock << "l\n"; 355 356 double stl_suc = (100.0 * double(global_stats.pop.steal.success) / global_stats.pop.steal.attempt); 357 double stl_len = double(global_stats.pop.steal.attempt ) / global_stats.pop.steal.success; 358 os << "Steal : " << stl_suc << " %, len " << stl_len << " (" << global_stats.pop.steal.attempt << " / " << global_stats.pop.steal.success << ")\n"; 359 os << "Steal Fail : " << global_stats.pop.steal.espec << "s, " << global_stats.pop.steal.eempty << "e, " << global_stats.pop.steal.elock << "l\n"; 360 361 double srh_suc = (100.0 * double(global_stats.pop.search.success) / global_stats.pop.search.attempt); 362 double srh_len = double(global_stats.pop.search.attempt ) / global_stats.pop.search.success; 363 os << "Search : " << srh_suc << " %, len " << srh_len << " (" << global_stats.pop.search.attempt << " / " << global_stats.pop.search.success << ")\n"; 364 os << "Search Fail : " << global_stats.pop.search.espec << "s, " << global_stats.pop.search.eempty << "e, " << global_stats.pop.search.elock << "l\n"; 365 os << "Helps : " << std::setw(15) << std::scientific << global_stats.help / duration << "/sec (" << global_stats.help << ")\n"; 219 366 } 220 367 private: -
doc/user/figures/Cdecl.fig
rfeacef9 r5407cdc 1 #FIG 3.2 Produced by xfig version 3.2. 5b1 #FIG 3.2 Produced by xfig version 3.2.7b 2 2 Landscape 3 3 Center 4 4 Inches 5 Letter 5 Letter 6 6 100.00 7 7 Single … … 19 19 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 20 20 2850 1200 3600 1200 3600 1350 2850 1350 2850 1200 21 4 1 0 50 -1 4 11 0.0000 2 120 90 2925 1325 0\00122 4 1 0 50 -1 4 11 0.0000 2 120 90 3075 1325 1\00123 4 1 0 50 -1 4 11 0.0000 2 120 90 3225 1325 2\00124 4 1 0 50 -1 4 11 0.0000 2 120 90 3375 1325 3\00125 4 1 0 50 -1 4 11 0.0000 2 120 90 3525 1325 4\00121 4 1 0 50 -1 4 11 0.0000 2 120 105 3075 1335 1\001 22 4 1 0 50 -1 4 11 0.0000 2 120 105 3225 1335 2\001 23 4 1 0 50 -1 4 11 0.0000 2 120 105 3375 1335 3\001 24 4 1 0 50 -1 4 11 0.0000 2 120 105 3525 1335 4\001 25 4 1 0 50 -1 4 11 0.0000 2 120 105 2925 1335 0\001 26 26 -6 27 27 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 … … 55 55 1 1 1.00 45.00 60.00 56 56 2550 1275 2850 1275 57 4 1 0 50 -1 4 11 0.0000 2 120 901350 1650 0\00158 4 1 0 50 -1 4 11 0.0000 2 120 901500 1650 1\00159 4 1 0 50 -1 4 11 0.0000 2 120 901650 1650 2\00160 4 1 0 50 -1 4 11 0.0000 2 120 901800 1650 3\00161 4 1 0 50 -1 4 11 0.0000 2 120 901950 1650 4\00157 4 1 0 50 -1 4 11 0.0000 2 120 105 1350 1650 0\001 58 4 1 0 50 -1 4 11 0.0000 2 120 105 1500 1650 1\001 59 4 1 0 50 -1 4 11 0.0000 2 120 105 1650 1650 2\001 60 4 1 0 50 -1 4 11 0.0000 2 120 105 1800 1650 3\001 61 4 1 0 50 -1 4 11 0.0000 2 120 105 1950 1650 4\001 62 62 4 1 0 50 -1 4 11 0.0000 2 90 90 1200 1325 x\001 63 63 4 1 0 50 -1 4 11 0.0000 2 90 90 2400 1325 x\001 -
doc/user/user.tex
rfeacef9 r5407cdc 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Mon Feb 15 13:48:53 202114 %% Update Count : 4 45213 %% Last Modified On : Sun Apr 25 19:03:03 2021 14 %% Update Count : 4951 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 66 66 % math escape $...$ (dollar symbol) 67 67 \input{common} % common CFA document macros 68 \setlength{\gcolumnposn}{3in} 68 69 \CFAStyle % use default CFA format-style 69 70 \lstset{language=CFA} % CFA default lnaguage 70 71 \lstnewenvironment{C++}[1][] % use C++ style 71 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{ @}{@},#1}}72 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}} 72 73 {} 73 74 … … 81 82 \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}} 82 83 \newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}} 83 \newcommand{\R}[1]{ \Textbf{#1}}84 \newcommand{\R C}[1]{\Textbf{\LstBasicStyle{#1}}}84 \newcommand{\R}[1]{{\color{red}#1}} 85 \newcommand{\RB}[1]{\Textbf{#1}} 85 86 \newcommand{\B}[1]{{\Textbf[blue]{#1}}} 86 87 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} … … 176 177 int main( void ) { 177 178 int x = 0, y = 1, z = 2; 178 @printf( "%d %d %d\n", x, y, z );@179 ®printf( "%d %d %d\n", x, y, z );® 179 180 } 180 181 \end{cfa} … … 185 186 int main( void ) { 186 187 int x = 0, y = 1, z = 2; 187 @sout | x | y | z;@$\indexc{sout}$188 ®sout | x | y | z;®$\indexc{sout}$ 188 189 } 189 190 \end{cfa} … … 194 195 int main() { 195 196 int x = 0, y = 1, z = 2; 196 @cout<<x<<" "<<y<<" "<<z<<endl;@197 ®cout<<x<<" "<<y<<" "<<z<<endl;® 197 198 } 198 199 \end{cfa} … … 224 225 \begin{tabular}{@{}rcccccccc@{}} 225 226 & 2021 & 2016 & 2011 & 2006 & 2001 & 1996 & 1991 & 1986 \\ \hline 226 \R {C} & \R{1} & \R{2} & \R{2} & \R{1} & \R{1} & \R{1} & \R{1} & \R{1}\\227 \RB{C} & \RB{1}& \RB{2}& \RB{2}& \RB{1}& \RB{1}& \RB{1}& \RB{1}& \RB{1}\\ 227 228 Java & 2 & 1 & 1 & 2 & 3 & 28 & - & - \\ 228 229 Python & 3 & 5 & 6 & 7 & 23 & 13 & - & - \\ … … 258 259 The signature feature of \CFA is \emph{\Index{overload}able} \Index{parametric-polymorphic} functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a ©forall© clause (giving the language its name): 259 260 \begin{cfa} 260 @forall( otype T )@T identity( T val ) { return val; }261 ®forall( otype T )® T identity( T val ) { return val; } 261 262 int forty_two = identity( 42 ); $\C{// T is bound to int, forty\_two == 42}$ 262 263 \end{cfa} … … 322 323 Whereas, \CFA wraps each of these routines into one overloaded name ©abs©: 323 324 \begin{cfa} 324 char @abs@( char );325 extern "C" { int @abs@( int ); } $\C{// use default C routine for int}$326 long int @abs@( long int );327 long long int @abs@( long long int );328 float @abs@( float );329 double @abs@( double );330 long double @abs@( long double );331 float _Complex @abs@( float _Complex );332 double _Complex @abs@( double _Complex );333 long double _Complex @abs@( long double _Complex );325 char ®abs®( char ); 326 extern "C" { int ®abs®( int ); } $\C{// use default C routine for int}$ 327 long int ®abs®( long int ); 328 long long int ®abs®( long long int ); 329 float ®abs®( float ); 330 double ®abs®( double ); 331 long double ®abs®( long double ); 332 float _Complex ®abs®( float _Complex ); 333 double _Complex ®abs®( double _Complex ); 334 long double _Complex ®abs®( long double _Complex ); 334 335 \end{cfa} 335 336 The problem is \Index{name clash} between the C name ©abs© and the \CFA names ©abs©, resulting in two name linkages\index{C linkage}: ©extern "C"© and ©extern "Cforall"© (default). … … 358 359 The 2011 C standard plus GNU extensions. 359 360 \item 360 \Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline] $-fgnu89-inline$}}361 \Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline]{-fgnu89-inline}}} 361 362 Use the traditional GNU semantics for inline routines in C11 mode, which allows inline routines in header files. 362 363 \end{description} … … 530 531 Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism: 531 532 \begin{cfa} 532 int @``@otype = 3; $\C{// make keyword an identifier}$533 double @``@forall = 3.5;533 int ®``®otype = 3; $\C{// make keyword an identifier}$ 534 double ®``®forall = 3.5; 534 535 \end{cfa} 535 536 … … 542 543 // include file uses the CFA keyword "with". 543 544 #if ! defined( with ) $\C{// nesting ?}$ 544 #define with @``@with $\C{// make keyword an identifier}$545 #define with ®``®with $\C{// make keyword an identifier}$ 545 546 #define __CFA_BFD_H__ 546 547 #endif … … 560 561 Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore} as a separator, \eg: 561 562 \begin{cfa} 562 2 @_@147@_@483@_@648; $\C{// decimal constant}$563 56 @_@ul; $\C{// decimal unsigned long constant}$564 0 @_@377; $\C{// octal constant}$565 0x @_@ff@_@ff; $\C{// hexadecimal constant}$566 0x @_@ef3d@_@aa5c; $\C{// hexadecimal constant}$567 3.141 @_@592@_@654; $\C{// floating constant}$568 10 @_@e@_@+1@_@00; $\C{// floating constant}$569 0x @_@ff@_@ff@_@p@_@3; $\C{// hexadecimal floating}$570 0x @_@1.ffff@_@ffff@_@p@_@128@_@l; $\C{// hexadecimal floating long constant}$571 L @_@$"\texttt{\textbackslash{x}}$@_@$\texttt{ff}$@_@$\texttt{ee}"$; $\C{// wide character constant}$563 2®_®147®_®483®_®648; $\C{// decimal constant}$ 564 56®_®ul; $\C{// decimal unsigned long constant}$ 565 0®_®377; $\C{// octal constant}$ 566 0x®_®ff®_®ff; $\C{// hexadecimal constant}$ 567 0x®_®ef3d®_®aa5c; $\C{// hexadecimal constant}$ 568 3.141®_®592®_®654; $\C{// floating constant}$ 569 10®_®e®_®+1®_®00; $\C{// floating constant}$ 570 0x®_®ff®_®ff®_®p®_®3; $\C{// hexadecimal floating}$ 571 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; $\C{// hexadecimal floating long constant}$ 572 L®_®$"\texttt{\textbackslash{x}}$®_®$\texttt{ff}$®_®$\texttt{ee}"$; $\C{// wide character constant}$ 572 573 \end{cfa} 573 574 The rules for placement of underscores are: … … 602 603 Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the exponent cannot be negative. 603 604 \begin{cfa} 604 sout | 1 @\@ 0 | 1 @\@ 1 | 2 @\@ 8 | -4 @\@ 3 | 5 @\@ 3 | 5 @\@ 32 | 5L @\@ 32 | 5L @\@ 64 | -4 @\@ -3 | -4.0 @\@ -3 | 4.0 @\@2.1605 | (1.0f+2.0fi) @\@(3.0f+2.0fi);606 1 1 256 -64 125 @0@ 3273344365508751233 @0@ @0@-0.015625 18.3791736799526 0.264715-1.1922i605 sout | 1 ®\® 0 | 1 ®\® 1 | 2 ®\® 8 | -4 ®\® 3 | 5 ®\® 3 | 5 ®\® 32 | 5L ®\® 32 | 5L ®\® 64 | -4 ®\® -3 | -4.0 ®\® -3 | 4.0 ®\® 2.1 606 | (1.0f+2.0fi) ®\® (3.0f+2.0fi); 607 1 1 256 -64 125 ®0® 3273344365508751233 ®0® ®0® -0.015625 18.3791736799526 0.264715-1.1922i 607 608 \end{cfa} 608 609 Note, ©5 \ 32© and ©5L \ 64© overflow, and ©-4 \ -3© is a fraction but stored in an integer so all three computations generate an integral zero. … … 612 613 \begin{cfa} 613 614 forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); } ) 614 T ? @\@?( T ep, unsigned int y );615 T ?®\®?( T ep, unsigned int y ); 615 616 forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); } ) 616 T ? @\@?( T ep, unsigned long int y );617 T ?®\®?( T ep, unsigned long int y ); 617 618 \end{cfa} 618 619 The user type ©T© must define multiplication, one (©1©), and ©*©. … … 624 625 625 626 626 %\subsection{\texorpdfstring{\protect\lstinline @if@/\protect\lstinline@while@Statement}{if Statement}}627 %\subsection{\texorpdfstring{\protect\lstinline{if}/\protect\lstinline{while} Statement}{if Statement}} 627 628 \subsection{\texorpdfstring{\LstKeywordStyle{if} / \LstKeywordStyle{while} Statement}{if / while Statement}} 628 629 … … 630 631 Declarations in the ©do©-©while© condition are not useful because they appear after the loop body.} 631 632 \begin{cfa} 632 if ( @int x = f()@) ... $\C{// x != 0}$633 if ( @int x = f(), y = g()@) ... $\C{// x != 0 \&\& y != 0}$634 if ( @int x = f(), y = g(); x < y@) ... $\C{// relational expression}$635 if ( @struct S { int i; } x = { f() }; x.i < 4@) $\C{// relational expression}$636 637 while ( @int x = f()@) ... $\C{// x != 0}$638 while ( @int x = f(), y = g()@) ... $\C{// x != 0 \&\& y != 0}$639 while ( @int x = f(), y = g(); x < y@) ... $\C{// relational expression}$640 while ( @struct S { int i; } x = { f() }; x.i < 4@) ... $\C{// relational expression}$633 if ( ®int x = f()® ) ... $\C{// x != 0}$ 634 if ( ®int x = f(), y = g()® ) ... $\C{// x != 0 \&\& y != 0}$ 635 if ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$ 636 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) $\C{// relational expression}$ 637 638 while ( ®int x = f()® ) ... $\C{// x != 0}$ 639 while ( ®int x = f(), y = g()® ) ... $\C{// x != 0 \&\& y != 0}$ 640 while ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$ 641 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$ 641 642 \end{cfa} 642 643 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical ©&&© operator. … … 645 646 646 647 647 %\section{\texorpdfstring{\protect\lstinline @case@Clause}{case Clause}}648 %\section{\texorpdfstring{\protect\lstinline{case} Clause}{case Clause}} 648 649 \subsection{\texorpdfstring{\LstKeywordStyle{case} Clause}{case Clause}} 649 650 \label{s:caseClause} … … 658 659 \begin{cfa} 659 660 switch ( i ) { 660 case @1, 3, 5@:661 case ®1, 3, 5®: 661 662 ... 662 case @2, 4, 6@:663 case ®2, 4, 6®: 663 664 ... 664 665 } … … 685 686 \end{cquote} 686 687 In addition, subranges are allowed to specify case values.\footnote{ 687 gcc has the same mechanism but awkward syntax, \lstinline @2 ...42@, because a space is required after a number, otherwise the period is a decimal point.}688 gcc has the same mechanism but awkward syntax, \lstinline{2 ...42}, because a space is required after a number, otherwise the period is a decimal point.} 688 689 \begin{cfa} 689 690 switch ( i ) { 690 case @1~5:@$\C{// 1, 2, 3, 4, 5}$691 case ®1~5:® $\C{// 1, 2, 3, 4, 5}$ 691 692 ... 692 case @10~15:@$\C{// 10, 11, 12, 13, 14, 15}$693 case ®10~15:® $\C{// 10, 11, 12, 13, 14, 15}$ 693 694 ... 694 695 } … … 696 697 Lists of subranges are also allowed. 697 698 \begin{cfa} 698 case @1~5, 12~21, 35~42@:699 \end{cfa} 700 701 702 %\section{\texorpdfstring{\protect\lstinline @switch@Statement}{switch Statement}}699 case ®1~5, 12~21, 35~42®: 700 \end{cfa} 701 702 703 %\section{\texorpdfstring{\protect\lstinline{switch} Statement}{switch Statement}} 703 704 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}} 704 705 … … 740 741 if ( argc == 3 ) { 741 742 // open output file 742 @// open input file743 @} else if ( argc == 2 ) {744 @// open input file (duplicate)745 746 @} else {743 ®// open input file 744 ®} else if ( argc == 2 ) { 745 ®// open input file (duplicate) 746 747 ®} else { 747 748 // usage message 748 749 } … … 755 756 \begin{cfa} 756 757 switch ( i ) { 757 @case 1: case 3: case 5:@// odd values758 ®case 1: case 3: case 5:® // odd values 758 759 // odd action 759 760 break; 760 @case 2: case 4: case 6:@// even values761 ®case 2: case 4: case 6:® // even values 761 762 // even action 762 763 break; … … 774 775 if ( j < k ) { 775 776 ... 776 @case 1:@// transfer into "if" statement777 ®case 1:® // transfer into "if" statement 777 778 ... 778 779 } // if … … 780 781 while ( j < 5 ) { 781 782 ... 782 @case 3:@// transfer into "while" statement783 ®case 3:® // transfer into "while" statement 783 784 ... 784 785 } // while … … 821 822 \begin{cfa} 822 823 switch ( x ) { 823 @int y = 1;@$\C{// unreachable initialization}$824 @x = 7;@$\C{// unreachable code without label/branch}$824 ®int y = 1;® $\C{// unreachable initialization}$ 825 ®x = 7;® $\C{// unreachable code without label/branch}$ 825 826 case 0: ... 826 827 ... 827 @int z = 0;@$\C{// unreachable initialization, cannot appear after case}$828 ®int z = 0;® $\C{// unreachable initialization, cannot appear after case}$ 828 829 z = 2; 829 830 case 1: 830 @x = z;@$\C{// without fall through, z is uninitialized}$831 ®x = z;® $\C{// without fall through, z is uninitialized}$ 831 832 } 832 833 \end{cfa} … … 860 861 Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, \eg: 861 862 \begin{cfa} 862 @choose@( i ) {863 ®choose® ( i ) { 863 864 case 1: case 2: case 3: 864 865 ... 865 @// implicit end of switch (break)866 @case 5:866 ®// implicit end of switch (break) 867 ®case 5: 867 868 ... 868 @fallthru@; $\C{// explicit fall through}$869 ®fallthru®; $\C{// explicit fall through}$ 869 870 case 7: 870 871 ... 871 @break@$\C{// explicit end of switch (redundant)}$872 ®break® $\C{// explicit end of switch (redundant)}$ 872 873 default: 873 874 j = 3; … … 890 891 \begin{cfa} 891 892 switch ( x ) { 892 @int i = 0;@$\C{// allowed only at start}$893 ®int i = 0;® $\C{// allowed only at start}$ 893 894 case 0: 894 895 ... 895 @int j = 0;@$\C{// disallowed}$896 ®int j = 0;® $\C{// disallowed}$ 896 897 case 1: 897 898 { 898 @int k = 0;@$\C{// allowed at different nesting levels}$899 ®int k = 0;® $\C{// allowed at different nesting levels}$ 899 900 ... 900 @case 2:@$\C{// disallow case in nested statements}$901 ®case 2:® $\C{// disallow case in nested statements}$ 901 902 } 902 903 ... … … 915 916 case 3: 916 917 if ( ... ) { 917 ... @fallthru;@// goto case 4918 ... ®fallthru;® // goto case 4 918 919 } else { 919 920 ... … … 930 931 choose ( ... ) { 931 932 case 3: 932 ... @fallthrough common;@933 ... ®fallthrough common;® 933 934 case 4: 934 ... @fallthrough common;@935 936 @common:@// below fallthrough935 ... ®fallthrough common;® 936 937 ®common:® // below fallthrough 937 938 // at case-clause level 938 939 ... // common code for cases 3/4 … … 950 951 for ( ... ) { 951 952 // multi-level transfer 952 ... @fallthru common;@953 ... ®fallthru common;® 953 954 } 954 955 ... 955 956 } 956 957 ... 957 @common:@// below fallthrough958 ®common:® // below fallthrough 958 959 // at case-clause level 959 960 \end{cfa} … … 970 971 \hline 971 972 \begin{cfa} 972 while @($\,$)@{ sout | "empty"; break; }973 do { sout | "empty"; break; } while @($\,$)@;974 for @($\,$)@{ sout | "empty"; break; }975 for ( @0@) { sout | "A"; } sout | "zero";976 for ( @1@) { sout | "A"; }977 for ( @10@) { sout | "A"; }978 for ( @= 10@) { sout | "A"; }979 for ( @1 ~= 10 ~ 2@) { sout | "B"; }980 for ( @10 -~= 1 ~ 2@) { sout | "C"; }981 for ( @0.5 ~ 5.5@) { sout | "D"; }982 for ( @5.5 -~ 0.5@) { sout | "E"; }983 for ( @i; 10@) { sout | i; }984 for ( @i; = 10@) { sout | i; }985 for ( @i; 1 ~= 10 ~ 2@) { sout | i; }986 for ( @i; 10 -~= 1 ~ 2@) { sout | i; }987 for ( @i; 0.5 ~ 5.5@) { sout | i; }988 for ( @i; 5.5 -~ 0.5@) { sout | i; }989 for ( @ui; 2u ~= 10u ~ 2u@) { sout | ui; }990 for ( @ui; 10u -~= 2u ~ 2u@) { sout | ui; }973 while ®($\,$)® { sout | "empty"; break; } 974 do { sout | "empty"; break; } while ®($\,$)®; 975 for ®($\,$)® { sout | "empty"; break; } 976 for ( ®0® ) { sout | "A"; } sout | "zero"; 977 for ( ®1® ) { sout | "A"; } 978 for ( ®10® ) { sout | "A"; } 979 for ( ®= 10® ) { sout | "A"; } 980 for ( ®1 ~= 10 ~ 2® ) { sout | "B"; } 981 for ( ®10 -~= 1 ~ 2® ) { sout | "C"; } 982 for ( ®0.5 ~ 5.5® ) { sout | "D"; } 983 for ( ®5.5 -~ 0.5® ) { sout | "E"; } 984 for ( ®i; 10® ) { sout | i; } 985 for ( ®i; = 10® ) { sout | i; } 986 for ( ®i; 1 ~= 10 ~ 2® ) { sout | i; } 987 for ( ®i; 10 -~= 1 ~ 2® ) { sout | i; } 988 for ( ®i; 0.5 ~ 5.5® ) { sout | i; } 989 for ( ®i; 5.5 -~ 0.5® ) { sout | i; } 990 for ( ®ui; 2u ~= 10u ~ 2u® ) { sout | ui; } 991 for ( ®ui; 10u -~= 2u ~ 2u® ) { sout | ui; } 991 992 enum { N = 10 }; 992 for ( @N@) { sout | "N"; }993 for ( @i; N@) { sout | i; }994 for ( @i; N -~ 0@) { sout | i; }993 for ( ®N® ) { sout | "N"; } 994 for ( ®i; N® ) { sout | i; } 995 for ( ®i; N -~ 0® ) { sout | i; } 995 996 const int start = 3, comp = 10, inc = 2; 996 for ( @i; start ~ comp ~ inc + 1@) { sout | i; }997 for ( i; 1 ~ $\R{@}$) { if ( i > 10 ) break; sout | i; }998 for ( i; 10 -~ $\R{@}$) { if ( i < 0 ) break; sout | i; }999 for ( i; 2 ~ $\R{@}$~ 2 ) { if ( i > 10 ) break; sout | i; }1000 for ( i; 2.1 ~ $\R{@}$ ~ $\R{@}$) { if ( i > 10.5 ) break; sout | i; i += 1.7; }1001 for ( i; 10 -~ $\R{@}$~ 2 ) { if ( i < 0 ) break; sout | i; }1002 for ( i; 12.1 ~ $\R{@}$ ~ $\R{@}$) { if ( i < 2.5 ) break; sout | i; i -= 1.7; }1003 for ( i; 5 @:@ j; -5 ~ $@$) { sout | i | j; }1004 for ( i; 5 @:@ j; -5 -~ $@$) { sout | i | j; }1005 for ( i; 5 @:@ j; -5 ~ $@$~ 2 ) { sout | i | j; }1006 for ( i; 5 @:@ j; -5 -~ $@$~ 2 ) { sout | i | j; }1007 for ( i; 5 @:@ j; -5 ~ $@$) { sout | i | j; }1008 for ( i; 5 @:@ j; -5 -~ $@$) { sout | i | j; }1009 for ( i; 5 @:@ j; -5 ~ $@$~ 2 ) { sout | i | j; }1010 for ( i; 5 @:@ j; -5 -~ $@$~ 2 ) { sout | i | j; }1011 for ( i; 5 @:@ j; -5 -~ $@$ ~ 2 @:@ k; 1.5 ~ $@$) { sout | i | j | k; }1012 for ( i; 5 @:@ j; -5 -~ $@$ ~ 2 @:@ k; 1.5 ~ $@$) { sout | i | j | k; }1013 for ( i; 5 @:@ k; 1.5 ~ $@$ @:@ j; -5 -~ $@$~ 2 ) { sout | i | j | k; }997 for ( ®i; start ~ comp ~ inc + 1® ) { sout | i; } 998 for ( i; 1 ~ ®@® ) { if ( i > 10 ) break; sout | i; } 999 for ( i; 10 -~ ®@® ) { if ( i < 0 ) break; sout | i; } 1000 for ( i; 2 ~ ®@® ~ 2 ) { if ( i > 10 ) break; sout | i; } 1001 for ( i; 2.1 ~ ®@® ~ ®@® ) { if ( i > 10.5 ) break; sout | i; i += 1.7; } 1002 for ( i; 10 -~ ®@® ~ 2 ) { if ( i < 0 ) break; sout | i; } 1003 for ( i; 12.1 ~ ®@® ~ ®@® ) { if ( i < 2.5 ) break; sout | i; i -= 1.7; } 1004 for ( i; 5 ®:® j; -5 ~ @ ) { sout | i | j; } 1005 for ( i; 5 ®:® j; -5 -~ @ ) { sout | i | j; } 1006 for ( i; 5 ®:® j; -5 ~ @ ~ 2 ) { sout | i | j; } 1007 for ( i; 5 ®:® j; -5 -~ @ ~ 2 ) { sout | i | j; } 1008 for ( i; 5 ®:® j; -5 ~ @ ) { sout | i | j; } 1009 for ( i; 5 ®:® j; -5 -~ @ ) { sout | i | j; } 1010 for ( i; 5 ®:® j; -5 ~ @ ~ 2 ) { sout | i | j; } 1011 for ( i; 5 ®:® j; -5 -~ @ ~ 2 ) { sout | i | j; } 1012 for ( i; 5 ®:® j; -5 -~ @ ~ 2 ®:® k; 1.5 ~ @ ) { sout | i | j | k; } 1013 for ( i; 5 ®:® j; -5 -~ @ ~ 2 ®:® k; 1.5 ~ @ ) { sout | i | j | k; } 1014 for ( i; 5 ®:® k; 1.5 ~ @ ®:® j; -5 -~ @ ~ 2 ) { sout | i | j | k; } 1014 1015 \end{cfa} 1015 1016 & … … 1089 1090 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M. 1090 1091 \begin{cfa} 1091 for ( i; @5@) $\C[2.5in]{// typeof(5) i; 5 is comparison value}$1092 for ( i; @1.5@~5.5~0.5 ) $\C{// typeof(1.5) i; 1.5 is start value}$1092 for ( i; ®5® ) $\C[2.5in]{// typeof(5) i; 5 is comparison value}$ 1093 for ( i; ®1.5®~5.5~0.5 ) $\C{// typeof(1.5) i; 1.5 is start value}$ 1093 1094 \end{cfa} 1094 1095 \item 1095 1096 An empty conditional implies comparison value of ©1© (true). 1096 1097 \begin{cfa} 1097 while ( $\R{/*empty*/}$ )$\C{// while ( true )}$1098 for ( $\R{/*empty*/}$) $\C{// for ( ; true; )}$1099 do ... while ( $\R{/*empty*/}$ )$\C{// do ... while ( true )}$1098 while ( ®/*empty*/® ) $\C{// while ( true )}$ 1099 for ( ®/*empty*/® ) $\C{// for ( ; true; )}$ 1100 do ... while ( ®/*empty*/® ) $\C{// do ... while ( true )}$ 1100 1101 \end{cfa} 1101 1102 \item 1102 1103 A comparison N is implicit up-to exclusive range [0,N\R{)}. 1103 1104 \begin{cfa} 1104 for ( @5@) $\C{// for ( typeof(5) i; i < 5; i += 1 )}$1105 for ( ®5® ) $\C{// for ( typeof(5) i; i < 5; i += 1 )}$ 1105 1106 \end{cfa} 1106 1107 \item 1107 1108 A comparison ©=© N is implicit up-to inclusive range [0,N\R{]}. 1108 1109 \begin{cfa} 1109 for ( @=@5 ) $\C{// for ( typeof(5) i; i <= 5; i += 1 )}$1110 for ( ®=®5 ) $\C{// for ( typeof(5) i; i <= 5; i += 1 )}$ 1110 1111 \end{cfa} 1111 1112 \item 1112 1113 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N\R{)}. 1113 1114 \begin{cfa} 1114 for ( 1 @~@5 ) $\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}$1115 for ( 1®~®5 ) $\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}$ 1115 1116 \end{cfa} 1116 1117 \item 1117 1118 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N\R{]}. 1118 1119 \begin{cfa} 1119 for ( 1 @~=@5 ) $\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}$1120 for ( 1®~=®5 ) $\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}$ 1120 1121 \end{cfa} 1121 1122 \item 1122 1123 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M\R{)}. 1123 1124 \begin{cfa} 1124 for ( 1 @-~@5 ) $\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}$1125 for ( 1®-~®5 ) $\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}$ 1125 1126 \end{cfa} 1126 1127 \item 1127 1128 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M\R{]}. 1128 1129 \begin{cfa} 1129 for ( 1 @-~=@5 ) $\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}$1130 for ( 1®-~=®5 ) $\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}$ 1130 1131 \end{cfa} 1131 1132 \item 1132 1133 ©@© means put nothing in this field. 1133 1134 \begin{cfa} 1134 for ( 1~ $\R{@}$~2 )$\C{// for ( typeof(1) i = 1; /*empty*/; i += 2 )}$1135 for ( 1~®@®~2 ) $\C{// for ( typeof(1) i = 1; /*empty*/; i += 2 )}$ 1135 1136 \end{cfa} 1136 1137 \item 1137 1138 ©:© means start another index. 1138 1139 \begin{cfa} 1139 for ( i; 5 @:@j; 2~12~3 ) $\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}\CRT$1140 for ( i; 5 ®:® j; 2~12~3 ) $\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}\CRT$ 1140 1141 \end{cfa} 1141 1142 \end{itemize} 1142 1143 1143 1144 1144 %\subsection{\texorpdfstring{Labelled \protect\lstinline @continue@ / \protect\lstinline@break@}{Labelled continue / break}}1145 %\subsection{\texorpdfstring{Labelled \protect\lstinline{continue} / \protect\lstinline{break}}{Labelled continue / break}} 1145 1146 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} 1146 1147 … … 1157 1158 \begin{lrbox}{\myboxA} 1158 1159 \begin{cfa}[tabsize=3] 1159 @Compound:@{1160 @Try:@try {1161 @For:@for ( ... ) {1162 @While:@while ( ... ) {1163 @Do:@do {1164 @If:@if ( ... ) {1165 @Switch:@switch ( ... ) {1160 ®Compound:® { 1161 ®Try:® try { 1162 ®For:® for ( ... ) { 1163 ®While:® while ( ... ) { 1164 ®Do:® do { 1165 ®If:® if ( ... ) { 1166 ®Switch:® switch ( ... ) { 1166 1167 case 3: 1167 @break Compound@;1168 @break Try@;1169 @break For@; /* or */ @continue For@;1170 @break While@; /* or */ @continue While@;1171 @break Do@; /* or */ @continue Do@;1172 @break If@;1173 @break Switch@;1168 ®break Compound®; 1169 ®break Try®; 1170 ®break For®; /* or */ ®continue For®; 1171 ®break While®; /* or */ ®continue While®; 1172 ®break Do®; /* or */ ®continue Do®; 1173 ®break If®; 1174 ®break Switch®; 1174 1175 } // switch 1175 1176 } else { 1176 ... @break If@; ... // terminate if1177 ... ®break If®; ... // terminate if 1177 1178 } // if 1178 1179 } while ( ... ); // do 1179 1180 } // while 1180 1181 } // for 1181 } @finally@{ // always executed1182 } ®finally® { // always executed 1182 1183 } // try 1183 1184 } // compound … … 1189 1190 { 1190 1191 1191 @ForC:@for ( ... ) {1192 @WhileC:@while ( ... ) {1193 @DoC:@do {1192 ®ForC:® for ( ... ) { 1193 ®WhileC:® while ( ... ) { 1194 ®DoC:® do { 1194 1195 if ( ... ) { 1195 1196 switch ( ... ) { 1196 1197 case 3: 1197 @goto Compound@;1198 @goto Try@;1199 @goto ForB@; /* or */ @goto ForC@;1200 @goto WhileB@; /* or */ @goto WhileC@;1201 @goto DoB@; /* or */ @goto DoC@;1202 @goto If@;1203 @goto Switch@;1204 } @Switch:@;1198 ®goto Compound®; 1199 ®goto Try®; 1200 ®goto ForB®; /* or */ ®goto ForC®; 1201 ®goto WhileB®; /* or */ ®goto WhileC®; 1202 ®goto DoB®; /* or */ ®goto DoC®; 1203 ®goto If®; 1204 ®goto Switch®; 1205 } ®Switch:® ; 1205 1206 } else { 1206 ... @goto If@; ... // terminate if1207 } @If:@;1208 } while ( ... ); @DoB:@;1209 } @WhileB:@;1210 } @ForB:@;1211 1212 1213 } @Compound:@;1207 ... ®goto If®; ... // terminate if 1208 } ®If:®; 1209 } while ( ... ); ®DoB:® ; 1210 } ®WhileB:® ; 1211 } ®ForB:® ; 1212 1213 1214 } ®Compound:® ; 1214 1215 \end{cfa} 1215 1216 \end{lrbox} … … 1240 1241 1241 1242 1242 %\subsection{\texorpdfstring{\protect\lstinline @with@Statement}{with Statement}}1243 %\subsection{\texorpdfstring{\protect\lstinline{with} Statement}{with Statement}} 1243 1244 \subsection{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}} 1244 1245 \label{s:WithStatement} … … 1255 1256 \begin{cfa} 1256 1257 Person p 1257 @p.@name; @p.@address; @p.@sex; $\C{// access containing fields}$1258 ®p.®name; ®p.®address; ®p.®sex; $\C{// access containing fields}$ 1258 1259 \end{cfa} 1259 1260 which extends to multiple levels of qualification for nested aggregates and multiple aggregates. 1260 1261 \begin{cfa} 1261 1262 struct Ticket { ... } t; 1262 @p.name@.first; @p.address@.street; $\C{// access nested fields}$1263 @t.@departure; @t.@cost; $\C{// access multiple aggregate}$1263 ®p.name®.first; ®p.address®.street; $\C{// access nested fields}$ 1264 ®t.®departure; ®t.®cost; $\C{// access multiple aggregate}$ 1264 1265 \end{cfa} 1265 1266 Repeated aggregate qualification is tedious and makes code difficult to read. … … 1284 1285 \begin{C++} 1285 1286 struct S { 1286 char @c@; int @i@; double @d@;1287 char ®c®; int ®i®; double ®d®; 1287 1288 void f( /* S * this */ ) { $\C{// implicit ``this'' parameter}$ 1288 @c@; @i@; @d@; $\C{// this->c; this->i; this->d;}$1289 ®c®; ®i®; ®d®; $\C{// this->c; this->i; this->d;}$ 1289 1290 } 1290 1291 } … … 1294 1295 \begin{cfa} 1295 1296 struct T { 1296 char @m@; int @i@; double @n@; $\C{// derived class variables}$1297 char ®m®; int ®i®; double ®n®; $\C{// derived class variables}$ 1297 1298 }; 1298 1299 struct S : public T { 1299 char @c@; int @i@; double @d@; $\C{// class variables}$1300 void g( double @d@, T & t ) {1301 d; @t@.m; @t@.i; @t@.n; $\C{// function parameter}$1302 c; i; @this->@d; @S::@d; $\C{// class S variables}$1303 m; @T::@i; n; $\C{// class T variables}$1300 char ®c®; int ®i®; double ®d®; $\C{// class variables}$ 1301 void g( double ®d®, T & t ) { 1302 d; ®t®.m; ®t®.i; ®t®.n; $\C{// function parameter}$ 1303 c; i; ®this->®d; ®S::®d; $\C{// class S variables}$ 1304 m; ®T::®i; n; $\C{// class T variables}$ 1304 1305 } 1305 1306 }; … … 1311 1312 Hence, the qualified fields become variables with the side-effect that it is simpler to write, easier to read, and optimize field references in a block. 1312 1313 \begin{cfa} 1313 void f( S & this ) @with ( this )@{ $\C{// with statement}$1314 @c@; @i@; @d@; $\C{// this.c, this.i, this.d}$1314 void f( S & this ) ®with ( this )® { $\C{// with statement}$ 1315 ®c®; ®i®; ®d®; $\C{// this.c, this.i, this.d}$ 1315 1316 } 1316 1317 \end{cfa} 1317 1318 with the generality of opening multiple aggregate-parameters: 1318 1319 \begin{cfa} 1319 void g( S & s, T & t ) @with ( s, t )@{ $\C{// multiple aggregate parameters}$1320 c; @s.@i; d; $\C{// s.c, s.i, s.d}$1321 m; @t.@i; n; $\C{// t.m, t.i, t.n}$1320 void g( S & s, T & t ) ®with ( s, t )® { $\C{// multiple aggregate parameters}$ 1321 c; ®s.®i; d; $\C{// s.c, s.i, s.d}$ 1322 m; ®t.®i; n; $\C{// t.m, t.i, t.n}$ 1322 1323 } 1323 1324 \end{cfa} … … 1338 1339 The difference between parallel and nesting occurs for fields with the same name and type: 1339 1340 \begin{cfa} 1340 struct Q { int @i@; int k; int @m@; } q, w;1341 struct R { int @i@; int j; double @m@; } r, w;1341 struct Q { int ®i®; int k; int ®m®; } q, w; 1342 struct R { int ®i®; int j; double ®m®; } r, w; 1342 1343 with ( r, q ) { 1343 1344 j + k; $\C{// unambiguous, r.j + q.k}$ … … 1372 1373 \begin{cfa} 1373 1374 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ 1374 @s.i = i;@j = 3; m = 5.5; $\C{// initialize fields}$1375 ®s.i = i;® j = 3; m = 5.5; $\C{// initialize fields}$ 1375 1376 } 1376 1377 \end{cfa} … … 1385 1386 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1386 1387 \begin{cfa} 1387 void ?{}( S & s, int @i@ ) with ( s ) @with( $\emph{\R{params}}$ )@{ // syntax not allowed, illustration only1388 s.i = @i@; j = 3; m = 5.5;1388 void ?{}( S & s, int ®i® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only 1389 s.i = ®i®; j = 3; m = 5.5; 1389 1390 } 1390 1391 \end{cfa} … … 1469 1470 For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way: 1470 1471 \begin{cfa} 1471 int @(*@f@())[@5@]@{...}; $\C{// definition}$1472 ... @(*@f@())[@3@]@+= 1; $\C{// usage}$1472 int ®(*®f®())[®5®]® {...}; $\C{// definition}$ 1473 ... ®(*®f®())[®3®]® += 1; $\C{// usage}$ 1473 1474 \end{cfa} 1474 1475 Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}). … … 1486 1487 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1487 1488 \begin{cfa}[moredelim={**[is][\color{blue}]{\#}{\#}}] 1488 #[5] *# @int@x1;1489 #* [5]# @int@x2;1490 #[* [5] int]# f @( int p )@;1489 #[5] *# ®int® x1; 1490 #* [5]# ®int® x2; 1491 #[* [5] int]# f®( int p )®; 1491 1492 \end{cfa} 1492 1493 & 1493 1494 \begin{cfa}[moredelim={**[is][\color{blue}]{\#}{\#}}] 1494 @int@#*# x1 #[5]#;1495 @int@#(*#x2#)[5]#;1496 #int (*#f @( int p )@#)[5]#;1495 ®int® #*# x1 #[5]#; 1496 ®int® #(*#x2#)[5]#; 1497 #int (*#f®( int p )®#)[5]#; 1497 1498 \end{cfa} 1498 1499 \end{tabular} … … 1506 1507 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1507 1508 \begin{cfa} 1508 @*@int x, y;1509 ®*® int x, y; 1509 1510 \end{cfa} 1510 1511 & 1511 1512 \begin{cfa} 1512 int @*@x, @*@y;1513 int ®*®x, ®*®y; 1513 1514 \end{cfa} 1514 1515 \end{tabular} … … 1519 1520 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1520 1521 \begin{cfa} 1521 @*@int x;1522 ®*® int x; 1522 1523 int y; 1523 1524 \end{cfa} 1524 1525 & 1525 1526 \begin{cfa} 1526 int @*@x, y;1527 int ®*®x, y; 1527 1528 1528 1529 \end{cfa} … … 1660 1661 & 1661 1662 \begin{cfa} 1662 int * @const@x = (int *)1001663 int * ®const® x = (int *)100 1663 1664 *x = 3; // implicit dereference 1664 int * @const@y = (int *)104;1665 int * ®const® y = (int *)104; 1665 1666 *y = *x; // implicit dereference 1666 1667 \end{cfa} … … 1700 1701 \begin{tabular}{@{}l@{\hspace{2em}}l@{}} 1701 1702 \begin{cfa} 1702 int x, y, @*@ p1, @*@ p2, @**@p3;1703 p1 = @&@x; // p1 points to x1703 int x, y, ®*® p1, ®*® p2, ®**® p3; 1704 p1 = ®&®x; // p1 points to x 1704 1705 p2 = p1; // p2 points to x 1705 p1 = @&@y; // p1 points to y1706 p1 = ®&®y; // p1 points to y 1706 1707 p3 = &p2; // p3 points to p2 1707 1708 \end{cfa} … … 1729 1730 \begin{cfa} 1730 1731 p1 = p2; $\C{// pointer address assignment}$ 1731 @*@p2 = @*@p1 + x; $\C{// pointed-to value assignment / operation}$1732 ®*®p2 = ®*®p1 + x; $\C{// pointed-to value assignment / operation}$ 1732 1733 \end{cfa} 1733 1734 The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©). … … 1745 1746 To support this common case, a reference type is introduced in \CFA, denoted by ©&©, which is the opposite dereference semantics to a pointer type, making the value at the pointed-to location the implicit semantics for dereferencing (similar but not the same as \CC \Index{reference type}s). 1746 1747 \begin{cfa} 1747 int x, y, @&@ r1, @&@ r2, @&&@r3;1748 @&@r1 = &x; $\C{// r1 points to x}$1749 @&@r2 = &r1; $\C{// r2 points to x}$1750 @&@r1 = &y; $\C{// r1 points to y}$1751 @&&@r3 = @&@&r2; $\C{// r3 points to r2}$1748 int x, y, ®&® r1, ®&® r2, ®&&® r3; 1749 ®&®r1 = &x; $\C{// r1 points to x}$ 1750 ®&®r2 = &r1; $\C{// r2 points to x}$ 1751 ®&®r1 = &y; $\C{// r1 points to y}$ 1752 ®&&®r3 = ®&®&r2; $\C{// r3 points to r2}$ 1752 1753 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); $\C{// implicit dereferencing}$ 1753 1754 \end{cfa} … … 1756 1757 One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in a declaration, so the previous example becomes: 1757 1758 \begin{cfa} 1758 @*@r2 = ((@*@r1 + @*@r2) @*@ (@**@r3 - @*@r1)) / (@**@r3 - 15);1759 ®*®r2 = ((®*®r1 + ®*®r2) ®*® (®**®r3 - ®*®r1)) / (®**®r3 - 15); 1759 1760 \end{cfa} 1760 1761 When a reference operation appears beside a dereference operation, \eg ©&*©, they cancel out. … … 1765 1766 For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}): 1766 1767 \begin{cfa} 1767 (& @*@)r1 = &x; $\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}$1768 (&®*®)r1 = &x; $\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}$ 1768 1769 \end{cfa} 1769 1770 Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}): 1770 1771 \begin{cfa} 1771 (&(& @*@)@*@)r3 = &(&@*@)r2; $\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}$1772 (&(&®*®)®*®)r3 = &(&®*®)r2; $\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}$ 1772 1773 \end{cfa} 1773 1774 Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth. … … 1792 1793 const int cx = 5; $\C{// cannot change cx;}$ 1793 1794 const int & cr = cx; $\C{// cannot change what cr points to}$ 1794 @&@cr = &cx; $\C{// can change cr}$1795 ®&®cr = &cx; $\C{// can change cr}$ 1795 1796 cr = 7; $\C{// error, cannot change cx}$ 1796 1797 int & const rc = x; $\C{// must be initialized}$ 1797 @&@rc = &x; $\C{// error, cannot change rc}$1798 ®&®rc = &x; $\C{// error, cannot change rc}$ 1798 1799 const int & const crc = cx; $\C{// must be initialized}$ 1799 1800 crc = 7; $\C{// error, cannot change cx}$ 1800 @&@crc = &cx; $\C{// error, cannot change crc}$1801 ®&®crc = &cx; $\C{// error, cannot change crc}$ 1801 1802 \end{cfa} 1802 1803 Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}: … … 1819 1820 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1820 1821 \begin{cfa} 1821 @const@ * @const@* const int ccp;1822 @const@ & @const@& const int ccr;1822 ®const® * ®const® * const int ccp; 1823 ®const® & ®const® & const int ccr; 1823 1824 \end{cfa} 1824 1825 & 1825 1826 \begin{cfa} 1826 const int * @const@ * @const@ccp;1827 const int * ®const® * ®const® ccp; 1827 1828 1828 1829 \end{cfa} … … 1856 1857 \begin{cfa} 1857 1858 int * p = &x; $\C{// assign address of x}$ 1858 @int * p = x;@$\C{// assign value of x}$1859 ®int * p = x;® $\C{// assign value of x}$ 1859 1860 int & r = x; $\C{// must have address of x}$ 1860 1861 \end{cfa} … … 1880 1881 When a pointer/reference parameter has a ©const© value (immutable), it is possible to pass literals and expressions. 1881 1882 \begin{cfa} 1882 void f( @const@int & cr );1883 void g( @const@int * cp );1884 f( 3 ); g( @&@3 );1885 f( x + y ); g( @&@(x + y) );1883 void f( ®const® int & cr ); 1884 void g( ®const® int * cp ); 1885 f( 3 ); g( ®&®3 ); 1886 f( x + y ); g( ®&®(x + y) ); 1886 1887 \end{cfa} 1887 1888 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. … … 1894 1895 void f( int & r ); 1895 1896 void g( int * p ); 1896 f( 3 ); g( @&@3 ); $\C{// compiler implicit generates temporaries}$1897 f( x + y ); g( @&@(x + y) ); $\C{// compiler implicit generates temporaries}$1897 f( 3 ); g( ®&®3 ); $\C{// compiler implicit generates temporaries}$ 1898 f( x + y ); g( ®&®(x + y) ); $\C{// compiler implicit generates temporaries}$ 1898 1899 \end{cfa} 1899 1900 Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{ … … 1916 1917 Instead, a routine object should be referenced by a ©const© reference: 1917 1918 \begin{cfa} 1918 @const@ void (@&@fr)( int ) = f; $\C{// routine reference}$1919 ®const® void (®&® fr)( int ) = f; $\C{// routine reference}$ 1919 1920 fr = ... $\C{// error, cannot change code}$ 1920 1921 &fr = ...; $\C{// changing routine reference}$ … … 1978 1979 \begin{cfa} 1979 1980 int x, &r = x, f( int p ); 1980 x = @r@ + f( @r@); $\C{// lvalue reference converts to rvalue}$1981 x = ®r® + f( ®r® ); $\C{// lvalue reference converts to rvalue}$ 1981 1982 \end{cfa} 1982 1983 An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped. 1983 1984 1984 1985 \item 1985 lvalue to reference conversion: \lstinline[deletekeywords=lvalue] @lvalue-type cv1 T@converts to ©cv2 T &©, which allows implicitly converting variables to references.1986 \begin{cfa} 1987 int x, &r = @x@, f( int & p ); $\C{// lvalue variable (int) convert to reference (int \&)}$1988 f( @x@); $\C{// lvalue variable (int) convert to reference (int \&)}$1986 lvalue to reference conversion: \lstinline[deletekeywords=lvalue]{lvalue-type cv1 T} converts to ©cv2 T &©, which allows implicitly converting variables to references. 1987 \begin{cfa} 1988 int x, &r = ®x®, f( int & p ); $\C{// lvalue variable (int) convert to reference (int \&)}$ 1989 f( ®x® ); $\C{// lvalue variable (int) convert to reference (int \&)}$ 1989 1990 \end{cfa} 1990 1991 Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost. … … 1996 1997 \begin{cfa} 1997 1998 int x, & f( int & p ); 1998 f( @x + 3@); $\C[1.5in]{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}$1999 @&f@(...) = &x; $\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}\CRT$1999 f( ®x + 3® ); $\C[1.5in]{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}$ 2000 ®&f®(...) = &x; $\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}\CRT$ 2000 2001 \end{cfa} 2001 2002 In both case, modifications to the temporary are inaccessible (\Index{warning}). … … 2164 2165 2165 2166 2167 \section{Enumeration} 2168 2169 An \newterm{enumeration} is a compile-time mechanism to alias names to constants, like ©typedef© is a mechanism to alias names to types. 2170 Its purpose is to define a restricted-value type providing code-readability and maintenance -- changing an enum's value automatically updates all name usages during compilation. 2171 2172 An enumeration type is a set of names, each called an \newterm{enumeration constant} (shortened to \newterm{enum}) aliased to a fixed value (constant). 2173 \begin{cfa} 2174 enum Days { Mon, Tue, Wed, Thu, Fri, Sat, Sun }; // enumeration type definition, set of 7 names & values 2175 Days days = Mon; // enumeration type declaration and initialization 2176 \end{cfa} 2177 The set of enums are injected into the variable namespace at the definition scope. 2178 Hence, enums may be overloaded with enum/variable/function names. 2179 \begin{cfa} 2180 enum Foo { Bar }; 2181 enum Goo { Bar }; $\C[1.75in]{// overload Foo.Bar}$ 2182 int Foo; $\C{// type/variable separate namespace}$ 2183 double Bar; $\C{// overload Foo.Bar, Goo.Bar}\CRT$ 2184 \end{cfa} 2185 An anonymous enumeration injects enums with specific values into a scope. 2186 \begin{cfa} 2187 enum { Prime = 103, BufferSize = 1024 }; 2188 \end{cfa} 2189 An enumeration is better than using C \Index{preprocessor} or constant declarations. 2190 \begin{cquote} 2191 \begin{tabular}{@{}l@{\hspace{4em}}l@{}} 2192 \begin{cfa} 2193 #define Mon 0 2194 ... 2195 #define Sun 6 2196 \end{cfa} 2197 & 2198 \begin{cfa} 2199 const int Mon = 0, 2200 ..., 2201 Sun = 6; 2202 \end{cfa} 2203 \end{tabular} 2204 \end{cquote} 2205 because the enumeration is succinct, has automatic numbering, can appear in ©case© labels, does not use storage, and is part of the language type-system. 2206 Finally, the type of an enum is implicitly or explicitly specified and the constant value can be implicitly or explicitly specified. 2207 Note, enum values may be repeated in an enumeration. 2208 2209 2210 \subsection{Enum type} 2211 2212 The type of enums can be any type, and an enum's value comes from this type. 2213 Because an enum is a constant, it cannot appear in a mutable context, \eg ©Mon = Sun© is disallowed, and has no address (it is an rvalue). 2214 Therefore, an enum is automatically converted to its constant's base-type, \eg comparing/printing an enum compares/prints its value rather than the enum name; 2215 there is no mechanism to print the enum name. 2216 2217 The default enum type is ©int©. 2218 Hence, ©Days© is the set type ©Mon©, ©Tue©, ...\,, ©Sun©, while the type of each enum is ©int© and each enum represents a fixed integral value. 2219 If no values are specified for an integral enum type, the enums are automatically numbered by one from left to right starting at zero. 2220 Hence, the value of enum ©Mon© is 0, ©Tue© is 1, ...\,, ©Sun© is 6. 2221 If an enum value is specified, numbering continues by one from that value for subsequent unnumbered enums. 2222 If an enum value is an expression, the compiler performs constant-folding to obtain a constant value. 2223 2224 \CFA allows other integral types with associated values. 2225 \begin{cfa} 2226 enum( ®char® ) Letter { A ®= 'A'®, B, C, I ®= 'I'®, J, K }; 2227 enum( ®long long int® ) BigNum { X = 123_456_789_012_345, Y = 345_012_789_456_123 }; 2228 \end{cfa} 2229 For enumeration ©Letter©, enum ©A©'s value is explicitly set to ©'A'©, with ©B© and ©C© implicitly numbered with increasing values from ©'A'©, and similarly for enums ©I©, ©J©, and ©K©. 2230 2231 Non-integral enum types must be explicitly initialized, \eg ©double© is not automatically numbered by one. 2232 \begin{cfa} 2233 // non-integral numeric 2234 enum( ®double® ) Math { PI_2 = 1.570796, PI = 3.141597, E = 2.718282 } 2235 // pointer 2236 enum( ®char *® ) Name { Fred = "Fred", Mary = "Mary", Jane = "Jane" }; 2237 int i, j, k; 2238 enum( ®int *® ) ptr { I = &i, J = &j, K = &k }; 2239 enum( ®int &® ) ref { I = i, J = j, K = k }; 2240 // tuple 2241 enum( ®[int, int]® ) { T = [ 1, 2 ] }; 2242 // function 2243 void f() {...} void g() {...} 2244 enum( ®void (*)()® ) funs { F = f, F = g }; 2245 // aggregate 2246 struct S { int i, j; }; 2247 enum( ®S® ) s { A = { 3, 4 }, B = { 7, 8 } }; 2248 // enumeration 2249 enum( ®Letter® ) Greek { Alph = A, Beta = B, /* more enums */ }; // alphabet intersection 2250 \end{cfa} 2251 Enumeration ©Greek© may have more or less enums than ©Letter©, but the enum values \emph{must} be from ©Letter©. 2252 Therefore, ©Greek© enums are a subset of type ©Letter© and are type compatible with enumeration ©Letter©, but ©Letter© enums are not type compatible with enumeration ©Greek©. 2253 2254 The following examples illustrate the difference between the enumeration type and the type of its enums. 2255 \begin{cfa} 2256 Math m = PI; $\C[1.5in]{// allowed}$ 2257 double d = PI; $\C{// allowed, conversion to base type}$ 2258 m = E; $\C{// allowed}$ 2259 m = Alph; $\C{// {\color{red}disallowed}}$ 2260 m = 3.141597; $\C{// {\color{red}disallowed}}$ 2261 d = m; $\C{// allowed}$ 2262 d = Alph; $\C{// {\color{red}disallowed}}$ 2263 Letter l = A; $\C{// allowed}$ 2264 Greek g = Alph; $\C{// allowed}$ 2265 l = Alph; $\C{// allowed, conversion to base type}$ 2266 g = A; $\C{// {\color{red}disallowed}}\CRT$ 2267 \end{cfa} 2268 2269 A constructor \emph{cannot} be used to initialize enums because a constructor executes at runtime. 2270 A fallback is explicit C-style initialization using ©@=©. 2271 \begin{cfa} 2272 enum( struct vec3 ) Axis { Up @= { 1, 0, 0 }, Left @= { 0, 1, 0 }, Front @= { 0, 0, 1 } } 2273 \end{cfa} 2274 Finally, enumeration variables are assignable and comparable only if the appropriate operators are defined for its enum type. 2275 2276 2277 \subsection{Inheritance} 2278 2279 \Index{Plan-9}\index{inheritance!enumeration} inheritance may be used with enumerations. 2280 \begin{cfa} 2281 enum( char * ) Name2 { ®inline Name®, Jack = "Jack", Jill = "Jill" }; 2282 enum ®/* inferred */® Name3 { ®inline Name2®, Sue = "Sue", Tom = "Tom" }; 2283 \end{cfa} 2284 Enumeration ©Name2© inherits all the enums and their values from enumeration ©Name© by containment, and a ©Name© enumeration is a subtype of enumeration ©Name2©. 2285 Note, enums must be unique in inheritance but enum values may be repeated. 2286 The enum type for the inheriting type must be the same as the inherited type; 2287 hence the enum type may be omitted for the inheriting enumeration and it is inferred from the inherited enumeration, as for ©Name3©. 2288 When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important, \eg the placement of ©Sue© and ©Tom© before or after ©inline Name2©. 2289 2290 Specifically, the inheritance relationship for ©Name©s is: 2291 \begin{cfa} 2292 Name $\(\subseteq\)$ Name2 $\(\subseteq\)$ Name3 $\(\subseteq\)$ const char * // enum type of Name 2293 \end{cfa} 2294 Hence, given 2295 \begin{cfa} 2296 void f( Name ); 2297 void g( Name2 ); 2298 void h( Name3 ); 2299 void j( const char * ); 2300 \end{cfa} 2301 the following calls are valid 2302 \begin{cfa} 2303 f( Fred ); 2304 g( Fred ); g( Jill ); 2305 h( Fred ); h( Jill ); h( Sue ); 2306 j( Fred ); j( Jill ); j( Sue ); j( 'W' ); 2307 \end{cfa} 2308 Note, the validity of calls is the same for call-by-reference as for call-by-value, and ©const© restrictions are the same as for other types. 2309 2310 Enums cannot be created at runtime, so inheritence problems, such as contra-variance do not apply. 2311 Only instances of the enum base-type may be created at runtime. 2312 2313 \begin{comment} 2314 The invariance of references, as I show at the bottom, is easy to overlook. Not shown, but on the same topic, is that returns work in the opposite direction as parameters. Hopefully our existing type rules already know both those facts, so that we'd only have to provide the rules that I suggest using the by-value parameters. 2315 2316 The Fred, Jack, and Mary declarations are picked verbatim from our earlier whiteboard, just repeated here for reference. 2317 2318 \begin{cfa} 2319 // Fred is a subset of char * 2320 enum( char *) Fred { A = "A", B = "B", C = "C" }; 2321 // Jack is a subset of Fred 2322 enum( enum Fred ) Jack { W = A, Y = C}; 2323 // Mary is a superset of Fred 2324 enum Mary { inline Fred, D = "hello" }; 2325 2326 // Demonstrating invariance of references 2327 2328 [void] frcs( & * char x ) { char * x0 = x; x = "bye"; } 2329 [void] frf ( & Fred x ) { Fred x0 = x; x = B; } 2330 [void] frj ( & Jack x ) { Jack x0 = x; x = W; } 2331 [void] frm ( & Mary x ) { Mary x0 = x; x = D; } 2332 2333 char * vcs; 2334 Fred vf; 2335 Jack vj; 2336 Mary vm; 2337 2338 // all variant calls: bad (here are noteworthy examples) 2339 frcs( vf ); // can't assign "bye" to vf 2340 frm ( vf ); // can't assign D to vf 2341 frf ( vj ); // can't assign B to vj 2342 vf = B ; frj ( vf ); // can't assign B to frj.x0 2343 vcs = "bye"; frf ( vcs ); // can't assign "bye" to frf.x0 2344 \end{cfa} 2345 2346 This example is really great. However, I think it's work explicitly doing one with ©const &©. 2347 \end{comment} 2348 2349 2166 2350 \section{Routine Definition} 2167 2351 2168 \CFA alsosupports a new syntax for routine definition, as well as \Celeven and K\&R routine syntax.2352 \CFA supports a new syntax for routine definition, as well as \Celeven and K\&R routine syntax. 2169 2353 The point of the new syntax is to allow returning multiple values from a routine~\cite{Galletly96,CLU}, \eg: 2170 2354 \begin{cfa} 2171 @[ int o1, int o2, char o3 ]@f( int i1, char i2, char i3 ) {2355 ®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) { 2172 2356 $\emph{routine body}$ 2173 2357 } 2174 2358 \end{cfa} 2175 2359 where routine ©f© has three output (return values) and three input parameters. 2176 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.2360 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. 2177 2361 2178 2362 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{ … … 2181 2365 Declaration qualifiers can only appear at the start of a routine definition, \eg: 2182 2366 \begin{cfa} 2183 @extern@[ int x ] g( int y ) {$\,$}2367 ®extern® [ int x ] g( int y ) {$\,$} 2184 2368 \end{cfa} 2185 2369 Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified; … … 2200 2384 int (*f(x))[ 5 ] int x; {} 2201 2385 \end{cfa} 2202 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 xof type array of 5 integers.2386 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. 2203 2387 Since the strings overlap starting with the open bracket, ©[©, there is an ambiguous interpretation for the string. 2204 2388 As well, \CFA-style declarations cannot be used to declare parameters for C-style routine-definitions because of the following ambiguity: … … 2239 2423 \begin{minipage}{\linewidth} 2240 2424 \begin{cfa} 2241 @[ int x, int y ]@f() {2425 ®[ int x, int y ]® f() { 2242 2426 int z; 2243 2427 ... x = 0; ... y = z; ... 2244 @return;@$\C{// implicitly return x, y}$2428 ®return;® $\C{// implicitly return x, y}$ 2245 2429 } 2246 2430 \end{cfa} … … 2574 2758 2575 2759 int fred() { 2576 s.t.c = @S.@R; // type qualification2577 struct @S.@T t = { @S.@R, 1, 2 };2578 enum @S.@C c;2579 union @S.T.@U u;2760 s.t.c = ®S.®R; // type qualification 2761 struct ®S.®T t = { ®S.®R, 1, 2 }; 2762 enum ®S.®C c; 2763 union ®S.T.®U u; 2580 2764 } 2581 2765 \end{cfa} … … 2603 2787 qsort( ia, size ); $\C{// sort ascending order using builtin ?<?}$ 2604 2788 { 2605 @int ?<?( int x, int y ) { return x > y; }@$\C{// nested routine}$2789 ®int ?<?( int x, int y ) { return x > y; }® $\C{// nested routine}$ 2606 2790 qsort( ia, size ); $\C{// sort descending order by local redefinition}$ 2607 2791 } … … 2613 2797 \begin{cfa} 2614 2798 [* [int]( int )] foo() { $\C{// int (* foo())( int )}$ 2615 int @i@= 7;2799 int ®i® = 7; 2616 2800 int bar( int p ) { 2617 @i@+= 1; $\C{// dependent on local variable}$2618 sout | @i@;2801 ®i® += 1; $\C{// dependent on local variable}$ 2802 sout | ®i®; 2619 2803 } 2620 2804 return bar; $\C{// undefined because of local dependence}$ … … 2634 2818 In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call. 2635 2819 \begin{cfa} 2636 f( @2, x, 3 + i@); $\C{// element list}$2820 f( ®2, x, 3 + i® ); $\C{// element list}$ 2637 2821 \end{cfa} 2638 2822 A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}. … … 2747 2931 In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}. 2748 2932 \begin{cfa} 2749 [int, int] @qr@= div( 13, 5 ); $\C{// initialize tuple variable}$2750 printf( "%d %d\n", @qr@); $\C{// print quotient/remainder}$2933 [int, int] ®qr® = div( 13, 5 ); $\C{// initialize tuple variable}$ 2934 printf( "%d %d\n", ®qr® ); $\C{// print quotient/remainder}$ 2751 2935 \end{cfa} 2752 2936 It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}. … … 3412 3596 \begin{cfa} 3413 3597 int x = 1, y = 2, z = 3; 3414 sout | x @|@ y @|@z;3598 sout | x ®|® y ®|® z; 3415 3599 \end{cfa} 3416 3600 & 3417 3601 \begin{cfa} 3418 3602 3419 cout << x @<< " "@ << y @<< " "@<< z << endl;3603 cout << x ®<< " "® << y ®<< " "® << z << endl; 3420 3604 \end{cfa} 3421 3605 & … … 3426 3610 \\ 3427 3611 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3428 1 @ @2@ @33612 1® ®2® ®3 3429 3613 \end{cfa} 3430 3614 & 3431 3615 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3432 1 @ @2@ @33616 1® ®2® ®3 3433 3617 \end{cfa} 3434 3618 & 3435 3619 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3436 1 @ @2@ @33620 1® ®2® ®3 3437 3621 \end{cfa} 3438 3622 \end{tabular} 3439 3623 \end{cquote} 3440 3624 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators and newline. 3441 Similar simplification occurs for \Index{tuple} I/O, which flattens the tuple and prints each value separated by ``\lstinline[showspaces=true] @, @''.3625 Similar simplification occurs for \Index{tuple} I/O, which flattens the tuple and prints each value separated by ``\lstinline[showspaces=true]{, }''. 3442 3626 \begin{cfa} 3443 3627 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ]; … … 3445 3629 \end{cfa} 3446 3630 \begin{cfa}[showspaces=true,aboveskip=0pt] 3447 1 @, @2@, @3 4@, @5@, @63631 1®, ®2®, ®3 4®, ®5®, ®6 3448 3632 \end{cfa} 3449 3633 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority \emph{overloadable} operator, other than assignment. … … 3454 3638 & 3455 3639 \begin{cfa} 3456 sout | x * 3 | y + 1 | z << 2 | x == y | @(@x | y@)@ | @(@x || y@)@ | @(@x > z ? 1 : 2@)@;3640 sout | x * 3 | y + 1 | z << 2 | x == y | ®(®x | y®)® | ®(®x || y®)® | ®(®x > z ? 1 : 2®)®; 3457 3641 \end{cfa} 3458 3642 \\ … … 3460 3644 & 3461 3645 \begin{cfa} 3462 cout << x * 3 << y + 1 << @(@z << 2@)@ << @(@x == y@)@ << @(@x | y@)@ << @(@x || y@)@ << @(@x > z ? 1 : 2@)@<< endl;3646 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << ®(®x | y®)® << ®(®x || y®)® << ®(®x > z ? 1 : 2®)® << endl; 3463 3647 \end{cfa} 3464 3648 \\ … … 3495 3679 \\ 3496 3680 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3497 @1@ @2.5@ @A@ 3681 ®1® ®2.5® ®A® 3498 3682 3499 3683 … … 3501 3685 & 3502 3686 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3503 @1@ @2.5@ @A@ 3687 ®1® ®2.5® ®A® 3504 3688 3505 3689 … … 3507 3691 & 3508 3692 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3509 @1@ 3510 @2.5@ 3511 @A@ 3693 ®1® 3694 ®2.5® 3695 ®A® 3512 3696 \end{cfa} 3513 3697 \end{tabular} … … 3545 3729 3546 3730 \item 3547 A separator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \LstStringStyle{,.;!?)]\}\%\textcent\guillemotright}, where \LstStringStyle{\guillemotright} a closing citation mark.3731 A separator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \LstStringStyle{,.;!?)]\}\%\textcent\guillemotright}, where \LstStringStyle{\guillemotright} is a closing citation mark. 3548 3732 \begin{cfa} 3549 3733 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" … … 3551 3735 \end{cfa} 3552 3736 \begin{cfa}[showspaces=true] 3553 1 @,@ x 2@.@ x 3@;@ x 4@!@ x 5@?@ x 6@%@ x 7$\R{\LstStringStyle{\textcent}}$ x 8$\R{\LstStringStyle{\guillemotright}}$ x 9@)@ x 10@]@ x 11@}@x3737 1®,® x 2®.® x 3®;® x 4®!® x 5®?® x 6®%® x 7$\R{\LstStringStyle{\textcent}}$ x 8$\R{\LstStringStyle{\guillemotright}}$ x 9®)® x 10®]® x 11®}® x 3554 3738 \end{cfa} 3555 3739 … … 3558 3742 %$ 3559 3743 \begin{cfa} 3560 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $ " | 5 | "x $\LstStringStyle{\textsterling}$" | 6 | "x $\LstStringStyle{\textyen}$"3744 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $\LstStringStyle{\textdollar}$" | 5 | "x $\LstStringStyle{\textsterling}$" | 6 | "x $\LstStringStyle{\textyen}$" 3561 3745 | 7 | "x $\LstStringStyle{\textexclamdown}$" | 8 | "x $\LstStringStyle{\textquestiondown}$" | 9 | "x $\LstStringStyle{\guillemotleft}$" | 10; 3562 3746 \end{cfa} 3563 3747 %$ 3564 3748 \begin{cfa}[showspaces=true] 3565 x @(@1 x @[@2 x @{@3 x @=@4 x $\LstStringStyle{\textdollar}$5 x $\R{\LstStringStyle{\textsterling}}$6 x $\R{\LstStringStyle{\textyen}}$7 x $\R{\LstStringStyle{\textexclamdown}}$8 x $\R{\LstStringStyle{\textquestiondown}}$9 x $\R{\LstStringStyle{\guillemotleft}}$103749 x ®(®1 x ®[®2 x ®{®3 x ®=®4 x $\LstStringStyle{\textdollar}$5 x $\R{\LstStringStyle{\textsterling}}$6 x $\R{\LstStringStyle{\textyen}}$7 x $\R{\LstStringStyle{\textexclamdown}}$8 x $\R{\LstStringStyle{\textquestiondown}}$9 x $\R{\LstStringStyle{\guillemotleft}}$10 3566 3750 \end{cfa} 3567 3751 %$ 3568 3752 3569 3753 \item 3570 A sep erator does not appear before/after a C string starting/ending with the \Index*{ASCII} quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]{`'": \t\v\f\r\n}3754 A separator does not appear before/after a C string starting/ending with the \Index*{ASCII} quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]{`'": \t\v\f\r\n} 3571 3755 \begin{cfa} 3572 3756 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx"; 3573 3757 \end{cfa} 3574 3758 \begin{cfa}[showspaces=true,showtabs=true] 3575 x @`@1@`@x$\R{\texttt{'}}$2$\R{\texttt{'}}$x$\R{\texttt{"}}$3$\R{\texttt{"}}$x@:@4@:@x@ @5@ @x@ @6@ @x3759 x®`®1®`®x$\R{\texttt{'}}$2$\R{\texttt{'}}$x$\R{\texttt{"}}$3$\R{\texttt{"}}$x®:®4®:®x® ®5® ®x® ®6® ®x 3576 3760 \end{cfa} 3577 3761 … … 3582 3766 \end{cfa} 3583 3767 \begin{cfa}[showspaces=true,showtabs=true] 3584 x ( @ @1@ @) x 2@ @, x 3@ @:x:@ @43768 x (® ®1® ®) x 2® ®, x 3® ®:x:® ®4 3585 3769 \end{cfa} 3586 3770 \end{enumerate} … … 3595 3779 \Indexc{sepSet}\index{manipulator!sepSet@©sepSet©} and \Indexc{sep}\index{manipulator!sep@©sep©}/\Indexc{sepGet}\index{manipulator!sepGet@©sepGet©} set and get the separator string. 3596 3780 The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 3597 \begin{cfa}[escapechar=off,belowskip=0pt] 3598 sepSet( sout, ", $" ); $\C{// set separator from " " to ", \$"}$ 3599 sout | 1 | 2 | 3 | " \"" | @sep@ | "\""; 3600 \end{cfa} 3601 %$ 3602 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt] 3603 1@, $@2@, $@3 @", $"@ 3604 \end{cfa} 3605 %$ 3781 \begin{cfa}[belowskip=0pt] 3782 sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); $\C{// set separator from " " to ", \$"}$ 3783 sout | 1 | 2 | 3 | " \"" | ®sep® | "\""; 3784 \end{cfa} 3785 \begin{cfa}[showspaces=true,aboveskip=0pt] 3786 1®, $\LstStringStyle{\textdollar}$®2®, $\LstStringStyle{\textdollar}$®3 ®", $\LstStringStyle{\textdollar}$"® 3787 \end{cfa} 3606 3788 \begin{cfa}[belowskip=0pt] 3607 3789 sepSet( sout, " " ); $\C{// reset separator to " "}$ 3608 sout | 1 | 2 | 3 | " \"" | @sepGet( sout )@| "\"";3790 sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\""; 3609 3791 \end{cfa} 3610 3792 \begin{cfa}[showspaces=true,aboveskip=0pt] 3611 1 @ @2@ @3 @" "@3793 1® ®2® ®3 ®" "® 3612 3794 \end{cfa} 3613 3795 ©sepGet© can be used to store a separator and then restore it: 3614 3796 \begin{cfa}[belowskip=0pt] 3615 char store[ @sepSize@]; $\C{// sepSize is the maximum separator size}$3797 char store[®sepSize®]; $\C{// sepSize is the maximum separator size}$ 3616 3798 strcpy( store, sepGet( sout ) ); $\C{// copy current separator}$ 3617 3799 sepSet( sout, "_" ); $\C{// change separator to underscore}$ … … 3619 3801 \end{cfa} 3620 3802 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3621 1 @_@2@_@33803 1®_®2®_®3 3622 3804 \end{cfa} 3623 3805 \begin{cfa}[belowskip=0pt] … … 3626 3808 \end{cfa} 3627 3809 \begin{cfa}[showspaces=true,aboveskip=0pt] 3628 1 @ @2@ @33810 1® ®2® ®3 3629 3811 \end{cfa} 3630 3812 … … 3634 3816 \begin{cfa}[belowskip=0pt] 3635 3817 sepSetTuple( sout, " " ); $\C{// set tuple separator from ", " to " "}$ 3636 sout | t1 | t2 | " \"" | @sepTuple@| "\"";3818 sout | t1 | t2 | " \"" | ®sepTuple® | "\""; 3637 3819 \end{cfa} 3638 3820 \begin{cfa}[showspaces=true,aboveskip=0pt] 3639 1 2 3 4 5 6 @" "@3821 1 2 3 4 5 6 ®" "® 3640 3822 \end{cfa} 3641 3823 \begin{cfa}[belowskip=0pt] 3642 3824 sepSetTuple( sout, ", " ); $\C{// reset tuple separator to ", "}$ 3643 sout | t1 | t2 | " \"" | @sepGetTuple( sout )@| "\"";3825 sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\""; 3644 3826 \end{cfa} 3645 3827 \begin{cfa}[showspaces=true,aboveskip=0pt] 3646 1, 2, 3 4, 5, 6 @", "@3828 1, 2, 3 4, 5, 6 ®", "® 3647 3829 \end{cfa} 3648 3830 As for ©sepGet©, ©sepGetTuple© can be use to store a tuple separator and then restore it. … … 3696 3878 \end{cfa} 3697 3879 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3698 @ @1 2 3@ @ 3880 ® ®1 2 3® ® 3699 3881 \end{cfa} 3700 3882 \end{enumerate} … … 3716 3898 For example, in: 3717 3899 \begin{cfa} 3718 sin | i | @nl@| j;3719 1 @2@3900 sin | i | ®nl® | j; 3901 1 ®2® 3720 3902 3 3721 3903 \end{cfa} … … 3758 3940 0b0 0b11011 0b11011 0b11011 0b11011 3759 3941 sout | bin( -27HH ) | bin( -27H ) | bin( -27 ) | bin( -27L ); 3760 0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b @(58 1s)@1001013942 0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b®(58 1s)®100101 3761 3943 \end{cfa} 3762 3944 … … 3794 3976 3795 3977 \item 3978 \Indexc{eng}( floating-point )\index{manipulator!eng@©eng©} print value in engineering notation with exponent, which means the exponent is adjusted to a multiple of 3. 3979 \begin{cfa}[belowskip=0pt] 3980 sout | eng( 0.0 ) | eng( 27000.5 ) | eng( -27.5e7 ); 3981 0®e0® 27.0005®e3® -275®e6® 3982 \end{cfa} 3983 3984 \item 3985 \Indexc{unit}( engineering-notation )\index{manipulator!unit@©unit©} print engineering exponent as a letter between the range $10^{-24}$ and $10^{24}$: 3986 ©y© $\Rightarrow 10^{-24}$, ©z© $\Rightarrow 10^{-21}$, ©a© $\Rightarrow 10^{-18}$, ©f© $\Rightarrow 10^{-15}$, ©p© $\Rightarrow 10^{-12}$, ©n© $\Rightarrow 10^{-9}$, ©u© $\Rightarrow 10^{-6}$, ©m© $\Rightarrow 10^{-3}$, ©K© $\Rightarrow 10^{3}$, ©M© $\Rightarrow 10^{6}$, ©G© $\Rightarrow 10^{9}$, ©T© $\Rightarrow 10^{12}$, ©P© $\Rightarrow 10^{15}$, ©E© $\Rightarrow 10^{18}$, ©Z© $\Rightarrow 10^{21}$, ©Y© $\Rightarrow 10^{24}$. 3987 For exponent $10^{0}$, no decimal point or letter is printed. 3988 \begin{cfa}[belowskip=0pt] 3989 sout | unit(eng( 0.0 )) | unit(eng( 27000.5 )) | unit(eng( -27.5e7 )); 3990 0 27.0005®K® -275®M® 3991 \end{cfa} 3992 3993 \item 3796 3994 \Indexc{upcase}( bin / hex / floating-point )\index{manipulator!upcase@©upcase©} print letters in a value in upper case. Lower case is the default. 3797 3995 \begin{cfa}[belowskip=0pt] 3798 3996 sout | upcase( bin( 27 ) ) | upcase( hex( 27 ) ) | upcase( 27.5e-10 ) | upcase( hex( 27.5 ) ); 3799 0 @B@11011 0@X@1@B@ 2.75@E@-09 0@X@1.@B@8@P@+43997 0®B®11011 0®X®1®B® 2.75®E®-09 0®X®1.®B®8®P®+4 3800 3998 \end{cfa} 3801 3999 … … 3813 4011 \begin{cfa}[belowskip=0pt] 3814 4012 sout | 0. | nodp( 0. ) | 27.0 | nodp( 27.0 ) | nodp( 27.5 ); 3815 0.0 @0@ 27.0 @27@27.54013 0.0 ®0® 27.0 ®27® 27.5 3816 4014 \end{cfa} 3817 4015 … … 3820 4018 \begin{cfa}[belowskip=0pt] 3821 4019 sout | sign( 27 ) | sign( -27 ) | sign( 27. ) | sign( -27. ) | sign( 27.5 ) | sign( -27.5 ); 3822 @+@27 -27 @+@27.0 -27.0 @+@27.5 -27.53823 \end{cfa} 3824 3825 \item 3826 \Indexc{wd} ©( unsigned char minimum, T val )©\index{manipulator!wd@©wd©}, ©wd( unsigned char minimum, unsigned char precision, T val )©3827 For all types, ©minimum© is the minimumnumber of printed characters.4020 ®+®27 -27 ®+®27.0 -27.0 ®+®27.5 -27.5 4021 \end{cfa} 4022 4023 \item 4024 \Indexc{wd}( minimum, value )\index{manipulator!wd@©wd©}, ©wd©( minimum, precision, value ) 4025 For all types, minimum is the number of printed characters. 3828 4026 If the value is shorter than the minimum, it is padded on the right with spaces. 3829 4027 \begin{cfa}[belowskip=0pt] … … 3833 4031 \end{cfa} 3834 4032 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3835 @ @34 @ @34 343836 @ @4.000000 @ @4.000000 4.0000003837 @ @ab @ @ab ab3838 \end{cfa} 3839 If the value is larger, it is printed without truncation, ignoring the ©minimum©.4033 ® ®34 ® ®34 34 4034 ® ®4.000000 ® ®4.000000 4.000000 4035 ® ®ab ® ®ab ab 4036 \end{cfa} 4037 If the value is larger, it is printed without truncation, ignoring the minimum. 3840 4038 \begin{cfa}[belowskip=0pt] 3841 4039 sout | wd( 4, 34567 ) | wd( 3, 34567 ) | wd( 2, 34567 ); … … 3844 4042 \end{cfa} 3845 4043 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3846 3456 @7@ 345@67@ 34@567@3847 3456 @.@ 345@6.@ 34@56.@3848 abcd @e@ abc@de@ ab@cde@3849 \end{cfa} 3850 3851 For integer types, ©precision©is the minimum number of printed digits.4044 3456®7® 345®67® 34®567® 4045 3456®.® 345®6.® 34®56.® 4046 abcd®e® abc®de® ab®cde® 4047 \end{cfa} 4048 4049 For integer types, precision is the minimum number of printed digits. 3852 4050 If the value is shorter, it is padded on the left with leading zeros. 3853 4051 \begin{cfa}[belowskip=0pt] … … 3855 4053 \end{cfa} 3856 4054 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3857 @0@34 @00@34 @00000000@343858 \end{cfa} 3859 If the value is larger, it is printed without truncation, ignoring the ©precision©.4055 ®0®34 ®00®34 ®00000000®34 4056 \end{cfa} 4057 If the value is larger, it is printed without truncation, ignoring the precision. 3860 4058 \begin{cfa}[belowskip=0pt] 3861 4059 sout | wd( 4,1, 3456 ) | wd( 8,2, 3456 ) | wd( 10,3, 3456 ); … … 3864 4062 3456 3456 3456 3865 4063 \end{cfa} 3866 If ©precision©is 0, nothing is printed for zero.3867 If ©precision©is greater than the minimum, it becomes the minimum.4064 If precision is 0, nothing is printed for zero. 4065 If precision is greater than the minimum, it becomes the minimum. 3868 4066 \begin{cfa}[belowskip=0pt] 3869 4067 sout | wd( 4,0, 0 ) | wd( 3,10, 34 ); 3870 4068 \end{cfa} 3871 4069 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3872 @ @ @00000000@343873 \end{cfa} 3874 For floating-point types, ©precision©is the minimum number of digits after the decimal point.4070 ® ® ®00000000®34 4071 \end{cfa} 4072 For floating-point types, precision is the minimum number of digits after the decimal point. 3875 4073 \begin{cfa}[belowskip=0pt] 3876 4074 sout | wd( 6,3, 27.5 ) | wd( 8,1, 27.5 ) | wd( 8,0, 27.5 ) | wd( 3,8, 27.5 ); 3877 4075 \end{cfa} 3878 4076 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3879 27. @500@ 27.@5@ 28. 27.@50000000@3880 \end{cfa} 3881 For the C-string type, ©precision©is the maximum number of printed characters, so the string is truncated if it exceeds the maximum.4077 27.®500® 27.®5® 28. 27.®50000000® 4078 \end{cfa} 4079 For the C-string type, precision is the maximum number of printed characters, so the string is truncated if it exceeds the maximum. 3882 4080 \begin{cfa}[belowskip=0pt] 3883 4081 sout | wd( 6,8, "abcd" ) | wd( 6,8, "abcdefghijk" ) | wd( 6,3, "abcd" ); … … 3888 4086 3889 4087 \item 3890 \Indexc{ws( unsigned char minimum, unsigned char significant, floating-point )}\index{manipulator!ws@©ws©} 3891 For floating-point type, ©minimum© is the same as for manipulator ©wd©, but ©significant© is the maximum number of significant digits to be printed for both the integer and fractions (versus only the fraction for ©wd©). 3892 If a value's significant digits is greater than ©significant©, the last significant digit is rounded up. 4088 \begin{sloppypar} 4089 \Indexc{ws}( minimum, significant, floating-point )\index{manipulator!ws@©ws©} 4090 For floating-point types, minimum is the same as for manipulator ©wd©, but significant is the maximum number of significant digits to be printed for both the integer and fractions (versus only the fraction for ©wd©). 4091 If a value's significant digits is greater than significant, the last significant digit is rounded up. 4092 \end{sloppypar} 3893 4093 \begin{cfa}[belowskip=0pt] 3894 4094 sout | ws(6,6, 234.567) | ws(6,5, 234.567) | ws(6,4, 234.567) | ws(6,3, 234.567); 3895 4095 \end{cfa} 3896 4096 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3897 234.567 234.5 @7@ 234.@6@ 23@5@3898 \end{cfa} 3899 If a value's magnitude is greater than ©significant©, the value is printed in scientific notation with the specified number of significant digits.4097 234.567 234.5®7® 234.®6® 23®5® 4098 \end{cfa} 4099 If a value's magnitude is greater than significant, the value is printed in scientific notation with the specified number of significant digits. 3900 4100 \begin{cfa}[belowskip=0pt] 3901 4101 sout | ws(6,6, 234567.) | ws(6,5, 234567.) | ws(6,4, 234567.) | ws(6,3, 234567.); 3902 4102 \end{cfa} 3903 4103 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3904 234567. 2.3457 @e+05@ 2.346@e+05@ 2.35@e+05@3905 \end{cfa} 3906 If ©significant© is greater than ©minimum©, it defines the number of printed characters.4104 234567. 2.3457®e+05® 2.346®e+05® 2.35®e+05® 4105 \end{cfa} 4106 If significant is greater than minimum, it defines the number of printed characters. 3907 4107 \begin{cfa}[belowskip=0pt] 3908 4108 sout | ws(3,6, 234567.) | ws(4,6, 234567.) | ws(5,6, 234567.) | ws(6,6, 234567.); … … 3918 4118 \end{cfa} 3919 4119 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 3920 27 @ @ 27.000000 27.500000 027 27.500@ @4120 27® ® 27.000000 27.500000 027 27.500® ® 3921 4121 \end{cfa} 3922 4122 … … 3925 4125 \begin{cfa}[belowskip=0pt] 3926 4126 sout | pad0( wd( 4, 27 ) ) | pad0( wd( 4,3, 27 ) ) | pad0( wd( 8,3, 27.5 ) ); 3927 @00@27 @0@27 @00@27.5004127 ®00®27 ®0®27 ®00®27.500 3928 4128 \end{cfa} 3929 4129 \end{enumerate} … … 3989 4189 3990 4190 The format of numeric input values in the same as C constants without a trailing type suffix, as the input value-type is denoted by the input variable. 3991 For © _Bool© type, the constants are ©true© and ©false©.4191 For ©bool© type, the constants are ©true© and ©false©. 3992 4192 For integral types, any number of digits, optionally preceded by a sign (©+© or ©-©), where a 3993 4193 \begin{itemize} … … 4010 4210 \begin{enumerate} 4011 4211 \item 4012 \Indexc{skip( const char * pattern )}\index{manipulator!skip@©skip©} / ©skip( unsigned int length )© / ©const char * pattern© 4013 The argument defines a ©pattern© or ©length©. 4014 The ©pattern© is composed of white-space and non-white-space characters, where \emph{any} white-space character matches 0 or more input white-space characters (hence, consecutive white-space characters in the pattern are combined), and each non-white-space character matches exactly with an input character. 4015 The ©length© is composed of the next $N$ characters, including the newline character. 4212 \Indexc{skip}( pattern )\index{manipulator!skip@©skip©}, ©skip©( length ) 4213 The pattern is composed of white-space and non-white-space characters, where \emph{any} white-space character matches 0 or more input white-space characters (hence, consecutive white-space characters in the pattern are combined), and each non-white-space character matches exactly with an input character. 4214 The length is composed of the next $N$ characters, including the newline character. 4016 4215 If the match successes, the input characters are discarded, and input continues with the next character. 4017 4216 If the match fails, the input characters are left unread. … … 4021 4220 \end{cfa} 4022 4221 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4023 @abc @ 4024 @abc @ 4025 @xx@ 4026 \end{cfa} 4027 4028 \item 4029 \Indexc{wdi} ©( unsigned int maximum, T & val )©\index{manipulator!wdi@©wdi©}4030 For all types except ©char©, ©maximum©is the maximum number of characters read for the current operation.4222 ®abc ® 4223 ®abc ® 4224 ®xx® 4225 \end{cfa} 4226 4227 \item 4228 \Indexc{wdi}( maximum, reference-value )\index{manipulator!wdi@©wdi©} 4229 For all types except ©char©, maximum is the maximum number of characters read for the current operation. 4031 4230 \begin{cfa}[belowskip=0pt] 4032 4231 char s[10]; int i; double d; … … 4034 4233 \end{cfa} 4035 4234 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4036 @abcd1233.456E+2@ 4235 ®abcd1233.456E+2® 4037 4236 \end{cfa} 4038 4237 Note, input ©wdi© cannot be overloaded with output ©wd© because both have the same parameters but return different types. … … 4040 4239 4041 4240 \item 4042 \Indexc{ignore ( T & val )}\index{manipulator!ignore@©ignore©}4241 \Indexc{ignore}( reference-value )\index{manipulator!ignore@©ignore©} 4043 4242 For all types, the data is read from the stream depending on the argument type but ignored, \ie it is not stored in the argument. 4044 4243 \begin{cfa}[belowskip=0pt] … … 4047 4246 \end{cfa} 4048 4247 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4049 @ -75.35e-4@254050 \end{cfa} 4051 4052 \item 4053 \Indexc{incl ( const char * scanset, char * s )}\index{manipulator!incl@©incl©}4054 For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{in} the set.4055 Matching characters are read into the C string and null terminated.4248 ® -75.35e-4® 25 4249 \end{cfa} 4250 4251 \item 4252 \Indexc{incl}( scanset, input-string )\index{manipulator!incl@©incl©} 4253 For C-string types, the scanset matches any number of characters \emph{in} the set. 4254 Matching characters are read into the C input-string and null terminated. 4056 4255 \begin{cfa}[belowskip=0pt] 4057 4256 char s[10]; … … 4059 4258 \end{cfa} 4060 4259 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4061 @bca@xyz4062 \end{cfa} 4063 4064 \item 4065 \Indexc{excl ( const char * scanset, char * s )}\index{manipulator!excl@©excl©}4066 For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{not in} the set.4067 Non-matching characters are read into the C string and null terminated.4260 ®bca®xyz 4261 \end{cfa} 4262 4263 \item 4264 \Indexc{excl}( scanset, input-string )\index{manipulator!excl@©excl©} 4265 For C-string types, the scanset matches any number of characters \emph{not in} the set. 4266 Non-matching characters are read into the C input-string and null terminated. 4068 4267 \begin{cfa}[belowskip=0pt] 4069 4268 char s[10]; … … 4071 4270 \end{cfa} 4072 4271 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 4073 @xyz@bca4272 ®xyz®bca 4074 4273 \end{cfa} 4075 4274 \end{enumerate} 4076 4275 4077 4276 4277 \subsection{Concurrent Stream Access} 4278 4279 When a stream is shared by multiple threads, input or output characters can be intermixed or cause failure. 4280 For example, if two threads execute the following: 4281 \begin{cfa} 4282 $\emph{thread\(_1\)}$ : sout | "abc " | "def "; 4283 $\emph{thread\(_2\)}$ : sout | "uvw " | "xyz "; 4284 \end{cfa} 4285 possible outputs are: 4286 \begin{cquote} 4287 \begin{tabular}{@{}l|l|l|l|l@{}} 4288 \begin{cfa} 4289 abc def 4290 uvw xyz 4291 \end{cfa} 4292 & 4293 \begin{cfa} 4294 abc uvw xyz 4295 def 4296 \end{cfa} 4297 & 4298 \begin{cfa} 4299 uvw abc xyz def 4300 4301 \end{cfa} 4302 & 4303 \begin{cfa} 4304 abuvwc dexf 4305 yz 4306 \end{cfa} 4307 & 4308 \begin{cfa} 4309 uvw abc def 4310 xyz 4311 \end{cfa} 4312 \end{tabular} 4313 \end{cquote} 4314 Concurrent operations can even corrupt the internal state of the stream resulting in failure. 4315 As a result, some form of mutual exclusion is required for concurrent stream access. 4316 4317 A coarse-grained solution is to perform all stream operations via a single thread or within a monitor providing the necessary mutual exclusion for the stream. 4318 A fine-grained solution is to have a lock for each stream, which is acquired and released around stream operations by each thread. 4319 \CFA provides a fine-grained solution where a \Index{recursive lock} is acquired and released indirectly via a manipulator ©acquire© or instantiating an \Index{RAII} type specific for the kind of stream: ©osacquire©\index{ostream@©ostream©!osacquire@©osacquire©} for output streams and ©isacquire©\index{isacquire@©isacquire©}\index{istream@©istream©!isacquire@©isacquire©} for input streams. 4320 4321 The common usage is manipulator ©acquire©\index{ostream@©ostream©!acquire@©acquire©} to lock a stream during a single cascaded I/O expression, with the manipulator appearing as the first item in a cascade list, \eg: 4322 \begin{cfa} 4323 $\emph{thread\(_1\)}$ : sout | ®acquire® | "abc " | "def "; // manipulator 4324 $\emph{thread\(_2\)}$ : sout | ®acquire® | "uvw " | "xyz "; 4325 \end{cfa} 4326 Now, the order of the thread execution is still non-deterministic, but the output is constrained to two possible lines in either order. 4327 \begin{cquote} 4328 \def\VRfont{\fontfamily{pcr}\upshape\selectfont} 4329 \begin{tabular}{@{}l|l@{}} 4330 \begin{cfa} 4331 abc def 4332 uvw xyz 4333 \end{cfa} 4334 & 4335 \begin{cfa} 4336 uvw xyz 4337 abc def 4338 \end{cfa} 4339 \end{tabular} 4340 \end{cquote} 4341 In summary, the stream lock is acquired by the ©acquire© manipulator and implicitly released at the end of the cascaded I/O expression ensuring all operations in the expression occur atomically. 4342 4343 To lock a stream across multiple I/O operations, an object of type ©osacquire© or ©isacquire© is declared to implicitly acquire/release the stream lock providing mutual exclusion for the object's duration, \eg: 4344 \begin{cfa} 4345 { // acquire sout for block duration 4346 ®osacquire® acq = { sout }; $\C{// named stream locker}$ 4347 sout | 1; 4348 sout | ®acquire® | 2 | 3; $\C{// unnecessary, but ok to acquire and release again}$ 4349 sout | 4; 4350 } // implicitly release the lock when "acq" is deallocated 4351 \end{cfa} 4352 Note, the unnecessary ©acquire© manipulator works because the recursive stream-lock can be acquired/released multiple times by the owner thread. 4353 Hence, calls to functions that also acquire a stream lock for their output do not result in \Index{deadlock}. 4354 4355 The previous values written by threads 1 and 2 can be read in concurrently: 4356 \begin{cfa} 4357 { // acquire sin lock for block duration 4358 ®isacquire acq = { sin };® $\C{// named stream locker}$ 4359 int x, y, z, w; 4360 sin | x; 4361 sin | ®acquire® | y | z; $\C{// unnecessary, but ok to acquire and release again}$ 4362 sin | w; 4363 } // implicitly release the lock when "acq" is deallocated 4364 \end{cfa} 4365 Again, the order of the reading threads is non-deterministic. 4366 Note, non-deterministic reading is rare. 4367 4368 \Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg: 4369 \begin{cfa} 4370 sout | ®acquire® | "data:" | rtn( mon ); $\C{// mutex call on monitor}$ 4371 \end{cfa} 4372 If the thread executing the I/O expression blocks in the monitor with the ©sout© lock, other threads writing to ©sout© also block until the thread holding the lock is unblocked and releases it. 4373 This scenario can lead to \Index{deadlock}, if the thread that is going to unblock the thread waiting in the monitor first writes to ©sout© (deadly embrace). 4374 To prevent nested locking, a simple precaution is to factor out the blocking call from the expression, \eg: 4375 \begin{cfa} 4376 int ®data® = rtn( mon ); 4377 sout | acquire | "data:" | ®data®; 4378 \end{cfa} 4379 4380 \Textbf{WARNING:} ©printf©\index{printf@©printf©}, ©scanf©\index{scanf@©scanf©} and their derivatives are unsafe when used with user-level threading, as in \CFA. 4381 These stream routines use kernel-thread locking (©futex©\index{futex@©futex©}), which block kernel threads, to prevent interleaving of I/O. 4382 However, the following simple example illustrates how a deadlock can occur (other complex scenarios are possible). 4383 Assume a single kernel thread and two user-level threads calling ©printf©. 4384 One user-level thread acquires the I/O lock and is time-sliced while performing ©printf©. 4385 The other user-level thread then starts execution, calls ©printf©, and blocks the only kernel thread because it cannot acquire the I/O lock. 4386 It does not help if the kernel lock is multiple acquisition, \ie, the lock owner can acquire it multiple times, because it then results in two user threads in the ©printf© critical section, corrupting the stream. 4387 4388 4389 \begin{comment} 4078 4390 \section{Types} 4079 4391 … … 4154 4466 process((int) s); // type is converted, no function is called 4155 4467 \end{cfa} 4468 \end{comment} 4156 4469 4157 4470 … … 4287 4600 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. 4288 4601 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. 4289 Defining special constants for a user-defined type is more efficient than defining a conversion to the type from © _Bool©.4602 Defining special constants for a user-defined type is more efficient than defining a conversion to the type from ©bool©. 4290 4603 4291 4604 Why just 0 and 1? Why not other integers? No other integers have special status in C. … … 4369 4682 \begin{table}[hbt] 4370 4683 \centering 4371 \input{../refrat/operidents} 4684 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 4685 \begin{tabular}{@{}ll@{}} 4686 ©?[?]© & subscripting \impl{?[?]} \\ 4687 ©?()© & function call \impl{?()} \\ 4688 ©?++© & postfix increment \impl{?++} \\ 4689 ©?--© & postfix decrement \impl{?--} \\ 4690 ©++?© & prefix increment \impl{++?} \\ 4691 ©--?© & prefix decrement \impl{--?} \\ 4692 ©*?© & dereference \impl{*?} \\ 4693 ©+?© & unary plus \impl{+?} \\ 4694 ©-?© & arithmetic negation \impl{-?} \\ 4695 ©~?© & bitwise negation \impl{~?} \\ 4696 ©!?© & logical complement \impl{"!?} \\ 4697 ©?\?© & exponentiation \impl{?\?} \\ 4698 ©?*?© & multiplication \impl{?*?} \\ 4699 ©?/?© & division \impl{?/?} \\ 4700 ©?%?© & remainder \impl{?%?} \\ 4701 \end{tabular} 4702 & 4703 \begin{tabular}{@{}ll@{}} 4704 ©?+?© & addition \impl{?+?} \\ 4705 ©?-?© & subtraction \impl{?-?} \\ 4706 ©?<<?© & left shift \impl{?<<?} \\ 4707 ©?>>?© & right shift \impl{?>>?} \\ 4708 ©?<?© & less than \impl{?<?} \\ 4709 ©?<=?© & less than or equal \impl{?<=?} \\ 4710 ©?>=?© & greater than or equal \impl{?>=?} \\ 4711 ©?>?© & greater than \impl{?>?} \\ 4712 ©?==?© & equality \impl{?==?} \\ 4713 ©?!=?© & inequality \impl{?"!=?} \\ 4714 ©?&?© & bitwise AND \impl{?&?} \\ 4715 ©?^?© & exclusive OR \impl{?^?} \\ 4716 ©?|?© & inclusive OR \impl{?"|?} \\ 4717 \\ 4718 \\ 4719 \end{tabular} 4720 & 4721 \begin{tabular}{@{}ll@{}} 4722 ©?=?© & simple assignment \impl{?=?} \\ 4723 ©?\=?© & exponentiation assignment \impl{?\=?} \\ 4724 ©?*=?© & multiplication assignment \impl{?*=?} \\ 4725 ©?/=?© & division assignment \impl{?/=?} \\ 4726 ©?%=?© & remainder assignment \impl{?%=?} \\ 4727 ©?+=?© & addition assignment \impl{?+=?} \\ 4728 ©?-=?© & subtraction assignment \impl{?-=?} \\ 4729 ©?<<=?© & left-shift assignment \impl{?<<=?} \\ 4730 ©?>>=?© & right-shift assignment \impl{?>>=?} \\ 4731 ©?&=?© & bitwise AND assignment \impl{?&=?} \\ 4732 ©?^=?© & exclusive OR assignment \impl{?^=?} \\ 4733 ©?|=?© & inclusive OR assignment \impl{?"|=?} \\ 4734 \\ 4735 \\ 4736 \\ 4737 \end{tabular} 4738 \end{tabular} 4372 4739 \caption{Operator Identifiers} 4373 4740 \label{opids} … … 4457 4824 For example, given 4458 4825 \begin{cfa} 4459 auto j = @...@4826 auto j = ®...® 4460 4827 \end{cfa} 4461 4828 and the need to write a routine to compute using ©j© 4462 4829 \begin{cfa} 4463 void rtn( @...@parm );4830 void rtn( ®...® parm ); 4464 4831 rtn( j ); 4465 4832 \end{cfa} … … 4698 5065 \begin{figure} 4699 5066 \begin{cfa} 4700 #include <fstream >4701 #include <coroutine>4702 4703 coroutineFibonacci {5067 #include <fstream.hfa> 5068 #include ®<coroutine.hfa>® 5069 5070 ®coroutine® Fibonacci { 4704 5071 int fn; $\C{// used for communication}$ 4705 5072 }; 4706 void ?{}( Fibonacci * this ) { 4707 this->fn = 0; 4708 } 4709 void main( Fibonacci * this ) { 5073 5074 void main( Fibonacci & fib ) with( fib ) { $\C{// called on first resume}$ 4710 5075 int fn1, fn2; $\C{// retained between resumes}$ 4711 this->fn = 0; $\C{// case 0}$ 4712 fn1 = this->fn; 4713 suspend(); $\C{// return to last resume}$ 4714 4715 this->fn = 1; $\C{// case 1}$ 4716 fn2 = fn1; 4717 fn1 = this->fn; 4718 suspend(); $\C{// return to last resume}$ 4719 4720 for ( ;; ) { $\C{// general case}$ 4721 this->fn = fn1 + fn2; 4722 fn2 = fn1; 4723 fn1 = this->fn; 4724 suspend(); $\C{// return to last resume}$ 4725 } // for 4726 } 4727 int next( Fibonacci * this ) { 4728 resume( this ); $\C{// transfer to last suspend}$ 4729 return this->fn; 5076 fn = 0; fn1 = fn; $\C{// 1st case}$ 5077 ®suspend;® $\C{// restart last resume}$ 5078 fn = 1; fn2 = fn1; fn1 = fn; $\C{// 2nd case}$ 5079 ®suspend;® $\C{// restart last resume}$ 5080 for () { 5081 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; $\C{// general case}$ 5082 ®suspend;® $\C{// restart last resume}$ 5083 } 5084 } 5085 int next( Fibonacci & fib ) with( fib ) { 5086 ®resume( fib );® $\C{// restart last suspend}$ 5087 return fn; 4730 5088 } 4731 5089 int main() { 4732 5090 Fibonacci f1, f2; 4733 for ( int i = 1; i <= 10; i += 1 ) { 4734 sout | next( &f1 ) | ' ' | next( &f2 ); 4735 } // for 4736 } 4737 \end{cfa} 5091 for ( 10 ) { $\C{// print N Fibonacci values}$ 5092 sout | next( f1 ) | next( f2 ); 5093 } 5094 } 5095 \end{cfa} 5096 \vspace*{-5pt} 4738 5097 \caption{Fibonacci Coroutine} 4739 5098 \label{f:FibonacciCoroutine} … … 4761 5120 \begin{figure} 4762 5121 \begin{cfa} 4763 #include <fstream> 4764 #include <kernel> 4765 #include <monitor> 4766 #include <thread> 4767 4768 monitor global_t { 4769 int value; 4770 }; 4771 4772 void ?{}(global_t * this) { 4773 this->value = 0; 4774 } 4775 4776 static global_t global; 4777 4778 void increment3( global_t * mutex this ) { 4779 this->value += 1; 4780 } 4781 void increment2( global_t * mutex this ) { 4782 increment3( this ); 4783 } 4784 void increment( global_t * mutex this ) { 4785 increment2( this ); 4786 } 5122 #include <fstream.hfa> 5123 #include ®<thread.hfa>® 5124 5125 ®monitor® AtomicCnt { int counter; }; 5126 void ?{}( AtomicCnt & c, int init = 0 ) with(c) { counter = init; } 5127 int inc( AtomicCnt & ®mutex® c, int inc = 1 ) with(c) { return counter += inc; } 5128 int dec( AtomicCnt & ®mutex® c, int dec = 1 ) with(c) { return counter -= dec; } 5129 forall( ostype & | ostream( ostype ) ) { $\C{// print any stream}$ 5130 ostype & ?|?( ostype & os, AtomicCnt c ) { return os | c.counter; } 5131 void ?|?( ostype & os, AtomicCnt c ) { (ostype &)(os | c.counter); ends( os ); } 5132 } 5133 5134 AtomicCnt global; $\C{// shared}$ 4787 5135 4788 5136 thread MyThread {}; 4789 4790 void main( MyThread* this) {4791 for(int i = 0; i < 1_000_000; i++) {4792 increment( &global );5137 void main( MyThread & ) { 5138 for ( i; 100_000 ) { 5139 inc( global ); 5140 dec( global ); 4793 5141 } 4794 5142 } 4795 int main(int argc, char* argv[]) { 4796 processor p; 5143 int main() { 5144 enum { Threads = 4 }; 5145 processor p[Threads - 1]; $\C{// + starting processor}$ 4797 5146 { 4798 MyThread f[4];5147 MyThread t[Threads]; 4799 5148 } 4800 sout | global .value;5149 sout | global; $\C{// print 0}$ 4801 5150 } 4802 5151 \end{cfa} 4803 5152 \caption{Atomic-Counter Monitor} 4804 \ caption{f:AtomicCounterMonitor}5153 \label{f:AtomicCounterMonitor} 4805 5154 \end{figure} 4806 5155 … … 6265 6614 6266 6615 C has a number of syntax ambiguities, which are resolved by taking the longest sequence of overlapping characters that constitute a token. 6267 For example, the program fragment ©x+++++y© is parsed as \lstinline[showspaces=true] @x ++ ++ + y@because operator tokens ©++© and ©+© overlap.6268 Unfortunately, the longest sequence violates a constraint on increment operators, even though the parse \lstinline[showspaces=true] @x ++ + ++ y@might yield a correct expression.6616 For example, the program fragment ©x+++++y© is parsed as \lstinline[showspaces=true]{x ++ ++ + y} because operator tokens ©++© and ©+© overlap. 6617 Unfortunately, the longest sequence violates a constraint on increment operators, even though the parse \lstinline[showspaces=true]{x ++ + ++ y} might yield a correct expression. 6269 6618 Hence, C programmers are aware that spaces have to added to disambiguate certain syntactic cases. 6270 6619 … … 6286 6635 requiring arbitrary whitespace look-ahead for the routine-call parameter-list to disambiguate. 6287 6636 However, the dereference operator \emph{must} have a parameter/argument to dereference ©*?(...)©. 6288 Hence, always interpreting the string ©*?()© as \lstinline[showspaces=true] @* ?()@does not preclude any meaningful program.6637 Hence, always interpreting the string ©*?()© as \lstinline[showspaces=true]{* ?()} does not preclude any meaningful program. 6289 6638 6290 6639 The remaining cases are with the increment/decrement operators and conditional expression, \eg: … … 6394 6743 \begin{cfa} 6395 6744 int i; $\C{// forward definition}$ 6396 int *j = @&i@; $\C{// forward reference, valid in C, invalid in \CFA}$6745 int *j = ®&i®; $\C{// forward reference, valid in C, invalid in \CFA}$ 6397 6746 int i = 0; $\C{// definition}$ 6398 6747 \end{cfa} … … 6402 6751 struct X { int i; struct X *next; }; 6403 6752 static struct X a; $\C{// forward definition}$ 6404 static struct X b = { 0, @&a@};$\C{// forward reference, valid in C, invalid in \CFA}$6753 static struct X b = { 0, ®&a® };$\C{// forward reference, valid in C, invalid in \CFA}$ 6405 6754 static struct X a = { 1, &b }; $\C{// definition}$ 6406 6755 \end{cfa} … … 6415 6764 \item[Change:] have ©struct© introduce a scope for nested types: 6416 6765 \begin{cfa} 6417 enum @Colour@{ R, G, B, Y, C, M };6766 enum ®Colour® { R, G, B, Y, C, M }; 6418 6767 struct Person { 6419 enum @Colour@{ R, G, B }; $\C[7cm]{// nested type}$6768 enum ®Colour® { R, G, B }; $\C[7cm]{// nested type}$ 6420 6769 struct Face { $\C{// nested type}$ 6421 @Colour@Eyes, Hair; $\C{// type defined outside (1 level)}$6770 ®Colour® Eyes, Hair; $\C{// type defined outside (1 level)}$ 6422 6771 }; 6423 @.Colour@shirt; $\C{// type defined outside (top level)}$6424 @Colour@pants; $\C{// type defined same level}$6772 ®.Colour® shirt; $\C{// type defined outside (top level)}$ 6773 ®Colour® pants; $\C{// type defined same level}$ 6425 6774 Face looks[10]; $\C{// type defined same level}$ 6426 6775 }; 6427 @Colour@c = R; $\C{// type/enum defined same level}$6428 Person @.Colour@ pc = Person@.@R;$\C{// type/enum defined inside}$6429 Person @.@Face pretty; $\C{// type defined inside}\CRT$6776 ®Colour® c = R; $\C{// type/enum defined same level}$ 6777 Person®.Colour® pc = Person®.®R;$\C{// type/enum defined inside}$ 6778 Person®.®Face pretty; $\C{// type defined inside}\CRT$ 6430 6779 \end{cfa} 6431 6780 In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, \ie the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing. … … 6502 6851 \label{s:CFAKeywords} 6503 6852 6504 \CFA introduces the following new keywords.6853 \CFA introduces the following new \Index{keyword}s, which cannot be used as identifiers. 6505 6854 6506 6855 \begin{cquote} 6507 \input{../refrat/keywords} 6856 \begin{tabular}{@{}lllllll@{}} 6857 \begin{tabular}{@{}l@{}} 6858 \Indexc{basetypeof} \\ 6859 \Indexc{choose} \\ 6860 \Indexc{coroutine} \\ 6861 \Indexc{disable} \\ 6862 \end{tabular} 6863 & 6864 \begin{tabular}{@{}l@{}} 6865 \Indexc{enable} \\ 6866 \Indexc{exception} \\ 6867 \Indexc{fallthrough} \\ 6868 \Indexc{fallthru} \\ 6869 \end{tabular} 6870 & 6871 \begin{tabular}{@{}l@{}} 6872 \Indexc{finally} \\ 6873 \Indexc{fixup} \\ 6874 \Indexc{forall} \\ 6875 \Indexc{generator} \\ 6876 \end{tabular} 6877 & 6878 \begin{tabular}{@{}l@{}} 6879 \Indexc{int128} \\ 6880 \Indexc{monitor} \\ 6881 \Indexc{mutex} \\ 6882 \Indexc{one_t} \\ 6883 \end{tabular} 6884 & 6885 \begin{tabular}{@{}l@{}} 6886 \Indexc{report} \\ 6887 \Indexc{suspend} \\ 6888 \Indexc{throw} \\ 6889 \Indexc{throwResume} \\ 6890 \end{tabular} 6891 & 6892 \begin{tabular}{@{}l@{}} 6893 \Indexc{trait} \\ 6894 \Indexc{try} \\ 6895 \Indexc{virtual} \\ 6896 \Indexc{waitfor} \\ 6897 \end{tabular} 6898 & 6899 \begin{tabular}{@{}l@{}} 6900 \Indexc{when} \\ 6901 \Indexc{with} \\ 6902 \Indexc{zero_t} \\ 6903 \\ 6904 \end{tabular} 6905 \end{tabular} 6508 6906 \end{cquote} 6509 6907 \CFA introduces the following new \Index{quasi-keyword}s, which can be used as identifiers. 6908 \begin{cquote} 6909 \begin{tabular}{@{}ll@{}} 6910 \begin{tabular}{@{}l@{}} 6911 \Indexc{catch} \\ 6912 \Indexc{catchResume} \\ 6913 \Indexc{finally} \\ 6914 \end{tabular} 6915 & 6916 \begin{tabular}{@{}l@{}} 6917 \Indexc{fixup} \\ 6918 \Indexc{or} \\ 6919 \Indexc{timeout} \\ 6920 \end{tabular} 6921 \end{tabular} 6922 \end{cquote} 6510 6923 6511 6924 \section{Standard Headers} … … 6666 7079 // assume ?|? operator for printing an S 6667 7080 6668 S & sp = * @new@( 3 ); $\C{// call constructor after allocation}$7081 S & sp = *®new®( 3 ); $\C{// call constructor after allocation}$ 6669 7082 sout | sp.i; 6670 @delete@( &sp );6671 6672 S * spa = @anew@( 10, 5 ); $\C{// allocate array and initialize each array element}$7083 ®delete®( &sp ); 7084 7085 S * spa = ®anew®( 10, 5 ); $\C{// allocate array and initialize each array element}$ 6673 7086 for ( i; 10 ) sout | spa[i] | nonl; 6674 7087 sout | nl; 6675 @adelete@( 10, spa );7088 ®adelete®( 10, spa ); 6676 7089 \end{cfa} 6677 7090 Allocation routines ©new©/©anew© allocate a variable/array and initialize storage using the allocated type's constructor. … … 6909 7322 [ int, long double ] remquo( long double, long double ); 6910 7323 6911 float div( float, float, int * );$\indexc{div}$ $\C{// alternative name for remquo}$6912 double div( double, double, int * );6913 long double div( long double, long double, int * );6914 7324 [ int, float ] div( float, float ); 6915 7325 [ int, double ] div( double, double ); … … 6972 7382 long double _Complex log( long double _Complex ); 6973 7383 6974 float log2( float );$\indexc{log2}$ 7384 int log2( unsigned int );$\indexc{log2}$ 7385 long int log2( unsigned long int ); 7386 long long int log2( unsigned long long int ) 7387 float log2( float ); 6975 7388 double log2( double ); 6976 7389 long double log2( long double ); … … 7154 7567 \leavevmode 7155 7568 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7569 // n / align * align 7570 signed char floor( signed char n, signed char align ); 7571 unsigned char floor( unsigned char n, unsigned char align ); 7572 short int floor( short int n, short int align ); 7573 unsigned short int floor( unsigned short int n, unsigned short int align ); 7574 int floor( int n, int align ); 7575 unsigned int floor( unsigned int n, unsigned int align ); 7576 long int floor( long int n, long int align ); 7577 unsigned long int floor( unsigned long int n, unsigned long int align ); 7578 long long int floor( long long int n, long long int align ); 7579 unsigned long long int floor( unsigned long long int n, unsigned long long int align ); 7580 7581 // (n + (align - 1)) / align 7582 signed char ceiling_div( signed char n, char align ); 7583 unsigned char ceiling_div( unsigned char n, unsigned char align ); 7584 short int ceiling_div( short int n, short int align ); 7585 unsigned short int ceiling_div( unsigned short int n, unsigned short int align ); 7586 int ceiling_div( int n, int align ); 7587 unsigned int ceiling_div( unsigned int n, unsigned int align ); 7588 long int ceiling_div( long int n, long int align ); 7589 unsigned long int ceiling_div( unsigned long int n, unsigned long int align ); 7590 long long int ceiling_div( long long int n, long long int align ); 7591 unsigned long long int ceiling_div( unsigned long long int n, unsigned long long int align ); 7592 7593 // floor( n + (n % align != 0 ? align - 1 : 0), align ) 7594 signed char ceiling( signed char n, signed char align ); 7595 unsigned char ceiling( unsigned char n, unsigned char align ); 7596 short int ceiling( short int n, short int align ); 7597 unsigned short int ceiling( unsigned short int n, unsigned short int align ); 7598 int ceiling( int n, int align ); 7599 unsigned int ceiling( unsigned int n, unsigned int align ); 7600 long int ceiling( long int n, long int align ); 7601 unsigned long int ceiling( unsigned long int n, unsigned long int align ); 7602 long long int ceiling( long long int n, long long int align ); 7603 unsigned long long int ceiling( unsigned long long int n, unsigned long long int align ); 7604 7156 7605 float floor( float );$\indexc{floor}$ 7157 7606 double floor( double ); … … 7249 7698 7250 7699 7251 %\subsection{\texorpdfstring{\protect\lstinline @Duration@}{Duration}}7700 %\subsection{\texorpdfstring{\protect\lstinline{Duration}}{Duration}} 7252 7701 \subsection{\texorpdfstring{\LstBasicStyle{Duration}}{Duration}} 7253 7702 \label{s:Duration} … … 7256 7705 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7257 7706 struct Duration { 7258 int64_t t v; $\C{// nanoseconds}$7707 int64_t tn; $\C{// nanoseconds}$ 7259 7708 }; 7260 7709 7261 7710 void ?{}( Duration & dur ); 7262 7711 void ?{}( Duration & dur, zero_t ); 7712 void ?{}( Duration & dur, timeval t ) 7713 void ?{}( Duration & dur, timespec t ) 7263 7714 7264 7715 Duration ?=?( Duration & dur, zero_t ); 7716 Duration ?=?( Duration & dur, timeval t ) 7717 Duration ?=?( Duration & dur, timespec t ) 7265 7718 7266 7719 Duration +?( Duration rhs ); … … 7284 7737 Duration ?%=?( Duration & lhs, Duration rhs ); 7285 7738 7286 _Bool ?==?( Duration lhs, Duration rhs);7287 _Bool ?!=?( Duration lhs, Duration rhs);7288 _Bool ?<? ( Duration lhs, Duration rhs);7289 _Bool ?<=?( Duration lhs, Duration rhs);7290 _Bool ?>? ( Duration lhs, Duration rhs);7291 _Bool ?>=?( Duration lhs, Duration rhs);7292 7293 _Bool ?==?( Duration lhs, zero_t);7294 _Bool ?!=?( Duration lhs, zero_t);7295 _Bool ?<? ( Duration lhs, zero_t);7296 _Bool ?<=?( Duration lhs, zero_t);7297 _Bool ?>? ( Duration lhs, zero_t);7298 _Bool ?>=?( Duration lhs, zero_t);7739 bool ?==?( Duration lhs, zero_t ); 7740 bool ?!=?( Duration lhs, zero_t ); 7741 bool ?<? ( Duration lhs, zero_t ); 7742 bool ?<=?( Duration lhs, zero_t ); 7743 bool ?>? ( Duration lhs, zero_t ); 7744 bool ?>=?( Duration lhs, zero_t ); 7745 7746 bool ?==?( Duration lhs, Duration rhs ); 7747 bool ?!=?( Duration lhs, Duration rhs ); 7748 bool ?<? ( Duration lhs, Duration rhs ); 7749 bool ?<=?( Duration lhs, Duration rhs ); 7750 bool ?>? ( Duration lhs, Duration rhs ); 7751 bool ?>=?( Duration lhs, Duration rhs ); 7299 7752 7300 7753 Duration abs( Duration rhs ); … … 7323 7776 int64_t ?`w( Duration dur ); 7324 7777 7778 double ?`dns( Duration dur ); 7779 double ?`dus( Duration dur ); 7780 double ?`dms( Duration dur ); 7781 double ?`ds( Duration dur ); 7782 double ?`dm( Duration dur ); 7783 double ?`dh( Duration dur ); 7784 double ?`dd( Duration dur ); 7785 double ?`dw( Duration dur ); 7786 7325 7787 Duration max( Duration lhs, Duration rhs ); 7326 7788 Duration min( Duration lhs, Duration rhs ); 7327 \end{cfa} 7328 7329 7330 %\subsection{\texorpdfstring{\protect\lstinline@\timeval@}{timeval}} 7789 7790 forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype & os, Duration dur ); 7791 \end{cfa} 7792 7793 7794 %\subsection{\texorpdfstring{\protect\lstinline{timeval}}{timeval}} 7331 7795 \subsection{\texorpdfstring{\LstBasicStyle{timeval}}{timeval}} 7332 7796 \label{s:timeval} … … 7335 7799 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7336 7800 void ?{}( timeval & t ); 7801 void ?{}( timeval & t, zero_t ); 7337 7802 void ?{}( timeval & t, time_t sec, suseconds_t usec ); 7338 7803 void ?{}( timeval & t, time_t sec ); 7339 void ?{}( timeval & t, zero_t );7340 7804 void ?{}( timeval & t, Time time ); 7341 7805 … … 7343 7807 timeval ?+?( timeval & lhs, timeval rhs ); 7344 7808 timeval ?-?( timeval & lhs, timeval rhs ); 7345 _Bool ?==?( timeval lhs, timeval rhs );7346 _Bool ?!=?( timeval lhs, timeval rhs );7347 \end{cfa} 7348 7349 7350 %\subsection{\texorpdfstring{\protect\lstinline @timespec@}{timespec}}7809 bool ?==?( timeval lhs, timeval rhs ); 7810 bool ?!=?( timeval lhs, timeval rhs ); 7811 \end{cfa} 7812 7813 7814 %\subsection{\texorpdfstring{\protect\lstinline{timespec}}{timespec}} 7351 7815 \subsection{\texorpdfstring{\LstBasicStyle{timespec}}{timespec}} 7352 7816 \label{s:timespec} … … 7355 7819 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7356 7820 void ?{}( timespec & t ); 7821 void ?{}( timespec & t, zero_t ); 7357 7822 void ?{}( timespec & t, time_t sec, __syscall_slong_t nsec ); 7358 7823 void ?{}( timespec & t, time_t sec ); 7359 void ?{}( timespec & t, zero_t );7360 7824 void ?{}( timespec & t, Time time ); 7361 7825 … … 7363 7827 timespec ?+?( timespec & lhs, timespec rhs ); 7364 7828 timespec ?-?( timespec & lhs, timespec rhs ); 7365 _Bool ?==?( timespec lhs, timespec rhs );7366 _Bool ?!=?( timespec lhs, timespec rhs );7367 \end{cfa} 7368 7369 7370 %\subsection{\texorpdfstring{\protect\lstinline @itimerval@}{itimerval}}7829 bool ?==?( timespec lhs, timespec rhs ); 7830 bool ?!=?( timespec lhs, timespec rhs ); 7831 \end{cfa} 7832 7833 7834 %\subsection{\texorpdfstring{\protect\lstinline{itimerval}}{itimerval}} 7371 7835 \subsection{\texorpdfstring{\LstBasicStyle{itimerval}}{itimerval}} 7372 7836 \label{s:itimerval} … … 7379 7843 7380 7844 7381 %\subsection{\texorpdfstring{\protect\lstinline @Time@}{Time}}7845 %\subsection{\texorpdfstring{\protect\lstinline{Time}}{Time}} 7382 7846 \subsection{\texorpdfstring{\LstBasicStyle{Time}}{Time}} 7383 7847 \label{s:Time} … … 7386 7850 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7387 7851 struct Time { 7388 uint64_t t v; $\C{// nanoseconds since UNIX epoch}$7852 uint64_t tn; $\C{// nanoseconds since UNIX epoch}$ 7389 7853 }; 7390 7854 7391 7855 void ?{}( Time & time ); 7392 7856 void ?{}( Time & time, zero_t ); 7857 void ?{}( Time & time, timeval t ); 7858 void ?{}( Time & time, timespec t ); 7393 7859 7394 7860 Time ?=?( Time & time, zero_t ); 7395 7396 void ?{}( Time & time, timeval t );7397 7861 Time ?=?( Time & time, timeval t ); 7398 7399 void ?{}( Time & time, timespec t );7400 7862 Time ?=?( Time & time, timespec t ); 7401 7863 … … 7407 7869 Time ?-?( Time lhs, Duration rhs ); 7408 7870 Time ?-=?( Time & lhs, Duration rhs ); 7409 _Bool ?==?( Time lhs, Time rhs ); 7410 _Bool ?!=?( Time lhs, Time rhs ); 7411 _Bool ?<?( Time lhs, Time rhs ); 7412 _Bool ?<=?( Time lhs, Time rhs ); 7413 _Bool ?>?( Time lhs, Time rhs ); 7414 _Bool ?>=?( Time lhs, Time rhs ); 7871 bool ?==?( Time lhs, Time rhs ); 7872 bool ?!=?( Time lhs, Time rhs ); 7873 bool ?<?( Time lhs, Time rhs ); 7874 bool ?<=?( Time lhs, Time rhs ); 7875 bool ?>?( Time lhs, Time rhs ); 7876 bool ?>=?( Time lhs, Time rhs ); 7877 7878 int64_t ?`ns( Time t ); 7415 7879 7416 7880 char * yy_mm_dd( Time time, char * buf ); 7417 char * ?`ymd( Time time, char * buf ) { // short form 7418 return yy_mm_dd( time, buf ); 7419 } // ymd 7881 char * ?`ymd( Time time, char * buf ); // short form 7420 7882 7421 7883 char * mm_dd_yy( Time time, char * buf ); 7422 char * ?`mdy( Time time, char * buf ) { // short form 7423 return mm_dd_yy( time, buf ); 7424 } // mdy 7884 char * ?`mdy( Time time, char * buf ); // short form 7425 7885 7426 7886 char * dd_mm_yy( Time time, char * buf ); 7427 char * ?`dmy( Time time, char * buf ) { // short form 7428 return dd_mm_yy( time, buf );; 7429 } // dmy 7887 char * ?`dmy( Time time, char * buf ); // short form 7430 7888 7431 7889 size_t strftime( char * buf, size_t size, const char * fmt, Time time ); 7432 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time ); 7890 7891 forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time ); 7433 7892 \end{cfa} 7434 7893 … … 7450 7909 7451 7910 7452 %\subsection{\texorpdfstring{\protect\lstinline @Clock@}{Clock}}7911 %\subsection{\texorpdfstring{\protect\lstinline{Clock}}{Clock}} 7453 7912 \subsection{\texorpdfstring{\LstBasicStyle{Clock}}{Clock}} 7454 7913 \label{s:Clock} … … 7456 7915 \leavevmode 7457 7916 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7458 struct Clock { 7459 Duration offset; $\C{// for virtual clock: contains offset from real-time}$ 7460 int clocktype; $\C{// implementation only -1 (virtual), CLOCK\_REALTIME}$ 7917 struct Clock { $\C{// virtual clock}$ 7918 Duration offset; $\C{// offset from computer real-time}$ 7461 7919 }; 7462 7920 7463 void resetClock( Clock & clk ); 7464 void resetClock( Clock & clk, Duration adj ); 7465 void ?{}( Clock & clk ); 7466 void ?{}( Clock & clk, Duration adj ); 7467 7468 Duration getResNsec(); $\C{// with nanoseconds}$ 7469 Duration getRes(); $\C{// without nanoseconds}$ 7470 7471 Time getTimeNsec(); $\C{// with nanoseconds}$ 7472 Time getTime(); $\C{// without nanoseconds}$ 7473 Time getTime( Clock & clk ); 7474 Time ?()( Clock & clk ); 7475 timeval getTime( Clock & clk ); 7476 tm getTime( Clock & clk ); 7921 void ?{}( Clock & clk ); $\C{// create no offset}$ 7922 void ?{}( Clock & clk, Duration adj ); $\C{// create with offset}$ 7923 void reset( Clock & clk, Duration adj ); $\C{// change offset}$ 7924 7925 Duration resolutionHi(); $\C{// clock resolution in nanoseconds (fine)}$ 7926 Duration resolution(); $\C{// clock resolution without nanoseconds (coarse)}$ 7927 7928 Time timeHiRes(); $\C{// real time with nanoseconds}$ 7929 Time time(); $\C{// real time without nanoseconds}$ 7930 Time time( Clock & clk ); $\C{// real time for given clock}$ 7931 Time ?()( Clock & clk ); $\C{//\ \ \ \ alternative syntax}$ 7932 timeval time( Clock & clk ); $\C{// convert to C time format}$ 7933 tm time( Clock & clk ); 7934 Duration processor(); $\C{// non-monotonic duration of kernel thread}$ 7935 Duration program(); $\C{// non-monotonic duration of program CPU}$ 7936 Duration boot(); $\C{// monotonic duration since computer boot}$ 7477 7937 \end{cfa} 7478 7938 … … 7645 8105 forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype * os, Int mp ); 7646 8106 \end{cfa} 7647 7648 The following factorial programs contrast using GMP with the \CFA and C interfaces, where the output from these programs appears in \VRef[Figure]{f:MultiPrecisionFactorials}. 8107 \VRef[Figure]{f:MultiPrecisionFactorials} shows \CFA and C factorial programs using the GMP interfaces. 7649 8108 (Compile with flag \Indexc{-lgmp} to link with the GMP library.) 8109 8110 \begin{figure} 7650 8111 \begin{cquote} 7651 8112 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}} 7652 \multicolumn{1}{ c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}} \\8113 \multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}@{}} \\ 7653 8114 \hline 7654 8115 \begin{cfa} … … 7659 8120 7660 8121 sout | 0 | fact; 7661 for ( unsigned int i = 1; i <= 40; i += 1) {8122 for ( i; 40 ) { 7662 8123 fact *= i; 7663 8124 sout | i | fact; … … 7669 8130 #include <gmp.h>$\indexc{gmp.h}$ 7670 8131 int main( void ) { 7671 @gmp_printf@( "Factorial Numbers\n" );7672 @mpz_t@fact;7673 @mpz_init_set_ui@( fact, 1 );7674 @gmp_printf@( "%d %Zd\n", 0, fact );8132 ®gmp_printf®( "Factorial Numbers\n" ); 8133 ®mpz_t® fact; 8134 ®mpz_init_set_ui®( fact, 1 ); 8135 ®gmp_printf®( "%d %Zd\n", 0, fact ); 7675 8136 for ( unsigned int i = 1; i <= 40; i += 1 ) { 7676 @mpz_mul_ui@( fact, fact, i );7677 @gmp_printf@( "%d %Zd\n", i, fact );8137 ®mpz_mul_ui®( fact, fact, i ); 8138 ®gmp_printf®( "%d %Zd\n", i, fact ); 7678 8139 } 7679 8140 } … … 7681 8142 \end{tabular} 7682 8143 \end{cquote} 7683 7684 \begin{figure} 8144 \small 7685 8145 \begin{cfa} 7686 8146 Factorial Numbers
Note:
See TracChangeset
for help on using the changeset viewer.