Changes in / [c7806122:91fb850]


Ignore:
Files:
3 deleted
23 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    rc7806122 r91fb850  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Wed Sep 23 21:21:55 2020
    14 %% Update Count     : 454
     13%% Last Modified On : Fri Sep  4 13:56:52 2020
     14%% Update Count     : 383
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\newlength{\parindentlnth}
    5656\setlength{\parindentlnth}{\parindent}
     57
     58\newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
     59\newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
     60\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
     61
     62\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     63\newlength{\columnposn}
     64\setlength{\gcolumnposn}{2.5in}
     65\setlength{\columnposn}{\gcolumnposn}
     66\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
     67\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
     68
     69% allow escape sequence in lstinline
     70%\usepackage{etoolbox}
     71%\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}
    5772
    5873\usepackage{pslatex}                                    % reduce size of san serif font
     
    229244\usepackage{listings}                                                                   % format program code
    230245\usepackage{lstlang}
    231 \makeatletter
    232 
    233 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
    234 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
    235 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    236 
    237 \newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    238 \newlength{\columnposn}
    239 \setlength{\gcolumnposn}{2.75in}
    240 \setlength{\columnposn}{\gcolumnposn}
    241 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
    242 \newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    243 
    244 % allow escape sequence in lstinline
    245 %\usepackage{etoolbox}
    246 %\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}
    247 
    248 % allow adding to lst literate
    249 \def\addToLiterate#1{\protect\edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}}
    250 \lst@Key{add to literate}{}{\addToLiterate{#1}}
    251 \makeatother
    252246
    253247\newcommand{\CFADefaults}{%
     
    268262belowskip=3pt,
    269263% replace/adjust listing characters that look bad in sanserif
    270 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     264literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    271265        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    272266        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
    273 }% lstset
    274 }% CFADefaults
    275 
    276 \ifdefined\CFALatin%
    277 \lstnewenvironment{cfa}[1][]{\CFADefaults
    278 \lstset{
    279 language=CFA,
    280 moredelim=**[is][\color{red}]{®}{®},    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     267moredelim=**[is][\color{red}]{?}{?},    % red highlighting ?...? (registered trademark symbol) emacs: C-q M-.
    281268moredelim=**[is][\color{blue}]{ß}{ß},   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    282269moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    283270moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    284 % replace/adjust listing characters that look bad in sanserif
    285 add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    286271}% lstset
    287 \lstset{#1}
    288 }{}
     272}% CFADefaults
     273\newcommand{\CFAStyle}{%
     274\CFADefaults
    289275% inline code ©...© (copyright symbol) emacs: C-q M-)
    290276\lstMakeShortInline©                                    % single-character for \lstinline
    291 \else% extra Latin-1 escape characters
    292 \lstset{
    293 language=CFA,
    294 escapechar=\$,                                                  % LaTeX escape in CFA code
    295 moredelim=**[is][\color{red}]{@}{@},    % red highlighting `...` (backtick symbol)
    296 }% lstset
    297 \lstnewenvironment{cfa}[1][]{\CFADefaults
    298 \lstset{
    299 language=CFA,
    300 escapechar=\$,                                                  % LaTeX escape in CFA code
    301 moredelim=**[is][\color{red}]{@}{@},    % red highlighting `...` (backtick symbol)
    302 }% lstset
    303 \lstset{#1}
    304 }{}
    305 % inline code @...@ (at symbol)
    306 \lstMakeShortInline@                                    % single-character for \lstinline
    307 \fi%
     277}% CFAStyle
     278
     279\lstnewenvironment{cfa}[1][]
     280{\CFADefaults\lstset{#1}}
     281{}
    308282
    309283% Local Variables: %
  • doc/LaTeXmacros/lstlang.sty

    rc7806122 r91fb850  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Wed Sep 23 22:40:04 2020
    11 %% Update Count     : 24
     10%% Last Modified On : Tue Jan  8 14:40:33 2019
     11%% Update Count     : 21
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    115115                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
    116116                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
    117                 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
     117                __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,
    118118                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
    119                 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, thread,
     119                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread,
    120120                _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
    121121                virtual, __volatile, __volatile__, waitfor, when, with, zero_t,
     
    125125
    126126% C++ programming language
    127 \lstdefinelanguage{C++}[ANSI]{C++}{
    128         morekeywords={nullptr,}
    129 }
     127\lstdefinelanguage{C++}[ANSI]{C++}{}
    130128
    131129% uC++ programming language, based on ANSI C++
  • doc/refrat/refrat.tex

    rc7806122 r91fb850  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Thu Sep 24 16:34:51 2020
    14 %% Update Count     : 109
     13%% Last Modified On : Wed Jan 31 17:30:23 2018
     14%% Update Count     : 108
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
     32\usepackage{xspace}
    3233\usepackage{varioref}                                                                   % extended references
     34\usepackage{listings}                                                                   % format program code
    3335\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3436\usepackage{latexsym}                                   % \Box glyph
    3537\usepackage{mathptmx}                                   % better math font with "times"
    3638\usepackage[usenames]{color}
    37 \newcommand{\CFALatin}{}
     39\input{common}                                          % common CFA document macros
     40\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     41\usepackage{breakurl}
     42\renewcommand{\UrlFont}{\small\sf}
     43
     44\usepackage[pagewise]{lineno}
     45\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     46\usepackage[firstpage]{draftwatermark}
     47\SetWatermarkLightness{0.9}
     48
     49% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     50% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     51% AFTER HYPERREF.
     52\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     53
     54\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     55\setlength{\headsep}{0.25in}
     56
     57%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     58
     59\CFAStyle                                                                                               % use default CFA format-style
     60\lstnewenvironment{C++}[1][]                            % use C++ style
     61{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}}
     62{}
     63
    3864% inline code ©...© (copyright symbol) emacs: C-q M-)
    3965% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    4369% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    4470% math escape $...$ (dollar symbol)
    45 \input{common}                                          % common CFA document macros
    46 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    47 \usepackage{breakurl}
    48 \renewcommand{\UrlFont}{\small\sf}
    49 
    50 \usepackage[pagewise]{lineno}
    51 \renewcommand{\linenumberfont}{\scriptsize\sffamily}
    52 \usepackage[firstpage]{draftwatermark}
    53 \SetWatermarkLightness{0.9}
    54 
    55 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    56 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    57 % AFTER HYPERREF.
    58 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    59 
    60 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
    61 \setlength{\headsep}{0.25in}
    6271
    6372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    6473
    65 \CFADefaults                                                                                    % use default CFA format-style
    66 \lstnewenvironment{C++}[1][]                            % use C++ style
    67 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
    68 {}
    69 
    70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    71 
    7274% Names used in the document.
    73 \newcommand{\Version}{\input{build/version}}
     75\newcommand{\Version}{\input{../../version}}
    7476\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    7577\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
  • doc/theses/andrew_beach_MMath/thesis.tex

    rc7806122 r91fb850  
    3434\usepackage[toc,abbreviations]{glossaries-extra}
    3535
    36 % Define all the glossaries.
    37 \input{glossaries}
     36% Main glossary entries -- definitions of relevant terminology
     37\newglossaryentry{computer}
     38{
     39name=computer,
     40description={A programmable machine that receives input data,
     41               stores and manipulates the data, and provides
     42               formatted output}
     43}
     44
     45% Nomenclature glossary entries -- New definitions, or unusual terminology
     46\newglossary*{nomenclature}{Nomenclature}
     47\newglossaryentry{dingledorf}
     48{
     49type=nomenclature,
     50name=dingledorf,
     51description={A person of supposed average intelligence who makes incredibly
     52               brainless misjudgments}
     53}
     54
     55% List of Abbreviations (abbreviations are from the glossaries-extra package)
     56\newabbreviation{aaaaz}{AAAAZ}{American Association of Amature Astronomers
     57               and Zoologists}
     58
     59% List of Symbols
     60\newglossary*{symbols}{List of Symbols}
     61\newglossaryentry{rvec}
     62{
     63name={$\mathbf{v}$},
     64sort={label},
     65type=symbols,
     66description={Random vector: a location in n-dimensional Cartesian space, where
     67               each dimensional component is determined by a random process}
     68}
    3869
    3970% Generate the glossaries defined above.
  • doc/theses/fangren_yu_COOP_S20/Report.tex

    rc7806122 r91fb850  
    2626\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    2727\newcommand{\NOTE}{\textbf{NOTE}}
    28 \newcommand{\TODO}[1]{{\color{Purple}#1}}
    2928
    3029\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     
    3635\lstset{
    3736language=C++,                                                                                   % make C++ the default language
     37escapechar=\$,                                                                                  % LaTeX escape in CFA code
     38moredelim=**[is][\color{red}]{`}{`},
    3839}% lstset
     40\lstMakeShortInline@%
    3941\lstnewenvironment{C++}[1][]                            % use C++ style
    40 {\lstset{language=C++,moredelim=**[is][\color{red}]{@}{@},#1}}{}
     42{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}}
     43{}
    4144
    4245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    8184\section{Overview}
    8285
    83 cfa-cc is the reference compiler for the \CFA programming language, which is a non-object-oriented extension to C.
    84 \CFA attempts to introduce productive modern programming language features to C while maintaining as much backward-compatibility as possible, so that most existing C programs can seamlessly work with \CFA.
    85 
    86 Since the \CFA project dates back to the early 2000s, and only restarted in the past few years, there is a significant amount of legacy code in the current compiler codebase with little documentation.
    87 The lack of documentation makes it difficult to develop new features from the current implementation and diagnose problems.
    88 
    89 Currently, the \CFA team is also facing poor compiler performance.
    90 For the development of a new programming language, writing standard libraries is an important component.
    91 The slow compiler causes building of the library files to take tens of minutes, making iterative development and testing almost impossible.
    92 There is an ongoing effort to rewrite the core data-structure of the compiler to overcome the performance issue, but many bugs have appeared during this work, and lack of documentation is hampering debugging.
    93 
    94 This developer's reference manual begins the documentation and should be continuously im\-proved until it eventually covers the entire compiler codebase.
    95 For now, the focus is mainly on the parts being rewritten, and also the primary performance bottleneck, namely the resolution algorithm.
    96 Its aimed is to provide new project developers with guidance in understanding the codebase, and clarify the purpose and behaviour of certain functions that are not mentioned in the previous \CFA research papers~\cite{Bilson03,Ditchfield92,Moss19}.
     86cfa-cc is the reference compiler for the \CFA programming language, which is a non-
     87object-oriented extension to C.
     88\CFA attempts to introduce productive modern programming language features to C
     89while maintaining as much backward-compatibility as possible, so that most existing C
     90programs can seamlessly work with \CFA.
     91
     92Since the \CFA project was dated back to the early 2000s, and only restarted in the past
     93few years, there is a significant amount of legacy code in the current compiler codebase,
     94with little proper documentation available. This becomes a difficulty while developing new
     95features based on the previous implementations, and especially while diagnosing
     96problems.
     97
     98Currently, the \CFA team is also facing another problem: bad compiler performance. For
     99the development of a new programming language, writing a standard library is an
     100important part. The incompetence of the compiler causes building the library files to take
     101tens of minutes, making iterative development and testing almost impossible. There is
     102ongoing effort to rewrite the core data structure of the compiler to overcome the
     103performance issue, but many bugs may appear during the work, and lack of documentation
     104makes debugging extremely difficult.
     105
     106This developer's reference will be continuously improved and eventually cover the
     107compiler codebase. For now, the focus is mainly on the parts being rewritten, and also the
     108performance bottleneck, namely the resolution algorithm. It is aimed to provide new
     109developers to the project enough guidance and clarify the purposes and behavior of certain
     110functions which are not mentioned in the previous \CFA research papers.
    97111
    98112
    99113\section{Compiler Framework}
    100114
    101 \CFA source code is first transformed into an abstract syntax tree (AST) by the parser before analyzed by the compiler.
    102 
    103 
    104115\subsection{AST Representation}
    105116
    106 
    107 There are 4 major categories of AST nodes used by the compiler, along with some derived structures.
    108 
    109 \subsubsection{Declaration Nodes}
     117Source code input is first transformed into abstract syntax tree (AST) representation by the
     118parser before analyzed by the compiler.
     119
     120There are 4 major categories of AST nodes used by the compiler, along with some derived
     121structures.
     122
     123\subsubsection{Declaration nodes}
    110124
    111125A declaration node represents either of:
    112126\begin{itemize}
    113127\item
    114 type declaration: @struct@, @union@, @typedef@ or type parameter \TODO{(see Appendix A.3)}
    115 \item
    116 variable declaration
    117 \item
    118 function declaration
     128Type declaration: struct, union, typedef or type parameter (see Appendix A.3)
     129\item
     130Variable declaration
     131\item
     132Function declaration
    119133\end{itemize}
    120134Declarations are introduced by standard C declarations, with the usual scoping rules.
    121 In addition, declarations can also be qualified by the \lstinline[language=CFA]@forall@ clause (which is the origin of \CFA's name):
     135In addition, declarations can also be introduced by the forall clause (which is the origin
     136of \CFA's name):
    122137\begin{cfa}
    123 forall ( <$\emph{TypeParameterList}$> | <$\emph{AssertionList}$> )
     138forall (<$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>)
    124139        $\emph{declaration}$
    125140\end{cfa}
    126 Type parameters in \CFA are similar to \CC template type parameters.
    127 The \CFA declaration
     141Type parameters in \CFA are similar to \CC template type parameters. The \CFA
     142declaration
    128143\begin{cfa}
    129144forall (dtype T) ...
    130145\end{cfa}
    131 behaves similarly to the \CC template declaration
     146behaves similarly as the \CC template declaration
    132147\begin{C++}
    133148template <typename T> ...
    134149\end{C++}
    135150
    136 Assertions are a distinctive feature of \CFA, similar to \emph{interfaces} in D and Go, and \emph{traits} in Rust.
    137 Contrary to the \CC template where arbitrary functions and operators can be used in a template definition, in a \CFA parametric function, operations on parameterized types must be declared in assertions.
     151Assertions are a distinctive feature of \CFA: contrary to the \CC template where
     152arbitrary functions and operators can be used in a template definition, in a \CFA
     153parametric function, operations on parameterized types must be declared in assertions.
     154
    138155Consider the following \CC template:
    139156\begin{C++}
    140 @template@ forall<typename T> T foo( T t ) {
    141         return t + t * t;
     157template <typename T> int foo(T t) {
     158        return bar(t) + baz(t);
    142159}
    143160\end{C++}
    144 where there are no explicit requirements on the type @T@.
    145 Therefore, the \CC compiler must deduce what operators are required during textual (macro) expansion of the template at each usage.
    146 As a result, templates cannot be compiled.
    147 \CFA assertions specify restrictions on type parameters:
     161Unless bar and baz are also parametric functions taking any argument type, they must be
     162declared in the assertions, or otherwise the code will not compile:
    148163\begin{cfa}
    149 forall( dtype T | @{ T ?+?( T, T ); T ?*?( T, T ) }@ ) int foo ( T t ) {
    150         return t + t * t;
     164forall (dtype T | { int bar(T); int baz(t); }) int foo (T t) {
     165        return bar(t) + baz(t);
    151166}
    152167\end{cfa}
    153 Assertions are written using the usual \CFA function declaration syntax.
    154 Only types with operators ``@+@'' and ``@*@'' work with this function, and the function prototype is sufficient to allow separate compilation.
    155 
    156 Type parameters and assertions are used in the following compiler data-structures.
    157 
    158 
    159 \subsubsection{Type Nodes}
    160 
    161 Type nodes represent the type of an object or expression.
    162 Named types reference the corresponding type declarations.
    163 The type of a function is its function pointer type (same as standard C).
    164 With the addition of type parameters, named types may contain a list of parameter values (actual parameter types).
    165 
    166 
    167 \subsubsection{Statement Nodes}
    168 
    169 Statement nodes represent the executable statements in the program, including basic expression statements, control flows and blocks.
     168Assertions are written using the usual function declaration syntax. The scope of type
     169parameters and assertions is the following declaration.
     170
     171\subsubsection{Type nodes}
     172
     173A type node represents the type of an object or expression.
     174Named types reference the corresponding type declarations. The type of a function is its
     175function pointer type (same as standard C).
     176With the addition of type parameters, named types may contain a list of parameter values
     177(actual parameter types).
     178
     179\subsubsection{Statement nodes}
     180
     181Statement nodes represent the statements in the program, including basic expression
     182statements, control flows and blocks.
    170183Local declarations (within a block statement) are represented as declaration statements.
    171184
    172 
    173 \subsubsection{Expression Nodes}
    174 
    175 Some expressions are represented differently before and after the resolution stage:
     185\subsubsection{Expression nodes}
     186
     187Some expressions are represented differently in the compiler before and after resolution
     188stage:
    176189\begin{itemize}
    177190\item
    178 Name expressions: @NameExpr@ pre-resolution, @VariableExpr@ post-resolution
    179 \item
    180 Member expressions: @UntypedMemberExpr@ pre-resolution, @MemberExpr@ post-resolution
    181 \item
    182 \begin{sloppypar}
    183 Function call expressions (including overloadable operators): @UntypedExpr@ pre-resolution, @ApplicationExpr@ post-resolution
    184 \end{sloppypar}
     191Name expressions: NameExpr pre-resolution, VariableExpr post-resolution
     192\item
     193Member expressions: UntypedMemberExpr pre-resolution, MemberExpr post-resolution
     194\item
     195Function call expressions (including overloadable operators): UntypedExpr pre-resolution, ApplicationExpr post-resolution
    185196\end{itemize}
    186 The pre-resolution representation contains only the symbols.
    187 Post-resolution links them to the actual variable and function declarations.
     197The pre-resolution representations contain only the symbols. Post-resolution results link
     198them to the actual variable and function declarations.
    188199
    189200
    190201\subsection{Compilation Passes}
    191202
    192 Compilation steps are implemented as passes, which follows a general structural recursion pattern on the syntax tree.
    193 
    194 The basic workflow of compilation passes follows preorder and postorder traversal on the AST data-structure, implemented with visitor pattern, and can be loosely described with the following pseudocode:
    195 \begin{C++}
    196 Pass::visit( node_t node ) {
    197         previsit( node );
    198         if ( visit_children )
     203Compilation steps are implemented as passes, which follows a general structural recursion
     204pattern on the syntax tree.
     205
     206The basic work flow of compilation passes follows preorder and postorder traversal on
     207tree data structure, implemented with visitor pattern, and can be loosely described with
     208the following pseudocode:
     209\begin{C++}
     210Pass::visit (node_t node) {
     211        previsit(node);
     212        if (visit_children)
    199213                for each child of node:
    200                         child.accept( this );
    201         postvisit( node );
     214                        child.accept(this);
     215        postvisit(node);
    202216}
    203217\end{C++}
    204 Operations in @previsit@ happen in preorder (top to bottom) and operations in @postvisit@ happen in postorder (bottom to top).
    205 The precise order of recursive operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and @AST/Pass.impl.hpp@ (new).
    206 
    207 Implementations of compilation passes follow certain conventions:
     218Operations in previsit() happen in preorder (top to bottom) and operations in
     219postvisit() happen in postorder (bottom to top). The precise order of recursive
     220operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and
     221@AST/Pass.impl.hpp@ (new).
     222Implementations of compilation passes need to follow certain conventions:
    208223\begin{itemize}
    209224\item
    210 Passes \textbf{should not} directly override the visit method (Non-virtual Interface principle);
    211 if a pass desires different recursion behaviour, it should set @visit_children@ to false and perform recursive calls manually within previsit or postvisit procedures.
    212 To enable this option, inherit from the @WithShortCircuiting@ mixin.
    213 \item
    214 previsit may mutate the node but \textbf{must not} change the node type or return @nullptr@.
    215 \item
    216 postvisit may mutate the node, reconstruct it to a different node type, or delete it by returning @nullptr@.
     225Passes \textbf{should not} directly override the visit method (Non-virtual Interface
     226principle); if a pass desires different recursion behavior, it should set
     227@visit_children@ to false and perform recursive calls manually within previsit or
     228postvisit procedures. To enable this option, inherit from @WithShortCircuiting@ mixin.
     229\item
     230previsit may mutate the node but \textbf{must not} change the node type or return null.
     231\item
     232postvisit may mutate the node, reconstruct it to a different node type, or delete it by
     233returning null.
    217234\item
    218235If the previsit or postvisit method is not defined for a node type, the step is skipped.
    219 If the return type is declared as @void@, the original node is returned by default.
    220 These behaviours are controlled by template specialization rules;
    221 see @Common/PassVisitor.proto.h@ (old) and @AST/@ @Pass.proto.hpp@ (new) for details.
     236If the return type is declared as void, the original node is returned by default. These
     237behaviors are controlled by template specialization rules; see
     238@Common/PassVisitor.proto.h@ (old) and @AST/Pass.proto.hpp@ (new) for details.
    222239\end{itemize}
    223240Other useful mixin classes for compilation passes include:
    224241\begin{itemize}
    225242\item
    226 @WithGuards@ allows saving and restoring variable values automatically upon entering/exiting the current node.
    227 \item
    228 @WithVisitorRef@ creates a wrapped entity for the current pass (the actual argument passed to recursive calls internally) for explicit recursion, usually used together with @WithShortCircuiting@.
    229 \item
    230 @WithSymbolTable@ gives a managed symbol table with built-in scoping-rule handling (\eg on entering and exiting a block statement)
     243WithGuards allows saving values of variables and restore automatically upon exiting
     244the current node.
     245\item
     246WithVisitorRef creates a wrapped entity of current pass (the actual argument
     247passed to recursive calls internally) for explicit recursion, usually used together
     248with WithShortCircuiting.
     249\item
     250WithSymbolTable gives a managed symbol table with built-in scoping rule handling
     251(\eg on entering and exiting a block statement)
    231252\end{itemize}
    232 \NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures to its own scope, or otherwise they are not picked up by template resolution:
     253\NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading
     254resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures
     255to its own scope, or otherwise they will not be picked up by template resolution:
    233256\begin{C++}
    234257class Pass2: public Pass1 {
    235         @using Pass1::previsit;@
    236         @using Pass1::postvisit;@
     258        using Pass1::previsit;
     259        using Pass1::postvisit;
    237260        // new procedures
    238261}
     
    240263
    241264
    242 \subsection{Data Structure Change (new-ast)}
    243 
    244 It has been observed that excessive copying of syntax tree structures accounts for a majority of computation cost and significantly slows down the compiler.
    245 In the previous implementation of the syntax tree, every internal node has a unique parent;
    246 therefore all copies are required to duplicate the entire subtree.
    247 A new, experimental re-implementation of the syntax tree (source under directory @AST/@ hereby referred to as ``new-ast'') attempts to overcome this issue with a functional approach that allows sharing of common sub-structures and only makes copies when necessary.
    248 
    249 The core of new-ast is a customized implementation of smart pointers, similar to @std::shared_ptr@ and @std::weak_ptr@ in the \CC standard library.
    250 Reference counting is used to detect sharing and allowing certain optimizations.
    251 For a purely functional (immutable) data-structure, all mutations are modelled by shallow copies along the path of mutation.
     265\subsection{Data Structure Change WIP (new-ast)}
     266
     267It has been observed that excessive copying of syntax tree structures accounts for a
     268majority of computation cost and significantly slows down the compiler. In the previous
     269implementation of the syntax tree, every internal node has a unique parent; therefore all
     270copies are required to duplicate everything down to the bottom. A new, experimental
     271re-implementation of the syntax tree (source under directory AST/ hereby referred to as
     272``new-ast'') attempts to overcome this issue with a functional approach that allows sharing
     273of common sub-structures and only makes copies when necessary.
     274
     275The core of new-ast is a customized implementation of smart pointers, similar to
     276@std::shared_ptr@ and @std::weak_ptr@ in \CC standard library. Reference counting is
     277used to detect sharing and allows optimization. For a purely functional (a.k.a. immutable)
     278data structure, all mutations are modelled by shallow copies along the path of mutation.
    252279With reference counting optimization, unique nodes are allowed to be mutated in place.
    253 This however, may potentially introduce some complications and bugs;
    254 a few issues are discussed near the end of this section.
    255 
    256 
    257 \subsubsection{Source: \lstinline{AST/Node.hpp}}
    258 
    259 Class @ast::Node@ is the base class of all new-ast node classes, which implements reference counting mechanism.
    260 Two different counters are recorded: ``strong'' reference count for number of nodes semantically owning it;
    261 ``weak'' reference count for number of nodes holding a mere reference and only need to observe changes.
    262 Class @ast::ptr_base@ is the smart pointer implementation and also takes care of resource management.
    263 
    264 Direct access through the smart pointer is read-only.
    265 A mutable access should be obtained by calling @shallowCopy@ or mutate as below.
    266 
    267 Currently, the weak pointers are only used to reference declaration nodes from a named type, or a variable expression.
    268 Since declaration nodes are intended to denote unique entities in the program, weak pointers always point to unique (unshared) nodes.
    269 This property may change in the future, and weak references to shared nodes may introduce some problems;
     280This however, may potentially introduce some complications and bugs; a few issues are
     281discussed near the end of this section.
     282
     283\subsubsection{Source: AST/Node.hpp}
     284
     285class @ast::Node@ is the base class of all new-ast node classes, which implements
     286reference counting mechanism. Two different counters are recorded: ``strong'' reference
     287count for number of nodes semantically owning it; ``weak'' reference count for number of
     288nodes holding a mere reference and only need to observe changes.
     289class @ast::ptr_base@ is the smart pointer implementation and also takes care of
     290resource management.
     291
     292Direct access through the smart pointer is read-only. A mutable access should be obtained
     293by calling shallowCopy or mutate as below.
     294
     295Currently, the weak pointers are only used to reference declaration nodes from a named
     296type, or a variable expression. Since declaration nodes are intended to denote unique
     297entities in the program, weak pointers always point to unique (unshared) nodes. This may
     298change in the future, and weak references to shared nodes may introduce some problems;
    270299see mutate function below.
    271300
    272 All node classes should always use smart pointers in structure definitions versus raw pointers.
    273 Function
     301All node classes should always use smart pointers in the structure and should not use raw
     302pointers.
     303
    274304\begin{C++}
    275305void ast::Node::increment(ref_type ref)
    276306\end{C++}
    277 increments this node's strong or weak reference count.
    278 Function
     307Increments this node's strong or weak reference count.
    279308\begin{C++}
    280309void ast::Node::decrement(ref_type ref, bool do_delete = true)
    281310\end{C++}
    282 decrements this node's strong or weak reference count.
    283 If strong reference count reaches zero, the node is deleted.
    284 \NOTE: Setting @do_delete@ to false may result in a detached node.
    285 Subsequent code should manually delete the node or assign it to a strong pointer to prevent memory leak.
    286 
     311Decrements this node's strong or weak reference count. If strong reference count reaches
     312zero, the node is deleted by default.
     313\NOTE: Setting @do_delete@ to false may result in a detached node. Subsequent code should
     314manually delete the node or assign it to a strong pointer to prevent memory leak.
    287315Reference counting functions are internally called by @ast::ptr_base@.
    288 Function
    289316\begin{C++}
    290317template<typename node_t>
    291318node_t * shallowCopy(const node_t * node)
    292319\end{C++}
    293 returns a mutable, shallow copy of node: all child pointers are pointing to the same child nodes.
    294 Function
     320Returns a mutable, shallow copy of node: all child pointers are pointing to the same child
     321nodes.
    295322\begin{C++}
    296323template<typename node_t>
    297324node_t * mutate(const node_t * node)
    298325\end{C++}
    299 returns a mutable pointer to the same node, if the node is unique (strong reference count is 1);
    300 otherwise, it returns @shallowCopy(node)@.
    301 It is an error to mutate a shared node that is weak-referenced.
    302 Currently this does not happen.
    303 A problem may appear once weak pointers to shared nodes (\eg expression nodes) are used;
    304 special care is needed.
    305 
    306 \NOTE: This naive uniqueness check may not be sufficient in some cases.
    307 A discussion of the issue is presented at the end of this section.
    308 Functions
     326If node is unique (strong reference count is 1), returns a mutable pointer to the same node.
     327Otherwise, returns shallowCopy(node).
     328It is an error to mutate a shared node that is weak-referenced. Currently this does not
     329happen. The problem may appear once weak pointers to shared nodes (\eg expression
     330nodes) are used; special care will be needed.
     331
     332\NOTE: This naive uniqueness check may not be sufficient in some cases. A discussion of the
     333issue is presented at the end of this section.
    309334\begin{C++}
    310335template<typename node_t, typename parent_t, typename field_t, typename assn_t>
    311 const node_t * mutate_field(const node_t * node, field_t parent_t::* field, assn_t && val)
     336const node_t * mutate_field(const node_t * node, field_t parent_t::*field, assn_t && val)
    312337\end{C++}
    313338\begin{C++}
     
    317342                field_t && val)
    318343\end{C++}
    319 are helpers for mutating a field on a node using pointer to a member function (creates shallow copy when necessary).
    320 
    321 
    322 \subsubsection{Issue: Undetected Sharing}
    323 
    324 The @mutate@ behaviour described above has a problem: deeper shared nodes may be
     344Helpers for mutating a field on a node using pointer to member (creates shallow copy
     345when necessary).
     346
     347\subsubsection{Issue: Undetected sharing}
     348
     349The @mutate@ behavior described above has a problem: deeper shared nodes may be
    325350mistakenly considered as unique. \VRef[Figure]{f:DeepNodeSharing} shows how the problem could arise:
    326351\begin{figure}
     
    330355\label{f:DeepNodeSharing}
    331356\end{figure}
    332 Given the tree rooted at P1, which is logically the chain P1-A-B, and P2 is irrelevant, assume @mutate(B)@ is called.
    333 The algorithm considers B as unique since it is only directly owned by A.
    334 However, the other tree P2-A-B indirectly shares the node B and is therefore wrongly mutated.
    335 
    336 To partly address this problem, if the mutation is called higher up the tree, a chain mutation helper can be used.
    337 
    338 \subsubsection{Source: \lstinline{AST/Chain.hpp}}
    339 
    340 Function
     357Suppose that we are working on the tree rooted at P1, which
     358is logically the chain P1-A-B and P2 is irrelevant, and then
     359mutate(B) is called. The algorithm considers B as unique since
     360it is only directly owned by A. However, the other tree P2-A-B
     361indirectly shares the node B and is therefore wrongly mutated.
     362
     363To partly address this problem, if the mutation is called higher up the tree, a chain
     364mutation helper can be used:
     365
     366\subsubsection{Source: AST/Chain.hpp}
     367
    341368\begin{C++}
    342369template<typename node_t, Node::ref_type ref_t>
    343370auto chain_mutate(ptr_base<node_t, ref_t> & base)
    344371\end{C++}
    345 returns a chain mutator handle that takes pointer-to-member to go down the tree, while creating shallow copies as necessary;
    346 see @struct _chain_mutator@ in the source code for details.
    347 
    348 For example, in the above diagram, if mutation of B is wanted while at P1, the call using @chain_mutate@ looks like the following:
     372This function returns a chain mutator handle which takes pointer-to-member to go down
     373the tree while creating shallow copies as necessary; see @struct _chain_mutator@ in the
     374source code for details.
     375
     376For example, in the above diagram, if mutation of B is wanted while at P1, the call using
     377@chain_mutate@ looks like the following:
    349378\begin{C++}
    350379chain_mutate(P1.a)(&A.b) = new_value_of_b;
    351380\end{C++}
    352 \NOTE: if some node in chain mutate is shared (therefore shallow copied), it implies that every node further down is also copied, thus correctly executing the functional mutation algorithm.
    353 This example code creates copies of both A and B and performs mutation on the new nodes, so that the other tree P2-A-B is untouched.
    354 However, if a pass traverses down to node B and performs mutation, for example, in @postvisit(B)@, information on sharing higher up is lost.
    355 Since the new-ast structure is only in experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up, this issue does not actually happen.
    356 It should be addressed in the future when other compilation passes are migrated to new-ast and many of them contain procedural mutations, where it might cause accidental mutations to other logically independent trees (\eg common sub-expression) and become a bug.
    357 
    358 
     381Note that if some node in chain mutate is shared (therefore shallow copied), it implies that
     382every node further down will also be copied, thus correctly executing the functional
     383mutation algorithm. This example code creates copies of both A and B and performs
     384mutation on the new nodes, so that the other tree P2-A-B is untouched.
     385However, if a pass traverses down to node B and performs mutation, for example, in
     386@postvisit(B)@, information on sharing higher up is lost. Since the new-ast structure is only in
     387experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up,
     388this issue does not actually happen. It should be addressed in the future when other
     389compilation passes are migrated to new-ast and many of them contain procedural
     390mutations, where it might cause accidental mutations to other logically independent trees
     391(\eg common sub-expression) and become a bug.
     392
     393
     394\vspace*{20pt} % FIX ME, spacing problem with this heading ???
    359395\section{Compiler Algorithm Documentation}
    360396
    361 This compiler algorithm documentation covers most of the resolver, data structures used in variable and expression resolution, and a few directly related passes.
    362 Later passes involving code generation are not included yet;
    363 documentation for those will be done latter.
    364 
     397This documentation currently covers most of the resolver, data structures used in variable
     398and expression resolution, and a few directly related passes. Later passes involving code
     399generation is not included yet; documentation for those will be done afterwards.
    365400
    366401\subsection{Symbol Table}
    367402
    368 \NOTE: For historical reasons, the symbol-table data-structure is called @indexer@ in the old implementation.
    369 Hereby, the name is changed to @SymbolTable@.
    370 The symbol table stores a mapping from names to declarations, implements a similar name-space separation rule, and provides the same scoping rules as standard C.\footnote{ISO/IEC 9899:1999, Sections 6.2.1 and 6.2.3.}
    371 The difference in name-space rule is that @typedef@ aliases are no longer considered ordinary identifiers.
    372 In addition to C tag-types (@struct@, @union@, @enum@), \CFA introduces another tag type, @trait@, which is a named collection of assertions.
    373 
    374 
    375 \subsubsection{Source: \lstinline{AST/SymbolTable.hpp}}
    376 
    377 \TODO{Add something here}
    378 
    379 
    380 \subsubsection{Source: \lstinline{SymTab/Indexer.h}}
    381 
    382 Function
     403\NOTE: For historical reasons, the symbol table data structure was called ``indexer'' in the
     404old implementation. Hereby we will be using the name SymbolTable everywhere.
     405The symbol table stores a mapping from names to declarations and implements a similar
     406name space separation rule, and the same scoping rules in standard C.\footnote{ISO/IEC 9899:1999, Sections 6.2.1 and 6.2.3} The difference in
     407name space rule is that typedef aliases are no longer considered ordinary identifiers.
     408In addition to C tag types (struct, union, enum), \CFA introduces another tag type, trait,
     409which is a named collection of assertions.
     410
     411\subsubsection{Source: AST/SymbolTable.hpp}
     412
     413\subsubsection{Source: SymTab/Indexer.h}
     414
    383415\begin{C++}
    384416SymbolTable::addId(const DeclWithType * decl)
    385417\end{C++}
    386 provides name mangling of identifiers, since \CFA allows overloading of variables and functions.
    387 The mangling scheme is closely based on the Itanium \CC ABI,\footnote{\url{https://itanium-cxx-abi.github.io/cxx-abi/abi.html}, Section 5.1} while making adaptations to \CFA specific features, mainly assertions and overloaded variables by type.
    388 
    389 Naming conflicts are handled by mangled names;
    390 lookup by name returns a list of declarations with the same identifier name.
    391 Functions
     418Since \CFA allows overloading of variables and functions, ordinary identifier names need
     419to be mangled. The mangling scheme is closely based on the Itanium \CC ABI,\footnote{\url{https://itanium-cxx-abi.github.io/cxx-abi/abi.html}, Section 5.1} while
     420making adaptations to \CFA specific features, mainly assertions and overloaded variables
     421by type. Naming conflicts are handled by mangled names; lookup by name returns a list of
     422declarations with the same literal identifier name.
     423
    392424\begin{C++}
    393425SymbolTable::addStruct(const StructDecl * decl)
     
    396428SymbolTable::addTrait(const TraitDecl * decl)
    397429\end{C++}
    398 add a tag-type declaration to the symbol table.
    399 Function
     430Adds a tag type declaration to the symbol table.
    400431\begin{C++}
    401432SymbolTable::addType(const NamedTypeDecl * decl)
    402433\end{C++}
    403 adds a @typedef@ alias to the symbol table.
    404 
    405 \textbf{C Incompatibility Note}: Since \CFA allows using @struct@, @union@ and @enum@ type-names without a prefix keyword, as in \CC, @typedef@ names and tag-type names cannot be disambiguated by syntax rules.
    406 Currently the compiler puts them together and disallows collision.
    407 The following program is valid C but invalid \CFA (and \CC):
     434Adds a typedef alias to the symbol table.
     435
     436\textbf{C Incompatibility Note}: Since Cforall allows using struct, union and enum type names
     437without the keywords, typedef names and tag type names cannot be disambiguated by
     438syntax rules. Currently the compiler puts them together and disallows collision. The
     439following program is valid C but not valid Cforall:
    408440\begin{C++}
    409441struct A {};
    410 typedef int A; // gcc: ok, cfa: Cannot redefine typedef A
    411 struct A sa; // C disambiguates via struct prefix
    412 A ia;
    413 \end{C++}
    414 In practices, such usage is extremely rare, and hence, this change (as in \CC) has minimal impact on existing C programs.
    415 The declaration
    416 \begin{C++}
    417 struct A {};
    418 typedef struct A A; // A is an alias for struct A
    419 A a;
    420 struct A b;
    421 \end{C++}
    422 is not an error because the alias name is identical to the original.
    423 Finally, the following program is allowed in \CFA:
    424 \begin{C++}
    425442typedef int A;
    426 void A(); // name mangled
     443// gcc: ok, cfa: Cannot redefine typedef A
     444\end{C++}
     445In actual practices however, such usage is extremely rare, and typedef struct A A; is
     446not considered an error, but silently discarded. Therefore, we expect this change to have
     447minimal impact on existing C programs.
     448Meanwhile, the following program is allowed in Cforall:
     449\begin{C++}
     450typedef int A;
     451void A();
    427452// gcc: A redeclared as different kind of symbol, cfa: ok
    428453\end{C++}
    429 because the function name is mangled.
    430 
    431454
    432455\subsection{Type Environment and Unification}
    433456
    434 The following core ideas underlie the parametric type-resolution algorithm.
    435 A type environment organizes type parameters into \textbf{equivalent classes} and maps them to actual types.
    436 Unification is the algorithm that takes two (possibly parametric) types and parameter mappings, and attempts to produce a common type by matching information in the type environments.
     457The core of parametric type resolution algorithm.
     458Type Environment organizes type parameters in \textbf{equivalent classes} and maps them to
     459actual types. Unification is the algorithm that takes two (possibly parametric) types and
     460parameter mappings and attempts to produce a common type by matching the type
     461environments.
    437462
    438463The unification algorithm is recursive in nature and runs in two different modes internally:
    439464\begin{itemize}
    440465\item
    441 Exact unification mode requires equivalent parameters to match perfectly.
    442 \item
    443 Inexact unification mode allows equivalent parameters to be converted to a common type.
     466\textbf{Exact} unification mode requires equivalent parameters to match perfectly;
     467\item
     468\textbf{Inexact} unification mode allows equivalent parameters to be converted to a
     469common type.
    444470\end{itemize}
    445 For a pair of matching parameters (actually, their equivalent classes), if either side is open (not bound to a concrete type yet), they are combined.
    446 
    447 Within the inexact mode, types are allowed to differ on their cv-qualifiers (\eg @const@, @volatile@, \etc);
    448 additionally, if a type never appear either in a parameter list or as the base type of a pointer, it may also be widened (\ie safely converted).
    449 As \CFA currently does not implement subclassing as in object-oriented languages, widening conversions are only on the primitive types, \eg conversion from @int@ to @long int@.
    450 
    451 The need for two unification modes comes from the fact that parametric types are considered compatible only if all parameters are exactly the same (not just compatible).
    452 Pointer types also behaves similarly;
    453 in fact, they may be viewed as a primitive kind of parametric types.
    454 @int *@ and @long *@ are different types, just like @vector(int)@ and @vector(long)@ are, for the parametric type @*(T)@ / @vector(T)@, respectively.
    455 
    456 The resolver uses the following @public@ functions:\footnote{
    457 Actual code also tracks assertions on type parameters; those extra arguments are omitted here for conciseness.}
    458 
    459 
    460 \subsubsection{Source: \lstinline{ResolvExpr/Unify.cc}}
    461 
    462 Function
    463 \begin{C++}
    464 bool unify(const Type * type1, const Type * type2, TypeEnvironment & env,
    465         OpenVarSet & openVars, const SymbolTable & symtab, Type *& commonType)
    466 \end{C++}
    467 returns a boolean indicating if the unification succeeds or fails after attempting to unify @type1@ and @type2@ within current type environment.
    468 If the unify succeeds, @env@ is modified by combining the equivalence classes of matching parameters in @type1@ and @type2@, and their common type is written to @commonType@.
    469 If the unify fails, nothing changes.
    470 Functions
    471 \begin{C++}
    472 bool typesCompatible(const Type * type1, const Type * type2, const SymbolTable & symtab,
    473         const TypeEnvironment & env)
    474 bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type * type2,
    475         const SymbolTable & symtab, const TypeEnvironment & env)
    476 \end{C++}
    477 return a boolean indicating if types @type1@ and @type2@ can possibly be the same type.
    478 The second version ignores the outermost cv-qualifiers if present.\footnote{
    479 In \lstinline@const int * const@, only the second \lstinline@const@ is ignored.}
    480 These function have no side effects.
    481 
    482 \NOTE: No attempt is made to widen the types (exact unification is used), although the function names may suggest otherwise, \eg @typesCompatible(int, long)@ returns false.
     471For a pair of matching parameters (actually, their equivalent classes), if either side is open
     472(not bound to a concrete type yet), they are simply combined.
     473
     474Within inexact mode, types are allowed to differ on their cv-qualifiers; additionally, if a
     475type never appear either in parameter list or as the base type of a pointer, it may also be
     476widened (i.e. safely converted). As Cforall currently does not implement subclassing similar
     477to object-oriented languages, widening conversions are on primitive types only, for
     478example the conversion from int to long.
     479
     480The need for two unification modes come from the fact that parametric types are
     481considered compatible only if all parameters are exactly the same (not just compatible).
     482Pointer types also behaves similarly; in fact, they may be viewed as a primitive kind of
     483parametric types. @int*@ and @long*@ are different types, just like @vector(int)@ and
     484@vector(long)@ are, for the parametric type @vector(T)@.
     485
     486The resolver should use the following ``@public@'' functions:\footnote{
     487Actual code also tracks assertions on type parameters; those extra arguments are omitted here for
     488conciseness.}
     489
     490
     491\subsubsection{Source: ResolvExpr/Unify.cc}
     492
     493\begin{C++}
     494bool unify(const Type *type1, const Type *type2, TypeEnvironment &env,
     495OpenVarSet &openVars, const SymbolTable &symtab, Type *&commonType)
     496\end{C++}
     497Attempts to unify @type1@ and @type2@ with current type environment.
     498
     499If operation succeeds, @env@ is modified by combining the equivalence classes of matching
     500parameters in @type1@ and @type2@, and their common type is written to commonType.
     501
     502If operation fails, returns false.
     503\begin{C++}
     504bool typesCompatible(const Type * type1, const Type * type2, const
     505SymbolTable &symtab, const TypeEnvironment &env)
     506bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type *
     507type2, const SymbolTable &symtab, const TypeEnvironment &env)
     508\end{C++}
     509
     510Determines if type1 and type2 can possibly be the same type. The second version ignores
     511the outermost cv-qualifiers if present.\footnote{
     512In const \lstinline@int * const@, only the second \lstinline@const@ is ignored.}
     513
     514The call has no side effect.
     515
     516\NOTE: No attempts are made to widen the types (exact unification is used), although the
     517function names may suggest otherwise. E.g. @typesCompatible(int, long)@ returns false.
    483518
    484519
    485520\subsection{Expression Resolution}
    486521
    487 The design of the current version of expression resolver is outlined in the Ph.D.\ thesis by Aaron Moss~\cite{Moss19}.
     522The design of the current version of expression resolver is outlined in the Ph.D. Thesis from
     523Aaron Moss~\cite{Moss19}.
     524
    488525A summary of the resolver algorithm for each expression type is presented below.
    489526
    490 All overloadable operators are modelled as function calls.
    491 For a function call, interpretations of the function and arguments are found recursively.
    492 Then the following steps produce a filtered list of valid interpretations:
     527All overloadable operators are modelled as function calls. For a function call,
     528interpretations of the function and arguments are found recursively. Then the following
     529steps produce a filtered list of valid interpretations:
    493530\begin{enumerate}
    494531\item
    495 From all possible combinations of interpretations of the function and arguments, those where argument types may be converted to function parameter types are considered valid.
     532From all possible combinations of interpretations of the function and arguments,
     533those where argument types may be converted to function parameter types are
     534considered valid.
    496535\item
    497536Valid interpretations with the minimum sum of argument costs are kept.
    498537\item
    499 \label{p:argcost}
    500 Argument costs are then discarded; the actual cost for the function call expression is the sum of conversion costs from the argument types to parameter types.
    501 \item
    502 \label{p:returntype}
    503 For each return type, the interpretations with satisfiable assertions are then sorted by actual cost computed in step~\ref{p:argcost}.
    504 If for a given type, the minimum cost interpretations are not unique, that return type is ambiguous.
    505 If the minimum cost interpretation is unique but contains an ambiguous argument, it is also ambiguous.
     538Argument costs are then discarded; the actual cost for the function call expression is
     539the sum of conversion costs from the argument types to parameter types.
     540\item
     541For each return type, the interpretations with satisfiable assertions are then sorted
     542by actual cost computed in step 3. If for a given type, the minimum cost
     543interpretations are not unique, it is said that for that return type the interpretation
     544is ambiguous. If the minimum cost interpretation is unique but contains an
     545ambiguous argument, it is also considered ambiguous.
    506546\end{enumerate}
    507 Therefore, for each return type, the resolver produces:
     547Therefore, for each return type, the resolver produces either of:
    508548\begin{itemize}
    509549\item
    510 no alternatives
    511 \item
    512 a single valid alternative
    513 \item
    514 an ambiguous alternative
     550No alternatives
     551\item
     552A single valid alternative
     553\item
     554An ambiguous alternative
    515555\end{itemize}
    516 \NOTE: an ambiguous alternative may be discarded at the parent expressions because a different return type matches better for the parent expressions.
    517 
    518 The \emph{non}-overloadable expressions in \CFA are: cast expressions, address-of (unary @&@) expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional expression (@?:@).
    519 
    520 For a cast expression, the convertible argument types are kept.
    521 Then the result is selected by lowest argument cost, and further by lowest conversion cost to target type.
    522 If the lowest cost is still not unique or an ambiguous argument interpretation is selected, the cast expression is ambiguous.
    523 In an expression statement, the top level expression is implicitly cast to @void@.
     556Note that an ambiguous alternative may be discarded at the parent expressions because a
     557different return type matches better for the parent expressions.
     558
     559The non-overloadable expressions in Cforall are: cast expressions, address-of (unary @&@)
     560expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional
     561expression (@?:@).
     562
     563For a cast expression, the convertible argument types are kept. Then the result is selected
     564by lowest argument cost, and further by lowest conversion cost to target type. If the lowest
     565cost is still not unique, or an ambiguous argument interpretation is selected, the cast
     566expression is ambiguous. In an expression statement, the top level expression is implicitly
     567cast to void.
    524568
    525569For an address-of expression, only lvalue results are kept and the minimum cost is selected.
    526570
    527 For logical expressions @&&@ and @||@, arguments are implicitly cast to @bool@, and follow the rules fr cast expression above.
    528 
    529 For the ternary conditional expression, the condition is implicitly cast to @bool@, and the branch expressions must have compatible types.
    530 Each pair of compatible branch expression types produce a possible interpretation, and the cost is defined as the sum of the expression costs plus the sum of conversion costs to the common type.
    531 
    532 \TODO{Write a specification for expression costs.}
     571For logical expressions @&&@ and @||@, arguments are implicitly cast to bool, and follow the rule
     572of cast expression as above.
     573
     574For the ternary conditional expression, the condition is implicitly cast to bool, and the
     575branch expressions must have compatible types. Each pair of compatible branch
     576expression types produce a possible interpretation, and the cost is defined as the sum of
     577expression costs plus the sum of conversion costs to the common type.
     578
     579TODO: Write a specification for expression costs.
    533580
    534581
    535582\subsection{Assertion Satisfaction}
    536583
    537 The resolver tries to satisfy assertions on expressions only when it is needed: either while selecting from multiple alternatives of a same result type for a function call (step \ref{p:returntype} of resolving function calls) or upon reaching the top level of an expression statement.
    538 
    539 Unsatisfiable alternatives are discarded.
    540 Satisfiable alternatives receive \textbf{implicit parameters}: in \CFA, parametric functions may be separately compiled, as opposed to \CC templates which are only compiled at instantiation.
    541 Given the parametric function-definition:
     584The resolver tries to satisfy assertions on expressions only when it is needed: either while
     585selecting from multiple alternatives of a same result type for a function call (step 4 of
     586resolving function calls), or upon reaching the top level of an expression statement.
     587
     588Unsatisfiable alternatives are discarded. Satisfiable alternatives receive \textbf{implicit
     589parameters}: in Cforall, parametric functions are designed such that they can be compiled
     590separately, as opposed to \CC templates which are only compiled at instantiation. Given a
     591parametric function definition:
    542592\begin{C++}
    543593forall (otype T | {void foo(T);})
    544594void bar (T t) { foo(t); }
    545595\end{C++}
    546 the function @bar@ does not know which @foo@ to call when compiled without knowing the call site, so it requests a function pointer to be passed as an extra argument.
    547 At the call site, implicit parameters are automatically inserted by the compiler.
    548 
    549 \TODO{Explain how recursive assertion satisfaction and polymorphic recursion work.}
     596The function bar does not know which @foo@ to call when compiled without knowing the call
     597site, so it requests a function pointer to be passed as an extra argument. At the call site,
     598implicit parameters are automatically inserted by the compiler.
     599
     600\textbf{TODO}: Explain how recursive assertion satisfaction and polymorphic recursion work.
    550601
    551602
     
    554605\subsection{Test Suites}
    555606
    556 Automatic test suites are located under the @tests/@ directory.
    557 A test case consists of an input CFA source file (suffix @.cfa@), and an expected output file located in the @tests/.expect/@ directory, with the same file name ending with suffix @.txt@.
    558 For example, the test named @tests/tuple/tupleCast.cfa@ has the following files, for example:
     607Automatic test suites are located under the @tests/@ directory. A test case consists of an
     608input CFA source file (name ending with @.cfa@), and an expected output file located
     609in @.expect/@ directory relative to the source file, with the same file name ending with @.txt@.
     610So a test named @tuple/tupleCast@ has the following files, for example:
    559611\begin{C++}
    560612tests/
    561         tuple/
    562                 .expect/
    563                         tupleCast.txt
    564                 tupleCast.cfa
    565 \end{C++}
    566 If compilation fails, the error output is compared to the expect file.
    567 If the compilation succeeds but does not generate an executable, the compilation output is compared to the expect file.
    568 If the compilation succeeds and generates an executable, the executable is run and its output is compared to the expect file.
    569 To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of test names to be run, or @--all@ (or @make all-tests@) to run all tests.
    570 The test script reports test cases fail/success, compilation time and program run time.
    571 To see all the options available for @test.py@ using the @--help@ option.
     613..     tuple/
     614......     .expect/
     615..........       tupleCast.txt
     616......     tupleCast.cfa
     617\end{C++}
     618If compilation fails, the error output is compared to the expect file. If compilation succeeds,
     619the built program is run and its output compared to the expect file.
     620To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of
     621test names to be run, or @--all@ to run all tests. The test script reports test cases
     622fail/success, compilation time and program run time.
    572623
    573624
    574625\subsection{Performance Reports}
    575626
    576 To turn on performance reports, pass the @-XCFA -S@ flag to the compiler.
    577 Three kinds of performance reports are available:
     627To turn on performance reports, pass @-S@ flag to the compiler.
     628
     6293 kinds of performance reports are available:
    578630\begin{enumerate}
    579631\item
     
    587639@Common/Stats/Counter.h@.
    588640\end{enumerate}
    589 It is suggested to run performance tests with optimization (@g++@ flag @-O3@).
     641It is suggested to run performance tests with optimized build (@g++@ flag @-O3@)
    590642
    591643
  • doc/user/user.tex

    rc7806122 r91fb850  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Thu Sep 24 16:34:52 2020
    14 %% Update Count     : 3997
     13%% Last Modified On : Fri Mar  6 13:34:52 2020
     14%% Update Count     : 3924
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
     32\usepackage{xspace}
    3233\usepackage{varioref}                                                                   % extended references
    33 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
    34 \renewcommand{\thesubfigure}{\alph{subfigure})}
     34\usepackage{listings}                                                                   % format program code
    3535\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3636\usepackage{latexsym}                                   % \Box glyph
    3737\usepackage{mathptmx}                                   % better math font with "times"
    3838\usepackage[usenames]{color}
    39 \newcommand{\CFALatin}{}
     39\input{common}                                          % common CFA document macros
     40\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     41\usepackage{breakurl}
     42
     43\usepackage[pagewise]{lineno}
     44\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     45\usepackage[firstpage]{draftwatermark}
     46\SetWatermarkLightness{0.9}
     47
     48% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     49% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     50% AFTER HYPERREF.
     51\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     52
     53\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     54\setlength{\headsep}{0.25in}
     55
     56%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     57
     58\CFAStyle                                                                                               % use default CFA format-style
     59\lstnewenvironment{C++}[1][]                            % use C++ style
     60{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     61{}
     62
    4063% inline code ©...© (copyright symbol) emacs: C-q M-)
    4164% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    4568% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    4669% math escape $...$ (dollar symbol)
    47 \input{common}                                          % common CFA document macros
    48 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    49 \usepackage{breakurl}
    50 
    51 \renewcommand\footnoterule{\kern -3pt\rule{0.3\linewidth}{0.15pt}\kern 2pt}
    52 
    53 \usepackage[pagewise]{lineno}
    54 \renewcommand{\linenumberfont}{\scriptsize\sffamily}
    55 \usepackage[firstpage]{draftwatermark}
    56 \SetWatermarkLightness{0.9}
    57 
    58 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    59 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    60 % AFTER HYPERREF.
    61 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    62 
    63 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
    64 \setlength{\headsep}{0.25in}
    65 
    66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    67 
    68 \CFADefaults                                                                                    % use default CFA format-style
    69 \lstnewenvironment{C++}[1][]                            % use C++ style
    70 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
    71 {}
    72 
    73 \newsavebox{\myboxA}
    74 \newsavebox{\myboxB}
    7570
    7671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    8479\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    8580\newcommand{\KWC}{K-W C\xspace}
     81
     82\newsavebox{\LstBox}
    8683
    8784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    256253
    257254The signature feature of \CFA is \emph{\Index{overload}able} \Index{parametric-polymorphic} functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a ©forall© clause (giving the language its name):
    258 \begin{cfa}
     255\begin{lstlisting}
    259256®forall( otype T )® T identity( T val ) { return val; }
    260257int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    261 \end{cfa}
     258\end{lstlisting}
    262259% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
    263260\CFA{}\hspace{1pt}'s polymorphism was originally formalized by \Index*{Glen Ditchfield}\index{Ditchfield, Glen}~\cite{Ditchfield92}, and first implemented by \Index*{Richard Bilson}\index{Bilson, Richard}~\cite{Bilson03}.
     
    278275\begin{comment}
    279276A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array:
    280 \begin{cfa}
     277\begin{lstlisting}
    281278void * bsearch( const void * key, const void * base, size_t dim, size_t size,
    282279                                int (* compar)( const void *, const void * ));
     
    287284double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    288285double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    289 \end{cfa}
     286\end{lstlisting}
    290287which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
    291 \begin{cfa}
     288\begin{lstlisting}
    292289forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
    293290        int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ }
     
    300297double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    301298int posn = bsearch( 5.0, vals, 10 );
    302 \end{cfa}
     299\end{lstlisting}
    303300The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result.
    304301Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
     
    308305\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations.
    309306For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©:
    310 \begin{cfa}
     307\begin{lstlisting}
    311308forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    312309int * ip = malloc(); §\C{// select type and size from left-hand side}§
    313310double * dp = malloc();
    314311struct S {...} * sp = malloc();
    315 \end{cfa}
     312\end{lstlisting}
    316313where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    317314\end{comment}
     
    946943the same level as a ©case© clause; the target label may be case ©default©, but only associated
    947944with the current ©switch©/©choose© statement.
     945
     946
     947\subsection{Loop Control}
     948
     949The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
     950\begin{itemize}
     951\item
     952The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.
     953\item
     954An empty conditional implies comparison value of ©1© (true).
     955\item
     956A comparison N is implicit up-to exclusive range [0,N©®)®©.
     957\item
     958A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
     959\item
     960The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
     961\item
     962The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
     963\item
     964The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
     965\item
     966The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.
     967\item
     968©0© is the implicit start value;
     969\item
     970©1© is the implicit increment value.
     971\item
     972The up-to range uses operator ©+=© for increment;
     973\item
     974The down-to range uses operator ©-=© for decrement.
     975\item
     976©@© means put nothing in this field.
     977\item
     978©:© means start another index.
     979\end{itemize}
    948980
    949981\begin{figure}
     
    10541086
    10551087
    1056 \subsection{Loop Control}
    1057 
    1058 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
    1059 \begin{itemize}
    1060 \item
    1061 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.
    1062 \item
    1063 An empty conditional implies comparison value of ©1© (true).
    1064 \item
    1065 A comparison N is implicit up-to exclusive range [0,N©®)®©.
    1066 \item
    1067 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
    1068 \item
    1069 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
    1070 \item
    1071 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
    1072 \item
    1073 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
    1074 \item
    1075 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.
    1076 \item
    1077 ©0© is the implicit start value;
    1078 \item
    1079 ©1© is the implicit increment value.
    1080 \item
    1081 The up-to range uses operator ©+=© for increment;
    1082 \item
    1083 The down-to range uses operator ©-=© for decrement.
    1084 \item
    1085 ©@© means put nothing in this field.
    1086 \item
    1087 ©:© means start another index.
    1088 \end{itemize}
    1089 
    1090 
    10911088%\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    10921089\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
     
    10981095for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
    10991096\VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels.
    1100 The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
     1097The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
    11011098
    11021099\begin{figure}
    1103 \centering
    1104 \begin{lrbox}{\myboxA}
    1105 \begin{cfa}[tabsize=3]
    1106 ®Compound:® {
    1107         ®Try:® try {
    1108                 ®For:® for ( ... ) {
    1109                         ®While:® while ( ... ) {
    1110                                 ®Do:® do {
    1111                                         ®If:® if ( ... ) {
    1112                                                 ®Switch:® switch ( ... ) {
    1113                                                         case 3:
    1114                                                                 ®break Compound®;
    1115                                                                 ®break Try®;
    1116                                                                 ®break For®;      /* or */  ®continue For®;
    1117                                                                 ®break While®;  /* or */  ®continue While®;
    1118                                                                 ®break Do®;      /* or */  ®continue Do®;
    1119                                                                 ®break If®;
    1120                                                                 ®break Switch®;
    1121                                                         } // switch
    1122                                                 } else {
    1123                                                         ... ®break If®; ...     // terminate if
    1124                                                 } // if
    1125                                 } while ( ... ); // do
    1126                         } // while
    1127                 } // for
    1128         } ®finally® { // always executed
    1129         } // try
     1100\begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     1101\multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}   & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
     1102\begin{cfa}
     1103®LC:® {
     1104        ... §declarations§ ...
     1105        ®LS:® switch ( ... ) {
     1106          case 3:
     1107                ®LIF:® if ( ... ) {
     1108                        ®LF:® for ( ... ) {
     1109                                ®LW:® while ( ... ) {
     1110                                        ... break ®LC®; ...
     1111                                        ... break ®LS®; ...
     1112                                        ... break ®LIF®; ...
     1113                                        ... continue ®LF;® ...
     1114                                        ... break ®LF®; ...
     1115                                        ... continue ®LW®; ...
     1116                                        ... break ®LW®; ...
     1117                                } // while
     1118                        } // for
     1119                } else {
     1120                        ... break ®LIF®; ...
     1121                } // if
     1122        } // switch
    11301123} // compound
    11311124\end{cfa}
    1132 \end{lrbox}
    1133 
    1134 \begin{lrbox}{\myboxB}
    1135 \begin{cfa}[tabsize=3]
     1125&
     1126\begin{cfa}
    11361127{
    1137 
    1138                 ®ForC:® for ( ... ) {
    1139                         ®WhileC:® while ( ... ) {
    1140                                 ®DoC:® do {
    1141                                         if ( ... ) {
    1142                                                 switch ( ... ) {
    1143                                                         case 3:
    1144                                                                 ®goto Compound®;
    1145                                                                 ®goto Try®;
    1146                                                                 ®goto ForB®;      /* or */  ®goto ForC®;
    1147                                                                 ®goto WhileB®;  /* or */  ®goto WhileC®;
    1148                                                                 ®goto DoB®;      /* or */  ®goto DoC®;
    1149                                                                 ®goto If®;
    1150                                                                 ®goto Switch®;
    1151                                                         } ®Switch:® ;
    1152                                                 } else {
    1153                                                         ... ®goto If®; ...      // terminate if
    1154                                                 } ®If:®;
    1155                                 } while ( ... ); ®DoB:® ;
    1156                         } ®WhileB:® ;
    1157                 } ®ForB:® ;
    1158 
    1159 
    1160 } ®Compound:® ;
    1161 \end{cfa}
    1162 \end{lrbox}
    1163 
    1164 \subfloat[\CFA]{\label{f:CFibonacci}\usebox\myboxA}
    1165 \hspace{2pt}
    1166 \vrule
    1167 \hspace{2pt}
    1168 \subfloat[C]{\label{f:CFAFibonacciGen}\usebox\myboxB}
     1128        ... §declarations§ ...
     1129        switch ( ... ) {
     1130          case 3:
     1131                if ( ... ) {
     1132                        for ( ... ) {
     1133                                while ( ... ) {
     1134                                        ... goto ®LC®; ...
     1135                                        ... goto ®LS®; ...
     1136                                        ... goto ®LIF®; ...
     1137                                        ... goto ®LFC®; ...
     1138                                        ... goto ®LFB®; ...
     1139                                        ... goto ®LWC®; ...
     1140                                        ... goto ®LWB®; ...
     1141                                  ®LWC®: ; } ®LWB:® ;
     1142                          ®LFC:® ; } ®LFB:® ;
     1143                } else {
     1144                        ... goto ®LIF®; ...
     1145                } ®L3:® ;
     1146        } ®LS:® ;
     1147} ®LC:® ;
     1148\end{cfa}
     1149&
     1150\begin{cfa}
     1151
     1152
     1153
     1154
     1155
     1156
     1157
     1158// terminate compound
     1159// terminate switch
     1160// terminate if
     1161// continue loop
     1162// terminate loop
     1163// continue loop
     1164// terminate loop
     1165
     1166
     1167
     1168// terminate if
     1169
     1170
     1171
     1172\end{cfa}
     1173\end{tabular}
    11691174\caption{Multi-level Exit}
    11701175\label{f:MultiLevelExit}
     
    14211426try {
    14221427        f(...);
    1423 } catch( E e ; §boolean-predicate§ ) {          §\C{// termination handler}§
     1428} catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
    14241429        // recover and continue
    1425 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
     1430} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
    14261431        // repair and return
    14271432} finally {
     
    34863491For implicit formatted input, the common case is reading a sequence of values separated by whitespace, where the type of an input constant must match with the type of the input variable.
    34873492\begin{cquote}
    3488 \begin{lrbox}{\myboxA}
     3493\begin{lrbox}{\LstBox}
    34893494\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    34903495int x;   double y   char z;
     
    34923497\end{lrbox}
    34933498\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}}
    3494 \multicolumn{1}{@{}l@{}}{\usebox\myboxA} \\
     3499\multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\
    34953500\multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
    34963501\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     
    66676672For example, an initial alignment and fill capability are preserved during a resize copy so the copy has the same alignment and extended storage is filled.
    66686673Without sticky properties it is dangerous to use ©realloc©, resulting in an idiom of manually performing the reallocation to maintain correctness.
    6669 \begin{cfa}
    6670 
    6671 \end{cfa}
    66726674
    66736675\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
     
    67196721
    67206722        // §\CFA§ safe general allocation, fill, resize, alignment, array
    6721         T * alloc( void );§\indexc{alloc}§                                      §\C[3.5in]{// variable, T size}§
    6722         T * alloc( size_t dim );                                                        §\C{// array[dim], T size elements}§
    6723         T * alloc( T ptr[], size_t dim );                                       §\C{// realloc array[dim], T size elements}§
    6724 
    6725         T * alloc_set( char fill );§\indexc{alloc_set}§         §\C{// variable, T size, fill bytes with value}§
    6726         T * alloc_set( T fill );                                                        §\C{// variable, T size, fill with value}§
    6727         T * alloc_set( size_t dim, char fill );                         §\C{// array[dim], T size elements, fill bytes with value}§
    6728         T * alloc_set( size_t dim, T fill );                            §\C{// array[dim], T size elements, fill elements with value}§
    6729         T * alloc_set( size_t dim, const T fill[] );            §\C{// array[dim], T size elements, fill elements with array}§
    6730         T * alloc_set( T ptr[], size_t dim, char fill );        §\C{// realloc array[dim], T size elements, fill bytes with value}§
    6731 
    6732         T * alloc_align( size_t align );                                        §\C{// aligned variable, T size}§
    6733         T * alloc_align( size_t align, size_t dim );            §\C{// aligned array[dim], T size elements}§
    6734         T * alloc_align( T ptr[], size_t align );                       §\C{// realloc new aligned array}§
    6735         T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§
    6736 
    6737         T * alloc_align_set( size_t align, char fill );         §\C{// aligned variable, T size, fill bytes with value}§
    6738         T * alloc_align_set( size_t align, T fill );            §\C{// aligned variable, T size, fill with value}§
    6739         T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§
    6740         T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§
    6741         T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§
    6742         T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§
     6723        T * alloc( void );§\indexc{alloc}§
     6724        T * alloc( size_t dim );
     6725        T * alloc( T ptr[], size_t dim );
     6726        T * alloc_set( char fill );§\indexc{alloc_set}§
     6727        T * alloc_set( T fill );
     6728        T * alloc_set( size_t dim, char fill );
     6729        T * alloc_set( size_t dim, T fill );
     6730        T * alloc_set( size_t dim, const T fill[] );
     6731        T * alloc_set( T ptr[], size_t dim, char fill );
     6732
     6733        T * alloc_align( size_t align );
     6734        T * alloc_align( size_t align, size_t dim );
     6735        T * alloc_align( T ptr[], size_t align ); // aligned realloc array
     6736        T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array
     6737        T * alloc_align_set( size_t align, char fill );
     6738        T * alloc_align_set( size_t align, T fill );
     6739        T * alloc_align_set( size_t align, size_t dim, char fill );
     6740        T * alloc_align_set( size_t align, size_t dim, T fill );
     6741        T * alloc_align_set( size_t align, size_t dim, const T fill[] );
     6742        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill );
    67436743
    67446744        // §\CFA§ safe initialization/copy, i.e., implicit size specification
  • src/AST/Convert.cpp

    rc7806122 r91fb850  
    177177        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
    178178                if ( inCache( node ) ) return nullptr;
    179 
    180                 // function decl contains real variables that the type must use.
    181                 // the structural change means function type in and out of decl
    182                 // must be handled **differently** on convert back to old.
    183                 auto ftype = new FunctionType(
    184                         cv(node->type),
    185                         (bool)node->type->isVarArgs
    186                 );
    187                 ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns);
    188                 ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
    189 
    190                 ftype->forall = get<TypeDecl>().acceptL( node->type->forall );
    191 
    192                 visitType(node->type, ftype);
    193 
    194179                auto decl = new FunctionDecl(
    195180                        node->name,
    196181                        Type::StorageClasses( node->storage.val ),
    197182                        LinkageSpec::Spec( node->linkage.val ),
    198                         ftype,
    199                         //get<FunctionType>().accept1( node->type ),
     183                        get<FunctionType>().accept1( node->type ),
    200184                        {},
    201185                        get<Attribute>().acceptL( node->attributes ),
     
    11681152
    11691153        const ast::Type * visit( const ast::FunctionType * node ) override final {
    1170                 static std::string dummy_paramvar_prefix = "__param_";
    1171                 static std::string dummy_returnvar_prefix = "__retval_";
    1172 
    11731154                auto ty = new FunctionType {
    11741155                        cv( node ),
    11751156                        (bool)node->isVarArgs
    11761157                };
    1177                 auto returns = get<Type>().acceptL(node->returns);
    1178                 auto params = get<Type>().acceptL(node->params);
    1179 
    1180                 int ret_index = 0;
    1181                 for (auto t: returns) {
    1182                         // xxx - LinkageSpec shouldn't matter but needs to be something
    1183                         ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
    1184                         ty->returnVals.push_back(dummy);
    1185                 }
    1186                 int param_index = 0;
    1187                 for (auto t: params) {
    1188                         ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
    1189                         ty->parameters.push_back(dummy);
    1190                 }
    1191 
    1192                 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    1193                 // ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     1158                ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
     1159                ty->parameters = get<DeclarationWithType>().acceptL( node->params );
    11941160                ty->forall = get<TypeDecl>().acceptL( node->forall );
    11951161                return visitType( node, ty );
     
    14081374        ast::Node * node = nullptr;
    14091375        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1410         /// in case that some nodes are dropped by conversion (due to possible structural change)
    1411         /// use smart pointers in cache value to prevent accidental invalidation.
    1412         /// at conversion stage, all created nodes are guaranteed to be unique, therefore
    1413         /// const_casting out of smart pointers is permitted.
    1414         std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {};
     1376        std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
    14151377
    14161378        // Local Utilities:
     
    14851447                auto it = cache.find( old );
    14861448                if ( it == cache.end() ) return false;
    1487                 node = const_cast<ast::Node *>(it->second.get());
     1449                node = it->second;
    14881450                return true;
    14891451        }
     
    15241486        virtual void visit( const FunctionDecl * old ) override final {
    15251487                if ( inCache( old ) ) return;
    1526                 auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType);
    1527                 auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType);
    1528                 auto forall = GET_ACCEPT_V(type->forall, TypeDecl);
    1529 
    1530                 // function type is now derived from parameter decls instead of storing them
    1531                 auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
    1532                 ftype->params.reserve(paramVars.size());
    1533                 ftype->returns.reserve(returnVars.size());
    1534 
    1535                 for (auto & v: paramVars) {
    1536                         ftype->params.emplace_back(v->get_type());
    1537                 }
    1538                 for (auto & v: returnVars) {
    1539                         ftype->returns.emplace_back(v->get_type());
    1540                 }
    1541                 ftype->forall = std::move(forall);
    1542                 visitType(old->type, ftype);
    1543 
    15441488                auto decl = new ast::FunctionDecl{
    15451489                        old->location,
    15461490                        old->name,
    1547                         // GET_ACCEPT_1(type, FunctionType),
    1548                         std::move(paramVars),
    1549                         std::move(returnVars),
     1491                        GET_ACCEPT_1(type, FunctionType),
    15501492                        {},
    15511493                        { old->storageClasses.val },
     
    15541496                        { old->get_funcSpec().val }
    15551497                };
    1556 
    1557                 decl->type = ftype;
    15581498                cache.emplace( old, decl );
    1559 
    15601499                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    15611500                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    25762515                        cv( old )
    25772516                };
    2578                 auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType);
    2579                 auto paramVars = GET_ACCEPT_V(parameters, DeclWithType);
    2580                 // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
    2581                 // ty->params = GET_ACCEPT_V( parameters, DeclWithType );
    2582                 for (auto & v: returnVars) {
    2583                         ty->returns.emplace_back(v->get_type());
    2584                 }
    2585                 for (auto & v: paramVars) {
    2586                         ty->params.emplace_back(v->get_type());
    2587                 }
     2517                ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
     2518                ty->params = GET_ACCEPT_V( parameters, DeclWithType );
    25882519                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25892520                visitType( old, ty );
  • src/AST/Decl.hpp

    rc7806122 r91fb850  
    124124class FunctionDecl : public DeclWithType {
    125125public:
    126         std::vector<ptr<DeclWithType>> params;
    127         std::vector<ptr<DeclWithType>> returns;
    128         // declared type, derived from parameter declarations
    129126        ptr<FunctionType> type;
    130127        ptr<CompoundStmt> stmts;
    131128        std::vector< ptr<Expr> > withExprs;
    132129
    133         FunctionDecl( const CodeLocation & loc, const std::string & name,
    134                 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     130        FunctionDecl( const CodeLocation & loc, const std::string & name, FunctionType * type,
    135131                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    136132                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
    137         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     133        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
    138134          stmts( stmts ) {}
    139135
  • src/AST/ForallSubstitutor.hpp

    rc7806122 r91fb850  
    3333        }
    3434
    35         template<typename node_t >
    36         std::vector<ptr<node_t>> operator() (const std::vector<ptr<node_t>> & o) {
    37                 std::vector<ptr<node_t>> n;
    38                 n.reserve(o.size());
    39                 for (const node_t * d : o) { n.emplace_back(d->accept(*visitor)); }
    40                 return n;
    41         }
    42        
    43         /*
    44 
    4535        /// Substitute parameter/return type
    4636        std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) {
     
    5848                return n;
    5949        }
    60 
    61         */
    6250};
    6351
  • src/AST/Pass.impl.hpp

    rc7806122 r91fb850  
    465465                        __pass::symtab::addId( core, 0, func );
    466466                        VISIT(
    467                                 // parameter declarations are now directly here
    468                                 maybe_accept( node, &FunctionDecl::params );
    469                                 maybe_accept( node, &FunctionDecl::returns );
    470                                 // foralls are still in function type
    471467                                maybe_accept( node, &FunctionDecl::type );
    472468                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
  • src/AST/SymbolTable.cpp

    rc7806122 r91fb850  
    335335}
    336336
    337 /*
    338337void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    339338        addTypes( ftype->forall );
     
    341340        addIds( ftype->params );
    342341}
    343 */
    344342
    345343void SymbolTable::lazyInitScope() {
     
    370368                assert( ! params.empty() );
    371369                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    372                 const Type * base = InitTweak::getPointerBase( params.front() );
     370                const Type * base = InitTweak::getPointerBase( params.front()->get_type() );
    373371                assert( base );
    374372                return Mangle::mangle( base );
  • src/AST/SymbolTable.hpp

    rc7806122 r91fb850  
    145145
    146146        /// convenience function for adding all of the declarations in a function type to the indexer
    147         // void addFunctionType( const FunctionType * ftype );
     147        void addFunctionType( const FunctionType * ftype );
    148148
    149149private:
  • src/AST/Type.cpp

    rc7806122 r91fb850  
    102102// --- FunctionType
    103103
    104 
    105104FunctionType::FunctionType( const FunctionType & o )
    106105: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     
    113112
    114113namespace {
    115         bool containsTtype( const std::vector<ptr<Type>> & l ) {
     114        bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
    116115                if ( ! l.empty() ) {
    117                         return Tuples::isTtype( l.back() );
     116                        return Tuples::isTtype( l.back()->get_type() );
    118117                }
    119118                return false;
  • src/AST/Type.hpp

    rc7806122 r91fb850  
    302302class FunctionType final : public ParameterizedType {
    303303public:
    304 //      std::vector<ptr<DeclWithType>> returns;
    305 //      std::vector<ptr<DeclWithType>> params;
    306 
    307         std::vector<ptr<Type>> returns;
    308         std::vector<ptr<Type>> params;
     304        std::vector<ptr<DeclWithType>> returns;
     305        std::vector<ptr<DeclWithType>> params;
    309306
    310307        /// Does the function accept a variable number of arguments following the arguments specified
  • src/InitTweak/InitTweak.cc

    rc7806122 r91fb850  
    10261026                if ( ftype->params.size() != 2 ) return false;
    10271027
    1028                 const ast::Type * t1 = getPointerBase( ftype->params.front() );
     1028                const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() );
    10291029                if ( ! t1 ) return false;
    1030                 const ast::Type * t2 = ftype->params.back();
     1030                const ast::Type * t2 = ftype->params.back()->get_type();
    10311031
    10321032                return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
  • src/ResolvExpr/CandidateFinder.cpp

    rc7806122 r91fb850  
    188188
    189189                        // mark conversion cost and also specialization cost of param type
    190                         // const ast::Type * paramType = (*param)->get_type();
     190                        const ast::Type * paramType = (*param)->get_type();
    191191                        cand->expr = ast::mutate_field_index(
    192192                                appExpr, &ast::ApplicationExpr::args, i,
    193193                                computeExpressionConversionCost(
    194                                         args[i], *param, symtab, cand->env, convCost ) );
    195                         convCost.decSpec( specCost( *param ) );
     194                                        args[i], paramType, symtab, cand->env, convCost ) );
     195                        convCost.decSpec( specCost( paramType ) );
    196196                        ++param;  // can't be in for-loop update because of the continue
    197197                }
     
    698698                        if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {
    699699                                // attempt to narrow based on expected target type
    700                                 const ast::Type * returnType = funcType->returns.front();
     700                                const ast::Type * returnType = funcType->returns.front()->get_type();
    701701                                if ( ! unify(
    702702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     
    712712                        std::size_t genStart = 0;
    713713
    714                         // xxx - how to handle default arg after change to ftype representation?
    715                         if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {
    716                                 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {
    717                                         // function may have default args only if directly calling by name
    718                                         // must use types on candidate however, due to RenameVars substitution
    719                                         auto nParams = funcType->params.size();
    720 
    721                                         for (size_t i=0; i<nParams; ++i) {
    722                                                 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    723                                                 if (!instantiateArgument(
    724                                                         funcType->params[i], obj->init, args, results, genStart, symtab)) return;
    725                                         }
    726                                         goto endMatch;
    727                                 }
    728                         }
    729                         for ( const auto & param : funcType->params ) {
     714                        for ( const ast::DeclWithType * param : funcType->params ) {
     715                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    730716                                // Try adding the arguments corresponding to the current parameter to the existing
    731717                                // matches
    732                                 // no default args for indirect calls
    733718                                if ( ! instantiateArgument(
    734                                         param, nullptr, args, results, genStart, symtab ) ) return;
    735                         }
    736 
    737                         endMatch:
     719                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
     720                        }
     721
    738722                        if ( funcType->isVarArgs ) {
    739723                                // append any unused arguments to vararg pack
  • src/ResolvExpr/CurrentObject.cc

    rc7806122 r91fb850  
    594594        class SimpleIterator final : public MemberIterator {
    595595                CodeLocation location;
    596                 const Type * type = nullptr;
     596                readonly< Type > type = nullptr;
    597597        public:
    598598                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
     
    630630        class ArrayIterator final : public MemberIterator {
    631631                CodeLocation location;
    632                 const ArrayType * array = nullptr;
    633                 const Type * base = nullptr;
     632                readonly< ArrayType > array = nullptr;
     633                readonly< Type > base = nullptr;
    634634                size_t index = 0;
    635635                size_t size = 0;
  • src/ResolvExpr/Resolver.cc

    rc7806122 r91fb850  
    12231223                template<typename Iter>
    12241224                inline bool nextMutex( Iter & it, const Iter & end ) {
    1225                         while ( it != end && ! (*it)->is_mutex() ) { ++it; }
     1225                        while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
    12261226                        return it != end;
    12271227                }
     
    16381638                                                                // Check if the argument matches the parameter type in the current
    16391639                                                                // scope
    1640                                                                 // ast::ptr< ast::Type > paramType = (*param)->get_type();
     1640                                                                ast::ptr< ast::Type > paramType = (*param)->get_type();
    16411641                                                                if (
    16421642                                                                        ! unify(
    1643                                                                                 arg->expr->result, *param, resultEnv, need, have, open,
     1643                                                                                arg->expr->result, paramType, resultEnv, need, have, open,
    16441644                                                                                symtab )
    16451645                                                                ) {
     
    16481648                                                                        ss << "candidate function not viable: no known conversion "
    16491649                                                                                "from '";
    1650                                                                         ast::print( ss, *param );
     1650                                                                        ast::print( ss, (*param)->get_type() );
    16511651                                                                        ss << "' to '";
    16521652                                                                        ast::print( ss, arg->expr->result );
  • src/ResolvExpr/SatisfyAssertions.cpp

    rc7806122 r91fb850  
    318318                                        if ( ! func ) continue;
    319319
    320                                         for ( const auto & param : func->params ) {
    321                                                 cost.decSpec( specCost( param ) );
     320                                        for ( const ast::DeclWithType * param : func->params ) {
     321                                                cost.decSpec( specCost( param->get_type() ) );
    322322                                        }
    323323
  • src/ResolvExpr/SpecCost.cc

    rc7806122 r91fb850  
    178178                void previsit( const ast::FunctionType * fty ) {
    179179                        int minCount = std::numeric_limits<int>::max();
    180                         updateMinimumPresent( minCount, fty->params, type_deref );
    181                         updateMinimumPresent( minCount, fty->returns, type_deref );
     180                        updateMinimumPresent( minCount, fty->params, decl_type );
     181                        updateMinimumPresent( minCount, fty->returns, decl_type );
    182182                        // Add another level to minCount if set.
    183183                        count = toNoneOrInc( minCount );
  • src/ResolvExpr/Unify.cc

    rc7806122 r91fb850  
    395395
    396396        template< typename Iterator1, typename Iterator2 >
    397         bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    398398                auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    399399                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    489489                                        || flatOther->isTtype()
    490490                        ) {
    491                                 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    492                                         if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     491                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     492                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    493493
    494494                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    784784
    785785                /// returns flattened version of `src`
    786                 static std::vector< ast::ptr< ast::Type > > flattenList(
    787                         const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
     787                        const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
    788788                ) {
    789                         std::vector< ast::ptr< ast::Type > > dst;
     789                        std::vector< ast::ptr< ast::DeclWithType > > dst;
    790790                        dst.reserve( src.size() );
    791                         for ( const auto & d : src ) {
     791                        for ( const ast::DeclWithType * d : src ) {
    792792                                ast::Pass<TtypeExpander_new> expander{ env };
    793793                                // TtypeExpander pass is impure (may mutate nodes in place)
    794794                                // need to make nodes shared to prevent accidental mutation
    795                                 ast::ptr<ast::Type> dc = d->accept(expander);
    796                                 auto types = flatten( dc );
     795                                ast::ptr<ast::DeclWithType> dc = d->accept(expander);
     796                                auto types = flatten( dc->get_type() );
    797797                                for ( ast::ptr< ast::Type > & t : types ) {
    798798                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     
    803803                                        // requirements than a non-mutex function
    804804                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    805                                         dst.emplace_back( t );
     805                                        dst.emplace_back( new ast::ObjectDecl{ dc->location, "", t } );
    806806                                }
    807807                        }
     
    811811                /// Creates a tuple type based on a list of DeclWithType
    812812                template< typename Iter >
    813                 static ast::ptr< ast::Type > tupleFromTypes( Iter crnt, Iter end ) {
     813                static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
    814814                        std::vector< ast::ptr< ast::Type > > types;
    815815                        while ( crnt != end ) {
    816816                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    817817                                // that this results in a flat tuple
    818                                 flatten( *crnt, types );
     818                                flatten( (*crnt)->get_type(), types );
    819819
    820820                                ++crnt;
     
    825825
    826826                template< typename Iter >
    827                 static bool unifyTypeList(
     827                static bool unifyDeclList(
    828828                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    829829                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     
    831831                ) {
    832832                        while ( crnt1 != end1 && crnt2 != end2 ) {
    833                                 const ast::Type * t1 = *crnt1;
    834                                 const ast::Type * t2 = *crnt2;
     833                                const ast::Type * t1 = (*crnt1)->get_type();
     834                                const ast::Type * t2 = (*crnt2)->get_type();
    835835                                bool isTuple1 = Tuples::isTtype( t1 );
    836836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    840840                                        // combine remainder of list2, then unify
    841841                                        return unifyExact(
    842                                                 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    843843                                                noWiden(), symtab );
    844844                                } else if ( ! isTuple1 && isTuple2 ) {
    845845                                        // combine remainder of list1, then unify
    846846                                        return unifyExact(
    847                                                 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    848848                                                noWiden(), symtab );
    849849                                }
     
    860860                        if ( crnt1 != end1 ) {
    861861                                // try unifying empty tuple with ttype
    862                                 const ast::Type * t1 = *crnt1;
     862                                const ast::Type * t1 = (*crnt1)->get_type();
    863863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    864864                                return unifyExact(
    865                                         t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    866866                                        noWiden(), symtab );
    867867                        } else if ( crnt2 != end2 ) {
    868868                                // try unifying empty tuple with ttype
    869                                 const ast::Type * t2 = *crnt2;
     869                                const ast::Type * t2 = (*crnt2)->get_type();
    870870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    871871                                return unifyExact(
    872                                         tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    873873                                        noWiden(), symtab );
    874874                        }
     
    877877                }
    878878
    879                 static bool unifyTypeList(
    880                         const std::vector< ast::ptr< ast::Type > > & list1,
    881                         const std::vector< ast::ptr< ast::Type > > & list2,
     879                static bool unifyDeclList(
     880                        const std::vector< ast::ptr< ast::DeclWithType > > & list1,
     881                        const std::vector< ast::ptr< ast::DeclWithType > > & list2,
    882882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    883883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    884884                ) {
    885                         return unifyTypeList(
     885                        return unifyDeclList(
    886886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    887887                                symtab );
     
    928928                        ) return;
    929929
    930                         if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
    931                         if ( ! unifyTypeList(
     930                        if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
     931                        if ( ! unifyDeclList(
    932932                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    933933
     
    12321232        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    12331233                if ( func->returns.empty() ) return new ast::VoidType{};
    1234                 if ( func->returns.size() == 1 ) return func->returns[0];
     1234                if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
    12351235
    12361236                std::vector<ast::ptr<ast::Type>> tys;
    1237                 for ( const auto & decl : func->returns ) {
    1238                         tys.emplace_back( decl );
     1237                for ( const ast::DeclWithType * decl : func->returns ) {
     1238                        tys.emplace_back( decl->get_type() );
    12391239                }
    12401240                return new ast::TupleType{ std::move(tys) };
  • src/SymTab/Mangler.cc

    rc7806122 r91fb850  
    551551                        GuardValue( inFunctionType );
    552552                        inFunctionType = true;
    553                         if (functionType->returns.empty()) mangleName << Encoding::void_t;
    554                         else accept_each( functionType->returns, *visitor );
     553                        std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
     554                        if (returnTypes.empty()) mangleName << Encoding::void_t;
     555                        else accept_each( returnTypes, *visitor );
    555556                        mangleName << "_";
    556                         accept_each( functionType->params, *visitor );
     557                        std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
     558                        accept_each( paramTypes, *visitor );
    557559                        mangleName << "_";
    558560                }
  • src/SymTab/Validate.cc

    rc7806122 r91fb850  
    13841384        /// Replaces enum types by int, and function/array types in function parameter and return
    13851385        /// lists by appropriate pointers
    1386         /*
    13871386        struct EnumAndPointerDecay_new {
    13881387                const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
     
    14351434                }
    14361435        };
    1437         */
    14381436
    14391437        /// expand assertions from a trait instance, performing appropriate type variable substitutions
     
    18391837const ast::Type * validateType(
    18401838                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1841         // ast::Pass< EnumAndPointerDecay_new > epc;
     1839        ast::Pass< EnumAndPointerDecay_new > epc;
    18421840        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    18431841        ast::Pass< ForallPointerDecay_new > fpd{ loc };
    18441842
    1845         return type->accept( lrt )->accept( fpd );
     1843        return type->accept( epc )->accept( lrt )->accept( fpd );
    18461844}
    18471845
Note: See TracChangeset for help on using the changeset viewer.