Changeset dafbde8


Ignore:
Timestamp:
Jan 20, 2021, 4:49:40 PM (11 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
454f478
Parents:
92bfda0 (diff), fd54fef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
2 added
141 edited

Legend:

Unmodified
Added
Removed
  • doc/bibliography/pl.bib

    r92bfda0 rdafbde8  
    688688    title       = {Asynchronous Exception Propagation in Blocked Tasks},
    689689    booktitle   = {4th International Workshop on Exception Handling (WEH.08)},
    690     organization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
     690    optorganization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
    691691    address     = {Atlanta, U.S.A},
    692692    month       = nov,
     
    72467246
    72477247@inproceedings{Edelson92,
    7248     keywords    = {persistence, pointers},
     7248    keywords    = {persistence, smart pointers},
    72497249    contributer = {pabuhr@plg},
    72507250    author      = {Daniel R. Edelson},
     
    72567256    year        = 1992,
    72577257    pages       = {1-19},
     7258}
     7259
     7260@incollection{smartpointers,
     7261    keywords    = {smart pointers},
     7262    contributer = {pabuhr@plg},
     7263    author      = {Andrei Alexandrescu},
     7264    title       = {Smart Pointers},
     7265    booktitle   = {Modern C++ Design: Generic Programming and Design Patterns Applied},
     7266    publisher   = {Addison-Wesley},
     7267    year        = 2001,
     7268    chapter     = 7,
     7269    optpages    = {?-?},
    72587270}
    72597271
     
    82458257}
    82468258
     8259@misc{vistorpattern,
     8260    keywords    = {visitor pattern},
     8261    contributer = {pabuhr@plg},
     8262    key         = {vistor pattern},
     8263    title       = {vistor pattern},
     8264    year        = 2020,
     8265    note        = {WikipediA},
     8266    howpublished= {\href{https://en.wikipedia.org/wiki/Visitor\_pattern}
     8267                  {https://\-en.wikipedia.org/\-wiki/\-Visitor\_pattern}},
     8268}
     8269
    82478270% W
    82488271
  • doc/theses/fangren_yu_COOP_F20/Report.tex

    r92bfda0 rdafbde8  
    7676\renewcommand{\subsectionmark}[1]{\markboth{\thesubsection\quad #1}{\thesubsection\quad #1}}
    7777\pagenumbering{roman}
    78 \linenumbers                                            % comment out to turn off line numbering
     78%\linenumbers                                            % comment out to turn off line numbering
    7979
    8080\maketitle
    8181\pdfbookmark[1]{Contents}{section}
    82 \tableofcontents
    83 
    84 \clearpage
     82
    8583\thispagestyle{plain}
    8684\pagenumbering{arabic}
    8785
    8886\begin{abstract}
    89 
    90 \CFA is an evolutionary extension to the C programming language, featuring a parametric type system, and is currently under active development. The reference compiler for \CFA language, @cfa-cc@, has some of its major components dated back to early 2000s, and is based on inefficient data structures and algorithms. Some improvements targeting the expression resolution algorithm, suggested by a recent prototype experiment on a simplified model, are implemented in @cfa-cc@ to support the full \CFA language. These optimizations speed up the compiler significantly by a factor of 20 across the existing \CFA codebase, bringing the compilation time of a mid-sized \CFA source file down to 10-second level. A few cases derived from realistic code examples that causes trouble to the compiler are analyzed in detail, with proposed solutions. This step of \CFA project development is critical to its eventual goal to be used alongside C for large software systems.
    91 
     87\CFA is an evolutionary, non-object-oriented extension of the C programming language, featuring a parametric type-system, and is currently under active development. The reference compiler for the \CFA language, @cfa-cc@, has some of its major components dated back to the early 2000s, which are based on inefficient data structures and algorithms. This report introduces improvements targeting the expression resolution algorithm, suggested by a recent prototype experiment on a simplified model, which are implemented in @cfa-cc@ to support the full \CFA language. These optimizations speed up the compiler by a factor of 20 across the existing \CFA codebase, bringing the compilation time of a mid-sized \CFA source file down to the 10-second level. A few problem cases derived from realistic code examples are analyzed in detail, with proposed solutions. This work is a critical step in the \CFA project development to achieve its eventual goal of being used alongside C for large software systems.
    9288\end{abstract}
    9389
     90\clearpage
     91\section*{Acknowledgements}
     92\begin{sloppypar}
     93I would like to thank everyone in the \CFA team for their contribution towards this project. Programming language design and development is a tough subject and requires a lot of teamwork. Without the collaborative efforts from the team, this project could not have been a success. Specifically, I would like to thank Andrew Beach for introducing me to the \CFA codebase, Thierry Delisle for maintaining the test and build automation framework, Michael Brooks for providing example programs of various experimental language and type system features, and most importantly, Professor Martin Karsten for recommending me to the \CFA team, and my supervisor, Professor Peter Buhr for encouraging me to explore deeply into intricate compiler algorithms. Finally, I gratefully acknowledge the help from Aaron Moss, former graduate from the team and the author of the precedent thesis work, to participate in the \CFA team's virtual conferences and email correspondence, and provide many critical arguments and suggestions. 2020 had been an unusually challenging year for everyone and we managed to keep a steady pace.
     94\end{sloppypar}
     95
     96\clearpage
     97\tableofcontents
     98
     99\clearpage
    94100\section{Introduction}
    95101
    96 \CFA language, developed by the Programming Language Group at University of Waterloo, has a long history, with the first proof-of-concept compiler built in 2003 by Richard Bilson~\cite{Bilson03}. Many new features are added to the language over time, but the core of \CFA, parametric functions introduced by the @forall@ clause (hence the name of the language), with the type system supporting parametric overloading, remains mostly unchanged.
    97 
    98 The current \CFA reference compiler @cfa-cc@ still includes many parts taken directly from the original Bilson's implementation, and serves as a starting point for the enhancement work to the type system. Unfortunately, it does not provide the efficiency required for the language to be used practically: a \CFA source file of approximately 1000 lines of code can take a few minutes to compile. The cause of the problem is that the old compiler used inefficient data structures and algorithms for expression resolution, which involved a lot of copying and redundant work.
    99 
    100 This paper presents a series of optimizations to the performance-critical parts of the resolver, with a major rework of the data structure used by the compiler, using a functional programming approach to reduce memory complexity. Subsequent improvements are mostly suggested by running the compiler builds with a performance profiler against the \CFA standard library source code and a test suite to find the most underperforming components in the compiler algorithm.
    101 
    102 The \CFA team endorses a pragmatic philosophy in work that mostly focuses on practical implications of language design and implementation, rather than the theoretical limits. In particular, the compiler is designed to work on production \CFA code efficiently and keep type safety, while sometimes making compromises to expressiveness in extreme corner cases. However, when these corner cases do appear in actual usage, they need to be thoroughly investigated. Analysis presented in this paper, therefore, are conducted on a case-by-case basis. Some of them eventually point to certain weaknesses in the language design and solutions are proposed based on experimental results.
    103 
    104 \section{Completed work}
     102\CFA language, developed by the Programming Language Group at the University of Waterloo, has a long history, with the initial language design in 1992 by Glen Ditchfield~\cite{Ditchfield92} and the first proof-of-concept compiler built in 2003 by Richard Bilson~\cite{Bilson03}. Many new features have been added to the language over time, but the core of \CFA's type-system --- parametric functions introduced by the @forall@ clause (hence the name of the language) providing parametric overloading --- remains mostly unchanged.
     103
     104The current \CFA reference compiler, @cfa-cc@, is designed using the visitor pattern~\cite{vistorpattern} over an abstract syntax tree (AST), where multiple passes over the AST modify it for subsequent passes. @cfa-cc@ still includes many parts taken directly from the original Bilson implementation, which served as the starting point for this enhancement work to the type system. Unfortunately, the prior implementation did not provide the efficiency required for the language to be practical: a \CFA source file of approximately 1000 lines of code can take a multiple minutes to compile. The cause of the problem is that the old compiler used inefficient data structures and algorithms for expression resolution, which involved significant copying and redundant work.
     105
     106This report presents a series of optimizations to the performance-critical parts of the resolver, with a major rework of the compiler data-structures using a functional-programming approach to reduce memory complexity. The improvements were suggested by running the compiler builds with a performance profiler against the \CFA standard-library source-code and a test suite to find the most underperforming components in the compiler algorithm.
     107
     108The \CFA team endorses a pragmatic philosophy that focuses on practical implications of language design and implementation rather than theoretical limits. In particular, the compiler is designed to be expressive with respect to code reuse while maintaining type safety, but compromise theoretical soundness in extreme corner cases. However, when these corner cases do appear in actual usage, they need to be thoroughly investigated. A case-by-case analysis is presented for several of these corner cases, some of which point to certain weaknesses in the language design with solutions proposed based on experimental results.
     109
     110\section{AST restructuring}
    105111
    106112\subsection{Memory model with sharing}
    107113
    108 A major rework of the abstract syntax tree (AST) data structure in the compiler is completed as the first step of the project. The majority of work were documented in the reference manual of the compiler~\cite{cfa-cc}. To summarize:
    109 \begin{itemize}
    110 \item
    111 AST nodes (and therefore subtrees) can be shared without copying when reused.
    112 \item
    113 Modifications apply the functional programming principle, making copies for local changes without affecting the original data shared by other owners. In-place mutations are permitted as a special case when sharing does not happen. The logic is implemented by reference counting.
    114 \item
    115 Memory allocation and freeing are performed automatically using smart pointers.
    116 \end{itemize}
    117 The resolver algorithm designed for overload resolution naturally introduces a significant amount of reused intermediate representations, especially in the following two places:
    118 \begin{itemize}
    119 \item
    120 Function overload candidates are computed by combining the argument candidates bottom-up, with many of them being a common term. For example, if $n$ overloads of a function @f@ all take an integer for the first parameter but different types for the second (@f( int, int )@, @f( int, double )@, etc.) the first term is reused $n$ times for each of the generated candidate expressions. This effect is particularly bad for deep expression trees.
    121 \item
    122 In the unification algorithm and candidate elimination step, actual types are obtained by substituting the type parameters by their bindings. Let $n$ be the complexity (\ie number of nodes in representation) of the original type, $m$ be the complexity of bound type for parameters, and $k$ be the number of occurrences of type parameters in the original type. If everything needs to be deep-copied, the substitution step takes $O(n+mk)$ time and memory, while using shared nodes it is reduced to $O(n)$ time and $O(k)$ memory.
    123 \end{itemize}
    124 One of the worst examples for the old compiler is a long chain of I/O operations
    125 \begin{cfa}
    126 sout | 1 | 2 | 3 | 4 | ...
    127 \end{cfa}
    128 The pipe operator is overloaded by \CFA I/O library for every primitive type in C language, as well as I/O manipulators defined by the library. In total there are around 50 overloads for the output stream operation. On resolving the $n$-th pipe operator in the sequence, the first term, which is the result of sub-expression containing $n-1$ pipe operators, is reused to resolve every overload. Therefore at least $O(n^2)$ copies of expression nodes are made during resolution, not even counting type unification cost; combined with two large factors from number of overloads of pipe operators, and that the ``output stream type'' in \CFA is a trait with 27 assertions (which adds to complexity of the pipe operator's type) this makes compiling a long output sequence extremely slow. In new AST representation only $O(n)$ copies are required and type of pipe operator is not copied at all.
    129 
    130 Reduction in space complexity is especially important, as preliminary profiling result on the old compiler build shows that over half of time spent in expression resolution are on memory allocations.
    131  
     114A major rework of the AST data-structure in the compiler was completed as the first step of the project. The majority of this work is documented in my prior report documenting the compiler reference-manual~\cite{cfa-cc}. To summarize:
     115\begin{itemize}
     116\item
     117AST nodes (and therefore subtrees) can be shared without copying.
     118\item
     119Modifications are performed using functional-programming principles, making copies for local changes without affecting the original data shared by other owners. In-place mutations are permitted as a special case when there is no sharing. The logic is implemented by reference counting.
     120\item
     121Memory allocation and freeing are performed automatically using smart pointers~\cite{smartpointers}.
     122\end{itemize}
     123
     124The resolver algorithm, designed for overload resolution, uses a significant amount of reused, and hence copying, for the intermediate representations, especially in the following two places:
     125\begin{itemize}
     126\item
     127Function overload candidates are computed by combining the argument candidates bottom-up, with many being a common term. For example, if $n$ overloads of a function @f@ all take an integer for the first parameter but different types for the second, \eg @f( int, int )@, @f( int, double )@, etc., the first term is copied $n$ times for each of the generated candidate expressions. This copying is particularly bad for deep expression trees.
     128\item
     129In the unification algorithm and candidate elimination step, actual types are obtained by substituting the type parameters by their bindings. Let $n$ be the complexity (\ie number of nodes in representation) of the original type, $m$ be the complexity of the bound type for parameters, and $k$ be the number of occurrences of type parameters in the original type. If every substitution needs to be deep-copied, these copy step takes $O(n+mk)$ time and memory, while using shared nodes it is reduced to $O(n)$ time and $O(k)$ memory.
     130\end{itemize}
     131One of the worst examples for the old compiler is a long chain of I/O operations:
     132\begin{cfa}
     133sout | 1 | 2 | 3 | 4 | ...;   // print integer constants
     134\end{cfa}
     135The pipe operator is overloaded by the \CFA I/O library for every primitive type in the C language, as well as I/O manipulators defined by the library. In total, there are around 50 overloads for the output stream operation. On resolving the $n$-th pipe operator in the sequence, the first term, which is the result of sub-expression containing $n-1$ pipe operators, is reused to resolve every overload. Therefore at least $O(n^2)$ copies of expression nodes are made during resolution, not even counting type unification cost; combined with the two large factors from number of overloads of pipe operators, and that the ``output stream type'' in \CFA is a trait with 27 assertions (which adds to complexity of the pipe operator's type) this makes compiling a long output sequence extremely slow. In the new AST representation, only $O(n)$ copies are required and the type of the pipe operator is not copied at all.
     136Reduction in space complexity is especially important, as preliminary profiling results on the old compiler build showed over half of the time spent in expression resolution is on memory allocations.
     137
     138Since the compiler codebase is large and the new memory model mostly benefits expression resolution, some of the old data structures are still kept, and a conversion pass happens before and after the general resolve phase. Rewriting every compiler module will take longer, and whether the new model is correct was unknown when this project started, therefore only the resolver is currently implemented with the new data structure.
     139
    132140
    133141\subsection{Merged resolver calls}
    134142
    135 The pre-resolve phase of compilation, inadequately called ``validate'' in the compiler source code, does more than just simple syntax validation, as it also normalizes input program. Some of them, however, requires type information on expressions and therefore needs to call the resolver before the general resolve phase. There are three notable places where the resolver is invoked:
    136 \begin{itemize}
    137 \item
    138 Attempt to generate default constructor, copy constructor and destructor for user-defined @struct@ types
    139 \item
    140 Resolve @with@ statements (the same as in Python, which introduces fields of a structure directly in scope)
     143The pre-resolve phase of compilation, inappropriately called ``validate'' in the compiler source code, has a number of passes that do more than simple syntax and semantic validation; some passes also normalizes the input program. A few of these passes require type information for expressions, and therefore, need to call the resolver before the general resolve phase. There are three notable places where the resolver is invoked:
     144\begin{itemize}
     145\item
     146Generate default constructor, copy constructor and destructor for user-defined @struct@ types.
     147\item
     148Resolve @with@ statements (the same as in Pascal~\cite{pascal}), which introduces fields of a structure directly into a scope.
    141149\item
    142150Resolve @typeof@ expressions (cf. @decltype@ in \CC); note that this step may depend on symbols introduced by @with@ statements.
    143151\end{itemize}
    144 Since the compiler codebase is large and the new memory model mostly only benefits expression resolution, the old data structure is still kept, and a conversion pass happens before and after resolve phase. Rewriting every compiler module will take a long time, and whether the new model is correct is still unknown when started, therefore only the resolver is implemented with the new data structure.
    145 
    146 Since the constructor calls were one of the most expensive to resolve (reason will be shown in the next section), pre-resolve phase were taking more time after resolver moves to the more efficient new implementation. To better facilitate the new resolver, every step that requires type information are reintegrated as part of resolver.
    147 
    148 A by-product of this work is that the reversed dependence of @with@ statement and @typeof@ can now be handled. Previously, the compiler is unable to handle cases such as
     152
     153Since the constructor calls are one of the most expensive to resolve (reason given in~\VRef{s:SpecialFunctionLookup}), this pre-resolve phase was taking a large amount of time even after the resolver was changed to the more efficient new implementation. The problem is that multiple resolutions repeat a significant amount of work. Therefore, to better facilitate the new resolver, every step that requires type information should be integrated as part of the general resolver phase.
     154
     155A by-product of this work is that reversed dependence between @with@ statement and @typeof@ can now be handled. Previously, the compiler was unable to handle cases such as:
    149156\begin{cfa}
    150157struct S { int x; };
    151158S foo();
    152159typeof( foo() ) s; // type is S
    153 with (s) { 
     160with (s) {
    154161        x; // refers to s.x
    155162}
    156163\end{cfa}
    157 since type of @s@ is still unresolved when handling @with@ expressions. Instead, the new (and correct) approach is to evaluate @typeof@ expressions when the declaration is first seen, and it suffices because of the declaration-before-use rule.
     164since the type of @s@ is unresolved when handling @with@ expressions because the @with@ pass follows the @typeof@ pass (interchanging passes only interchanges the problem). Instead, the new (and correct) approach is to evaluate @typeof@ expressions when the declaration is first seen during resolution, and it suffices because of the declaration-before-use rule.
    158165
    159166
    160167\subsection{Special function lookup}
    161 
    162 Reducing the number of functions looked up for overload resolution is an effective way to gain performance when there are many overloads but most of them are trivially wrong. In practice, most functions have few (if any) overloads but there are notable exceptions. Most importantly, constructor @?{}@, destructor @^?{}@, and assignment @?=?@ are generated for every user-defined type, and in a large source file there can be hundreds of them. Furthermore, many calls to them are generated for initializing variables and passing arguments. This fact makes them the most overloaded and most called functions.
    163 
    164 In an object-oriented programming language, object has methods declared with their types, so a call such as @obj.f()@ only needs to perform lookup in the method table corresponding to type of @obj@. \CFA on the other hand, does not have methods, and all types are open (\ie new operations can be defined on them), so a similar approach will not work in general. However, the ``big 3'' operators have a unique property enforced by the language rules, such that the first parameter must have a reference type. Since \CFA does not have class inheritance, reference type must always match exactly. Therefore, argument-dependent lookup can be implemented for these operators, by using a dedicated symbol table.
    165 
    166 The lookup key used for the special functions is the mangled type name of the first parameter, which acts as the @this@ parameter in an object-oriented language. To handle generic types, the type parameters are stripped off, and only the base type is matched. Note that a constructor (destructor, assignment operator) taking arbitrary @this@ argument, for example @forall( dtype T ) void ?{}( T & );@ is not allowed, and it guarantees that if the @this@ type is known, all possible overloads can be found by searching with the given type. In case that the @this@ argument itself is overloaded, it is resolved first and all possible result types are used for lookup.
    167 
    168 Note that for the generated expressions, the particular variable for @this@ argument is fully known, without overloads, so the majority of constructor call resolutions only need to check for one given object type. Explicit constructor calls and assignment statements sometimes may require lookup for multiple types. In the extremely rare case that type of @this@ argument is yet unbound, everything will have to be checked, just like without the argument-dependent lookup algorithm; fortunately, this case almost never happens in practice. An example is found in the library function @new@:
     168\label{s:SpecialFunctionLookup}
     169
     170Reducing the number of function looked ups for overload resolution is an effective way to gain performance when there are many overloads but most of them are trivially wrong. In practice, most functions have few (if any) overloads but there are notable exceptions. Most importantly, constructor @?{}@, destructor @^?{}@, and assignment @?=?@ are generated for every user-defined type (@struct@ and @union@ in C), and in a large source file there can be hundreds of them. Furthermore, many calls are generated for initializing variables, passing arguments and copying values. This fact makes them the most overloaded and most called functions.
     171
     172In an object-oriented programming language, the object-method types are scoped within a class, so a call such as @obj.f()@ only needs to perform lookup in the method table corresponding to the type of @obj@. \CFA on the other hand, does not have methods, and all types are open, \ie new operations can be defined on them without inheritance; at best a \CFA type can be constrained by a translation unit. However, the ``big 3'' operators have a unique property enforced by the language rules: the first parameter must be a reference to its associated type, which acts as the @this@ parameter in an object-oriented language. Since \CFA does not have class inheritance, the reference type must always match exactly. Therefore, argument-dependent lookup can be implemented for these operators by using a dedicated, fast symbol-table.
     173
     174The lookup key for the special functions is the mangled type name of the first parameter. To handle generic types, the type parameters are stripped off, and only the base type is matched. Note a constructor (destructor, assignment operator) may not take an arbitrary @this@ argument, \eg @forall( dtype T ) void ?{}( T & )@, thus guaranteeing that if the @this@ type is known, all possible overloads can be found by searching with this given type. In the case where the @this@ argument itself is overloaded, it is resolved first and all possible result types are used for lookup.
     175
     176Note that for a generated expression, the particular variable for the @this@ argument is fully known, without overloads, so the majority of constructor-call resolutions only need to check for one given object type. Explicit constructor calls and assignment statements sometimes require lookup for multiple types. In the extremely rare case that the @this@-argument type is unbound, all necessary types are guaranteed to be checked, as for the previous lookup without the argument-dependent lookup; fortunately, this complex case almost never happens in practice. An example is found in the library function @new@:
    169177\begin{cfa}
    170178forall( dtype T | sized( T ), ttype TT | { void ?{}( T &, TT ); } )
    171179T * new( TT p ) { return &(*malloc()){ p }; }
    172180\end{cfa}
    173 as @malloc@ may return a pointer to any type, depending on context. 
    174 
    175 Interestingly, this particular line of code actually caused another complicated issue, where the unusually massive work of checking every constructor in presence makes the case even worse. Section~\ref{s:TtypeResolutionInfiniteRecursion} presents a detailed analysis for the problem.
    176 
    177 The ``callable'' operator @?()@ (cf. @operator()@ in \CC) could also be included in the special operator list, as it is usually only on user-defined types, and the restriction that first argument must be a reference seems reasonable in this case.
     181as @malloc@ may return a pointer to any type, depending on context.
     182
     183Interestingly, this particular declaration actually causes another complicated issue, making the complex checking of every constructor even worse. \VRef[Section]{s:TtypeResolutionInfiniteRecursion} presents a detailed analysis of this problem.
     184
     185The ``callable'' operator @?()@ (cf. @operator()@ in \CC) can also be included in this special operator list, as it is usually only on user-defined types, and the restriction that the first argument must be a reference seems reasonable in this case.
    178186
    179187
    180188\subsection{Improvement of function type representation}
    181189
    182 Since substituting type parameters with their bound types is one fundamental operation in many parts of resolver algorithm (particularly unification and environment binding), making as few copies of type nodes as possible helps reducing memory complexity. Even with the new memory management model, allocation is still a significant factor of resolver performance. Conceptually, operations on type nodes of AST should be performed in functional programming style, treating the data structure as immutable and only copy when necessary. The in-place mutation is a mere optimization that does not change logic of operations.
    183 The model was broken on function types by an inappropriate design. Function types require some special treatment due to the existence of assertions. In particular, it must be able to distinguish two different kinds of type parameter usage:
     190Since substituting type parameters with their bound types is one fundamental operation in many parts of resolver algorithm (particularly unification and environment binding), making as few copies of type nodes as possible helps reducing memory complexity. Even with the new memory management model, allocation is still a significant factor of resolver performance. Conceptually, operations on type nodes of the AST should be performed in functional-programming style, treating the data structure as immutable and only copying when necessary. The in-place mutation is a mere optimization that does not change the logic for operations.
     191
     192However, the model was broken for function types by an inappropriate design. Function types require special treatment due to the existence of assertions that constrain the types it supports. Specifically, it must be possible to distinguish two different kinds of type parameter usage:
    184193\begin{cfa}
    185194forall( dtype T ) void foo( T * t ) {
    186         forall( dtype U ) void bar( T * t, U * u ) { ... }
    187 }
    188 \end{cfa}
    189 Here, only @U@ is a free parameter in declaration of @bar@, as it appears in the function's own forall clause; while @T@ is not free.
    190 
    191 Moreover, the resolution algorithm also has to distinguish type bindings of multiple calls to the same function, for example with
     195        forall( dtype U ) void bar( @T@ * t, @U@ * u ) { ... }
     196}
     197\end{cfa}
     198Here, only @U@ is a free parameter in the nested declaration of function @bar@, as @T@ must be bound at the call site when resolving @bar@.
     199
     200Moreover, the resolution algorithm also has to distinguish type bindings of multiple calls to the same function, \eg:
    192201\begin{cfa}
    193202forall( dtype T ) int foo( T x );
    194 foo( foo( 1.0 ) );
    195 \end{cfa}
    196 The inner call has binding (T: double) while the outer call has binding (T: int). Therefore a unique representation of free parameters in each expression is required. This was previously done by creating a copy of the parameter declarations inside function type, and fixing references afterwards. However, fixing references is an inherently deep operation that does not work well with functional programming model, as it must be evaluated eagerly on the entire syntax tree representing the function type.
    197 
    198 The revised approach generates a unique ID value for each function call expression instance and represents an occurrence of free parameter type with a pair of generated ID and the original parameter declaration, so that references do not need to be fixed, and a shallow copy of function type is possible.
    199 
    200 Note that after the change, all declaration nodes in syntax tree representation maps one-to-one with the actual declarations in the program, and therefore are guaranteed to be unique. Such property can potentially enable more optimizations, and some related ideas are presented after Section~\ref{s:SharedSub-ExpressionCaseUniqueExpressions}.
     203int i = foo( foo( 1.0 ) );
     204\end{cfa}
     205The inner call has binding (T: double) while the outer call has binding (T: int). Therefore a unique representation for the free parameters is required in each expression. This type binding was previously done by creating a copy of the parameter declarations inside the function type and fixing references afterwards. However, fixing references is an inherently deep operation that does not work well with the functional-programming style, as it forces eager evaluation on the entire syntax tree representing the function type.
     206
     207The revised approach generates a unique ID value for each function call expression instance and represents an occurrence of a free-parameter type with a pair of generated ID and original parameter declaration, so references are unique and a shallow copy of the function type is possible.
     208
     209Note that after the change, all declaration nodes in the syntax-tree representation now map one-to-one with the actual declarations in the program, and therefore are guaranteed to be unique. This property can potentially enable more optimizations, and some related ideas are presented at the end of \VRef{s:SharedSub-ExpressionCaseUniqueExpressions}.
    201210
    202211
    203212\subsection{Improvement of pruning steps}
    204213
    205 A minor improvement for candidate elimination is to skip the step on the function overloads themselves and only perform on results of function application. As function calls are usually by name, the name resolution rule dictates that every function candidate necessarily has a different type; indirect function calls are rare, and when they do appear, they usually will not have many possible interpretations, and those rarely matches exactly in argument type. Since function types have a much more complex representation than data types (with multiple parameters and assertions), checking equality on them also takes longer.
    206 
    207 A brief test of this approach shows that the number of function overloads considered in expression resolution increases by a negligible amount of less than 1 percent, while type comparisons in candidate elimination are cut by more than half. Improvement is consistent over all \CFA source files in the test suite.
     214A minor improvement for candidate elimination is to skip the step on the function overloads and only check the results of function application. As function calls are usually by name (versus pointers to functions), the name resolution rule dictates that every function candidate necessarily has a different type; indirect function calls are rare, and when they do appear, there are even fewer cases with multiple interpretations, and these rarely match exactly in argument type. Since function types have a much more complex representation (with multiple parameters and assertions) than data types, checking equality on them also takes longer.
     215
     216A brief test of this approach shows that the number of function overloads considered in expression resolution increases by an amount of less than 1 percent, while type comparisons in candidate elimination are reduced by more than half. This improvement is consistent over all \CFA source files in the test suite.
    208217
    209218
     
    211220\label{s:SharedSub-ExpressionCaseUniqueExpressions}
    212221
    213 Unique expression denotes an expression that must be evaluated only once, to prevent unwanted side effects. It is currently only a compiler artifact, generated on tuple member expression of the form
     222Unique expression denotes an expression evaluated only once to prevent unwanted side effects. It is currently only a compiler artifact, generated for tuple-member expression of the form:
    214223\begin{cfa}
    215224struct S { int a; int b; };
     
    217226s.[a, b]; // tuple member expression, type is [int, int]
    218227\end{cfa}
    219 If the aggregate expression contains function calls, it cannot be evaluated multiple times:
     228If the aggregate expression is function call, it cannot be evaluated multiple times:
    220229\begin{cfa}
    221230S makeS();
    222 makeS().[a, b]; // this should only make one S
     231makeS().[a, b]; // this should only generate a unique S
    223232\end{cfa}
    224233Before code generation, the above expression is internally represented as
     
    237246\end{cfa}
    238247at code generation, where @_unique_var@ and @_unique_var_evaluated@ are generated variables whose scope covers all appearances of the same expression.
    239 
    240 Note that although the unique expression is only used for tuple expansion now, it is a generally useful construction, and can be seen in other languages, such as Scala's @lazy val@~\cite{Scala}; therefore it could be worthwhile to introduce the unique expression to a broader context in \CFA and even make it directly available to programmers.
    241 
    242 In the compiler's visitor pattern, however, this creates a problem where multiple paths to a logically unique expression exist, so it may be modified more than once and become ill-formed; some specific intervention is required to ensure that unique expressions are only visited once. Furthermore, a unique expression appearing in more than one places will be copied on mutation so its representation is no longer unique. Some hacks are required to keep it in sync, and the methods are different when mutating the unique expression instance itself or its underlying expression.
    243 
    244 Example when mutating the underlying expression (visit-once guard)
     248The conditional check ensures a single call to @makeS()@ even though there are logically multiple calls because of the tuple field expansion.
     249
     250Note that although the unique expression is only used for tuple expansion now, it is a generally useful construction, and is seen in other programming languages, such as Scala's @lazy val@~\cite{Scala}; therefore it may be worthwhile to introduce the unique expression to a broader context in \CFA and even make it directly available to programmers.
     251
     252In the compiler's visitor pattern, however, this creates a problem where multiple paths to a logically unique expression exist, so it may be modified more than once and become ill-formed; some specific intervention is required to ensure unique expressions are only visited once. Furthermore, a unique expression appearing in more than one places is copied on mutation so its representation is no longer unique.
     253
     254Currently, special cases are required to keep everything synchronized, and the methods are different when mutating the unique expression instance itself or its underlying expression:
     255\begin{itemize}
     256\item
     257When mutating the underlying expression (visit-once guard)
    245258\begin{cfa}
    246259void InsertImplicitCalls::previsit( const ast::UniqueExpr * unqExpr ) {
    247         if ( visitedIds.count( unqExpr->id ) ) visit_children = false;
     260        @if ( visitedIds.count( unqExpr->id ) ) visit_children = false;@
    248261        else visitedIds.insert( unqExpr->id );
    249262}
    250263\end{cfa}
    251 Example when mutating the unique instance itself, which actually creates copies
     264\item
     265When mutating the unique instance itself, which actually creates copies
    252266\begin{cfa}
    253267auto mutExpr = mutate( unqExpr ); // internally calls copy when shared
    254 if ( ! unqMap.count( unqExpr->id ) ) {
     268@if ( ! unqMap.count( unqExpr->id ) ) {@
    255269        ...
    256270} else {
     
    259273}
    260274\end{cfa}
    261 Such workaround seems difficult to be fit into a common visitor template. This suggests the memory model may need different kinds of nodes to accurately represent the syntax tree.
    262 
    263 Together with the fact that declaration nodes are always unique, it is possible that AST nodes can be classified by three different types:
    264 \begin{itemize}
    265 \item
    266 \textbf{Strictly unique} with only one owner (declarations);
    267 \item
    268 \textbf{Logically unique} with (possibly) many owners but should not be copied (unique expression example presented here);
    269 \item
    270 \textbf{Shared} by functional programming model, which assume immutable data structure and are copied on mutation.
     275\end{itemize}
     276Such workarounds are difficult to fit into the common visitor pattern, which suggests the memory model may need different kinds of nodes to accurately represent this feature in the AST.
     277
     278Given that declaration nodes are unique, it is possible for AST nodes to be divided into three different types:
     279\begin{itemize}
     280\item
     281\textbf{Singleton} with only one owner (declarations);
     282\item
     283\textbf{No-copy} with multiple owners but cannot be copied (unique expression example presented here);
     284\item
     285\textbf{Copy} by functional-programming style, which assumes immutable data structures that are copied on mutation.
    271286\end{itemize}
    272287The boilerplate code can potentially handle these three cases differently.
     
    275290\section{Analysis of resolver algorithm complexity}
    276291
    277 The focus of this chapter is to identify and analyze some realistic cases that cause resolver algorithm to have an exponential run time. As previous work has shown [3], the overload resolution problem in \CFA has worst-case exponential complexity; however, only few specific patterns can trigger the exponential complexity in practice. Implementing heuristic-based optimization for those selected cases is helpful to alleviate the problem.
     292The focus of this section is to identify and analyze some realistic cases that cause the resolver algorithm to have an exponential runtime. As previous work has shown~\cite[\S~4.2.1]{Moss19}, the overload resolution problem in \CFA has worst-case exponential complexity; however, only few specific patterns can trigger the exponential complexity in practice. Implementing heuristic-based optimization for those selected cases is helpful to alleviate the problem.
    278293
    279294
     
    281296\label{s:UnboundReturnType}
    282297
    283 The interaction of return type overloading and polymorphic functions creates this problem of function calls with unbound return type, and is further complicated by the presence of assertions.
     298The interaction of return-type overloading and polymorphic functions creates function calls with unbounded return-type, and is further complicated by the presence of assertions.
    284299The prime example of a function with unbound return type is the type-safe version of C @malloc@:
    285300\begin{cfa}
    286 // size deduced from type, so no need to provide the size argument
    287 forall( dtype T | sized( T ) ) T * malloc( void );
    288 \end{cfa}
    289 Unbound return type can be problematic in resolver algorithm complexity because a single match of function call with unbound return type may create multiple candidates. In the worst case, consider a function declared to return any @otype@:
     301forall( dtype T | sized( T ) )
     302T * malloc( void ) { return (T *)malloc( sizeof(T) ); } // call C malloc
     303int * i = malloc();  // type deduced from left-hand size $\Rightarrow$ no size argument or return cast
     304\end{cfa}
     305An unbound return-type is problematic in resolver complexity because a single match of a function call with an unbound return type may create multiple candidates. In the worst case, consider a function declared that returns any @otype@ (defined \VPageref{otype}):
    290306\begin{cfa}
    291307forall( otype T ) T anyObj( void );
    292308\end{cfa}
    293 As the resolver attempts to satisfy the otype constraint on @T@, a single call to @anyObj()@ without the result type known creates at least as many candidates as the number of complete types currently in scope; with generic types it becomes even worse, for example, assuming a declaration of generic pair is available at that point:
     309As the resolver attempts to satisfy the otype constraint on @T@, a call to @anyObj()@ in an expression, without the result type known, creates at least as many candidates as the number of complete types currently in scope; with generic types it becomes even worse, \eg assuming a declaration of a generic @pair@ is available at that point:
    294310\begin{cfa}
    295311forall( otype T, otype U ) struct pair { T first; U second; };
    296312\end{cfa}
    297 Then an @anyObj()@ call can result in arbitrarily complex types, such as @pair( pair( int,int ), pair( int,int ) )@, and the depth can grow indefinitely until the specified parameter depth limit, thus creating exponentially many candidates. However, the expected types allowed by parent expressions are practically very few, so most of those interpretations are invalid; if the result type is never bound up to top level, by the semantic rules it is ambiguous if there are more than one valid bindings, and resolution can fail fast. It is therefore reasonable to delay resolving assertions on an unbound parameter in return type; however, with the current cost model, such behavior may further cause irregularities in candidate selection, such that the presence of assertions can change the preferred candidate, even when order of expression costs are supposed to stay the same. Detailed analysis of this issue will be presented later, in the correctness part.
     313Then an @anyObj()@ call can result in arbitrarily complex types, such as @pair( pair( int, int ), pair( int, int ) )@, and the depth can grow indefinitely until a specified parameter-depth limit, thus creating exponentially many candidates. However, the expected types allowed by parent expressions are practically very few, so most of those interpretations are invalid; if the result type is never bound up to the top level, by the semantic rules it is ambiguous if there is more than one valid binding and resolution fails quickly. It is therefore reasonable to delay resolving assertions on an unbound parameter in a return type; however, with the current cost model, such behavior may further cause irregularities in candidate selection, such that the presence of assertions can change the preferred candidate, even when order of expression costs are supposed to stay the same. A detailed analysis of this issue is presented in \VRef{s:AnalysisTypeSystemCorrectness}.
    298314
    299315
     
    301317\label{s:TtypeResolutionInfiniteRecursion}
    302318
    303 @ttype@ (``tuple type'') is a relatively new addition to the language that attempts to provide type-safe variadic argument semantics. Unlike regular @dtype@ parameters, @ttype@ is only valid in function parameter list, and may only appear once as the type of last parameter. At the call site, a @ttype@ parameter is bound to the tuple type of all remaining function call arguments.
     319@ttype@ (``tuple type'') is a relatively new addition to the language that attempts to provide type-safe variadic argument semantics. Unlike regular @dtype@ parameters, @ttype@ is only valid in a function parameter-list, and may only appear once as the last parameter type. At the call site, a @ttype@ parameter is bound to the tuple type of all remaining function-call arguments.
    304320
    305321There are two kinds of idiomatic @ttype@ usage: one is to provide flexible argument forwarding, similar to the variadic template in \CC (\lstinline[language=C++]|template<typename... args>|), as shown below in the implementation of @unique_ptr@
     
    309325        T * data;
    310326};
    311 forall( dtype T | sized( T ), ttype Args | { void ?{}( T &, Args ); })
    312 void ?{}( unique_ptr( T ) & this, Args args ) {
    313         this.data = new( args );
    314 }
    315 \end{cfa}
    316 the other is to implement structural recursion in the first-rest manner:
    317 \begin{cfa}
    318 forall( otype T, ttype Params | { void process( T ); void func( Params ); })
     327forall( dtype T | sized( T ), @ttype Args@ | { void ?{}( T &, Args ); })
     328void ?{}( unique_ptr( T ) & this, Args @args@ ) {
     329        this.data = new( @args@ );  // forward constructor arguments to dynamic allocator
     330}
     331\end{cfa}
     332The other usage is to implement structural recursion in the first-rest pattern:
     333\begin{cfa}
     334forall( otype T, @ttype Params@ | { void process( T ); void func( Params ); })
    319335void func( T arg1, Params p ) {
    320336        process( arg1 );
    321         func( p );
    322 }
    323 \end{cfa}
    324 For the second use case, it is important that the number of parameters in the recursive call go down, since the call site must deduce all assertion candidates, and that is only possible if by just looking at argument types (and not their values), the recursion is known to be completed in a finite number of steps.
    325 
    326 In recent experiments, however, some flaw in the type binding rules can lead to the first kind of @ttype@ use case produce an invalid candidate that the resolver enters an infinite loop.
    327 
    328 This bug was discovered in an attempt to raise assertion recursive depth limit and one of the library program takes exponentially longer time to compile. The cause of the problem is identified to be the following set of functions.
    329 File @memory.cfa@ contains
    330 \begin{cfa}
    331 #include "memory.hfa"
    332 #include "stdlib.hfa"
    333 \end{cfa}
    334 where file @memory.hfa@ contains the @unique_ptr@ declaration above, and two other similar functions with @ttype@ parameter:
    335 \begin{cfa}
    336 forall( dtype T | sized( T ), ttype Args | { void ?{}( T &, Args ); }) {
     337        func( @p@ );  // recursive call until base case of one argument
     338}
     339\end{cfa}
     340For the second use case, it is imperative the number of parameters in the recursive call goes down, since the call site must deduce all assertion candidates, and that is only possible if by observation of the argument types (and not their values), the recursion is known to be completed in a finite number of steps.
     341
     342In recent experiments, however, a flaw in the type-binding rules can lead to the first kind of @ttype@ use case producing an invalid candidate and the resolver enters an infinite loop.
     343This bug was discovered in an attempt to raise the assertion recursive-depth limit and one of the library programs took exponentially longer to compile. The cause of the problem is the following set of functions:
     344\begin{cfa}
     345// unique_ptr  declaration from above
     346
     347forall( dtype T | sized( T ), ttype Args | { void ?{}( T &, Args ); } ) { // distribute forall clause
    337348        void ?{}( counter_data( T ) & this, Args args );
    338349        void ?{}( counter_ptr( T ) & this, Args args );
    339350        void ?{}( unique_ptr( T ) & this, Args args );
    340351}
    341 \end{cfa}
    342 File @stdlib.hfa@ contains
    343 \begin{cfa}
     352
    344353forall( dtype T | sized( T ), ttype TT | { void ?{}( T &, TT ); } )
    345 T * new( TT p ) { return &(*malloc()){ p }; }
    346 \end{cfa}
    347 
    348 In the expression @(*malloc()){p}@, the type of object being constructed is yet unknown, since the return type information is not immediately provided. That caused every constructor to be searched, and while normally a bound @ttype@ cannot be unified with any free parameter, it is possible with another free @ttype@. Therefore in addition to the correct option provided by assertion, 3 wrong options are examined, each of which again requires the same assertion, for an unknown base type T and @ttype@ arguments, and that becomes an infinite loop, until the specified recursion limit and resolution is forced to fail. Moreover, during the recursion steps, number of candidates grows exponentially, since there are always 3 options at each step.
    349 
    350 Unfortunately, @ttype@ to @ttype@ binding is necessary, to allow calling the function provided by assertion indirectly.
    351 \begin{cfa}
    352 forall( dtype T | sized( T ), ttype Args | { void ?{}( T &, Args ); })
    353 void ?{}( unique_ptr( T ) & this, Args args ) { this.data = (T * )new( args ); }
    354 \end{cfa}
    355 Here the constructor assertion is used for the @new( args )@ call.
     354T * new( TT p ) { return @&(*malloc()){ p };@ }
     355\end{cfa}
     356In the expression @(*malloc()){p}@, the type of the object being constructed is unknown, since the return-type information is not immediately available. That causes every constructor to be searched, and while normally a bound @ttype@ cannot be unified with any free parameter, it is possible with another free @ttype@. Therefore, in addition to the correct option provided by the assertion, 3 wrong options are examined, each of which again requires the same assertion, for an unknown base-type @T@ and @ttype@ argument, which becomes an infinite loop until the specified recursion limit and resolution is fails. Moreover, during the recursion steps, the number of candidates grows exponentially, since there are always 3 options at each step.
     357
     358Unfortunately, @ttype@ to @ttype@ binding is necessary, to allow indirectly calling a function provided in an assertion.
     359\begin{cfa}
     360forall( dtype T | sized( T ), ttype Args | { @void ?{}( T &, Args );@ })
     361void ?{}( unique_ptr( T ) & this, Args args ) { this.data = (T *)@new( args )@; } // constructor call
     362\end{cfa}
     363Here the constructor assertion is used by the @new( args )@ call to indirectly call the constructor on the allocated storage.
    356364Therefore, it is hard, perhaps impossible, to solve this problem by tweaking the type binding rules. An assertion caching algorithm can help improve this case by detecting cycles in recursion.
    357365
    358 Meanwhile, without the caching algorithm implemented, some changes in the \CFA source code are enough to eliminate this problem, at least in the current codebase. Note that the issue only happens with an overloaded variadic function, which rarely appears in practice, since the idiomatic use cases are for argument forwarding and self-recursion. The only overloaded @ttype@ function so far discovered in all of \CFA standard library code is the constructor, and by utilizing the argument-dependent lookup process described in Section~\ref{s:UnboundReturnType}, adding a cast before constructor call gets rid of the issue.
    359 \begin{cfa}
    360 T * new( TT p ) { return &(*(T * )malloc()){ p }; }
     366Meanwhile, without a caching algorithm implemented, some changes in the \CFA source code are enough to eliminate this problem, at least in the current codebase. Note that the issue only happens with an overloaded variadic function, which rarely appears in practice, since the idiomatic use cases are for argument forwarding and self-recursion. The only overloaded @ttype@ function so far discovered in all of \CFA standard library is the constructor, and by utilizing the argument-dependent lookup process described in \VRef{s:UnboundReturnType}, adding a cast before the constructor call removes the issue.
     367\begin{cfa}
     368T * new( TT p ) { return &(*@(T * )@malloc()){ p }; }
    361369\end{cfa}
    362370
     
    364372\subsection{Reused assertions in nested generic type}
    365373
    366 The following test of deeply nested dynamic generic type reveals that locally caching reused assertions is necessary, rather than just a resolver optimization, because recomputing assertions can result in bloated generated code size:
     374The following test of deeply nested, dynamic generic type reveals that locally caching reused assertions is necessary, rather than just a resolver optimization, because recomputing assertions can result in bloated generated code size:
    367375\begin{cfa}
    368376struct nil {};
     
    372380int main() {
    373381        #if   N==0
    374         nil x;   
     382        nil @x@;
    375383        #elif N==1
    376         cons( size_t, nil ) x;
     384        cons( size_t, nil ) @x@;
    377385        #elif N==2
    378         cons( size_t, cons( size_t, nil ) ) x;
     386        cons( size_t, cons( size_t, nil ) ) @x@;
    379387        #elif N==3
    380         cons( size_t, cons( size_t, cons( size_t, nil ) ) ) x;
     388        cons( size_t, cons( size_t, cons( size_t, nil ) ) ) @x@;
    381389        // similarly for N=4,5,6
    382390        #endif
    383391}
    384392\end{cfa}
    385 At the declaration of @x@, it is implicitly initialized by generated constructor call, whose signature is given by
     393At the declaration of @x@, it is implicitly initialized by generated constructor call, with signature:
    386394\begin{cfa}
    387395forall( otype L, otype R ) void ?{}( cons( L, R ) & );
    388396\end{cfa}
    389 Note that the @otype@ constraint contains 4 assertions:
     397where the @otype@ constraint contains the 4 assertions:\label{otype}
    390398\begin{cfa}
    391399void ?{}( L & ); // default constructor
     
    394402L & ?=?( L &, L & ); // assignment
    395403\end{cfa}
    396 Now since the right hand side of outermost cons is again a cons, recursive assertions are required. When the compiler cannot cache and reuse already resolved assertions, it becomes a problem, as each of those 4 pending assertions again asks for 4 more assertions one level below. Without any caching, number of resolved assertions grows exponentially, while that is obviously unnecessary since there are only $n+1$ different types involved. Even worse, this causes exponentially many wrapper functions generated later at the codegen step, and results in huge compiled binary.
    397 
    398 \begin{table}[h]
     404
     405\begin{table}[htb]
     406\centering
    399407\caption{Compilation results of nested cons test}
     408\label{t:NestedConsTest}
    400409\begin{tabular}{|r|r|r|}
    401410\hline
     
    413422\end{table}
    414423
    415 As the local functions are implemented by emitting executable code on the stack~\cite{gcc-nested-func}, it eventually means that compiled code also has exponential run time. This problem has evident practical implications, as nested collection types are frequently used in real production code.
    416 
     424Now since the right hand side of outermost cons is again a cons, recursive assertions are required. \VRef[Table]{t:NestedConsTest} shows when the compiler does not cache and reuse already resolved assertions, it becomes a problem, as each of these 4 pending assertions again asks for 4 more assertions one level below. Without caching, the number of resolved assertions grows exponentially, which is unnecessary since there are only $n+1$ different types involved. Even worse, this problem causes exponentially many wrapper functions to be generated at the backend, resulting in a huge binary. As the local functions are implemented by emitting executable code on the stack~\cite{gcc-nested-func}, it means that compiled code also has exponential run time. This problem has practical implications, as nested collection types are frequently used in real production code.
    417425
    418426\section{Analysis of type system correctness}
     427\label{s:AnalysisTypeSystemCorrectness}
    419428
    420429In Moss' thesis~\cite[\S~4.1.2,~p.~45]{Moss19}, the author presents the following example:
     
    433442From the set of candidates whose parameter and argument types have been unified and whose assertions have been satisfied, those whose sub-expression interpretations have the smallest total cost of conversion are selected ... The total cost of conversion for each of these candidates is then calculated based on the implicit conversions and polymorphism involved in adapting the types of the sub-expression interpretations to the formal parameter types.
    434443\end{quote}
    435 With this model, the algorithm picks @g1@ in resolving the @f( g( 42 ) )@ call, which seems to be undesirable.
    436 
    437 There are further evidence that shows the Bilson model is fundamentally incorrect, following the discussion of unbound return type in Section~\ref{s:UnboundReturnType}. By the conversion cost specification, a binding from a polymorphic type parameter to a concrete type incurs a polymorphic cost of 1. It remains unspecified \emph{when} the type parameters should become bound. When the parameterized types appear in the function parameters, they can be deduced from the argument type, and there is no ambiguity. In the unbound return case, however, the binding may happen at any stage in expression resolution, therefore it is impossible to define a unique local conversion cost. Note that type binding happens exactly once per parameter in resolving the entire expression, so the global binding cost is unambiguously 1.
    438 
    439 As per the current compiler implementation, it does have a notable inconsistency in handling such case. For any unbound parameter that does \emph{not} come with an associated assertion, it remains unbound to the parent expression; for those that does however, they are immediately bound in the assertion resolution step, and concrete result types are used in the parent expressions.
    440 
     444With this model, the algorithm picks @g1@ in resolving the @f( g( 42 ) )@ call, which is undesirable.
     445
     446There is further evidence that shows the Bilson model is fundamentally incorrect, following the discussion of unbound return type in \VRef{s:UnboundReturnType}. By the conversion-cost specification, a binding from a polymorphic type-parameter to a concrete type incurs a polymorphic cost of 1. It remains unspecified \emph{when} the type parameters should become bound. When the parameterized types appear in function parameters, they can be deduced from the argument type, and there is no ambiguity. In the unbound return case, however, the binding may happen at any stage in expression resolution, therefore it is impossible to define a unique local conversion cost. Note that type binding happens exactly once per parameter in resolving the entire expression, so the global binding cost is unambiguously 1.
     447
     448In the current compiler implementation, there is a notable inconsistency in handling this case. For any unbound parameter that does \emph{not} come with an associated assertion, it remains unbound to the parent expression; for those that do, however, they are immediately bound in the assertion resolution step, and concrete result types are used in the parent expressions.
    441449Consider the following example:
    442450\begin{cfa}
     
    444452void h( int * );
    445453\end{cfa}
    446 The expression @h( f() )@ eventually has a total cost of 1 from binding (T: int), but in the eager resolution model, the cost of 1 may occur either at call to @f@ or at call to @h@, and with the assertion resolution triggering a binding, the local cost of @f()@ is (0 poly, 0 spec) with no assertions, but (1 poly, -1 spec) with an assertion:
    447 \begin{cfa}
    448 forall( dtype T | { void g( T * ); } ) T * f( void );
     454The expression @h( f() )@ eventually has a total cost of 1 from binding (T: int), but in the eager-resolution model, the cost of 1 may occur either at the call to @f@ or at call to @h@, and with the assertion resolution triggering a binding, the local cost of @f()@ is (0 poly, 0 spec) with no assertions, but (1 poly, -1 spec) with an assertion:
     455\begin{cfa}
     456forall( dtype T | @{ void g( T * ); }@ ) T * f( void );
    449457void g( int * );
    450458void h( int * );
    451459\end{cfa}
    452 and that contradicts the principle that adding assertions should make expression cost lower. Furthermore, the time at which type binding and assertion resolution happens is an implementation detail of the compiler, but not a part of language definition. That means two compliant \CFA compilers, one performing immediate assertion resolution at each step, and one delaying assertion resolution on unbound types, can produce different expression costs and therefore different candidate selection, making the language rule itself partially undefined and therefore unsound. By the above reasoning, the updated cost model using global sum of costs should be accepted as the standard. It also allows the compiler to freely choose when to resolve assertions, as the sum of total costs is independent of that choice; more optimizations regarding assertion resolution can also be implemented.
     460and that contradicts the principle that adding assertions should make expression cost lower. Furthermore, the time at which type binding and assertion resolution happens is an implementation detail of the compiler, not part of the language definition. That means two compliant \CFA compilers, one performing immediate assertion resolution at each step, and one delaying assertion resolution on unbound types, can produce different expression costs and therefore different candidate selection, making the language rule itself partially undefined, and therefore, unsound. By the above reasoning, the updated cost model using global sum of costs should be accepted as the standard. It also allows the compiler to freely choose when to resolve assertions, as the sum of total costs is independent of that choice; more optimizations regarding assertion resolution can also be implemented.
    453461
    454462
    455463\section{Timing results}
    456464
    457 For the timing results presented here, the \CFA compiler is built with gcc 9.3.0, and tested on a server machine running Ubuntu 20.04, 64GB RAM and 32-core 2.2 GHz CPU, results reported by the time command, and using only 8 cores in parallel such that the time is close to the case with 100\% CPU utilization on a single thread.
    458 
    459 On the most recent build, the \CFA standard library (~1.3 MB of source code) compiles in 4 minutes 47 seconds total processor time (single thread equivalent), with the slowest file taking 13 seconds. The test suite (178 test cases, ~2.2MB of source code) completes within 25 minutes total processor time,\footnote{Including a few runtime tests; total time spent in compilation is approximately 21 minutes.} with the slowest file taking 23 seconds. In contrast, the library build on old compiler takes 85 minutes total, 5 minutes for the slowest file. Full test suite takes too long with old compiler build and is therefore not run, but the slowest test cases take approximately 5 minutes. Overall, the most recent build compared to old build in April 2020, before the project started, is consistently faster by a factor of 20.
    460 
    461 Additionally, 6 selected \CFA source files with distinct features from library and test suite are used to test compiler performance after each of the optimizations are implemented. Test files are from the most recent build and run through C preprocessor to eliminate the factor of header file changes. The selected tests are:
    462 \begin{itemize}
    463 \item
    464 @lib/fstream@ (112 KB)\footnote{File sizes are after preprocessing, with no line information (\lstinline|gcc -E -P|).}: implementation of I/O library
     465For the timing results presented here, the \CFA compiler is built with gcc 9.3.0, and tested on a server machine running Ubuntu 20.04, 64GB RAM and 32-core 2.2 GHz CPU.
     466Timing is reported by the @time@ command and an experiment is run using 8 cores, where each core is at 100\% CPU utilization.
     467
     468On the most recent build, the \CFA standard library ($\approx$1.3 MB of source code) compiles in 4 minutes 47 seconds total processor time (single thread equivalent), with the slowest file taking 13 seconds. The test suite (178 test cases, $\approx$2.2MB of source code) completes within 25 minutes total processor time,
     469% PAB: I do not understand this footnote.
     470%\footnote{Including a few runtime tests; total time spent in compilation is approximately 21 minutes.}
     471with the slowest file taking 23 seconds. In contrast, the library build with the old compiler takes 85 minutes total, 5 minutes for the slowest file. The full test-suite takes too long with old compiler build and is therefore not run, but the slowest test cases take approximately 5 minutes. Overall, the most recent build compared to an old build is consistently faster by a factor of 20.
     472
     473Additionally, 6 selected \CFA source files with distinct features from the library and test suite are used to illustrate the compiler performance change after each of the implemented optimizations. Test files are from the most recent build and run through the C preprocessor to expand header file, perform macro expansions, but no line number information (@gcc -E -P@).
     474\VRef[Table]{t:SelectedFileByCompilerBuild} shows the selected tests:
     475\begin{itemize}
     476\item
     477@lib/fstream@ (112 KB)
    465478\item
    466479@lib/mutex@ (166 KB): implementation of concurrency primitive
     
    470483@lib/stdlib@ (64 KB): type-safe wrapper to @void *@-based C standard library functions
    471484\item
    472 @test/ISO2@ (55 KB): application of I/O library
     485@test/io2@ (55 KB): application of I/O library
    473486\item
    474487@test/thread@ (188 KB): application of threading library
    475488\end{itemize}
    476 
    477 The \CFA compiler builds are picked from git commit history that passed the test suite, and implement the optimizations incrementally:
    478 \begin{itemize}
    479 \item
    480 \#0 is the first working build of new AST data structure
     489versus \CFA compiler builds picked from the git commit history that implement the optimizations incrementally:
     490\begin{itemize}
     491\item
     492old resolver
     493\item
     494\#0 is the first working build of the new AST data structure
    481495\item
    482496\#1 implements special symbol table and argument-dependent lookup
    483497\item
    484 \#2 implements late assertion satisfaction
    485 \item
    486 \#3 implements revised function type representation
    487 \item
    488 \#4 skips pruning on expressions with function type (most recent build)
    489 \end{itemize}
    490 The old resolver with no memory sharing and none of the optimizations above is also tested.
    491 \begin{table}
     498\#2 implements late assertion-satisfaction
     499\item
     500\#3 implements revised function-type representation
     501\item
     502\#4 skips pruning on expressions for function types (most recent build)
     503\end{itemize}
     504Reading left to right for a test shows the benefit of each optimization on the cost of compilation.
     505
     506\begin{table}[htb]
     507\centering
    492508\caption{Compile time of selected files by compiler build, in seconds}
     509\label{t:SelectedFileByCompilerBuild}
    493510\begin{tabular}{|l|r|r|r|r|r|r|}
    494511\hline
     
    513530\end{table}
    514531
    515 
    516532\section{Conclusion}
    517533
    518 Over the course of 8 months of active research and development in \CFA type system and compiler algorithm, performance of the reference \CFA compiler, cfa-cc, has been greatly improved, allowing mid-sized \CFA programs to be compiled and built reasonably fast. As there are also ongoing efforts in the team on building a standard library, evaluating the runtime performance, and attempting to incorporate \CFA with existing software written in C, this project is especially meaningful for practical purposes.
    519 
    520 Analysis conducted in the project were based significantly on heuristics and practical evidence, as the theoretical bounds and average cases for the expression resolution problem differ. This approach was difficult at start to follow, with an unacceptably slow compiler, since running the program through debugger and validation tools (\eg @gdb@, @valgrind@) adds another order of magnitude to run time, which was already in minutes. However, near the end of the project, many significant improvements have already been made and new optimizations can be tested immediately. The positive feedback in development cycle benefits the \CFA team as a whole, more than just for the compiler optimizations.
    521 
    522 Some potential issues of the language that may happen frequently in practice have been identified. Due to the time constraint and complex nature of these problems, a handful of them remain unsolved, but some constructive proposals are made. Notably, introducing a local assertion cache in the resolver is a common solution for a few remaining problems, so that should be the focus of work soon.
    523 
    524 The \CFA team are planning on a public alpha release of the language as the compiler performance becomes promising, and other parts of the system, such as a standard library, are also being enhanced. Ideally, the remaining problems should be resolved before release, and the solutions will also be integral to drafting a formal specification.
     534Over the course of 8 months of active research and development of the \CFA type system and compiler algorithms, performance of the reference \CFA compiler, cfa-cc, has been greatly improved. Now, mid-sized \CFA programs are compiled reasonably fast. Currently, there are ongoing efforts by the \CFA team to augment the standard library and evaluate its runtime performance, and incorporate \CFA with existing software written in C; therefore this project is especially meaningful for these practical purposes.
     535
     536Accomplishing this work was difficult. Analysis conducted in the project is based significantly on heuristics and practical evidence, as the theoretical bounds and average cases for the expression resolution problem differ. As well, the slowness of the initial compiler made attempts to understand why and where problems exist extremely difficult because both debugging and validation tools (\eg @gdb@, @valgrind@, @pref@) further slowed down compilation time. However, by the end of the project, I had found and fixed several significant problems and new optimizations are easier to introduce and test. The reduction in the development cycle benefits the \CFA team as a whole.
     537
     538Some potential issues of the language, which happen frequently in practice, have been identified. Due to the time constraint and complex nature of these problems, a handful of them remain unsolved, but some constructive proposals are made. Notably, introducing a local assertion cache in the resolver is a reasonable solution for a few remaining problems, so that should be the focus of future work.
     539
     540The \CFA team are planning on a public alpha release of the language as the compiler performance, given my recent improvements, is now useable. Other parts of the system, such as the standard library, have made significant gains due to the speed up in the development cycle. Ideally, the remaining problems should be resolved before release, and the solutions will also be integral to drafting a formal specification.
    525541
    526542\addcontentsline{toc}{section}{\refname}
  • driver/cfa.cc

    r92bfda0 rdafbde8  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov 17 14:27:28 2020
    13 // Update Count     : 440
     12// Last Modified On : Sat Jan 16 07:30:19 2021
     13// Update Count     : 442
    1414//
    1515
     
    499499                args[nargs++] = "-no-integrated-cpp";
    500500                args[nargs++] = "-Wno-deprecated";
     501                args[nargs++] = "-Wno-strict-aliasing";                 // casting from one type to another
    501502                #ifdef HAVE_CAST_FUNCTION_TYPE
    502503                args[nargs++] = "-Wno-cast-function-type";
  • libcfa/prelude/builtins.c

    r92bfda0 rdafbde8  
    1818// type that wraps a pointer and a destructor-like function - used in generating implicit destructor calls for struct members in user-defined functions
    1919// Note: needs to occur early, because it is used to generate destructor calls during code generation
    20 forall(dtype T)
     20forall(T &)
    2121struct __Destructor {
    2222        T * object;
     
    2525
    2626// defined destructor in the case that non-generated code wants to use __Destructor
    27 forall(dtype T)
     27forall(T &)
    2828static inline void ^?{}(__Destructor(T) & x) {
    2929        if (x.object && x.dtor) {
     
    3434// easy interface into __Destructor's destructor for easy codegen purposes
    3535extern "C" {
    36         forall(dtype T)
     36        forall(T &)
    3737        static inline void __destroy_Destructor(__Destructor(T) * dtor) {
    3838                ^(*dtor){};
     
    5151void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
    5252
    53 forall(dtype T)
     53forall(T &)
    5454static inline T & identity(T & i) {
    5555        return i;
     
    6464static inline void ^?{}($generator &) {}
    6565
    66 trait is_generator(dtype T) {
     66trait is_generator(T &) {
    6767      void main(T & this);
    6868      $generator * get_generator(T & this);
    6969};
    7070
    71 forall(dtype T | is_generator(T))
     71forall(T & | is_generator(T))
    7272static inline T & resume(T & gen) {
    7373        main(gen);
     
    7878
    7979static inline {
    80         forall( dtype DT | { DT & ?+=?( DT &, one_t ); } )
     80        forall( DT & | { DT & ?+=?( DT &, one_t ); } )
    8181        DT & ++?( DT & x ) { return x += 1; }
    8282
    83         forall( dtype DT | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?+=?( DT &, one_t ); } )
     83        forall( DT & | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?+=?( DT &, one_t ); } )
    8484        DT & ?++( DT & x ) { DT tmp = x; x += 1; return tmp; }
    8585
    86         forall( dtype DT | { DT & ?-=?( DT &, one_t ); } )
     86        forall( DT & | { DT & ?-=?( DT &, one_t ); } )
    8787        DT & --?( DT & x ) { return x -= 1; }
    8888
    89         forall( dtype DT | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?-=?( DT &, one_t ); } )
     89        forall( DT & | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?-=?( DT &, one_t ); } )
    9090        DT & ?--( DT & x ) { DT tmp = x; x -= 1; return tmp; }
    9191
    92         forall( dtype DT | { int ?!=?( const DT &, zero_t ); } )
     92        forall( DT & | { int ?!=?( const DT &, zero_t ); } )
    9393        int !?( const DT & x ) { return !( x != 0 ); }
    9494} // distribution
    9595
    9696// universal typed pointer constant
    97 static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
     97static inline forall( DT & ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    9898static inline forall( ftype FT ) FT * intptr( uintptr_t addr ) { return (FT *)addr; }
    9999
     
    156156#define __CFA_EXP_OVERFLOW__()
    157157
    158 static inline forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } ) {
     158static inline forall( OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } ) {
    159159        OT ?\?( OT ep, unsigned int y ) { __CFA_EXP__(); }
    160160        OT ?\?( OT ep, unsigned long int y ) { __CFA_EXP__(); }
  • libcfa/prelude/prelude-gen.cc

    r92bfda0 rdafbde8  
    159159int main() {
    160160        cout << "# 2 \"prelude.cfa\"  // needed for error messages from this file" << endl;
    161         cout << "trait sized(dtype T) {};" << endl;
     161        cout << "trait sized(T &) {};" << endl;
    162162
    163163        cout << "//////////////////////////" << endl;
     
    264264                for (auto cvq : qualifiersPair) {
    265265                        for (auto is_vol : { "        ", "volatile" }) {
    266                                 cout << "forall(dtype DT) void  ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
     266                                cout << "forall(DT &) void  ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
    267267                        }
    268268                }
     
    279279        for (auto cvq : qualifiersSingle) {
    280280                for (auto is_vol : { "        ", "volatile" }) {
    281                         cout << "forall(dtype DT) void  ?{}(" << cvq << "  DT" << " * " << is_vol << " &);" << endl;
     281                        cout << "forall(DT &) void  ?{}(" << cvq << "  DT" << " * " << is_vol << " &);" << endl;
    282282                }
    283283                for (auto is_vol : { "        ", "volatile" }) {
    284                         cout << "forall(dtype DT) void ^?{}(" << cvq << "  DT" << " * " << is_vol << " &);" << endl;
     284                        cout << "forall(DT &) void ^?{}(" << cvq << "  DT" << " * " << is_vol << " &);" << endl;
    285285                }
    286286        }
     
    290290                for (auto is_vol : { "        ", "volatile" }) {
    291291                        for (auto cvq : qualifiersSingle) {
    292                                 cout << "forall(dtype DT) void ?{}( " << cvq << type << " * " << is_vol << " &, zero_t);" << endl;
     292                                cout << "forall(DT &) void ?{}( " << cvq << type << " * " << is_vol << " &, zero_t);" << endl;
    293293                        }
    294294                }
     
    317317        for (auto op : pointerOperators) {
    318318                auto forall = [&op]() {
    319                         cout << "forall(dtype DT" << op.sized << ") ";
     319                        cout << "forall(DT &" << op.sized << ") ";
    320320                };
    321321                for (auto type : { "DT"/*, "void"*/ } ) {
     
    408408        for (auto is_vol : { "        ", "volatile" }) {
    409409                for (auto cvq : qualifiersPair) {
    410                                 cout << "forall(dtype DT) " << cvq.first << "void * ?=?( " << cvq.first << "void * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
     410                                cout << "forall(DT &) " << cvq.first << "void * ?=?( " << cvq.first << "void * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
    411411                }
    412412                for (auto cvq : qualifiersSingle) {
    413                         cout << "forall(dtype DT) " << cvq <<   "  DT * ?=?( " << cvq << "  DT * " << is_vol << " &, zero_t);" << endl;
     413                        cout << "forall(DT &) " << cvq <<   "  DT * ?=?( " << cvq << "  DT * " << is_vol << " &, zero_t);" << endl;
    414414                }
    415415        }
  • libcfa/prelude/prelude.old.cf

    r92bfda0 rdafbde8  
    2323// ------------------------------------------------------------
    2424
    25 trait sized(dtype T) {};
     25trait sized(T &) {};
    2626
    2727// ------------------------------------------------------------
     
    6868long double _Complex    ?--( long double _Complex & ),          ?--( volatile long double _Complex & );
    6969
    70 forall( dtype T | sized(T) ) T *                         ?++(                T *& );
    71 forall( dtype T | sized(T) ) const T *           ?++( const          T *& );
    72 forall( dtype T | sized(T) ) volatile T *                ?++(       volatile T *& );
    73 forall( dtype T | sized(T) ) const volatile T *  ?++( const volatile T *& );
    74 forall( dtype T | sized(T) ) T *                         ?--(                T *& );
    75 forall( dtype T | sized(T) ) const T *           ?--( const          T *& );
    76 forall( dtype T | sized(T) ) volatile T *                ?--(       volatile T *& );
    77 forall( dtype T | sized(T) ) const volatile T *  ?--( const volatile T *& );
    78 
    79 forall( dtype T | sized(T) ) T &                 ?[?](                T *,          ptrdiff_t );
    80 forall( dtype T | sized(T) ) const T &   ?[?]( const          T *,          ptrdiff_t );
    81 forall( dtype T | sized(T) ) volatile T &        ?[?](       volatile T *,          ptrdiff_t );
    82 forall( dtype T | sized(T) ) const volatile T & ?[?]( const volatile T *,           ptrdiff_t );
    83 forall( dtype T | sized(T) ) T &                 ?[?](          ptrdiff_t,                T * );
    84 forall( dtype T | sized(T) ) const T &   ?[?](          ptrdiff_t, const          T * );
    85 forall( dtype T | sized(T) ) volatile T &        ?[?](          ptrdiff_t,       volatile T * );
    86 forall( dtype T | sized(T) ) const volatile T & ?[?](           ptrdiff_t, const volatile T * );
     70forall( T & | sized(T) ) T *                     ?++(                T *& );
     71forall( T & | sized(T) ) const T *               ?++( const          T *& );
     72forall( T & | sized(T) ) volatile T *            ?++(       volatile T *& );
     73forall( T & | sized(T) ) const volatile T *      ?++( const volatile T *& );
     74forall( T & | sized(T) ) T *                     ?--(                T *& );
     75forall( T & | sized(T) ) const T *               ?--( const          T *& );
     76forall( T & | sized(T) ) volatile T *            ?--(       volatile T *& );
     77forall( T & | sized(T) ) const volatile T *      ?--( const volatile T *& );
     78
     79forall( T & | sized(T) ) T &             ?[?](                T *,          ptrdiff_t );
     80forall( T & | sized(T) ) const T &       ?[?]( const          T *,          ptrdiff_t );
     81forall( T & | sized(T) ) volatile T &    ?[?](       volatile T *,          ptrdiff_t );
     82forall( T & | sized(T) ) const volatile T & ?[?]( const volatile T *,       ptrdiff_t );
     83forall( T & | sized(T) ) T &             ?[?](          ptrdiff_t,                T * );
     84forall( T & | sized(T) ) const T &       ?[?](          ptrdiff_t, const          T * );
     85forall( T & | sized(T) ) volatile T &    ?[?](          ptrdiff_t,       volatile T * );
     86forall( T & | sized(T) ) const volatile T & ?[?](               ptrdiff_t, const volatile T * );
    8787
    8888// ------------------------------------------------------------
     
    107107long double _Complex    ++?( long double _Complex & ),          --?( long double _Complex & );
    108108
    109 forall( dtype T | sized(T) ) T *                         ++?(                T *& );
    110 forall( dtype T | sized(T) ) const T *           ++?( const          T *& );
    111 forall( dtype T | sized(T) ) volatile T *                ++?(       volatile T *& );
    112 forall( dtype T | sized(T) ) const volatile T *  ++?( const volatile T *& );
    113 forall( dtype T | sized(T) ) T *                         --?(                T *& );
    114 forall( dtype T | sized(T) ) const T *           --?( const          T *& );
    115 forall( dtype T | sized(T) ) volatile T *                --?(       volatile T *& );
    116 forall( dtype T | sized(T) ) const volatile T *  --?( const volatile T *& );
    117 
    118 forall( dtype T | sized(T) ) T &                 *?(                 T * );
    119 forall( dtype T | sized(T) ) const T &           *?( const           T * );
    120 forall( dtype T | sized(T) ) volatile T &        *?(       volatile  T * );
    121 forall( dtype T | sized(T) ) const volatile T & *?( const volatile  T * );
     109forall( T & | sized(T) ) T *                     ++?(                T *& );
     110forall( T & | sized(T) ) const T *               ++?( const          T *& );
     111forall( T & | sized(T) ) volatile T *            ++?(       volatile T *& );
     112forall( T & | sized(T) ) const volatile T *      ++?( const volatile T *& );
     113forall( T & | sized(T) ) T *                     --?(                T *& );
     114forall( T & | sized(T) ) const T *               --?( const          T *& );
     115forall( T & | sized(T) ) volatile T *            --?(       volatile T *& );
     116forall( T & | sized(T) ) const volatile T *      --?( const volatile T *& );
     117
     118forall( T & | sized(T) ) T &             *?(                 T * );
     119forall( T & | sized(T) ) const T &               *?( const           T * );
     120forall( T & | sized(T) ) volatile T &    *?(       volatile  T * );
     121forall( T & | sized(T) ) const volatile T & *?( const volatile  T * );
    122122forall( ftype FT ) FT &          *?( FT * );
    123123
     
    142142                !?( float _Complex ),           !?( double _Complex ),          !?( long double _Complex );
    143143
    144 forall( dtype DT ) int !?(                DT * );
    145 forall( dtype DT ) int !?( const          DT * );
    146 forall( dtype DT ) int !?(       volatile DT * );
    147 forall( dtype DT ) int !?( const volatile DT * );
     144forall( DT & ) int !?(                DT * );
     145forall( DT & ) int !?( const          DT * );
     146forall( DT & ) int !?(       volatile DT * );
     147forall( DT & ) int !?( const volatile DT * );
    148148forall( ftype FT ) int !?( FT * );
    149149
     
    191191long double _Complex    ?+?( long double _Complex, long double _Complex ),      ?-?( long double _Complex, long double _Complex );
    192192
    193 forall( dtype T | sized(T) ) T *                ?+?(                T *,          ptrdiff_t );
    194 forall( dtype T | sized(T) ) T *                ?+?(          ptrdiff_t,                T * );
    195 forall( dtype T | sized(T) ) const T *          ?+?( const          T *,          ptrdiff_t );
    196 forall( dtype T | sized(T) ) const T *          ?+?(          ptrdiff_t, const          T * );
    197 forall( dtype T | sized(T) ) volatile T *       ?+?(       volatile T *,          ptrdiff_t );
    198 forall( dtype T | sized(T) ) volatile T *       ?+?(          ptrdiff_t,       volatile T * );
    199 forall( dtype T | sized(T) ) const volatile T * ?+?( const volatile T *,          ptrdiff_t );
    200 forall( dtype T | sized(T) ) const volatile T * ?+?(          ptrdiff_t, const volatile T * );
    201 forall( dtype T | sized(T) ) T *                ?-?(                T *,          ptrdiff_t );
    202 forall( dtype T | sized(T) ) const T *          ?-?( const          T *,          ptrdiff_t );
    203 forall( dtype T | sized(T) ) volatile T *       ?-?(       volatile T *,          ptrdiff_t );
    204 forall( dtype T | sized(T) ) const volatile T * ?-?( const volatile T *,          ptrdiff_t );
    205 forall( dtype T | sized(T) ) ptrdiff_t          ?-?( const volatile T *, const volatile T * );
     193forall( T & | sized(T) ) T *            ?+?(                T *,          ptrdiff_t );
     194forall( T & | sized(T) ) T *            ?+?(          ptrdiff_t,                T * );
     195forall( T & | sized(T) ) const T *              ?+?( const          T *,          ptrdiff_t );
     196forall( T & | sized(T) ) const T *              ?+?(          ptrdiff_t, const          T * );
     197forall( T & | sized(T) ) volatile T *   ?+?(       volatile T *,          ptrdiff_t );
     198forall( T & | sized(T) ) volatile T *   ?+?(          ptrdiff_t,       volatile T * );
     199forall( T & | sized(T) ) const volatile T *     ?+?( const volatile T *,          ptrdiff_t );
     200forall( T & | sized(T) ) const volatile T *     ?+?(          ptrdiff_t, const volatile T * );
     201forall( T & | sized(T) ) T *            ?-?(                T *,          ptrdiff_t );
     202forall( T & | sized(T) ) const T *              ?-?( const          T *,          ptrdiff_t );
     203forall( T & | sized(T) ) volatile T *   ?-?(       volatile T *,          ptrdiff_t );
     204forall( T & | sized(T) ) const volatile T *     ?-?( const volatile T *,          ptrdiff_t );
     205forall( T & | sized(T) ) ptrdiff_t              ?-?( const volatile T *, const volatile T * );
    206206
    207207// ------------------------------------------------------------
     
    255255           ?>?( long double, long double ),                             ?>=?( long double, long double );
    256256
    257 forall( dtype DT ) signed int ?<?(                 DT *,                DT * );
    258 forall( dtype DT ) signed int ?<?(  const          DT *, const          DT * );
    259 forall( dtype DT ) signed int ?<?(        volatile DT *,       volatile DT * );
    260 forall( dtype DT ) signed int ?<?(  const volatile DT *, const volatile DT * );
    261 
    262 forall( dtype DT ) signed int ?>?(                 DT *,                DT * );
    263 forall( dtype DT ) signed int ?>?(  const          DT *, const          DT * );
    264 forall( dtype DT ) signed int ?>?(        volatile DT *,       volatile DT * );
    265 forall( dtype DT ) signed int ?>?(  const volatile DT *, const volatile DT * );
    266 
    267 forall( dtype DT ) signed int ?<=?(                 DT *,                DT * );
    268 forall( dtype DT ) signed int ?<=?(  const          DT *, const          DT * );
    269 forall( dtype DT ) signed int ?<=?(        volatile DT *,       volatile DT * );
    270 forall( dtype DT ) signed int ?<=?( const volatile DT *, const volatile DT * );
    271 
    272 forall( dtype DT ) signed int ?>=?(                 DT *,                DT * );
    273 forall( dtype DT ) signed int ?>=?(  const          DT *, const          DT * );
    274 forall( dtype DT ) signed int ?>=?(        volatile DT *,       volatile DT * );
    275 forall( dtype DT ) signed int ?>=?( const volatile DT *, const volatile DT * );
     257forall( DT & ) signed int ?<?(                 DT *,                DT * );
     258forall( DT & ) signed int ?<?(  const          DT *, const          DT * );
     259forall( DT & ) signed int ?<?(        volatile DT *,       volatile DT * );
     260forall( DT & ) signed int ?<?(  const volatile DT *, const volatile DT * );
     261
     262forall( DT & ) signed int ?>?(                 DT *,                DT * );
     263forall( DT & ) signed int ?>?(  const          DT *, const          DT * );
     264forall( DT & ) signed int ?>?(        volatile DT *,       volatile DT * );
     265forall( DT & ) signed int ?>?(  const volatile DT *, const volatile DT * );
     266
     267forall( DT & ) signed int ?<=?(                 DT *,                DT * );
     268forall( DT & ) signed int ?<=?(  const          DT *, const          DT * );
     269forall( DT & ) signed int ?<=?(        volatile DT *,       volatile DT * );
     270forall( DT & ) signed int ?<=?( const volatile DT *, const volatile DT * );
     271
     272forall( DT & ) signed int ?>=?(                 DT *,                DT * );
     273forall( DT & ) signed int ?>=?(  const          DT *, const          DT * );
     274forall( DT & ) signed int ?>=?(        volatile DT *,       volatile DT * );
     275forall( DT & ) signed int ?>=?( const volatile DT *, const volatile DT * );
    276276
    277277// ------------------------------------------------------------
     
    302302signed int ?==?( one_t, one_t ),                                                        ?!=?( one_t, one_t );
    303303
    304 forall( dtype DT ) signed int ?==?(                DT *,                DT * );
    305 forall( dtype DT ) signed int ?==?( const          DT *, const          DT * );
    306 forall( dtype DT ) signed int ?==?(       volatile DT *,       volatile DT * );
    307 forall( dtype DT ) signed int ?==?( const volatile DT *, const volatile DT * );
     304forall( DT & ) signed int ?==?(            DT *,                DT * );
     305forall( DT & ) signed int ?==?( const      DT *, const          DT * );
     306forall( DT & ) signed int ?==?(       volatile DT *,       volatile DT * );
     307forall( DT & ) signed int ?==?( const volatile DT *, const volatile DT * );
    308308forall( ftype FT ) signed int ?==?( FT *, FT * );
    309 forall( dtype DT ) signed int ?!=?(                DT *,                DT * );
    310 forall( dtype DT ) signed int ?!=?( const          DT *, const          DT * );
    311 forall( dtype DT ) signed int ?!=?(       volatile DT *,       volatile DT * );
    312 forall( dtype DT ) signed int ?!=?( const volatile DT *, const volatile DT * );
     309forall( DT & ) signed int ?!=?(            DT *,                DT * );
     310forall( DT & ) signed int ?!=?( const      DT *, const          DT * );
     311forall( DT & ) signed int ?!=?(       volatile DT *,       volatile DT * );
     312forall( DT & ) signed int ?!=?( const volatile DT *, const volatile DT * );
    313313forall( ftype FT ) signed int ?!=?( FT *, FT * );
    314314
     
    376376
    377377forall( ftype FT ) FT *                 ?=?( FT *&, FT * );
    378 forall( ftype FT ) FT *                 ?=?( FT * volatile &, FT * );
    379 
    380 forall( dtype DT ) DT *                 ?=?(                 DT *          &,                   DT * );
    381 forall( dtype DT ) DT *                 ?=?(                 DT * volatile &,                   DT * );
    382 forall( dtype DT ) const DT *           ?=?( const           DT *          &,                   DT * );
    383 forall( dtype DT ) const DT *           ?=?( const           DT * volatile &,                   DT * );
    384 forall( dtype DT ) const DT *           ?=?( const           DT *          &, const             DT * );
    385 forall( dtype DT ) const DT *           ?=?( const           DT * volatile &, const             DT * );
    386 forall( dtype DT ) volatile DT *        ?=?(       volatile  DT *          &,                   DT * );
    387 forall( dtype DT ) volatile DT *        ?=?(       volatile  DT * volatile &,                   DT * );
    388 forall( dtype DT ) volatile DT *        ?=?(       volatile  DT *          &,       volatile    DT * );
    389 forall( dtype DT ) volatile DT *        ?=?(       volatile  DT * volatile &,       volatile    DT * );
    390 
    391 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT *          &,                   DT * );
    392 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT * volatile &,                   DT * );
    393 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT *          &, const             DT * );
    394 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT * volatile &, const             DT * );
    395 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT *          &,       volatile    DT * );
    396 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT * volatile &,       volatile    DT * );
    397 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT *          &, const volatile    DT * );
    398 forall( dtype DT ) const volatile DT *  ?=?( const volatile  DT * volatile &, const volatile    DT * );
    399 
    400 forall( dtype DT ) void *                ?=?(                void *          &,                 DT * );
    401 forall( dtype DT ) void *                ?=?(                void * volatile &,                 DT * );
    402 forall( dtype DT ) const void *          ?=?( const          void *          &,                 DT * );
    403 forall( dtype DT ) const void *          ?=?( const          void * volatile &,                 DT * );
    404 forall( dtype DT ) const void *          ?=?( const          void *          &, const           DT * );
    405 forall( dtype DT ) const void *          ?=?( const          void * volatile &, const           DT * );
    406 forall( dtype DT ) volatile void *       ?=?(       volatile void *          &,                 DT * );
    407 forall( dtype DT ) volatile void *       ?=?(       volatile void * volatile &,                 DT * );
    408 forall( dtype DT ) volatile void *       ?=?(       volatile void *          &,       volatile  DT * );
    409 forall( dtype DT ) volatile void *       ?=?(       volatile void * volatile &,       volatile  DT * );
    410 forall( dtype DT ) const volatile void * ?=?( const volatile void *          &,                 DT * );
    411 forall( dtype DT ) const volatile void * ?=?( const volatile void * volatile &,                 DT * );
    412 forall( dtype DT ) const volatile void * ?=?( const volatile void *          &, const           DT * );
    413 forall( dtype DT ) const volatile void * ?=?( const volatile void * volatile &, const           DT * );
    414 forall( dtype DT ) const volatile void * ?=?( const volatile void *          &,       volatile  DT * );
    415 forall( dtype DT ) const volatile void * ?=?( const volatile void * volatile &,       volatile  DT * );
    416 forall( dtype DT ) const volatile void * ?=?( const volatile void *          &, const volatile  DT * );
    417 forall( dtype DT ) const volatile void * ?=?( const volatile void * volatile &, const volatile  DT * );
     378forall( ftyep FT ) FT *                 ?=?( FT * volatile &, FT * );
     379
     380forall( DT & ) DT *                     ?=?(                 DT *          &,                   DT * );
     381forall( DT & ) DT *                     ?=?(                 DT * volatile &,                   DT * );
     382forall( DT & ) const DT *               ?=?( const           DT *          &,                   DT * );
     383forall( DT & ) const DT *               ?=?( const           DT * volatile &,                   DT * );
     384forall( DT & ) const DT *               ?=?( const           DT *          &, const             DT * );
     385forall( DT & ) const DT *               ?=?( const           DT * volatile &, const             DT * );
     386forall( DT & ) volatile DT *    ?=?(       volatile  DT *          &,                   DT * );
     387forall( DT & ) volatile DT *    ?=?(       volatile  DT * volatile &,                   DT * );
     388forall( DT & ) volatile DT *    ?=?(       volatile  DT *          &,       volatile    DT * );
     389forall( DT & ) volatile DT *    ?=?(       volatile  DT * volatile &,       volatile    DT * );
     390
     391forall( DT & ) const volatile DT *      ?=?( const volatile  DT *          &,                   DT * );
     392forall( DT & ) const volatile DT *  ?=?( const volatile  DT * volatile &,                       DT * );
     393forall( DT & ) const volatile DT *  ?=?( const volatile  DT *      &, const             DT * );
     394forall( DT & ) const volatile DT *  ?=?( const volatile  DT * volatile &, const         DT * );
     395forall( DT & ) const volatile DT *  ?=?( const volatile  DT *      &,       volatile    DT * );
     396forall( DT & ) const volatile DT *  ?=?( const volatile  DT * volatile &,           volatile    DT * );
     397forall( DT & ) const volatile DT *  ?=?( const volatile  DT *      &, const volatile    DT * );
     398forall( DT & ) const volatile DT *  ?=?( const volatile  DT * volatile &, const volatile        DT * );
     399
     400forall( DT & ) void *            ?=?(                void *          &,                 DT * );
     401forall( DT & ) void *            ?=?(                void * volatile &,                 DT * );
     402forall( DT & ) const void *              ?=?( const          void *          &,                 DT * );
     403forall( DT & ) const void *              ?=?( const          void * volatile &,                 DT * );
     404forall( DT & ) const void *              ?=?( const          void *          &, const           DT * );
     405forall( DT & ) const void *              ?=?( const          void * volatile &, const           DT * );
     406forall( DT & ) volatile void *   ?=?(       volatile void *          &,                 DT * );
     407forall( DT & ) volatile void *   ?=?(       volatile void * volatile &,                 DT * );
     408forall( DT & ) volatile void *   ?=?(       volatile void *          &,       volatile  DT * );
     409forall( DT & ) volatile void *   ?=?(       volatile void * volatile &,       volatile  DT * );
     410forall( DT & ) const volatile void * ?=?( const volatile void *      &,                 DT * );
     411forall( DT & ) const volatile void * ?=?( const volatile void * volatile &,                     DT * );
     412forall( DT & ) const volatile void * ?=?( const volatile void *      &, const           DT * );
     413forall( DT & ) const volatile void * ?=?( const volatile void * volatile &, const               DT * );
     414forall( DT & ) const volatile void * ?=?( const volatile void *      &,       volatile  DT * );
     415forall( DT & ) const volatile void * ?=?( const volatile void * volatile &,           volatile  DT * );
     416forall( DT & ) const volatile void * ?=?( const volatile void *      &, const volatile  DT * );
     417forall( DT & ) const volatile void * ?=?( const volatile void * volatile &, const volatile      DT * );
    418418
    419419//forall( dtype DT ) DT *                       ?=?(                DT *          &, zero_t );
    420420//forall( dtype DT ) DT *                       ?=?(                DT * volatile &, zero_t );
    421 forall( dtype DT ) const DT *           ?=?( const          DT *          &, zero_t );
    422 forall( dtype DT ) const DT *           ?=?( const          DT * volatile &, zero_t );
     421forall( DT & ) const DT *               ?=?( const          DT *          &, zero_t );
     422forall( DT & ) const DT *               ?=?( const          DT * volatile &, zero_t );
    423423//forall( dtype DT ) volatile DT *      ?=?( volatile       DT *          &, zero_t );
    424424//forall( dtype DT ) volatile DT *      ?=?( volatile       DT * volatile &, zero_t );
    425 forall( dtype DT ) const volatile DT *  ?=?( const volatile DT *          &, zero_t );
    426 forall( dtype DT ) const volatile DT *  ?=?( const volatile DT * volatile &, zero_t );
     425forall( DT & ) const volatile DT *      ?=?( const volatile DT *          &, zero_t );
     426forall( DT & ) const volatile DT *      ?=?( const volatile DT * volatile &, zero_t );
    427427
    428428forall( ftype FT ) FT *                 ?=?( FT *          &, zero_t );
    429429forall( ftype FT ) FT *                 ?=?( FT * volatile &, zero_t );
    430430
    431 forall( dtype T | sized(T) ) T *                ?+=?(                T *          &, ptrdiff_t );
    432 forall( dtype T | sized(T) ) T *                ?+=?(                T * volatile &, ptrdiff_t );
    433 forall( dtype T | sized(T) ) const T *          ?+=?( const          T *          &, ptrdiff_t );
    434 forall( dtype T | sized(T) ) const T *          ?+=?( const          T * volatile &, ptrdiff_t );
    435 forall( dtype T | sized(T) ) volatile T *       ?+=?(       volatile T *          &, ptrdiff_t );
    436 forall( dtype T | sized(T) ) volatile T *       ?+=?(       volatile T * volatile &, ptrdiff_t );
    437 forall( dtype T | sized(T) ) const volatile T * ?+=?( const volatile T *          &, ptrdiff_t );
    438 forall( dtype T | sized(T) ) const volatile T * ?+=?( const volatile T * volatile &, ptrdiff_t );
    439 forall( dtype T | sized(T) ) T *                ?-=?(                T *          &, ptrdiff_t );
    440 forall( dtype T | sized(T) ) T *                ?-=?(                T * volatile &, ptrdiff_t );
    441 forall( dtype T | sized(T) ) const T *          ?-=?( const          T *          &, ptrdiff_t );
    442 forall( dtype T | sized(T) ) const T *          ?-=?( const          T * volatile &, ptrdiff_t );
    443 forall( dtype T | sized(T) ) volatile T *       ?-=?(       volatile T *          &, ptrdiff_t );
    444 forall( dtype T | sized(T) ) volatile T *       ?-=?(       volatile T * volatile &, ptrdiff_t );
    445 forall( dtype T | sized(T) ) const volatile T * ?-=?( const volatile T *          &, ptrdiff_t );
    446 forall( dtype T | sized(T) ) const volatile T * ?-=?( const volatile T * volatile &, ptrdiff_t );
     431forall( T & | sized(T) ) T *            ?+=?(                T *          &, ptrdiff_t );
     432forall( T & | sized(T) ) T *            ?+=?(                T * volatile &, ptrdiff_t );
     433forall( T & | sized(T) ) const T *              ?+=?( const          T *          &, ptrdiff_t );
     434forall( T & | sized(T) ) const T *              ?+=?( const          T * volatile &, ptrdiff_t );
     435forall( T & | sized(T) ) volatile T *   ?+=?(       volatile T *          &, ptrdiff_t );
     436forall( T & | sized(T) ) volatile T *   ?+=?(       volatile T * volatile &, ptrdiff_t );
     437forall( T & | sized(T) ) const volatile T *     ?+=?( const volatile T *          &, ptrdiff_t );
     438forall( T & | sized(T) ) const volatile T *     ?+=?( const volatile T * volatile &, ptrdiff_t );
     439forall( T & | sized(T) ) T *            ?-=?(                T *          &, ptrdiff_t );
     440forall( T & | sized(T) ) T *            ?-=?(                T * volatile &, ptrdiff_t );
     441forall( T & | sized(T) ) const T *              ?-=?( const          T *          &, ptrdiff_t );
     442forall( T & | sized(T) ) const T *              ?-=?( const          T * volatile &, ptrdiff_t );
     443forall( T & | sized(T) ) volatile T *   ?-=?(       volatile T *          &, ptrdiff_t );
     444forall( T & | sized(T) ) volatile T *   ?-=?(       volatile T * volatile &, ptrdiff_t );
     445forall( T & | sized(T) ) const volatile T *     ?-=?( const volatile T *          &, ptrdiff_t );
     446forall( T & | sized(T) ) const volatile T *     ?-=?( const volatile T * volatile &, ptrdiff_t );
    447447
    448448_Bool                   ?=?( _Bool &, _Bool ),                                  ?=?( volatile _Bool &, _Bool );
     
    723723forall( ftype FT ) void ?{}( FT * volatile &, FT * );
    724724
    725 forall( dtype DT ) void ?{}(                 DT *          &,                   DT * );
    726 forall( dtype DT ) void ?{}( const           DT *          &,                   DT * );
    727 forall( dtype DT ) void ?{}( const           DT *          &, const             DT * );
    728 forall( dtype DT ) void ?{}(       volatile  DT *          &,                   DT * );
    729 forall( dtype DT ) void ?{}(       volatile  DT *          &,       volatile    DT * );
    730 forall( dtype DT ) void ?{}( const volatile  DT *          &,                   DT * );
    731 forall( dtype DT ) void ?{}( const volatile  DT *          &, const             DT * );
    732 forall( dtype DT ) void ?{}( const volatile  DT *          &,       volatile    DT * );
    733 forall( dtype DT ) void ?{}( const volatile  DT *          &, const volatile    DT * );
    734 
    735 forall( dtype DT ) void ?{}(                 void *          &,                 DT * );
    736 forall( dtype DT ) void ?{}( const           void *          &,                 DT * );
    737 forall( dtype DT ) void ?{}( const           void *          &, const           DT * );
    738 forall( dtype DT ) void ?{}(        volatile void *          &,                 DT * );
    739 forall( dtype DT ) void ?{}(        volatile void *          &,       volatile  DT * );
    740 forall( dtype DT ) void ?{}( const volatile void *           &,                 DT * );
    741 forall( dtype DT ) void ?{}( const volatile void *           &, const           DT * );
    742 forall( dtype DT ) void ?{}( const volatile void *           &,       volatile  DT * );
    743 forall( dtype DT ) void ?{}( const volatile void *           &, const volatile  DT * );
     725forall( DT & ) void ?{}(                     DT *          &,                   DT * );
     726forall( DT & ) void ?{}( const       DT *          &,                   DT * );
     727forall( DT & ) void ?{}( const       DT *          &, const             DT * );
     728forall( DT & ) void ?{}(           volatile  DT *          &,                   DT * );
     729forall( DT & ) void ?{}(           volatile  DT *          &,       volatile    DT * );
     730forall( DT & ) void ?{}( const volatile  DT *      &,                   DT * );
     731forall( DT & ) void ?{}( const volatile  DT *      &, const             DT * );
     732forall( DT & ) void ?{}( const volatile  DT *      &,       volatile    DT * );
     733forall( DT & ) void ?{}( const volatile  DT *      &, const volatile    DT * );
     734
     735forall( DT & ) void ?{}(                     void *          &,                 DT * );
     736forall( DT & ) void ?{}( const       void *          &,                 DT * );
     737forall( DT & ) void ?{}( const       void *          &, const           DT * );
     738forall( DT & ) void ?{}(            volatile void *          &,                 DT * );
     739forall( DT & ) void ?{}(            volatile void *          &,       volatile  DT * );
     740forall( DT & ) void ?{}( const volatile void *       &,                 DT * );
     741forall( DT & ) void ?{}( const volatile void *       &, const           DT * );
     742forall( DT & ) void ?{}( const volatile void *       &,       volatile  DT * );
     743forall( DT & ) void ?{}( const volatile void *       &, const volatile  DT * );
    744744
    745745//forall( dtype DT ) void ?{}(              DT *          &, zero_t );
    746746//forall( dtype DT ) void ?{}(              DT * volatile &, zero_t );
    747 forall( dtype DT ) void ?{}( const          DT *          &, zero_t );
     747forall( DT & ) void ?{}( const      DT *          &, zero_t );
    748748//forall( dtype DT ) void ?{}( volatile     DT *          &, zero_t );
    749749//forall( dtype DT ) void ?{}( volatile     DT * volatile &, zero_t );
    750 forall( dtype DT ) void ?{}( const volatile DT *          &, zero_t );
     750forall( DT & ) void ?{}( const volatile DT *      &, zero_t );
    751751
    752752forall( ftype FT ) void ?{}( FT *          &, zero_t );
     
    755755forall( ftype FT ) void ?{}( FT *          & );
    756756
    757 forall( dtype DT ) void ?{}(                 DT *          &);
    758 forall( dtype DT ) void ?{}( const           DT *          &);
    759 forall( dtype DT ) void ?{}(       volatile  DT *          &);
    760 forall( dtype DT ) void ?{}( const volatile  DT *          &);
     757forall( DT & ) void     ?{}(                 DT *          &);
     758forall( DT & ) void     ?{}( const           DT *          &);
     759forall( DT & ) void     ?{}(       volatile  DT *          &);
     760forall( DT & ) void ?{}( const volatile  DT *      &);
    761761
    762762void    ?{}(                void *          &);
     
    768768forall( ftype FT ) void ^?{}( FT *         & );
    769769
    770 forall( dtype DT ) void ^?{}(                DT *          &);
    771 forall( dtype DT ) void ^?{}( const          DT *          &);
    772 forall( dtype DT ) void ^?{}(      volatile  DT *          &);
    773 forall( dtype DT ) void ^?{}( const volatile  DT *         &);
     770forall( DT & ) void     ^?{}(                DT *          &);
     771forall( DT & ) void     ^?{}( const          DT *          &);
     772forall( DT & ) void     ^?{}(      volatile  DT *          &);
     773forall( DT & ) void ^?{}( const volatile  DT *     &);
    774774
    775775void ^?{}(                  void *          &);
  • libcfa/prelude/sync-builtins.cf

    r92bfda0 rdafbde8  
    206206_Bool __sync_bool_compare_and_swap(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    207207#endif
    208 forall(dtype T) _Bool __sync_bool_compare_and_swap(T * volatile *, T *, T*, ...);
     208forall(T &) _Bool __sync_bool_compare_and_swap(T * volatile *, T *, T*, ...);
    209209
    210210char __sync_val_compare_and_swap(volatile char *, char, char,...);
     
    223223unsigned __int128 __sync_val_compare_and_swap(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    224224#endif
    225 forall(dtype T) T * __sync_val_compare_and_swap(T * volatile *, T *, T*,...);
     225forall(T &) T * __sync_val_compare_and_swap(T * volatile *, T *, T*,...);
    226226
    227227char __sync_lock_test_and_set(volatile char *, char,...);
     
    326326void __atomic_exchange(volatile unsigned __int128 *, volatile unsigned __int128 *, volatile unsigned __int128 *, int);
    327327#endif
    328 forall(dtype T) T * __atomic_exchange_n(T * volatile *, T *, int);
    329 forall(dtype T) void __atomic_exchange(T * volatile *, T * volatile *, T * volatile *, int);
     328forall(T &) T * __atomic_exchange_n(T * volatile *, T *, int);
     329forall(T &) void __atomic_exchange(T * volatile *, T * volatile *, T * volatile *, int);
    330330
    331331_Bool __atomic_load_n(const volatile _Bool *, int);
     
    359359void __atomic_load(const volatile unsigned __int128 *, volatile unsigned __int128 *, int);
    360360#endif
    361 forall(dtype T) T * __atomic_load_n(T * const volatile *, int);
    362 forall(dtype T) void __atomic_load(T * const volatile *, T **, int);
     361forall(T &) T * __atomic_load_n(T * const volatile *, int);
     362forall(T &) void __atomic_load(T * const volatile *, T **, int);
    363363
    364364_Bool __atomic_compare_exchange_n(volatile char *, char *, char, _Bool, int, int);
     
    390390_Bool __atomic_compare_exchange   (volatile unsigned __int128 *, unsigned __int128 *, unsigned __int128 *, _Bool, int, int);
    391391#endif
    392 forall(dtype T) _Bool __atomic_compare_exchange_n (T * volatile *, T **, T*, _Bool, int, int);
    393 forall(dtype T) _Bool __atomic_compare_exchange   (T * volatile *, T **, T**, _Bool, int, int);
     392forall(T &) _Bool __atomic_compare_exchange_n (T * volatile *, T **, T*, _Bool, int, int);
     393forall(T &) _Bool __atomic_compare_exchange   (T * volatile *, T **, T**, _Bool, int, int);
    394394
    395395void __atomic_store_n(volatile _Bool *, _Bool, int);
     
    423423void __atomic_store(volatile unsigned __int128 *, unsigned __int128 *, int);
    424424#endif
    425 forall(dtype T) void __atomic_store_n(T * volatile *, T *, int);
    426 forall(dtype T) void __atomic_store(T * volatile *, T **, int);
     425forall(T &) void __atomic_store_n(T * volatile *, T *, int);
     426forall(T &) void __atomic_store(T * volatile *, T **, int);
    427427
    428428char __atomic_add_fetch  (volatile char *, char, int);
  • libcfa/src/bitmanip.hfa

    r92bfda0 rdafbde8  
    100100        unsigned long long int floor2( unsigned long long int n, unsigned long long int align ) { verify( is_pow2( align ) ); return n & -align; }
    101101
    102         // forall( otype T | { T ?&?( T, T ); T -?( T ); } )
     102        // forall( T | { T ?&?( T, T ); T -?( T ); } )
    103103        // T floor2( T n, T align ) { verify( is_pow2( align ) ); return n & -align; }
    104104
     
    115115        unsigned long long int ceiling2( unsigned long long int n, unsigned long long int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); }
    116116
    117         // forall( otype T | { T floor2( T, T ); T -?( T ); } )
     117        // forall( T | { T floor2( T, T ); T -?( T ); } )
    118118        // T ceiling2( T n, T align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); }
    119119} // distribution
  • libcfa/src/bits/algorithm.hfa

    r92bfda0 rdafbde8  
    1717
    1818#ifdef SAFE_SORT
    19 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort2( T * arr );
    20 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort3( T * arr );
    21 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort4( T * arr );
    22 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort5( T * arr );
    23 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort6( T * arr );
    24 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sortN( T * arr, size_t dim );
     19forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort2( T * arr );
     20forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort3( T * arr );
     21forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort4( T * arr );
     22forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort5( T * arr );
     23forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sort6( T * arr );
     24forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } ) static inline void __libcfa_small_sortN( T * arr, size_t dim );
    2525
    26 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     26forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    2727static inline void __libcfa_small_sort( T * arr, size_t dim ) {
    2828        switch( dim ) {
     
    4141#define SWAP(x,y) { T a = min(arr[x], arr[y]); T b = max(arr[x], arr[y]); arr[x] = a; arr[y] = b;}
    4242
    43 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     43forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    4444static inline void __libcfa_small_sort2( T * arr ) {
    4545        SWAP(0, 1);
    4646}
    4747
    48 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     48forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    4949static inline void __libcfa_small_sort3( T * arr ) {
    5050        SWAP(1, 2);
     
    5353}
    5454
    55 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     55forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    5656static inline void __libcfa_small_sort4( T * arr ) {
    5757        SWAP(0, 1);
     
    6262}
    6363
    64 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     64forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    6565static inline void __libcfa_small_sort5( T * arr ) {
    6666        SWAP(0, 1);
     
    7575}
    7676
    77 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     77forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    7878static inline void __libcfa_small_sort6( T * arr ) {
    7979        SWAP(1, 2);
     
    9191}
    9292
    93 forall( otype T | {  int ?<?( T, T ); int ?>?( T, T ); } )
     93forall( T | {  int ?<?( T, T ); int ?>?( T, T ); } )
    9494static inline void __libcfa_small_sortN( T * arr, size_t dim ) {
    9595        int i, j;
     
    112112static inline void __libcfa_small_sortN( void* * arr, size_t dim );
    113113
    114 forall( dtype T )
     114forall( T & )
    115115static inline void __libcfa_small_sort( T* * arr, size_t dim ) {
    116116        switch( dim ) {
  • libcfa/src/bits/collection.hfa

    r92bfda0 rdafbde8  
    3131
    3232        // // wrappers to make Collection have T
    33         // forall( dtype T ) {
     33        // forall( T & ) {
    3434        //      T *& Next( T * n ) {
    3535        //              return (T *)Next( (Colable *)n );
     
    3838} // distribution
    3939
    40 forall( dtype T | { T *& Next ( T * ); } ) {
     40forall( T & | { T *& Next ( T * ); } ) {
    4141        bool listed( T * n ) {
    4242                return Next( n ) != 0p;
     
    7676        } // post: elts = null
    7777
    78         forall( dtype T ) {
     78        forall( T & ) {
    7979                T * Curr( ColIter & ci ) with( ci ) {
    8080                        return (T *)curr;
  • libcfa/src/bits/containers.hfa

    r92bfda0 rdafbde8  
    2323
    2424#ifdef __cforall
    25         forall(dtype T)
     25        forall(T &)
    2626#else
    2727        #define T void
     
    4040
    4141#ifdef __cforall
    42         // forall(otype T | sized(T))
     42        // forall(T | sized(T))
    4343        // static inline void ?{}(__small_array(T) & this) {}
    4444
    45         forall(dtype T | sized(T))
     45        forall(T & | sized(T))
    4646        static inline T & ?[?]( __small_array(T) & this, __lock_size_t idx ) {
    4747                return ((typeof(this.data))this.data)[idx];
    4848        }
    4949
    50         forall(dtype T | sized(T))
     50        forall(T & | sized(T))
    5151        static inline T & ?[?]( const __small_array(T) & this, __lock_size_t idx ) {
    5252                return ((typeof(this.data))this.data)[idx];
    5353        }
    5454
    55         forall(dtype T)
     55        forall(T &)
    5656        static inline T * begin( const __small_array(T) & this ) {
    5757                return ((typeof(this.data))this.data);
    5858        }
    5959
    60         forall(dtype T | sized(T))
     60        forall(T & | sized(T))
    6161        static inline T * end( const __small_array(T) & this ) {
    6262                return ((typeof(this.data))this.data) + this.size;
     
    6969
    7070#ifdef __cforall
    71         trait is_node(dtype T) {
     71        trait is_node(T &) {
    7272                T *& get_next( T & );
    7373        };
     
    7878//-----------------------------------------------------------------------------
    7979#ifdef __cforall
    80         forall(dtype TYPE)
     80        forall(TYPE &)
    8181        #define T TYPE
    8282#else
     
    9595
    9696#ifdef __cforall
    97         forall(dtype T)
     97        forall(T &)
    9898        static inline void ?{}( __stack(T) & this ) {
    9999                (this.top){ 0p };
    100100        }
    101101
    102         static inline forall( dtype T | is_node(T) ) {
     102        static inline forall( T & | is_node(T) ) {
    103103                void push( __stack(T) & this, T * val ) {
    104104                        verify( !get_next( *val ) );
     
    126126//-----------------------------------------------------------------------------
    127127#ifdef __cforall
    128         forall(dtype TYPE)
     128        forall(TYPE &)
    129129        #define T TYPE
    130130#else
     
    144144
    145145#ifdef __cforall
    146         static inline forall( dtype T | is_node(T) ) {
     146        static inline forall( T & | is_node(T) ) {
    147147                void ?{}( __queue(T) & this ) with( this ) {
    148148                        (this.head){ 1p };
     
    215215//-----------------------------------------------------------------------------
    216216#ifdef __cforall
    217         forall(dtype TYPE)
     217        forall(TYPE &)
    218218        #define T TYPE
    219219        #define __getter_t * [T * & next, T * & prev] ( T & )
     
    237237
    238238#ifdef __cforall
    239         forall(dtype T )
     239        forall(T & )
    240240        static inline [void] ?{}( __dllist(T) & this, * [T * & next, T * & prev] ( T & ) __get ) {
    241241                (this.head){ 0p };
     
    245245        #define next 0
    246246        #define prev 1
    247         static inline forall(dtype T) {
     247        static inline forall(T &) {
    248248                void push_front( __dllist(T) & this, T & node ) with( this ) {
    249249                        verify(__get);
  • libcfa/src/bits/queue.hfa

    r92bfda0 rdafbde8  
    99// instead of being null.
    1010
    11 forall( dtype T | { T *& Next ( T * ); } ) {
     11forall( T & | { T *& Next ( T * ); } ) {
    1212        struct Queue {
    1313                inline Collection;                                                              // Plan 9 inheritance
     
    151151} // distribution
    152152
    153 forall( dtype T | { T *& Next ( T * ); } ) {
     153forall( T & | { T *& Next ( T * ); } ) {
    154154        struct QueueIter {
    155155                inline ColIter;                                                                 // Plan 9 inheritance
  • libcfa/src/bits/sequence.hfa

    r92bfda0 rdafbde8  
    2929
    3030        // // wrappers to make Collection have T
    31         // forall( dtype T ) {
     31        // forall( T & ) {
    3232        //      T *& Back( T * n ) {
    3333        //              return (T *)Back( (Seqable *)n );
     
    4343// and the back field of the last node points at the first node (circular).
    4444
    45 forall( dtype T | { T *& Back ( T * ); T *& Next ( T * ); } ) {
     45forall( T & | { T *& Back ( T * ); T *& Next ( T * ); } ) {
    4646        struct Sequence {
    4747                inline Collection;                                                              // Plan 9 inheritance
     
    231231} // distribution
    232232
    233 forall( dtype T | { T *& Back ( T * ); T *& Next ( T * ); } ) {
     233forall( T & | { T *& Back ( T * ); T *& Next ( T * ); } ) {
    234234        // SeqIter(T) is used to iterate over a Sequence(T) in head-to-tail order.
    235235        struct SeqIter {
  • libcfa/src/bits/stack.hfa

    r92bfda0 rdafbde8  
    99// instead of being null.
    1010
    11 forall( dtype T | { T *& Next ( T * ); } ) {
     11forall( T & | { T *& Next ( T * ); } ) {
    1212        struct Stack {
    1313                inline Collection;                                                              // Plan 9 inheritance
     
    6767// order returned by drop().
    6868
    69 forall( dtype T | { T *& Next ( T * ); } ) {
     69forall( T & | { T *& Next ( T * ); } ) {
    7070        struct StackIter {
    7171                inline ColIter;                                                                 // Plan 9 inheritance
  • libcfa/src/common.cfa

    r92bfda0 rdafbde8  
    2323[ long int, long int ] div( long int num, long int denom ) { ldiv_t qr = ldiv( num, denom ); return [ qr.quot, qr.rem ]; }
    2424[ long long int, long long int ] div( long long int num, long long int denom ) { lldiv_t qr = lldiv( num, denom ); return [ qr.quot, qr.rem ]; }
    25 forall( otype T | { T ?/?( T, T ); T ?%?( T, T ); } )
     25forall( T | { T ?/?( T, T ); T ?%?( T, T ); } )
    2626[ T, T ] div( T num, T denom ) { return [ num / denom, num % denom ]; }
    2727
  • libcfa/src/common.hfa

    r92bfda0 rdafbde8  
    2121[ long int, long int ] div( long int num, long int denom );
    2222[ long long int, long long int ] div( long long int num, long long int denom );
    23 forall( otype T | { T ?/?( T, T ); T ?%?( T, T ); } )
     23forall( T | { T ?/?( T, T ); T ?%?( T, T ); } )
    2424[ T, T ] div( T num, T demon );
    2525
     
    6161} // distribution
    6262
    63 forall( otype T | { void ?{}( T &, zero_t ); int ?<?( T, T ); T -?( T ); } )
     63forall( T | { void ?{}( T &, zero_t ); int ?<?( T, T ); T -?( T ); } )
    6464T abs( T );
    6565
     
    7070        intptr_t min( intptr_t t1, intptr_t t2 ) { return t1 < t2 ? t1 : t2; } // optimization
    7171        uintptr_t min( uintptr_t t1, uintptr_t t2 ) { return t1 < t2 ? t1 : t2; } // optimization
    72         forall( otype T | { int ?<?( T, T ); } )
     72        forall( T | { int ?<?( T, T ); } )
    7373        T min( T t1, T t2 ) { return t1 < t2 ? t1 : t2; }
    7474
     
    7676        intptr_t max( intptr_t t1, intptr_t t2 ) { return t1 > t2 ? t1 : t2; } // optimization
    7777        uintptr_t max( uintptr_t t1, uintptr_t t2 ) { return t1 > t2 ? t1 : t2; } // optimization
    78         forall( otype T | { int ?>?( T, T ); } )
     78        forall( T | { int ?>?( T, T ); } )
    7979        T max( T t1, T t2 ) { return t1 > t2 ? t1 : t2; }
    8080
    81         forall( otype T | { T min( T, T ); T max( T, T ); } )
     81        forall( T | { T min( T, T ); T max( T, T ); } )
    8282        T clamp( T value, T min_val, T max_val ) { return max( min_val, min( value, max_val ) ); }
    8383
    84         forall( otype T )
     84        forall( T )
    8585        void swap( T & v1, T & v2 ) { T temp = v1; v1 = v2; v2 = temp; }
    8686} // distribution
  • libcfa/src/concurrency/coroutine.cfa

    r92bfda0 rdafbde8  
    4646
    4747//-----------------------------------------------------------------------------
    48 FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
    49 
    50 forall(dtype T)
     48FORALL_DATA_INSTANCE(CoroutineCancelled, (coroutine_t &), (coroutine_t))
     49
     50forall(T &)
    5151void mark_exception(CoroutineCancelled(T) *) {}
    5252
    53 forall(dtype T)
     53forall(T &)
    5454void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
    5555        dst->virtual_table = src->virtual_table;
     
    5858}
    5959
    60 forall(dtype T)
     60forall(T &)
    6161const char * msg(CoroutineCancelled(T) *) {
    6262        return "CoroutineCancelled(...)";
     
    6464
    6565// This code should not be inlined. It is the error path on resume.
    66 forall(dtype T | is_coroutine(T))
     66forall(T & | is_coroutine(T))
    6767void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) {
    6868        verify( desc->cancellation );
     
    148148// Part of the Public API
    149149// Not inline since only ever called once per coroutine
    150 forall(dtype T | is_coroutine(T))
     150forall(T & | is_coroutine(T))
    151151void prime(T& cor) {
    152152        $coroutine* this = get_coroutine(cor);
  • libcfa/src/concurrency/coroutine.hfa

    r92bfda0 rdafbde8  
    2222//-----------------------------------------------------------------------------
    2323// Exception thrown from resume when a coroutine stack is cancelled.
    24 FORALL_DATA_EXCEPTION(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) (
     24FORALL_DATA_EXCEPTION(CoroutineCancelled, (coroutine_t &), (coroutine_t)) (
    2525        coroutine_t * the_coroutine;
    2626        exception_t * the_exception;
    2727);
    2828
    29 forall(dtype T)
     29forall(T &)
    3030void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
    3131
    32 forall(dtype T)
     32forall(T &)
    3333const char * msg(CoroutineCancelled(T) *);
    3434
     
    3737// Anything that implements this trait can be resumed.
    3838// Anything that is resumed is a coroutine.
    39 trait is_coroutine(dtype T | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
     39trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
    4040        void main(T & this);
    4141        $coroutine * get_coroutine(T & this);
     
    6060//-----------------------------------------------------------------------------
    6161// Public coroutine API
    62 forall(dtype T | is_coroutine(T))
     62forall(T & | is_coroutine(T))
    6363void prime(T & cor);
    6464
     
    7272        void __cfactx_invoke_coroutine(void (*main)(void *), void * this);
    7373
    74         forall(dtype T)
     74        forall(T &)
    7575        void __cfactx_start(void (*main)(T &), struct $coroutine * cor, T & this, void (*invoke)(void (*main)(void *), void *));
    7676
     
    129129}
    130130
    131 forall(dtype T | is_coroutine(T))
     131forall(T & | is_coroutine(T))
    132132void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc );
    133133
    134134// Resume implementation inlined for performance
    135 forall(dtype T | is_coroutine(T))
     135forall(T & | is_coroutine(T))
    136136static inline T & resume(T & cor) {
    137137        // optimization : read TLS once and reuse it
  • libcfa/src/concurrency/future.hfa

    r92bfda0 rdafbde8  
    1919#include "monitor.hfa"
    2020
    21 forall( otype T ) {
     21forall( T ) {
    2222        struct future {
    2323                inline future_t;
     
    5858}
    5959
    60 forall( otype T ) {
     60forall( T ) {
    6161        monitor multi_future {
    6262                inline future_t;
  • libcfa/src/concurrency/io/setup.cfa

    r92bfda0 rdafbde8  
    113113
    114114        static struct {
    115                 pthread_t       thrd;    // pthread handle to io poller thread
    116                 void *          stack;   // pthread stack for io poller thread
    117                 int             epollfd; // file descriptor to the epoll instance
    118                 volatile bool   run;     // Whether or not to continue
    119                 volatile size_t epoch;   // Epoch used for memory reclamation
     115                      pthread_t  thrd;    // pthread handle to io poller thread
     116                      void *     stack;   // pthread stack for io poller thread
     117                      int        epollfd; // file descriptor to the epoll instance
     118                volatile     bool run;     // Whether or not to continue
     119                volatile     bool stopped; // Whether the poller has finished running
     120                volatile uint64_t epoch;   // Epoch used for memory reclamation
    120121        } iopoll;
    121122
     
    130131                __cfadbg_print_safe(io_core, "Kernel : Starting io poller thread\n" );
    131132
    132                 iopoll.run = true;
    133                 iopoll.stack = __create_pthread( &iopoll.thrd, iopoll_loop, 0p );
    134                 iopoll.epoch = 0;
     133                iopoll.stack   = __create_pthread( &iopoll.thrd, iopoll_loop, 0p );
     134                iopoll.run     = true;
     135                iopoll.stopped = false;
     136                iopoll.epoch   = 0;
    135137        }
    136138
     
    205207                        }
    206208                }
     209
     210                __atomic_store_n(&iopoll.stopped, true, __ATOMIC_SEQ_CST);
    207211
    208212                __cfadbg_print_safe(io_core, "Kernel : IO poller thread stopping\n" );
     
    536540
    537541                // Wait for the next epoch
    538                 while(curr == __atomic_load_n(&iopoll.epoch, __ATOMIC_RELAXED)) yield();
     542                while(curr == iopoll.epoch && !iopoll.stopped) Pause();
    539543        }
    540544
  • libcfa/src/concurrency/locks.cfa

    r92bfda0 rdafbde8  
    77//-----------------------------------------------------------------------------
    88// info_thread
    9 forall(dtype L | is_blocking_lock(L)) {
     9forall(L & | is_blocking_lock(L)) {
    1010        struct info_thread {
    1111                // used to put info_thread on a dl queue (aka sequence)
     
    195195//-----------------------------------------------------------------------------
    196196// alarm node wrapper
    197 forall(dtype L | is_blocking_lock(L)) {
     197forall(L & | is_blocking_lock(L)) {
    198198        struct alarm_node_wrap {
    199199                alarm_node_t alarm_node;
     
    239239//-----------------------------------------------------------------------------
    240240// condition variable
    241 forall(dtype L | is_blocking_lock(L)) {
     241forall(L & | is_blocking_lock(L)) {
    242242
    243243        void ?{}( condition_variable(L) & this ){
  • libcfa/src/concurrency/locks.hfa

    r92bfda0 rdafbde8  
    1313//-----------------------------------------------------------------------------
    1414// is_blocking_lock
    15 trait is_blocking_lock(dtype L | sized(L)) {
     15trait is_blocking_lock(L & | sized(L)) {
    1616        // For synchronization locks to use when acquiring
    1717        void on_notify( L &, struct $thread * );
     
    3131// the info thread is a wrapper around a thread used
    3232// to store extra data for use in the condition variable
    33 forall(dtype L | is_blocking_lock(L)) {
     33forall(L & | is_blocking_lock(L)) {
    3434        struct info_thread;
    3535
     
    120120//-----------------------------------------------------------------------------
    121121// Synchronization Locks
    122 forall(dtype L | is_blocking_lock(L)) {
     122forall(L & | is_blocking_lock(L)) {
    123123        struct condition_variable {
    124124                // Spin lock used for mutual exclusion
  • libcfa/src/concurrency/monitor.cfa

    r92bfda0 rdafbde8  
    5050static inline [$thread *, int] search_entry_queue( const __waitfor_mask_t &, $monitor * monitors [], __lock_size_t count );
    5151
    52 forall(dtype T | sized( T ))
     52forall(T & | sized( T ))
    5353static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val );
    5454static inline __lock_size_t count_max    ( const __waitfor_mask_t & mask );
     
    949949}
    950950
    951 forall(dtype T | sized( T ))
     951forall(T & | sized( T ))
    952952static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val ) {
    953953        if( !val ) return size;
  • libcfa/src/concurrency/monitor.hfa

    r92bfda0 rdafbde8  
    2222#include "stdlib.hfa"
    2323
    24 trait is_monitor(dtype T) {
     24trait is_monitor(T &) {
    2525        $monitor * get_monitor( T & );
    2626        void ^?{}( T & mutex );
     
    5959void ^?{}( monitor_dtor_guard_t & this );
    6060
    61 static inline forall( dtype T | sized(T) | { void ^?{}( T & mutex ); } )
     61static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } )
    6262void delete( T * th ) {
    6363        ^(*th){};
  • libcfa/src/concurrency/mutex.cfa

    r92bfda0 rdafbde8  
    164164}
    165165
    166 forall(dtype L | is_lock(L))
     166forall(L & | is_lock(L))
    167167void wait(condition_variable & this, L & l) {
    168168        lock( this.lock __cfaabi_dbg_ctx2 );
     
    176176//-----------------------------------------------------------------------------
    177177// Scopes
    178 forall(dtype L | is_lock(L))
     178forall(L & | is_lock(L))
    179179void lock_all  ( L * locks[], size_t count) {
    180180        // Sort locks based on addresses
     
    188188}
    189189
    190 forall(dtype L | is_lock(L))
     190forall(L & | is_lock(L))
    191191void unlock_all( L * locks[], size_t count) {
    192192        // Lock all
  • libcfa/src/concurrency/mutex.hfa

    r92bfda0 rdafbde8  
    7070void unlock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
    7171
    72 trait is_lock(dtype L | sized(L)) {
     72trait is_lock(L & | sized(L)) {
    7373        void lock  (L &);
    7474        void unlock(L &);
     
    9494void wait(condition_variable & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
    9595
    96 forall(dtype L | is_lock(L))
     96forall(L & | is_lock(L))
    9797void wait(condition_variable & this, L & l) __attribute__((deprecated("use concurrency/locks.hfa instead")));
    9898
    9999//-----------------------------------------------------------------------------
    100100// Scopes
    101 forall(dtype L | is_lock(L)) {
     101forall(L & | is_lock(L)) {
    102102        #if !defined( __TUPLE_ARRAYS_EXIST__ )
    103103        void lock  ( L * locks [], size_t count);
  • libcfa/src/concurrency/thread.cfa

    r92bfda0 rdafbde8  
    6262}
    6363
    64 FORALL_DATA_INSTANCE(ThreadCancelled, (dtype thread_t), (thread_t))
     64FORALL_DATA_INSTANCE(ThreadCancelled, (thread_t &), (thread_t))
    6565
    66 forall(dtype T)
     66forall(T &)
    6767void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src) {
    6868        dst->virtual_table = src->virtual_table;
     
    7171}
    7272
    73 forall(dtype T)
     73forall(T &)
    7474const char * msg(ThreadCancelled(T) *) {
    7575        return "ThreadCancelled";
    7676}
    7777
    78 forall(dtype T)
     78forall(T &)
    7979static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
    8080        abort( "Unhandled thread cancellation.\n" );
    8181}
    8282
    83 forall(dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
     83forall(T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
    8484void ?{}( thread_dtor_guard_t & this,
    85                 T & thrd, void(*defaultResumptionHandler)(ThreadCancelled(T) &)) {
    86         $monitor * m = get_monitor(thrd);
     85                T & thrd, void(*cancelHandler)(ThreadCancelled(T) &)) {
     86        $monitor * m = get_monitor(thrd);
    8787        $thread * desc = get_thread(thrd);
    8888
    8989        // Setup the monitor guard
    9090        void (*dtor)(T& mutex this) = ^?{};
    91         bool join = defaultResumptionHandler != (void(*)(ThreadCancelled(T)&))0;
     91        bool join = cancelHandler != (void(*)(ThreadCancelled(T)&))0;
    9292        (this.mg){&m, (void(*)())dtor, join};
    9393
     
    103103        }
    104104        desc->state = Cancelled;
    105         if (!join) {
    106                 defaultResumptionHandler = default_thread_cancel_handler;
    107         }
     105        void(*defaultResumptionHandler)(ThreadCancelled(T) &) =
     106                join ? cancelHandler : default_thread_cancel_handler;
    108107
    109108        ThreadCancelled(T) except;
     
    125124//-----------------------------------------------------------------------------
    126125// Starting and stopping threads
    127 forall( dtype T | is_thread(T) )
     126forall( T & | is_thread(T) )
    128127void __thrd_start( T & this, void (*main_p)(T &) ) {
    129128        $thread * this_thrd = get_thread(this);
     
    141140//-----------------------------------------------------------------------------
    142141// Support for threads that don't ues the thread keyword
    143 forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T&); } )
     142forall( T & | sized(T) | is_thread(T) | { void ?{}(T&); } )
    144143void ?{}( scoped(T)& this ) with( this ) {
    145144        handle{};
     
    147146}
    148147
    149 forall( dtype T, ttype P | sized(T) | is_thread(T) | { void ?{}(T&, P); } )
     148forall( T &, P... | sized(T) | is_thread(T) | { void ?{}(T&, P); } )
    150149void ?{}( scoped(T)& this, P params ) with( this ) {
    151150        handle{ params };
     
    153152}
    154153
    155 forall( dtype T | sized(T) | is_thread(T) )
     154forall( T & | sized(T) | is_thread(T) )
    156155void ^?{}( scoped(T)& this ) with( this ) {
    157156        ^handle{};
     
    159158
    160159//-----------------------------------------------------------------------------
    161 forall(dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
     160forall(T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
    162161T & join( T & this ) {
    163162        thread_dtor_guard_t guard = { this, defaultResumptionHandler };
  • libcfa/src/concurrency/thread.hfa

    r92bfda0 rdafbde8  
    2626//-----------------------------------------------------------------------------
    2727// thread trait
    28 trait is_thread(dtype T) {
     28trait is_thread(T &) {
    2929        void ^?{}(T& mutex this);
    3030        void main(T& this);
     
    3232};
    3333
    34 FORALL_DATA_EXCEPTION(ThreadCancelled, (dtype thread_t), (thread_t)) (
     34FORALL_DATA_EXCEPTION(ThreadCancelled, (thread_t &), (thread_t)) (
    3535        thread_t * the_thread;
    3636        exception_t * the_exception;
    3737);
    3838
    39 forall(dtype T)
     39forall(T &)
    4040void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src);
    4141
    42 forall(dtype T)
     42forall(T &)
    4343const char * msg(ThreadCancelled(T) *);
    4444
     
    4747
    4848// Inline getters for threads/coroutines/monitors
    49 forall( dtype T | is_thread(T) )
     49forall( T & | is_thread(T) )
    5050static inline $coroutine* get_coroutine(T & this) __attribute__((const)) { return &get_thread(this)->self_cor; }
    5151
    52 forall( dtype T | is_thread(T) )
     52forall( T & | is_thread(T) )
    5353static inline $monitor  * get_monitor  (T & this) __attribute__((const)) { return &get_thread(this)->self_mon; }
    5454
     
    6060extern struct cluster * mainCluster;
    6161
    62 forall( dtype T | is_thread(T) )
     62forall( T & | is_thread(T) )
    6363void __thrd_start( T & this, void (*)(T &) );
    6464
     
    8282};
    8383
    84 forall( dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
     84forall( T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
    8585void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
    8686void ^?{}( thread_dtor_guard_t & this );
     
    8989// thread runner
    9090// Structure that actually start and stop threads
    91 forall( dtype T | sized(T) | is_thread(T) )
     91forall( T & | sized(T) | is_thread(T) )
    9292struct scoped {
    9393        T handle;
    9494};
    9595
    96 forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T&); } )
     96forall( T & | sized(T) | is_thread(T) | { void ?{}(T&); } )
    9797void ?{}( scoped(T)& this );
    9898
    99 forall( dtype T, ttype P | sized(T) | is_thread(T) | { void ?{}(T&, P); } )
     99forall( T &, P... | sized(T) | is_thread(T) | { void ?{}(T&, P); } )
    100100void ?{}( scoped(T)& this, P params );
    101101
    102 forall( dtype T | sized(T) | is_thread(T) )
     102forall( T & | sized(T) | is_thread(T) )
    103103void ^?{}( scoped(T)& this );
    104104
     
    115115void unpark( $thread * this );
    116116
    117 forall( dtype T | is_thread(T) )
     117forall( T & | is_thread(T) )
    118118static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );}
    119119
     
    128128//----------
    129129// join
    130 forall( dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
     130forall( T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
    131131T & join( T & this );
    132132
  • libcfa/src/containers/list.hfa

    r92bfda0 rdafbde8  
    6666#define __DLISTED_MGD_JUSTIMPL(STRUCT)
    6767
    68 forall( dtype tE ) {
     68forall( tE & ) {
    6969        struct $mgd_link {
    7070                tE *elem;
     
    8383                (this.is_terminator){ 1 };
    8484        }
    85         forall ( otype tInit | { void ?{}( $mgd_link(tE) &, tInit); } )
     85        forall ( tInit | { void ?{}( $mgd_link(tE) &, tInit); } )
    8686        static inline void ?=?( $mgd_link(tE) &this, tInit i ) {
    8787                ^?{}( this );
     
    115115  __DLISTED_MGD_COMMON(STRUCT, STRUCT, $links)
    116116
    117 trait $dlistable(dtype Tnode, dtype Telem) {
     117trait $dlistable(Tnode &, Telem &) {
    118118        $mgd_link(Telem) & $prev_link(Tnode &);
    119119        $mgd_link(Telem) & $next_link(Tnode &);
     
    125125};
    126126
    127 forall (dtype Tnode, dtype Telem | $dlistable(Tnode, Telem)) {
     127forall (Tnode &, Telem & | $dlistable(Tnode, Telem)) {
    128128
    129129        // implemented as a sentinel item in an underlying cicrular list
  • libcfa/src/containers/maybe.cfa

    r92bfda0 rdafbde8  
    1818
    1919
    20 forall(otype T)
     20forall(T)
    2121void ?{}(maybe(T) & this) {
    2222        this.has_value = false;
    2323}
    2424
    25 forall(otype T)
     25forall(T)
    2626void ?{}(maybe(T) & this, T value) {
    2727        this.has_value = true;
     
    2929}
    3030
    31 forall(otype T)
     31forall(T)
    3232void ?{}(maybe(T) & this, maybe(T) other) {
    3333        this.has_value = other.has_value;
     
    3737}
    3838
    39 forall(otype T)
     39forall(T)
    4040maybe(T) ?=?(maybe(T) & this, maybe(T) that) {
    4141        if (this.has_value && that.has_value) {
     
    5151}
    5252
    53 forall(otype T)
     53forall(T)
    5454void ^?{}(maybe(T) & this) {
    5555        if (this.has_value) {
     
    5858}
    5959
    60 forall(otype T)
     60forall(T)
    6161bool ?!=?(maybe(T) this, zero_t) {
    6262        return this.has_value;
    6363}
    6464
    65 forall(otype T)
     65forall(T)
    6666maybe(T) maybe_value(T value) {
    6767        return (maybe(T)){value};
    6868}
    6969
    70 forall(otype T)
     70forall(T)
    7171maybe(T) maybe_none() {
    7272        return (maybe(T)){};
    7373}
    7474
    75 forall(otype T)
     75forall(T)
    7676bool has_value(maybe(T) * this) {
    7777        return this->has_value;
    7878}
    7979
    80 forall(otype T)
     80forall(T)
    8181T get(maybe(T) * this) {
    8282        assertf(this->has_value, "attempt to get from maybe without value");
     
    8484}
    8585
    86 forall(otype T)
     86forall(T)
    8787void set(maybe(T) * this, T value) {
    8888        if (this->has_value) {
     
    9494}
    9595
    96 forall(otype T)
     96forall(T)
    9797void set_none(maybe(T) * this) {
    9898        if (this->has_value) {
  • libcfa/src/containers/maybe.hfa

    r92bfda0 rdafbde8  
    1919
    2020// DO NOT USE DIRECTLY!
    21 forall(otype T)
     21forall(T)
    2222struct maybe {
    2323    bool has_value;
     
    2626
    2727
    28 forall(otype T)
     28forall(T)
    2929void ?{}(maybe(T) & this);
    3030
    31 forall(otype T)
     31forall(T)
    3232void ?{}(maybe(T) & this, T value);
    3333
    34 forall(otype T)
     34forall(T)
    3535void ?{}(maybe(T) & this, maybe(T) other);
    3636
    37 forall(otype T)
     37forall(T)
    3838void ^?{}(maybe(T) & this);
    3939
    40 forall(otype T)
     40forall(T)
    4141maybe(T) ?=?(maybe(T) & this, maybe(T) other);
    4242
    43 forall(otype T)
     43forall(T)
    4444bool ?!=?(maybe(T) this, zero_t);
    4545
    4646/* Waiting for bug#11 to be fixed.
    47 forall(otype T)
     47forall(T)
    4848maybe(T) maybe_value(T value);
    4949
    50 forall(otype T)
     50forall(T)
    5151maybe(T) maybe_none();
    5252*/
    5353
    54 forall(otype T)
     54forall(T)
    5555bool has_value(maybe(T) * this);
    5656
    57 forall(otype T)
     57forall(T)
    5858T get(maybe(T) * this);
    5959
    60 forall(otype T)
     60forall(T)
    6161void set(maybe(T) * this, T value);
    6262
    63 forall(otype T)
     63forall(T)
    6464void set_none(maybe(T) * this);
    6565
  • libcfa/src/containers/pair.cfa

    r92bfda0 rdafbde8  
    1313#include <containers/pair.hfa>
    1414
    15 forall(otype R, otype S
     15forall(R, S
    1616        | { int ?==?(R, R); int ?<?(R, R); int ?<?(S, S); })
    1717int ?<?(pair(R, S) p, pair(R, S) q) {
     
    1919}
    2020
    21 forall(otype R, otype S
     21forall(R, S
    2222        | { int ?==?(R, R); int ?<?(R, R); int ?<=?(S, S); })
    2323int ?<=?(pair(R, S) p, pair(R, S) q) {
     
    2525}
    2626
    27 forall(otype R, otype S | { int ?==?(R, R); int ?==?(S, S); })
     27forall(R, S | { int ?==?(R, R); int ?==?(S, S); })
    2828int ?==?(pair(R, S) p, pair(R, S) q) {
    2929        return p.first == q.first && p.second == q.second;
    3030}
    3131
    32 forall(otype R, otype S | { int ?!=?(R, R); int ?!=?(S, S); })
     32forall(R, S | { int ?!=?(R, R); int ?!=?(S, S); })
    3333int ?!=?(pair(R, S) p, pair(R, S) q) {
    3434        return p.first != q.first || p.second != q.second;
    3535}
    3636
    37 forall(otype R, otype S
     37forall(R, S
    3838        | { int ?==?(R, R); int ?>?(R, R); int ?>?(S, S); })
    3939int ?>?(pair(R, S) p, pair(R, S) q) {
     
    4141}
    4242
    43 forall(otype R, otype S
     43forall(R, S
    4444        | { int ?==?(R, R); int ?>?(R, R); int ?>=?(S, S); })
    4545int ?>=?(pair(R, S) p, pair(R, S) q) {
  • libcfa/src/containers/pair.hfa

    r92bfda0 rdafbde8  
    1616#pragma once
    1717
    18 forall(otype R, otype S) struct pair {
     18forall(R, S) struct pair {
    1919        R first;
    2020        S second;
    2121};
    2222
    23 forall(otype R, otype S
     23forall(R, S
    2424        | { int ?==?(R, R); int ?<?(R, R); int ?<?(S, S); })
    2525int ?<?(pair(R, S) p, pair(R, S) q);
    2626
    27 forall(otype R, otype S
     27forall(R, S
    2828        | { int ?==?(R, R); int ?<?(R, R); int ?<=?(S, S); })
    2929int ?<=?(pair(R, S) p, pair(R, S) q);
    3030
    31 forall(otype R, otype S | { int ?==?(R, R); int ?==?(S, S); })
     31forall(R, S | { int ?==?(R, R); int ?==?(S, S); })
    3232int ?==?(pair(R, S) p, pair(R, S) q);
    3333
    34 forall(otype R, otype S | { int ?!=?(R, R); int ?!=?(S, S); })
     34forall(R, S | { int ?!=?(R, R); int ?!=?(S, S); })
    3535int ?!=?(pair(R, S) p, pair(R, S) q);
    3636
    37 forall(otype R, otype S
     37forall(R, S
    3838        | { int ?==?(R, R); int ?>?(R, R); int ?>?(S, S); })
    3939int ?>?(pair(R, S) p, pair(R, S) q);
    4040
    41 forall(otype R, otype S
     41forall(R, S
    4242        | { int ?==?(R, R); int ?>?(R, R); int ?>=?(S, S); })
    4343int ?>=?(pair(R, S) p, pair(R, S) q);
  • libcfa/src/containers/result.cfa

    r92bfda0 rdafbde8  
    1818
    1919
    20 forall(otype T, otype E)
     20forall(T, E)
    2121void ?{}(result(T, E) & this) {
    2222        this.has_value = false;
     
    2424}
    2525
    26 forall(otype T, otype E)
     26forall(T, E)
    2727void ?{}(result(T, E) & this, one_t, T value) {
    2828        this.has_value = true;
     
    3030}
    3131
    32 forall(otype T, otype E)
     32forall(T, E)
    3333void ?{}(result(T, E) & this, zero_t, E error) {
    3434        this.has_value = false;
     
    3636}
    3737
    38 forall(otype T, otype E)
     38forall(T, E)
    3939void ?{}(result(T, E) & this, result(T, E) other) {
    4040        this.has_value = other.has_value;
     
    4646}
    4747
    48 forall(otype T, otype E)
     48forall(T, E)
    4949result(T, E) ?=?(result(T, E) & this, result(T, E) that) {
    5050        if (this.has_value && that.has_value) {
     
    6363}
    6464
    65 forall(otype T, otype E)
     65forall(T, E)
    6666void ^?{}(result(T, E) & this) {
    6767        if (this.has_value) {
     
    7272}
    7373
    74 forall(otype T, otype E)
     74forall(T, E)
    7575bool ?!=?(result(T, E) this, zero_t) {
    7676        return this.has_value;
    7777}
    7878
    79 forall(otype T, otype E)
     79forall(T, E)
    8080result(T, E) result_value(T value) {
    8181        return (result(T, E)){1, value};
    8282}
    8383
    84 forall(otype T, otype E)
     84forall(T, E)
    8585result(T, E) result_error(E error) {
    8686        return (result(T, E)){0, error};
    8787}
    8888
    89 forall(otype T, otype E)
     89forall(T, E)
    9090bool has_value(result(T, E) * this) {
    9191        return this->has_value;
    9292}
    9393
    94 forall(otype T, otype E)
     94forall(T, E)
    9595T get(result(T, E) * this) {
    9696        assertf(this->has_value, "attempt to get from result without value");
     
    9898}
    9999
    100 forall(otype T, otype E)
     100forall(T, E)
    101101E get_error(result(T, E) * this) {
    102102        assertf(!this->has_value, "attempt to get from result without error");
     
    104104}
    105105
    106 forall(otype T, otype E)
     106forall(T, E)
    107107void set(result(T, E) * this, T value) {
    108108        if (this->has_value) {
     
    115115}
    116116
    117 forall(otype T, otype E)
     117forall(T, E)
    118118void set_error(result(T, E) * this, E error) {
    119119        if (this->has_value) {
  • libcfa/src/containers/result.hfa

    r92bfda0 rdafbde8  
    1919
    2020// DO NOT USE DIRECTLY!
    21 forall(otype T, otype E)
     21forall(T, E)
    2222union inner_result{
    2323        T value;
     
    2525};
    2626
    27 forall(otype T, otype E)
     27forall(T, E)
    2828struct result {
    2929        bool has_value;
     
    3232
    3333
    34 forall(otype T, otype E)
     34forall(T, E)
    3535void ?{}(result(T, E) & this);
    3636
    37 forall(otype T, otype E)
     37forall(T, E)
    3838void ?{}(result(T, E) & this, one_t, T value);
    3939
    40 forall(otype T, otype E)
     40forall(T, E)
    4141void ?{}(result(T, E) & this, zero_t, E error);
    4242
    43 forall(otype T, otype E)
     43forall(T, E)
    4444void ?{}(result(T, E) & this, result(T, E) other);
    4545
    46 forall(otype T, otype E)
     46forall(T, E)
    4747void ^?{}(result(T, E) & this);
    4848
    49 forall(otype T, otype E)
     49forall(T, E)
    5050result(T, E) ?=?(result(T, E) & this, result(T, E) other);
    5151
    52 forall(otype T, otype E)
     52forall(T, E)
    5353bool ?!=?(result(T, E) this, zero_t);
    5454
    5555/* Wating for bug#11 to be fixed.
    56 forall(otype T, otype E)
     56forall(T, E)
    5757result(T, E) result_value(T value);
    5858
    59 forall(otype T, otype E)
     59forall(T, E)
    6060result(T, E) result_error(E error);
    6161*/
    6262
    63 forall(otype T, otype E)
     63forall(T, E)
    6464bool has_value(result(T, E) * this);
    6565
    66 forall(otype T, otype E)
     66forall(T, E)
    6767T get(result(T, E) * this);
    6868
    69 forall(otype T, otype E)
     69forall(T, E)
    7070E get_error(result(T, E) * this);
    7171
    72 forall(otype T, otype E)
     72forall(T, E)
    7373void set(result(T, E) * this, T value);
    7474
    75 forall(otype T, otype E)
     75forall(T, E)
    7676void set_error(result(T, E) * this, E error);
    7777
  • libcfa/src/containers/stackLockFree.hfa

    r92bfda0 rdafbde8  
    1717#include <stdint.h>
    1818
    19 forall( dtype T )
     19forall( T & )
    2020union Link {
    2121        struct {                                                                                        // 32/64-bit x 2
     
    3131}; // Link
    3232
    33 forall( otype T | sized(T) | { Link(T) * ?`next( T * ); } ) {
     33forall( T | sized(T) | { Link(T) * ?`next( T * ); } ) {
    3434        struct StackLF {
    3535                Link(T) stack;
  • libcfa/src/containers/vector.cfa

    r92bfda0 rdafbde8  
    1818#include <stdlib.hfa>
    1919
    20 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     20forall(T, allocator_t | allocator_c(T, allocator_t))
    2121void copy_internal(vector(T, allocator_t)* this, vector(T, allocator_t)* other);
    2222
    2323//------------------------------------------------------------------------------
    2424//Initialization
    25 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     25forall(T, allocator_t | allocator_c(T, allocator_t))
    2626void ?{}(vector(T, allocator_t)& this)
    2727{
     
    3030}
    3131
    32 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     32forall(T, allocator_t | allocator_c(T, allocator_t))
    3333void ?{}(vector(T, allocator_t)& this, vector(T, allocator_t) rhs)
    3434{
     
    3737}
    3838
    39 // forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     39// forall(T, allocator_t | allocator_c(T, allocator_t))
    4040// vector(T, allocator_t) ?=?(vector(T, allocator_t)* this, vector(T, allocator_t) rhs)
    4141// {
     
    4545// }
    4646
    47 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     47forall(T, allocator_t | allocator_c(T, allocator_t))
    4848void ^?{}(vector(T, allocator_t)& this)
    4949{
     
    5454//------------------------------------------------------------------------------
    5555//Modifiers
    56 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     56forall(T, allocator_t | allocator_c(T, allocator_t))
    5757void push_back(vector(T, allocator_t)* this, T value)
    5858{
     
    6262}
    6363
    64 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     64forall(T, allocator_t | allocator_c(T, allocator_t))
    6565void pop_back(vector(T, allocator_t)* this)
    6666{
     
    6969}
    7070
    71 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     71forall(T, allocator_t | allocator_c(T, allocator_t))
    7272void clear(vector(T, allocator_t)* this)
    7373{
     
    8282//Internal Helpers
    8383
    84 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     84forall(T, allocator_t | allocator_c(T, allocator_t))
    8585void copy_internal(vector(T, allocator_t)* this, vector(T, allocator_t)* other)
    8686{
     
    9393//------------------------------------------------------------------------------
    9494//Allocator
    95 forall(otype T)
     95forall(T)
    9696void ?{}(heap_allocator(T)& this)
    9797{
     
    100100}
    101101
    102 forall(otype T)
     102forall(T)
    103103void ?{}(heap_allocator(T)& this, heap_allocator(T) rhs)
    104104{
     
    107107}
    108108
    109 forall(otype T)
     109forall(T)
    110110heap_allocator(T) ?=?(heap_allocator(T)& this, heap_allocator(T) rhs)
    111111{
     
    115115}
    116116
    117 forall(otype T)
     117forall(T)
    118118void ^?{}(heap_allocator(T)& this)
    119119{
     
    121121}
    122122
    123 forall(otype T)
     123forall(T)
    124124inline void realloc_storage(heap_allocator(T)* this, size_t size)
    125125{
  • libcfa/src/containers/vector.hfa

    r92bfda0 rdafbde8  
    2020//------------------------------------------------------------------------------
    2121//Allocator
    22 forall(otype T)
     22forall(T)
    2323struct heap_allocator
    2424{
     
    2727};
    2828
    29 forall(otype T)
     29forall(T)
    3030void ?{}(heap_allocator(T)& this);
    3131
    32 forall(otype T)
     32forall(T)
    3333void ?{}(heap_allocator(T)& this, heap_allocator(T) rhs);
    3434
    35 forall(otype T)
     35forall(T)
    3636heap_allocator(T) ?=?(heap_allocator(T)& this, heap_allocator(T) rhs);
    3737
    38 forall(otype T)
     38forall(T)
    3939void ^?{}(heap_allocator(T)& this);
    4040
    41 forall(otype T)
     41forall(T)
    4242void realloc_storage(heap_allocator(T)* this, size_t size);
    4343
    44 forall(otype T)
     44forall(T)
    4545static inline T* data(heap_allocator(T)* this)
    4646{
     
    5050//------------------------------------------------------------------------------
    5151//Declaration
    52 trait allocator_c(otype T, otype allocator_t)
     52trait allocator_c(T, allocator_t)
    5353{
    5454        void realloc_storage(allocator_t*, size_t);
     
    5656};
    5757
    58 forall(otype T, otype allocator_t = heap_allocator(T) | allocator_c(T, allocator_t))
     58forall(T, allocator_t = heap_allocator(T) | allocator_c(T, allocator_t))
    5959struct vector;
    6060
    6161//------------------------------------------------------------------------------
    6262//Initialization
    63 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     63forall(T, allocator_t | allocator_c(T, allocator_t))
    6464void ?{}(vector(T, allocator_t)& this);
    6565
    66 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     66forall(T, allocator_t | allocator_c(T, allocator_t))
    6767void ?{}(vector(T, allocator_t)& this, vector(T, allocator_t) rhs);
    6868
    69 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     69forall(T, allocator_t | allocator_c(T, allocator_t))
    7070vector(T, allocator_t) ?=?(vector(T, allocator_t)& this, vector(T, allocator_t) rhs);
    7171
    72 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     72forall(T, allocator_t | allocator_c(T, allocator_t))
    7373void ^?{}(vector(T, allocator_t)& this);
    7474
    75 forall(otype T, otype allocator_t = heap_allocator(T) | allocator_c(T, allocator_t))
     75forall(T, allocator_t = heap_allocator(T) | allocator_c(T, allocator_t))
    7676struct vector
    7777{
     
    8282//------------------------------------------------------------------------------
    8383//Capacity
    84 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     84forall(T, allocator_t | allocator_c(T, allocator_t))
    8585static inline bool empty(vector(T, allocator_t)* this)
    8686{
     
    8888}
    8989
    90 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     90forall(T, allocator_t | allocator_c(T, allocator_t))
    9191static inline size_t size(vector(T, allocator_t)* this)
    9292{
     
    9494}
    9595
    96 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     96forall(T, allocator_t | allocator_c(T, allocator_t))
    9797static inline void reserve(vector(T, allocator_t)* this, size_t size)
    9898{
     
    102102//------------------------------------------------------------------------------
    103103//Element access
    104 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     104forall(T, allocator_t | allocator_c(T, allocator_t))
    105105static inline T at(vector(T, allocator_t)* this, size_t index)
    106106{
     
    108108}
    109109
    110 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     110forall(T, allocator_t | allocator_c(T, allocator_t))
    111111static inline T ?[?](vector(T, allocator_t)* this, size_t index)
    112112{
     
    114114}
    115115
    116 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     116forall(T, allocator_t | allocator_c(T, allocator_t))
    117117static inline T front(vector(T, allocator_t)* this)
    118118{
     
    120120}
    121121
    122 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     122forall(T, allocator_t | allocator_c(T, allocator_t))
    123123static inline T back(vector(T, allocator_t)* this)
    124124{
     
    128128//------------------------------------------------------------------------------
    129129//Modifiers
    130 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     130forall(T, allocator_t | allocator_c(T, allocator_t))
    131131void push_back(vector(T, allocator_t)* this, T value);
    132132
    133 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     133forall(T, allocator_t | allocator_c(T, allocator_t))
    134134void pop_back(vector(T, allocator_t)* this);
    135135
    136 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     136forall(T, allocator_t | allocator_c(T, allocator_t))
    137137void clear(vector(T, allocator_t)* this);
    138138
    139139//------------------------------------------------------------------------------
    140140//Iterators
    141 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     141forall(T, allocator_t | allocator_c(T, allocator_t))
    142142static inline T* begin(vector(T, allocator_t)* this)
    143143{
     
    145145}
    146146
    147 // forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     147// forall(T, allocator_t | allocator_c(T, allocator_t))
    148148// static inline const T* cbegin(const vector(T, allocator_t)* this)
    149149// {
     
    151151// }
    152152
    153 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     153forall(T, allocator_t | allocator_c(T, allocator_t))
    154154static inline T* end(vector(T, allocator_t)* this)
    155155{
     
    157157}
    158158
    159 // forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     159// forall(T, allocator_t | allocator_c(T, allocator_t))
    160160// static inline const T* cend(const vector(T, allocator_t)* this)
    161161// {
  • libcfa/src/exception.h

    r92bfda0 rdafbde8  
    101101// implemented in the .c file either so they all have to be inline.
    102102
    103 trait is_exception(dtype exceptT, dtype virtualT) {
     103trait is_exception(exceptT &, virtualT &) {
    104104        /* The first field must be a pointer to a virtual table.
    105105         * That virtual table must be a decendent of the base exception virtual table.
     
    109109};
    110110
    111 trait is_termination_exception(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT)) {
     111trait is_termination_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
    112112        void defaultTerminationHandler(exceptT &);
    113113};
    114114
    115 trait is_resumption_exception(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT)) {
     115trait is_resumption_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
    116116        void defaultResumptionHandler(exceptT &);
    117117};
    118118
    119 forall(dtype exceptT, dtype virtualT | is_termination_exception(exceptT, virtualT))
     119forall(exceptT &, virtualT & | is_termination_exception(exceptT, virtualT))
    120120static inline void $throw(exceptT & except) {
    121121        __cfaehm_throw_terminate(
     
    125125}
    126126
    127 forall(dtype exceptT, dtype virtualT | is_resumption_exception(exceptT, virtualT))
     127forall(exceptT &, virtualT & | is_resumption_exception(exceptT, virtualT))
    128128static inline void $throwResume(exceptT & except) {
    129129        __cfaehm_throw_resume(
     
    133133}
    134134
    135 forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
     135forall(exceptT &, virtualT & | is_exception(exceptT, virtualT))
    136136static inline void cancel_stack(exceptT & except) __attribute__((noreturn)) {
    137137        __cfaehm_cancel_stack( (exception_t *)&except );
    138138}
    139139
    140 forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
     140forall(exceptT &, virtualT & | is_exception(exceptT, virtualT))
    141141static inline void defaultTerminationHandler(exceptT & except) {
    142142        return cancel_stack( except );
    143143}
    144144
    145 forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
     145forall(exceptT &, virtualT & | is_exception(exceptT, virtualT))
    146146static inline void defaultResumptionHandler(exceptT & except) {
    147147        throw except;
  • libcfa/src/executor.cfa

    r92bfda0 rdafbde8  
    77#include <containers/list.hfa>
    88
    9 forall( dtype T | $dlistable(T, T) ) {
     9forall( T & | $dlistable(T, T) ) {
    1010        monitor Buffer {                                                                        // unbounded buffer
    1111                dlist( T, T ) queue;                                                    // unbounded list of work requests
  • libcfa/src/gmp.hfa

    r92bfda0 rdafbde8  
    255255
    256256        // I/O
    257         forall( dtype istype | istream( istype ) )
     257        forall( istype & | istream( istype ) )
    258258                istype & ?|?( istype & is, Int & mp ) {
    259259                gmp_scanf( "%Zd", &mp );
     
    261261        } // ?|?
    262262
    263         forall( dtype ostype | ostream( ostype ) ) {
     263        forall( ostype & | ostream( ostype ) ) {
    264264                ostype & ?|?( ostype & os, Int mp ) {
    265265                        if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
  • libcfa/src/iostream.cfa

    r92bfda0 rdafbde8  
    3636
    3737
    38 forall( dtype ostype | ostream( ostype ) ) {
     38forall( ostype & | ostream( ostype ) ) {
    3939        ostype & ?|?( ostype & os, bool b ) {
    4040                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
     
    402402
    403403// tuples
    404 forall( dtype ostype, otype T, ttype Params | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } ) {
     404forall( ostype &, T, Params... | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } ) {
    405405        ostype & ?|?( ostype & os, T arg, Params rest ) {
    406406                (ostype &)(os | arg);                                                   // print first argument
     
    421421
    422422// writes the range [begin, end) to the given stream
    423 forall( dtype ostype, otype elt_type | writeable( elt_type, ostype ), otype iterator_type | iterator( iterator_type, elt_type ) ) {
     423forall( ostype &, elt_type | writeable( elt_type, ostype ), iterator_type | iterator( iterator_type, elt_type ) ) {
    424424        void write( iterator_type begin, iterator_type end, ostype & os ) {
    425425                void print( elt_type i ) { os | i; }
     
    442442// Default prefix for non-decimal prints is 0b, 0, 0x.
    443443#define IntegralFMTImpl( T, IFMTNP, IFMTP ) \
    444 forall( dtype ostype | ostream( ostype ) ) { \
     444forall( ostype & | ostream( ostype ) ) { \
    445445        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    446446                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
     
    535535// Default prefix for non-decimal prints is 0b, 0, 0x.
    536536#define IntegralFMTImpl128( T, SIGNED, CODE, IFMTNP, IFMTP ) \
    537 forall( dtype ostype | ostream( ostype ) ) \
     537forall( ostype & | ostream( ostype ) ) \
    538538static void base10_128( ostype & os, _Ostream_Manip(T) f ) { \
    539539        if ( f.val > UINT64_MAX ) { \
     
    552552        } /* if */ \
    553553} /* base10_128 */ \
    554 forall( dtype ostype | ostream( ostype ) ) { \
     554forall( ostype & | ostream( ostype ) ) { \
    555555        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    556556                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
     
    654654#if defined( __SIZEOF_INT128__ )
    655655// Default prefix for non-decimal prints is 0b, 0, 0x.
    656 forall( dtype ostype | ostream( ostype ) )
     656forall( ostype & | ostream( ostype ) )
    657657static inline void base_128( ostype & os, unsigned int128 val, unsigned int128 power, _Ostream_Manip(uint64_t) & f, unsigned int maxdig, unsigned int bits, unsigned int cnt = 0 ) {
    658658        int wd = 1;                                                                                     // f.wd is never 0 because 0 implies left-pad
     
    719719
    720720#define IntegralFMTImpl128( T ) \
    721 forall( dtype ostype | ostream( ostype ) ) { \
     721forall( ostype & | ostream( ostype ) ) { \
    722722        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    723723                _Ostream_Manip(uint64_t) fmt; \
     
    767767
    768768#define FloatingPointFMTImpl( T, DFMTNP, DFMTP ) \
    769 forall( dtype ostype | ostream( ostype ) ) { \
     769forall( ostype & | ostream( ostype ) ) { \
    770770        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    771771                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
     
    801801// *********************************** character ***********************************
    802802
    803 forall( dtype ostype | ostream( ostype ) ) {
     803forall( ostype & | ostream( ostype ) ) {
    804804        ostype & ?|?( ostype & os, _Ostream_Manip(char) f ) {
    805805                if ( f.base != 'c' ) {                                                  // bespoke binary/octal/hex format
     
    834834// *********************************** C string ***********************************
    835835
    836 forall( dtype ostype | ostream( ostype ) ) {
     836forall( ostype & | ostream( ostype ) ) {
    837837        ostype & ?|?( ostype & os, _Ostream_Manip(const char *) f ) {
    838838                if ( ! f.val ) return os;                                               // null pointer ?
     
    882882
    883883
    884 forall( dtype istype | istream( istype ) ) {
     884forall( istype & | istream( istype ) ) {
    885885        istype & ?|?( istype & is, bool & b ) {
    886886                char val[6];
     
    10481048// *********************************** manipulators ***********************************
    10491049
    1050 forall( dtype istype | istream( istype ) )
     1050forall( istype & | istream( istype ) )
    10511051istype & ?|?( istype & is, _Istream_Cstr f ) {
    10521052        // skip xxx
     
    10831083} // ?|?
    10841084
    1085 forall( dtype istype | istream( istype ) )
     1085forall( istype & | istream( istype ) )
    10861086istype & ?|?( istype & is, _Istream_Char f ) {
    10871087        fmt( is, "%*c" );                                                                       // argument variable unused
     
    10901090
    10911091#define InputFMTImpl( T, CODE ) \
    1092 forall( dtype istype | istream( istype ) ) \
     1092forall( istype & | istream( istype ) ) \
    10931093istype & ?|?( istype & is, _Istream_Manip(T) f ) { \
    10941094        enum { size = 16 }; \
     
    11191119InputFMTImpl( long double, "Lf" )
    11201120
    1121 forall( dtype istype | istream( istype ) )
     1121forall( istype & | istream( istype ) )
    11221122istype & ?|?( istype & is, _Istream_Manip(float _Complex) fc ) {
    11231123        float re, im;
     
    11301130} // ?|?
    11311131
    1132 forall( dtype istype | istream( istype ) )
     1132forall( istype & | istream( istype ) )
    11331133istype & ?|?( istype & is, _Istream_Manip(double _Complex) dc ) {
    11341134        double re, im;
     
    11411141} // ?|?
    11421142
    1143 forall( dtype istype | istream( istype ) )
     1143forall( istype & | istream( istype ) )
    11441144istype & ?|?( istype & is, _Istream_Manip(long double _Complex) ldc ) {
    11451145        long double re, im;
  • libcfa/src/iostream.hfa

    r92bfda0 rdafbde8  
    2222
    2323
    24 trait ostream( dtype ostype ) {
     24trait ostream( ostype & ) {
    2525        // private
    2626        bool $sepPrt( ostype & );                                                       // get separator state (on/off)
     
    5656}; // ostream
    5757
    58 // trait writeable( otype T ) {
    59 //      forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, T );
     58// trait writeable( T ) {
     59//      forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype &, T );
    6060// }; // writeable
    6161
    62 trait writeable( otype T, dtype ostype | ostream( ostype ) ) {
     62trait writeable( T, ostype & | ostream( ostype ) ) {
    6363        ostype & ?|?( ostype &, T );
    6464}; // writeable
     
    6666// implement writable for intrinsic types
    6767
    68 forall( dtype ostype | ostream( ostype ) ) {
     68forall( ostype & | ostream( ostype ) ) {
    6969        ostype & ?|?( ostype &, bool );
    7070        void ?|?( ostype &, bool );
     
    140140
    141141// tuples
    142 forall( dtype ostype, otype T, ttype Params | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } ) {
     142forall( ostype &, T, Params... | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } ) {
    143143        ostype & ?|?( ostype & os, T arg, Params rest );
    144144        void ?|?( ostype & os, T arg, Params rest );
     
    146146
    147147// writes the range [begin, end) to the given stream
    148 forall( dtype ostype, otype elt_type | writeable( elt_type, ostype ), otype iterator_type | iterator( iterator_type, elt_type ) ) {
     148forall( ostype &, elt_type | writeable( elt_type, ostype ), iterator_type | iterator( iterator_type, elt_type ) ) {
    149149        void write( iterator_type begin, iterator_type end, ostype & os );
    150150        void write_reverse( iterator_type begin, iterator_type end, ostype & os );
     
    153153// *********************************** manipulators ***********************************
    154154
    155 forall( otype T )
     155forall( T )
    156156struct _Ostream_Manip {
    157157        T val;                                                                                          // polymorphic base-type
     
    193193        _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \
    194194} /* distribution */ \
    195 forall( dtype ostype | ostream( ostype ) ) { \
     195forall( ostype & | ostream( ostype ) ) { \
    196196        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
    197197        void ?|?( ostype & os, _Ostream_Manip(T) f ); \
     
    234234        _Ostream_Manip(T) & nodp( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
    235235} /* distribution */ \
    236 forall( dtype ostype | ostream( ostype ) ) { \
     236forall( ostype & | ostream( ostype ) ) { \
    237237        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
    238238        void ?|?( ostype & os, _Ostream_Manip(T) f ); \
     
    254254        _Ostream_Manip(char) & nobase( _Ostream_Manip(char) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
    255255} // distribution
    256 forall( dtype ostype | ostream( ostype ) ) {
     256forall( ostype & | ostream( ostype ) ) {
    257257        ostype & ?|?( ostype & os, _Ostream_Manip(char) f );
    258258        void ?|?( ostype & os, _Ostream_Manip(char) f );
     
    272272        _Ostream_Manip(const char *) & nobase( _Ostream_Manip(const char *) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
    273273} // distribution
    274 forall( dtype ostype | ostream( ostype ) ) {
     274forall( ostype & | ostream( ostype ) ) {
    275275        ostype & ?|?( ostype & os, _Ostream_Manip(const char *) f );
    276276        void ?|?( ostype & os, _Ostream_Manip(const char *) f );
     
    281281
    282282
    283 trait istream( dtype istype ) {
     283trait istream( istype & ) {
    284284        void nlOn( istype & );                                                          // read newline
    285285        void nlOff( istype & );                                                         // scan newline
     
    294294}; // istream
    295295
    296 trait readable( otype T ) {
    297         forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, T );
     296trait readable( T ) {
     297        forall( istype & | istream( istype ) ) istype & ?|?( istype &, T );
    298298}; // readable
    299299
    300 forall( dtype istype | istream( istype ) ) {
     300forall( istype & | istream( istype ) ) {
    301301        istype & ?|?( istype &, bool & );
    302302
     
    363363        _Istream_Cstr & wdi( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; }
    364364} // distribution
    365 forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Cstr f );
     365forall( istype & | istream( istype ) ) istype & ?|?( istype & is, _Istream_Cstr f );
    366366
    367367struct _Istream_Char {
     
    373373        _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
    374374} // distribution
    375 forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Char f );
    376 
    377 forall( dtype T | sized( T ) )
     375forall( istype & | istream( istype ) ) istype & ?|?( istype & is, _Istream_Char f );
     376
     377forall( T & | sized( T ) )
    378378struct _Istream_Manip {
    379379        T & val;                                                                                        // polymorphic base-type
     
    389389        _Istream_Manip(T) & wdi( unsigned int w, _Istream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \
    390390} /* distribution */ \
    391 forall( dtype istype | istream( istype ) ) { \
     391forall( istype & | istream( istype ) ) { \
    392392        istype & ?|?( istype & is, _Istream_Manip(T) f ); \
    393393} // ?|?
     
    418418#include <time_t.hfa>                                                                   // Duration (constructors) / Time (constructors)
    419419
    420 forall( dtype ostype | ostream( ostype ) ) {
     420forall( ostype & | ostream( ostype ) ) {
    421421        ostype & ?|?( ostype & os, Duration dur );
    422422        void ?|?( ostype & os, Duration dur );
  • libcfa/src/iterator.cfa

    r92bfda0 rdafbde8  
    1616#include "iterator.hfa"
    1717
    18 forall( otype iterator_type, otype elt_type | iterator( iterator_type, elt_type ) )
     18forall( iterator_type, elt_type | iterator( iterator_type, elt_type ) )
    1919void for_each( iterator_type begin, iterator_type end, void (* func)( elt_type ) ) {
    2020        for ( iterator_type i = begin; i != end; ++i ) {
     
    2323} // for_each
    2424
    25 forall( otype iterator_type, otype elt_type | iterator( iterator_type, elt_type ) )
     25forall( iterator_type, elt_type | iterator( iterator_type, elt_type ) )
    2626void for_each_reverse( iterator_type begin, iterator_type end, void (* func)( elt_type ) ) {
    2727        for ( iterator_type i = end; i != begin; ) {
  • libcfa/src/iterator.hfa

    r92bfda0 rdafbde8  
    1717
    1818// An iterator can be used to traverse a data structure.
    19 trait iterator( otype iterator_type, otype elt_type ) {
     19trait iterator( iterator_type, elt_type ) {
    2020        // point to the next element
    2121//      iterator_type ?++( iterator_type & );
     
    3131};
    3232
    33 trait iterator_for( otype iterator_type, otype collection_type, otype elt_type | iterator( iterator_type, elt_type ) ) {
     33trait iterator_for( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) ) {
    3434//      [ iterator_type begin, iterator_type end ] get_iterators( collection_type );
    3535        iterator_type begin( collection_type );
     
    3737};
    3838
    39 forall( otype iterator_type, otype elt_type | iterator( iterator_type, elt_type ) )
     39forall( iterator_type, elt_type | iterator( iterator_type, elt_type ) )
    4040void for_each( iterator_type begin, iterator_type end, void (* func)( elt_type ) );
    4141
    42 forall( otype iterator_type, otype elt_type | iterator( iterator_type, elt_type ) )
     42forall( iterator_type, elt_type | iterator( iterator_type, elt_type ) )
    4343void for_each_reverse( iterator_type begin, iterator_type end, void (* func)( elt_type ) );
    4444
  • libcfa/src/math.hfa

    r92bfda0 rdafbde8  
    286286        unsigned long long int floor( unsigned long long int n, unsigned long long int align ) { return n / align * align; }
    287287
    288         // forall( otype T | { T ?/?( T, T ); T ?*?( T, T ); } )
     288        // forall( T | { T ?/?( T, T ); T ?*?( T, T ); } )
    289289        // T floor( T n, T align ) { return n / align * align; }
    290290
     
    300300        unsigned long long int ceiling_div( unsigned long long int n, unsigned long long int align ) { return (n + (align - 1)) / align; }
    301301
    302         // forall( otype T | { T ?+?( T, T ); T ?-?( T, T ); T ?%?( T, T ); } )
     302        // forall( T | { T ?+?( T, T ); T ?-?( T, T ); T ?%?( T, T ); } )
    303303        // T ceiling_div( T n, T align ) { verify( is_pow2( align ) );return (n + (align - 1)) / align; }
    304304       
     
    315315        unsigned long long int ceiling( unsigned long long int n, unsigned long long int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); }
    316316
    317         // forall( otype T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T ); T ?/?( T, T ); } )
     317        // forall( T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T ); T ?/?( T, T ); } )
    318318        // T ceiling( T n, T align ) { return return floor( n + (n % align != 0 ? align - 1 : 0), align ); *}
    319319
     
    414414
    415415static inline {
    416         forall( otype T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T );T ?*?( T, T ); } )
     416        forall( T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T );T ?*?( T, T ); } )
    417417        T lerp( T x, T y, T a ) { return x * ((T){1} - a) + y * a; }
    418418
    419         forall( otype T | { void ?{}( T &, zero_t ); void ?{}( T &, one_t ); int ?<?( T, T ); } )
     419        forall( T | { void ?{}( T &, zero_t ); void ?{}( T &, one_t ); int ?<?( T, T ); } )
    420420        T step( T edge, T x ) { return x < edge ? (T){0} : (T){1}; }
    421421
    422         forall( otype T | { void ?{}( T &, int ); T clamp( T, T, T ); T ?-?( T, T ); T ?*?( T, T ); T ?/?( T, T ); } )
     422        forall( T | { void ?{}( T &, int ); T clamp( T, T, T ); T ?-?( T, T ); T ?*?( T, T ); T ?/?( T, T ); } )
    423423        T smoothstep( T edge0, T edge1, T x ) { T t = clamp( (x - edge0) / (edge1 - edge0), (T){0}, (T){1} ); return t * t * ((T){3} - (T){2} * t); }
    424424} // distribution
  • libcfa/src/memory.cfa

    r92bfda0 rdafbde8  
    1818
    1919// Internal data object.
    20 forall(dtype T | sized(T), ttype Args | { void ?{}(T &, Args); })
     20forall(T & | sized(T), Args... | { void ?{}(T &, Args); })
    2121void ?{}(counter_data(T) & this, Args args) {
    2222        (this.counter){1};
     
    2424}
    2525
    26 forall(dtype T | sized(T) | { void ^?{}(T &); })
     26forall(T & | sized(T) | { void ^?{}(T &); })
    2727void ^?{}(counter_data(T) & this) {
    2828        assert(0 == this.counter);
     
    3131
    3232// This is one of many pointers keeping this alive.
    33 forall(dtype T | sized(T))
     33forall(T & | sized(T))
    3434void ?{}(counter_ptr(T) & this) {
    3535        this.data = 0p;
    3636}
    3737
    38 forall(dtype T | sized(T))
     38forall(T & | sized(T))
    3939void ?{}(counter_ptr(T) & this, zero_t) {
    4040        this.data = 0p;
    4141}
    4242
    43 forall(dtype T | sized(T) | { void ^?{}(T &); })
     43forall(T & | sized(T) | { void ^?{}(T &); })
    4444static void internal_decrement(counter_ptr(T) & this) {
    4545        if (this.data && 0 == --this.data->counter) {
     
    4848}
    4949
    50 forall(dtype T | sized(T))
     50forall(T & | sized(T))
    5151static void internal_copy(counter_ptr(T) & this, counter_ptr(T) & that) {
    5252        this.data = that.data;
     
    5656}
    5757
    58 forall(dtype T | sized(T) | { void ^?{}(T &); })
     58forall(T & | sized(T) | { void ^?{}(T &); })
    5959void ?{}(counter_ptr(T) & this, counter_ptr(T) that) {
    6060        // `that` is a copy but it should have neither a constructor
     
    6464}
    6565
    66 forall(dtype T | sized(T), ttype Args | { void ?{}(T&, Args); })
     66forall(T & | sized(T), Args... | { void ?{}(T&, Args); })
    6767void ?{}(counter_ptr(T) & this, Args args) {
    6868        this.data = (counter_data(T)*)new(args);
    6969}
    7070
    71 forall(dtype T | sized(T) | { void ^?{}(T &); })
     71forall(T & | sized(T) | { void ^?{}(T &); })
    7272void ^?{}(counter_ptr(T) & this) {
    7373        internal_decrement(this);
    7474}
    7575
    76 forall(dtype T | sized(T))
     76forall(T & | sized(T))
    7777T & *?(counter_ptr(T) & this) {
    7878        return *((this.data) ? &this.data->object : 0p);
    7979}
    8080
    81 forall(dtype T | sized(T) | { void ^?{}(T &); })
     81forall(T & | sized(T) | { void ^?{}(T &); })
    8282void ?=?(counter_ptr(T) & this, counter_ptr(T) that) {
    8383        if (this.data != that.data) {
     
    8787}
    8888
    89 forall(dtype T | sized(T) | { void ^?{}(T &); })
     89forall(T & | sized(T) | { void ^?{}(T &); })
    9090void ?=?(counter_ptr(T) & this, zero_t) {
    9191        internal_decrement(this);
     
    9393}
    9494
    95 forall(dtype T | sized(T))
     95forall(T & | sized(T))
    9696int ?==?(counter_ptr(T) const & this, counter_ptr(T) const & that) {
    9797        return this.data == that.data;
    9898}
    9999
    100 forall(dtype T | sized(T))
     100forall(T & | sized(T))
    101101int ?!=?(counter_ptr(T) const & this, counter_ptr(T) const & that) {
    102102        return !?==?(this, that);
    103103}
    104104
    105 forall(dtype T | sized(T))
     105forall(T & | sized(T))
    106106int ?==?(counter_ptr(T) const & this, zero_t) {
    107107        return this.data == 0;
    108108}
    109109
    110 forall(dtype T | sized(T))
     110forall(T & | sized(T))
    111111int ?!=?(counter_ptr(T) const & this, zero_t) {
    112112        return !?==?(this, (zero_t)0);
     
    114114
    115115// This is the only pointer that keeps this alive.
    116 forall(dtype T)
     116forall(T &)
    117117void ?{}(unique_ptr(T) & this) {
    118118        this.data = 0p;
    119119}
    120120
    121 forall(dtype T)
     121forall(T &)
    122122void ?{}(unique_ptr(T) & this, zero_t) {
    123123        this.data = 0p;
    124124}
    125125
    126 forall(dtype T | sized(T), ttype Args | { void ?{}(T &, Args); })
     126forall(T & | sized(T), Args... | { void ?{}(T &, Args); })
    127127void ?{}(unique_ptr(T) & this, Args args) {
    128128        this.data = (T *)new(args);
    129129}
    130130
    131 forall(dtype T | { void ^?{}(T &); })
     131forall(T & | { void ^?{}(T &); })
    132132void ^?{}(unique_ptr(T) & this) {
    133133        delete(this.data);
    134134}
    135135
    136 forall(dtype T)
     136forall(T &)
    137137T & *?(unique_ptr(T) & this) {
    138138        return *this.data;
    139139}
    140140
    141 forall(dtype T | { void ^?{}(T &); })
     141forall(T & | { void ^?{}(T &); })
    142142void ?=?(unique_ptr(T) & this, zero_t) {
    143143        delete(this.data);
     
    145145}
    146146
    147 forall(dtype T | { void ^?{}(T &); })
     147forall(T & | { void ^?{}(T &); })
    148148void move(unique_ptr(T) & this, unique_ptr(T) & that) {
    149149        delete(this.data);
     
    152152}
    153153
    154 forall(dtype T)
     154forall(T &)
    155155int ?==?(unique_ptr(T) const & this, unique_ptr(T) const & that) {
    156156        return this.data == that.data;
    157157}
    158158
    159 forall(dtype T)
     159forall(T &)
    160160int ?!=?(unique_ptr(T) const & this, unique_ptr(T) const & that) {
    161161        return !?==?(this, that);
    162162}
    163163
    164 forall(dtype T)
     164forall(T &)
    165165int ?==?(unique_ptr(T) const & this, zero_t) {
    166166        return this.data == 0;
    167167}
    168168
    169 forall(dtype T)
     169forall(T &)
    170170int ?!=?(unique_ptr(T) const & this, zero_t) {
    171171        return !?==?(this, (zero_t)0);
  • libcfa/src/memory.hfa

    r92bfda0 rdafbde8  
    1717
    1818// Internal data object.
    19 forall(dtype T | sized(T)) {
     19forall(T & | sized(T)) {
    2020        struct counter_data {
    2121                unsigned int counter;
     
    2323        };
    2424
    25         forall(ttype Args | { void ?{}(T &, Args); })
     25        forall(Args... | { void ?{}(T &, Args); })
    2626        void ?{}(counter_data(T) & this, Args args);
    2727
     
    3131
    3232// This is one of many pointers keeping this alive.
    33 forall(dtype T | sized(T)) {
     33forall(T & | sized(T)) {
    3434        struct counter_ptr {
    3535                counter_data(T) * data;
     
    4040        forall( | { void ^?{}(T &); })
    4141        void ?{}(counter_ptr(T) & this, counter_ptr(T) that);
    42         forall(ttype Args | { void ?{}(T&, Args); })
     42        forall(Args... | { void ?{}(T&, Args); })
    4343        void ?{}(counter_ptr(T) & this, Args args);
    4444
     
    6060
    6161// This is the only pointer that keeps this alive.
    62 forall(dtype T) {
     62forall(T &) {
    6363        struct unique_ptr {
    6464                T * data;
     
    6868        void ?{}(unique_ptr(T) & this, zero_t);
    6969        void ?{}(unique_ptr(T) & this, unique_ptr(T) that) = void;
    70         forall( | sized(T), ttype Args | { void ?{}(T &, Args); })
     70        forall( | sized(T), Args... | { void ?{}(T &, Args); })
    7171        void ?{}(unique_ptr(T) & this, Args args);
    7272
  • libcfa/src/parseargs.hfa

    r92bfda0 rdafbde8  
    1414static inline void ?{}( cfa_option & this ) {}
    1515
    16 forall(dtype T | { bool parse(const char *, T & ); })
     16forall(T & | { bool parse(const char *, T & ); })
    1717static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable ) {
    1818      this.val        = 0;
     
    2424}
    2525
    26 forall(dtype T)
     26forall(T &)
    2727static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable, bool (*parse)(const char *, T & )) {
    2828      this.val        = 0;
  • libcfa/src/rational.cfa

    r92bfda0 rdafbde8  
    1818#include "stdlib.hfa"
    1919
    20 forall( otype RationalImpl | arithmetic( RationalImpl ) ) {
     20forall( RationalImpl | arithmetic( RationalImpl ) ) {
    2121        // helper routines
    2222
     
    159159        // I/O
    160160
    161         forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
     161        forall( istype & | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    162162        istype & ?|?( istype & is, Rational(RationalImpl) & r ) {
    163163                is | r.numerator | r.denominator;
     
    168168        } // ?|?
    169169
    170         forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } ) {
     170        forall( ostype & | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } ) {
    171171                ostype & ?|?( ostype & os, Rational(RationalImpl) r ) {
    172172                        return os | r.numerator | '/' | r.denominator;
     
    179179} // distribution
    180180
    181 forall( otype RationalImpl | arithmetic( RationalImpl ) | { RationalImpl ?\?( RationalImpl, unsigned long ); } )
     181forall( RationalImpl | arithmetic( RationalImpl ) | { RationalImpl ?\?( RationalImpl, unsigned long ); } )
    182182Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y ) {
    183183        if ( y < 0 ) {
     
    190190// conversion
    191191
    192 forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
     192forall( RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
    193193double widen( Rational(RationalImpl) r ) {
    194194        return convert( r.numerator ) / convert( r.denominator );
    195195} // widen
    196196
    197 forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); RationalImpl convert( double ); } )
     197forall( RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); RationalImpl convert( double ); } )
    198198Rational(RationalImpl) narrow( double f, RationalImpl md ) {
    199199        // http://www.ics.uci.edu/~eppstein/numth/frap.c
  • libcfa/src/rational.hfa

    r92bfda0 rdafbde8  
    2020#include "iostream.hfa"
    2121
    22 trait scalar( otype T ) {
     22trait scalar( T ) {
    2323};
    2424
    25 trait arithmetic( otype T | scalar( T ) ) {
     25trait arithmetic( T | scalar( T ) ) {
    2626        int !?( T );
    2727        int ?==?( T, T );
     
    4646// implementation
    4747
    48 forall( otype RationalImpl | arithmetic( RationalImpl ) ) {
     48forall( RationalImpl | arithmetic( RationalImpl ) ) {
    4949        struct Rational {
    5050                RationalImpl numerator, denominator;                    // invariant: denominator > 0
     
    8989
    9090        // I/O
    91         forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
     91        forall( istype & | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    9292        istype & ?|?( istype &, Rational(RationalImpl) & );
    9393
    94         forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } ) {
     94        forall( ostype & | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } ) {
    9595                ostype & ?|?( ostype &, Rational(RationalImpl) );
    9696                void ?|?( ostype &, Rational(RationalImpl) );
     
    9898} // distribution
    9999
    100 forall( otype RationalImpl | arithmetic( RationalImpl ) |{RationalImpl ?\?( RationalImpl, unsigned long );} )
     100forall( RationalImpl | arithmetic( RationalImpl ) |{RationalImpl ?\?( RationalImpl, unsigned long );} )
    101101Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y );
    102102
    103103// conversion
    104 forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
     104forall( RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
    105105double widen( Rational(RationalImpl) r );
    106 forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl );  RationalImpl convert( double );} )
     106forall( RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl );  RationalImpl convert( double );} )
    107107Rational(RationalImpl) narrow( double f, RationalImpl md );
    108108
  • libcfa/src/stdlib.cfa

    r92bfda0 rdafbde8  
    2828// Cforall allocation/deallocation and constructor/destructor, array types
    2929
    30 forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } )
     30forall( T & | sized(T), TT... | { void ?{}( T &, TT ); } )
    3131T * anew( size_t dim, TT p ) {
    3232        T * arr = alloc( dim );
     
    3737} // anew
    3838
    39 forall( dtype T | sized(T) | { void ^?{}( T & ); } )
     39forall( T & | sized(T) | { void ^?{}( T & ); } )
    4040void adelete( T arr[] ) {
    4141        if ( arr ) {                                                                            // ignore null
     
    4848} // adelete
    4949
    50 forall( dtype T | sized(T) | { void ^?{}( T & ); }, ttype TT | { void adelete( TT ); } )
     50forall( T & | sized(T) | { void ^?{}( T & ); }, TT... | { void adelete( TT ); } )
    5151void adelete( T arr[], TT rest ) {
    5252        if ( arr ) {                                                                            // ignore null
     
    9797//---------------------------------------
    9898
    99 forall( otype E | { int ?<?( E, E ); } ) {
     99forall( E | { int ?<?( E, E ); } ) {
    100100        E * bsearch( E key, const E * vals, size_t dim ) {
    101101                int cmp( const void * t1, const void * t2 ) {
     
    156156
    157157
    158 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } ) {
     158forall( K, E | { int ?<?( K, K ); K getKey( const E & ); } ) {
    159159        E * bsearch( K key, const E * vals, size_t dim ) {
    160160                int cmp( const void * t1, const void * t2 ) {
  • libcfa/src/stdlib.hfa

    r92bfda0 rdafbde8  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Dec 12 13:52:34 2020
    13 // Update Count     : 536
     12// Last Modified On : Sat Jan 16 09:07:10 2021
     13// Update Count     : 568
    1414//
    1515
     
    4848        else return (T *)alignment( _Alignof(T), dim, sizeof(T) )
    4949
    50 static inline forall( dtype T | sized(T) ) {
     50static inline forall( T & | sized(T) ) {
    5151        // CFA safe equivalents, i.e., implicit size specification
    5252
     
    108108
    109109        1. Replace the current forall-block that contains defintions of S_fill and S_realloc with following:
    110                 forall( dtype T | sized(T) ) {
     110                forall( T & | sized(T) ) {
    111111                        union  U_fill           { char c; T * a; T t; };
    112112                        struct S_fill           { char tag; U_fill(T) fill; };
     
    151151typedef struct S_resize                 { inline void *;  }     T_resize;
    152152
    153 forall( dtype T ) {
     153forall( T & ) {
    154154        struct S_fill           { char tag; char c; size_t size; T * at; char t[50]; };
    155155        struct S_realloc        { inline T *; };
     
    159159static inline T_resize  ?`resize  ( void * a )  { return (T_resize){a}; }
    160160
    161 static inline forall( dtype T | sized(T) ) {
     161static inline forall( T & | sized(T) ) {
    162162        S_fill(T) ?`fill ( T t ) {
    163163                S_fill(T) ret = { 't' };
    164164                size_t size = sizeof(T);
    165                 if(size > sizeof(ret.t)) { printf("ERROR: const object of size greater than 50 bytes given for dynamic memory fill\n"); exit(1); }
     165                if ( size > sizeof(ret.t) ) {
     166                        abort( "ERROR: const object of size greater than 50 bytes given for dynamic memory fill\n" );
     167                } // if
    166168                memcpy( &ret.t, &t, size );
    167169                return ret;
     
    173175        S_realloc(T)    ?`realloc ( T * a )                             { return (S_realloc(T)){a}; }
    174176
    175         T * $alloc_internal( void * Resize, T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill) {
     177        T * $alloc_internal( void * Resize, T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill ) {
    176178                T * ptr = NULL;
    177179                size_t size = sizeof(T);
     
    181183                        ptr = (T*) (void *) resize( (void *)Resize, Align, Dim * size );
    182184                } else if ( Realloc ) {
    183                         if (Fill.tag != '0') copy_end = min(malloc_size( Realloc ), Dim * size);
    184                         ptr = (T*) (void *) realloc( (void *)Realloc, Align, Dim * size );
     185                        if ( Fill.tag != '0' ) copy_end = min(malloc_size( Realloc ), Dim * size );
     186                        ptr = (T *) (void *) realloc( (void *)Realloc, Align, Dim * size );
    185187                } else {
    186                         ptr = (T*) (void *) memalign( Align, Dim * size );
    187                 }
    188 
    189                 if(Fill.tag == 'c') {
     188                        ptr = (T *) (void *) memalign( Align, Dim * size );
     189                }
     190
     191                if ( Fill.tag == 'c' ) {
    190192                        memset( (char *)ptr + copy_end, (int)Fill.c, Dim * size - copy_end );
    191                 } else if(Fill.tag == 't') {
     193                } else if ( Fill.tag == 't' ) {
    192194                        for ( int i = copy_end; i < Dim * size; i += size ) {
    193 #pragma GCC diagnostic push
    194 #pragma GCC diagnostic ignored "-Warray-bounds"
    195 #pragma GCC diagnostic push
    196 #pragma GCC diagnostic ignored "-Wstringop-overflow="
    197                                 memcpy( (char *)ptr + i, &Fill.t, size );
    198 #pragma GCC diagnostic pop
    199 #pragma GCC diagnostic pop
     195                                #pragma GCC diagnostic push
     196                                #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     197                                memcpy( (char *)ptr + i, &Fill.t, sizeof(Fill.t) );
     198                                #pragma GCC diagnostic pop
    200199                        }
    201                 } else if(Fill.tag == 'a') {
     200                } else if ( Fill.tag == 'a' ) {
    202201                        memcpy( (char *)ptr + copy_end, Fill.at, min(Dim * size - copy_end, Fill.size) );
    203                 } else if(Fill.tag == 'T') {
    204                         for ( int i = copy_end; i < Dim * size; i += size ) {
    205                                 memcpy( (char *)ptr + i, Fill.at, size );
    206                         }
     202                } else if ( Fill.tag == 'T' ) {
     203                        memcpy( (char *)ptr + copy_end, Fill.at, Dim * size );
    207204                }
    208205
     
    210207        } // $alloc_internal
    211208
    212         forall( ttype TT | { T * $alloc_internal( void *, T *, size_t, size_t, S_fill(T), TT ); } ) {
     209        forall( TT... | { T * $alloc_internal( void *, T *, size_t, size_t, S_fill(T), TT ); } ) {
    213210
    214211                T * $alloc_internal( void *       , T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {
     
    239236} // distribution T
    240237
    241 static inline forall( dtype T | sized(T) ) {
     238static inline forall( T & | sized(T) ) {
    242239        // CFA safe initialization/copy, i.e., implicit size specification, non-array types
    243240        T * memset( T * dest, char fill ) {
     
    260257
    261258// CFA deallocation for multiple objects
    262 static inline forall( dtype T )                                                 // FIX ME, problems with 0p in list
     259static inline forall( T & )                                                     // FIX ME, problems with 0p in list
    263260void free( T * ptr ) {
    264261        free( (void *)ptr );                                                            // C free
    265262} // free
    266 static inline forall( dtype T, ttype TT | { void free( TT ); } )
     263static inline forall( T &, TT... | { void free( TT ); } )
    267264void free( T * ptr, TT rest ) {
    268265        free( ptr );
     
    271268
    272269// CFA allocation/deallocation and constructor/destructor, non-array types
    273 static inline forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } )
     270static inline forall( T & | sized(T), TT... | { void ?{}( T &, TT ); } )
    274271T * new( TT p ) {
    275272        return &(*(T *)malloc()){ p };                                                  // run constructor
    276273} // new
    277274
    278 static inline forall( dtype T | { void ^?{}( T & ); } )
     275static inline forall( T & | { void ^?{}( T & ); } )
    279276void delete( T * ptr ) {
    280277        // special case for 0-sized object => always call destructor
     
    284281        free( ptr );                                                                            // always call free
    285282} // delete
    286 static inline forall( dtype T, ttype TT | { void ^?{}( T & ); void delete( TT ); } )
     283static inline forall( T &, TT... | { void ^?{}( T & ); void delete( TT ); } )
    287284void delete( T * ptr, TT rest ) {
    288285        delete( ptr );
     
    291288
    292289// CFA allocation/deallocation and constructor/destructor, array types
    293 forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } ) T * anew( size_t dim, TT p );
    294 forall( dtype T | sized(T) | { void ^?{}( T & ); } ) void adelete( T arr[] );
    295 forall( dtype T | sized(T) | { void ^?{}( T & ); }, ttype TT | { void adelete( TT ); } ) void adelete( T arr[], TT rest );
     290forall( T & | sized(T), TT... | { void ?{}( T &, TT ); } ) T * anew( size_t dim, TT p );
     291forall( T & | sized(T) | { void ^?{}( T & ); } ) void adelete( T arr[] );
     292forall( T & | sized(T) | { void ^?{}( T & ); }, TT... | { void adelete( TT ); } ) void adelete( T arr[], TT rest );
    296293
    297294//---------------------------------------
     
    333330//---------------------------------------
    334331
    335 forall( otype E | { int ?<?( E, E ); } ) {
     332forall( E | { int ?<?( E, E ); } ) {
    336333        E * bsearch( E key, const E * vals, size_t dim );
    337334        size_t bsearch( E key, const E * vals, size_t dim );
     
    342339} // distribution
    343340
    344 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } ) {
     341forall( K, E | { int ?<?( K, K ); K getKey( const E & ); } ) {
    345342        E * bsearch( K key, const E * vals, size_t dim );
    346343        size_t bsearch( K key, const E * vals, size_t dim );
     
    351348} // distribution
    352349
    353 forall( otype E | { int ?<?( E, E ); } ) {
     350forall( E | { int ?<?( E, E ); } ) {
    354351        void qsort( E * vals, size_t dim );
    355352} // distribution
  • libcfa/src/time.cfa

    r92bfda0 rdafbde8  
    3131
    3232
    33 forall( dtype ostype | ostream( ostype ) ) {
     33forall( ostype & | ostream( ostype ) ) {
    3434        ostype & ?|?( ostype & os, Duration dur ) with( dur ) {
    3535                (ostype &)(os | tn / TIMEGRAN);                                 // print seconds
     
    136136} // strftime
    137137
    138 forall( dtype ostype | ostream( ostype ) ) {
     138forall( ostype & | ostream( ostype ) ) {
    139139        ostype & ?|?( ostype & os, Time time ) with( time ) {
    140140                char buf[32];                                                                   // at least 26
  • libcfa/src/vec/vec.hfa

    r92bfda0 rdafbde8  
    1818#include <math.hfa>
    1919
    20 trait fromint(otype T) {
     20trait fromint(T) {
    2121    void ?{}(T&, int);
    2222};
    23 trait zeroinit(otype T) {
     23trait zeroinit(T) {
    2424    void ?{}(T&, zero_t);
    2525};
    26 trait zero_assign(otype T) {
     26trait zero_assign(T) {
    2727    T ?=?(T&, zero_t);
    2828};
    29 trait subtract(otype T) {
     29trait subtract(T) {
    3030    T ?-?(T, T);
    3131};
    32 trait negate(otype T) {
     32trait negate(T) {
    3333    T -?(T);
    3434};
    35 trait add(otype T) {
     35trait add(T) {
    3636    T ?+?(T, T);
    3737};
    38 trait multiply(otype T) {
     38trait multiply(T) {
    3939    T ?*?(T, T);
    4040};
    41 trait divide(otype T) {
     41trait divide(T) {
    4242    T ?/?(T, T);
    4343};
    44 trait lessthan(otype T) {
     44trait lessthan(T) {
    4545    int ?<?(T, T);
    4646};
    47 trait equality(otype T) {
     47trait equality(T) {
    4848    int ?==?(T, T);
    4949};
    50 trait sqrt(otype T) {
     50trait sqrt(T) {
    5151    T sqrt(T);
    5252};
     
    6868}
    6969
    70 trait dottable(otype V, otype T) {
     70trait dottable(V, T) {
    7171    T dot(V, V);
    7272};
     
    7474static inline {
    7575
    76 forall(otype T | sqrt(T), otype V | dottable(V, T))
     76forall(T | sqrt(T), V | dottable(V, T))
    7777T length(V v) {
    7878   return sqrt(dot(v, v));
    7979}
    8080
    81 forall(otype T, otype V | dottable(V, T))
     81forall(T, V | dottable(V, T))
    8282T length_squared(V v) {
    8383   return dot(v, v);
    8484}
    8585
    86 forall(otype T, otype V | { T length(V); } | subtract(V))
     86forall(T, V | { T length(V); } | subtract(V))
    8787T distance(V v1, V v2) {
    8888    return length(v1 - v2);
    8989}
    9090
    91 forall(otype T, otype V | { T length(V); V ?/?(V, T); })
     91forall(T, V | { T length(V); V ?/?(V, T); })
    9292V normalize(V v) {
    9393    return v / length(v);
     
    9595
    9696// Project vector u onto vector v
    97 forall(otype T, otype V | dottable(V, T) | { V normalize(V); V ?*?(V, T); })
     97forall(T, V | dottable(V, T) | { V normalize(V); V ?*?(V, T); })
    9898V project(V u, V v) {
    9999    V v_norm = normalize(v);
     
    102102
    103103// Reflect incident vector v with respect to surface with normal n
    104 forall(otype T | fromint(T), otype V | { V project(V, V); V ?*?(T, V); V ?-?(V,V); })
     104forall(T | fromint(T), V | { V project(V, V); V ?*?(T, V); V ?-?(V,V); })
    105105V reflect(V v, V n) {
    106106    return v - (T){2} * project(v, n);
     
    111111// entering material (i.e., from air to water, eta = 1/1.33)
    112112// v and n must already be normalized
    113 forall(otype T | fromint(T) | subtract(T) | multiply(T) | add(T) | lessthan(T) | sqrt(T),
    114        otype V | dottable(V, T) | { V ?*?(T, V); V ?-?(V,V); void ?{}(V&, zero_t); })
     113forall(T | fromint(T) | subtract(T) | multiply(T) | add(T) | lessthan(T) | sqrt(T),
     114       V | dottable(V, T) | { V ?*?(T, V); V ?-?(V,V); void ?{}(V&, zero_t); })
    115115V refract(V v, V n, T eta) {
    116116    T dotValue = dot(n, v);
     
    128128// i is the incident vector
    129129// ng is the geometric normal of the surface
    130 forall(otype T | lessthan(T) | zeroinit(T), otype V | dottable(V, T) | negate(V))
     130forall(T | lessthan(T) | zeroinit(T), V | dottable(V, T) | negate(V))
    131131V faceforward(V n, V i, V ng) {
    132132    return dot(ng, i) < (T){0} ? n : -n;
  • libcfa/src/vec/vec2.hfa

    r92bfda0 rdafbde8  
    1919#include "vec.hfa"
    2020
    21 forall (otype T) {
     21forall (T) {
    2222    struct vec2 {
    2323        T x, y;
     
    2525}
    2626
    27 forall (otype T) {
     27forall (T) {
    2828    static inline {
    2929
     
    279279}
    280280
    281 forall(dtype ostype, otype T | writeable(T, ostype)) {
     281forall(ostype &, T | writeable(T, ostype)) {
    282282    ostype & ?|?(ostype & os, vec2(T) v) with (v) {
    283283        return os | '<' | x | ',' | y | '>';
  • libcfa/src/vec/vec3.hfa

    r92bfda0 rdafbde8  
    1919#include "vec.hfa"
    2020
    21 forall (otype T) {
     21forall (T) {
    2222    struct vec3 {
    2323        T x, y, z;
     
    2525}
    2626
    27 forall (otype T) {
     27forall (T) {
    2828    static inline {
    2929
     
    288288}
    289289
    290 forall(dtype ostype, otype T | writeable(T, ostype)) {
     290forall(ostype &, T | writeable(T, ostype)) {
    291291    ostype & ?|?(ostype & os, vec3(T) v) with (v) {
    292292        return os | '<' | x | ',' | y | ',' | z | '>';
  • libcfa/src/vec/vec4.hfa

    r92bfda0 rdafbde8  
    1919#include "vec.hfa"
    2020
    21 forall (otype T) {
     21forall (T) {
    2222    struct vec4 {
    2323        T x, y, z, w;
     
    2525}
    2626
    27 forall (otype T) {
     27forall (T) {
    2828    static inline {
    2929
     
    283283}
    284284
    285 forall(dtype ostype, otype T | writeable(T, ostype)) {
     285forall(ostype &, T | writeable(T, ostype)) {
    286286    ostype & ?|?(ostype & os, vec4(T) v) with (v) {
    287287        return os | '<' | x | ',' | y | ',' | z | ',' | w | '>';
  • src/Parser/parser.yy

    r92bfda0 rdafbde8  
    24412441type_parameter:                                                                                 // CFA
    24422442        type_class identifier_or_type_name
    2443                 { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
     2443                {   typedefTable.addToScope( *$2, TYPEDEFname, "9" );
     2444                        if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated" ); }
     2445                        if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated" ); }
     2446                        if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated" ); }
     2447                }
    24442448          type_initializer_opt assertion_list_opt
    24452449                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
  • src/ResolvExpr/PolyCost.cc

    r92bfda0 rdafbde8  
    3535                PassVisitor<PolyCost> coster( env, indexer );
    3636                type->accept( coster );
    37                 return coster.pass.result;
     37                return (coster.pass.result > 0) ? 1 : 0;
    3838        }
    3939
     
    8787        ast::Pass<PolyCost_new> costing( symtab, env );
    8888        type->accept( costing );
    89         return costing.core.result;
     89        return (costing.core.result > 0) ? 1 : 0;
    9090}
    9191
  • src/ResolvExpr/SpecCost.cc

    r92bfda0 rdafbde8  
    4343                // mark specialization of base type
    4444                void postvisit(ReferenceType*) { if ( count >= 0 ) ++count; }
     45
     46                void postvisit(StructInstType*) { if ( count >= 0 ) ++count; }
     47                void postvisit(UnionInstType*) { if ( count >= 0 ) ++count; }
    4548
    4649        private:
     
    8285                void previsit(StructInstType* sty) {
    8386                        count = minover( sty->parameters );
    84                         visit_children = false;
    8587                }
    8688
     
    8890                void previsit(UnionInstType* uty) {
    8991                        count = minover( uty->parameters );
    90                         visit_children = false;
    9192                }
    9293
     
    174175                void postvisit( const ast::ArrayType * ) { if ( count >= 0 ) ++count; }
    175176                void postvisit( const ast::ReferenceType * ) { if ( count >= 0 ) ++count; }
     177
     178                void postvisit( const ast::StructInstType * ) { if ( count >= 0 ) ++count; }
     179                void postvisit( const ast::UnionInstType * ) { if ( count >= 0 ) ++count; }
    176180
    177181                // Use the minimal specialization value over returns and params.
     
    189193                void previsit( const ast::StructInstType * sty ) {
    190194                        count = minimumPresent( sty->params, expr_result );
    191                         visit_children = false;
    192195                }
    193196
     
    195198                void previsit( const ast::UnionInstType * uty ) {
    196199                        count = minimumPresent( uty->params, expr_result );
    197                         visit_children = false;
    198200                }
    199201
  • tests/avltree/avl-private.cfa

    r92bfda0 rdafbde8  
    1111// an AVL tree's height is easy to compute
    1212// just follow path with the larger balance
    13 forall(otype K | Comparable(K), otype V)
     13forall(K | Comparable(K), V)
    1414int height(tree(K, V) * t){
    1515  int helper(tree(K, V) * t, int ht){
     
    2727}
    2828
    29 forall(otype K | Comparable(K), otype V)
     29forall(K | Comparable(K), V)
    3030int calcBalance(tree(K, V) * t){
    3131  int l = height(t->left);
     
    3636
    3737// re-establish the link between parent and child
    38 forall(otype K | Comparable(K), otype V)
     38forall(K | Comparable(K), V)
    3939void relinkToParent(tree(K, V) * t){
    4040  tree(K, V) * parent = t->parent; // FIX ME!!
     
    4949
    5050// rotate left from t
    51 forall(otype K | Comparable(K), otype V)
     51forall(K | Comparable(K), V)
    5252tree(K, V) * rotateLeft(tree(K, V) * t){
    5353  tree(K, V) * newRoot = t->right;
     
    6868
    6969// rotate right from t
    70 forall(otype K | Comparable(K), otype V)
     70forall(K | Comparable(K), V)
    7171tree(K, V) * rotateRight(tree(K, V) * t){
    7272  tree(K, V) * newRoot = t->left;
     
    8787
    8888// balances a node that has balance factor -2 or 2
    89 forall(otype K | Comparable(K), otype V)
     89forall(K | Comparable(K), V)
    9090tree(K, V) * fix(tree(K, V) * t){
    9191  // ensure that t's balance factor is one of
     
    113113
    114114// attempt to fix the tree, if necessary
    115 forall(otype K | Comparable(K), otype V)
     115forall(K | Comparable(K), V)
    116116tree(K, V) * tryFix(tree(K, V) * t){
    117117  int b = calcBalance(t);
     
    126126
    127127// sets parent field of c to be p
    128 forall(otype K | Comparable(K), otype V)
     128forall(K | Comparable(K), V)
    129129void setParent(tree(K, V) * c, tree(K, V) * p){
    130130  if (! empty(c)){
  • tests/avltree/avl-private.h

    r92bfda0 rdafbde8  
    55
    66// attempt to fix the tree, if necessary
    7 forall(otype K | Comparable(K), otype V)
     7forall(K | Comparable(K), V)
    88tree(K, V) * tryFix(tree(K, V) * t);
    99
    1010// sets parent field of c to be p
    11 forall(otype K | Comparable(K), otype V)
     11forall(K | Comparable(K), V)
    1212void setParent(tree(K, V) * c, tree(K, V) * p);
    1313
    14 forall(otype K | Comparable(K), otype V)
     14forall(K | Comparable(K), V)
    1515int height(tree(K, V) * t);
  • tests/avltree/avl.h

    r92bfda0 rdafbde8  
    99// #include <lib.h>
    1010
    11 trait Comparable(otype T) {
     11trait Comparable(T) {
    1212  int ?<?(T, T);
    1313};
    1414
    15 forall(otype T | Comparable(T))
     15forall(T | Comparable(T))
    1616int ?==?(T t1, T t2);
    1717
    18 forall(otype T | Comparable(T))
     18forall(T | Comparable(T))
    1919int ?>?(T t1, T t2);
    2020
     
    4141
    4242// temporary: need forward decl to get around typedef problem
    43 forall(otype K | Comparable(K), otype V)
     43forall(K | Comparable(K), V)
    4444struct tree;
    4545
    46 forall(otype K | Comparable(K), otype V)
     46forall(K | Comparable(K), V)
    4747struct tree {
    4848  K key;
     
    5454};
    5555
    56 forall(otype K | Comparable(K), otype V)
     56forall(K | Comparable(K), V)
    5757void ?{}(tree(K, V) &t, K key, V value);
    5858
    59 forall(otype K, otype V)
     59forall(K | Comparable(K), V)
    6060void ^?{}(tree(K, V) & t);
    6161
    62 forall(otype K | Comparable(K), otype V)
     62forall(K | Comparable(K), V)
    6363tree(K, V) * create(K key, V value);
    6464
    65 forall(otype K | Comparable(K), otype V)
     65forall(K | Comparable(K), V)
    6666V * find(tree(K, V) * t, K key);
    6767
    68 forall(otype K | Comparable(K), otype V)
     68forall(K | Comparable(K), V)
    6969int empty(tree(K, V) * t);
    7070
    7171// returns the root of the tree
    72 forall(otype K | Comparable(K), otype V)
     72forall(K | Comparable(K), V)
    7373int insert(tree(K, V) ** t, K key, V value);
    7474
    75 forall(otype K | Comparable(K), otype V)
     75forall(K | Comparable(K), V)
    7676int remove(tree(K, V) ** t, K key);
    7777
    78 forall(otype K | Comparable(K), otype V)
     78forall(K | Comparable(K), V)
    7979void copy(tree(K, V) * src, tree(K, V) ** ret);
    8080
    81 forall(otype K | Comparable(K), otype V)
     81forall(K | Comparable(K), V)
    8282void for_each(tree(K, V) * t, void (*func)(V));
    8383
  • tests/avltree/avl0.cfa

    r92bfda0 rdafbde8  
    11#include "avl.h"
    22
    3 forall(otype T | Comparable(T))
     3forall(T | Comparable(T))
    44int ?==?(T t1, T t2) {
    55  return !(t1 < t2) && !(t2 < t1);
    66}
    77
    8 forall(otype T | Comparable(T))
     8forall(T | Comparable(T))
    99int ?>?(T t1, T t2) {
    1010  return t2 < t1;
  • tests/avltree/avl1.cfa

    r92bfda0 rdafbde8  
    33#include <stdlib.hfa>
    44
    5 forall(otype K | Comparable(K), otype V)
     5forall(K | Comparable(K), V)
    66void ?{}(tree(K, V) &t, K key, V value){
    77  (t.key) { key };
     
    1313}
    1414
    15 forall(otype K, otype V)
     15forall(K| Comparable(K), V)
    1616void ^?{}(tree(K, V) & t){
    1717  delete(t.left);
     
    2121}
    2222
    23 forall(otype K | Comparable(K), otype V)
     23forall(K | Comparable(K), V)
    2424tree(K, V) * create(K key, V value) {
    2525  // infinite loop trying to resolve ... t = malloc();
  • tests/avltree/avl2.cfa

    r92bfda0 rdafbde8  
    22#include "avl-private.h"
    33
    4 forall(otype K | Comparable(K), otype V)
     4forall(K | Comparable(K), V)
    55V * find(tree(K, V) * t, K key){
    66  if (empty(t)){
     
    1818}
    1919
    20 forall(otype K | Comparable(K), otype V)
     20forall(K | Comparable(K), V)
    2121int empty(tree(K, V) * t){
    2222  return t == NULL;
     
    2424
    2525// returns the root of the tree
    26 forall(otype K | Comparable(K), otype V)
     26forall(K | Comparable(K), V)
    2727int insert(tree(K, V) ** t, K key, V value) {
    2828  // handles a non-empty tree
  • tests/avltree/avl3.cfa

    r92bfda0 rdafbde8  
    44
    55// swaps the data within two tree nodes
    6 forall(otype K | Comparable(K), otype V)
     6forall(K | Comparable(K), V)
    77void node_swap(tree(K, V) * t, tree(K, V) * t2){
    88        swap( t->key,  t2->key);